probe-finder.c 46.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * probe-finder.c : C expression to kprobe event converter
 *
 * Written by Masami Hiramatsu <mhiramat@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 */

22
#include <inttypes.h>
23 24 25 26 27 28 29 30 31 32
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
33
#include <dwarf-regs.h>
34

35
#include <linux/bitops.h>
36
#include "event.h"
37
#include "dso.h"
38
#include "debug.h"
39
#include "intlist.h"
40
#include "util.h"
41
#include "symbol.h"
42
#include "probe-finder.h"
43
#include "probe-file.h"
44
#include "string2.h"
45

46 47 48
/* Kprobe tracer basic type is up to u64 */
#define MAX_BASIC_TYPE_BITS	64

49 50 51 52 53 54 55 56 57 58 59 60 61 62
/* Dwarf FL wrappers */
static char *debuginfo_path;	/* Currently dummy */

static const Dwfl_Callbacks offline_callbacks = {
	.find_debuginfo = dwfl_standard_find_debuginfo,
	.debuginfo_path = &debuginfo_path,

	.section_address = dwfl_offline_section_address,

	/* We use this table for core files too.  */
	.find_elf = dwfl_build_id_find_elf,
};

/* Get a Dwarf from offline image */
63
static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
64
					 const char *path)
65
{
66
	int fd;
67

68 69 70
	fd = open(path, O_RDONLY);
	if (fd < 0)
		return fd;
71

72 73
	dbg->dwfl = dwfl_begin(&offline_callbacks);
	if (!dbg->dwfl)
74
		goto error;
75

76
	dwfl_report_begin(dbg->dwfl);
77 78
	dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
	if (!dbg->mod)
79 80
		goto error;

81 82
	dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
	if (!dbg->dbg)
83 84
		goto error;

85 86
	dwfl_report_end(dbg->dwfl, NULL, NULL);

87
	return 0;
88
error:
89 90
	if (dbg->dwfl)
		dwfl_end(dbg->dwfl);
91 92
	else
		close(fd);
93
	memset(dbg, 0, sizeof(*dbg));
94 95

	return -ENOENT;
96 97
}

98
static struct debuginfo *__debuginfo__new(const char *path)
99
{
100 101
	struct debuginfo *dbg = zalloc(sizeof(*dbg));
	if (!dbg)
102 103
		return NULL;

104 105
	if (debuginfo__init_offline_dwarf(dbg, path) < 0)
		zfree(&dbg);
106 107
	if (dbg)
		pr_debug("Open Debuginfo file: %s\n", path);
108
	return dbg;
109 110
}

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
enum dso_binary_type distro_dwarf_types[] = {
	DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
	DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
	DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
	DSO_BINARY_TYPE__NOT_FOUND,
};

struct debuginfo *debuginfo__new(const char *path)
{
	enum dso_binary_type *type;
	char buf[PATH_MAX], nil = '\0';
	struct dso *dso;
	struct debuginfo *dinfo = NULL;

	/* Try to open distro debuginfo files */
	dso = dso__new(path);
	if (!dso)
		goto out;

	for (type = distro_dwarf_types;
	     !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND;
	     type++) {
		if (dso__read_binary_type_filename(dso, *type, &nil,
						   buf, PATH_MAX) < 0)
			continue;
		dinfo = __debuginfo__new(buf);
	}
139
	dso__put(dso);
140 141 142 143 144 145

out:
	/* if failed to open all distro debuginfo, open given binary */
	return dinfo ? : __debuginfo__new(path);
}

146
void debuginfo__delete(struct debuginfo *dbg)
147
{
148 149 150 151
	if (dbg) {
		if (dbg->dwfl)
			dwfl_end(dbg->dwfl);
		free(dbg);
152
	}
153
}
154

155 156 157 158
/*
 * Probe finder related functions
 */

159
static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
160
{
161 162
	struct probe_trace_arg_ref *ref;
	ref = zalloc(sizeof(struct probe_trace_arg_ref));
163 164 165 166 167
	if (ref != NULL)
		ref->offset = offs;
	return ref;
}

168 169 170
/*
 * Convert a location into trace_arg.
 * If tvar == NULL, this just checks variable can be converted.
171 172
 * If fentry == true and vr_die is a parameter, do huristic search
 * for the location fuzzed by function entry mcount.
173 174
 */
static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
175
				     Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
176
				     unsigned int machine,
177
				     struct probe_trace_arg *tvar)
178
{
179
	Dwarf_Attribute attr;
180
	Dwarf_Addr tmp = 0;
181 182
	Dwarf_Op *op;
	size_t nops;
183 184
	unsigned int regn;
	Dwarf_Word offs = 0;
185
	bool ref = false;
186
	const char *regs;
187
	int ret, ret2 = 0;
188

189 190 191
	if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
		goto static_var;

192
	/* TODO: handle more than 1 exprs */
193 194 195 196
	if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
		return -EINVAL;	/* Broken DIE ? */
	if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
		ret = dwarf_entrypc(sp_die, &tmp);
197 198 199 200 201 202 203 204 205 206 207 208 209
		if (ret)
			return -ENOENT;

		if (probe_conf.show_location_range &&
			(dwarf_tag(vr_die) == DW_TAG_variable)) {
			ret2 = -ERANGE;
		} else if (addr != tmp ||
			dwarf_tag(vr_die) != DW_TAG_formal_parameter) {
			return -ENOENT;
		}

		ret = dwarf_highpc(sp_die, &tmp);
		if (ret)
210 211 212 213 214 215 216 217 218 219
			return -ENOENT;
		/*
		 * This is fuzzed by fentry mcount. We try to find the
		 * parameter location at the earliest address.
		 */
		for (addr += 1; addr <= tmp; addr++) {
			if (dwarf_getlocation_addr(&attr, addr, &op,
						   &nops, 1) > 0)
				goto found;
		}
220 221
		return -ENOENT;
	}
222 223 224 225
found:
	if (nops == 0)
		/* TODO: Support const_value */
		return -ENOENT;
226 227

	if (op->atom == DW_OP_addr) {
228
static_var:
229
		if (!tvar)
230
			return ret2;
231 232 233 234 235 236 237 238 239
		/* Static variables on memory (not stack), make @varname */
		ret = strlen(dwarf_diename(vr_die));
		tvar->value = zalloc(ret + 2);
		if (tvar->value == NULL)
			return -ENOMEM;
		snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
		tvar->ref = alloc_trace_arg_ref((long)offs);
		if (tvar->ref == NULL)
			return -ENOMEM;
240
		return ret2;
241
	}
242 243

	/* If this is based on frame buffer, set the offset */
244
	if (op->atom == DW_OP_fbreg) {
245
		if (fb_ops == NULL)
246
			return -ENOTSUP;
247
		ref = true;
248
		offs = op->number;
249
		op = &fb_ops[0];
250
	}
251

252 253 254
	if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
		regn = op->atom - DW_OP_breg0;
		offs += op->number;
255
		ref = true;
256 257 258 259 260
	} else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
		regn = op->atom - DW_OP_reg0;
	} else if (op->atom == DW_OP_bregx) {
		regn = op->number;
		offs += op->number2;
261
		ref = true;
262 263
	} else if (op->atom == DW_OP_regx) {
		regn = op->number;
264
	} else {
265
		pr_debug("DW_OP %x is not supported.\n", op->atom);
266 267
		return -ENOTSUP;
	}
268

269
	if (!tvar)
270
		return ret2;
271

272
	regs = get_dwarf_regstr(regn, machine);
273
	if (!regs) {
274
		/* This should be a bug in DWARF or this tool */
M
Masami Hiramatsu 已提交
275 276
		pr_warning("Mapping for the register number %u "
			   "missing on this architecture.\n", regn);
277
		return -ENOTSUP;
278
	}
279

280 281 282 283
	tvar->value = strdup(regs);
	if (tvar->value == NULL)
		return -ENOMEM;

284
	if (ref) {
285
		tvar->ref = alloc_trace_arg_ref((long)offs);
286 287
		if (tvar->ref == NULL)
			return -ENOMEM;
288
	}
289
	return ret2;
290 291
}

292 293
#define BYTES_TO_BITS(nb)	((nb) * BITS_PER_LONG / sizeof(long))

294
static int convert_variable_type(Dwarf_Die *vr_die,
295
				 struct probe_trace_arg *tvar,
296
				 const char *cast)
297
{
298
	struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
299 300
	Dwarf_Die type;
	char buf[16];
301
	char sbuf[STRERR_BUFSIZE];
302
	int bsize, boffs, total;
303
	int ret;
304
	char prefix;
305

306
	/* TODO: check all types */
307
	if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "x") != 0 &&
308
	    strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
309
		/* Non string type is OK */
310
		/* and respect signedness/hexadecimal cast */
311 312 313 314
		tvar->type = strdup(cast);
		return (tvar->type == NULL) ? -ENOMEM : 0;
	}

315 316
	bsize = dwarf_bitsize(vr_die);
	if (bsize > 0) {
317
		/* This is a bitfield */
318 319 320 321 322 323
		boffs = dwarf_bitoffset(vr_die);
		total = dwarf_bytesize(vr_die);
		if (boffs < 0 || total < 0)
			return -ENOENT;
		ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs,
				BYTES_TO_BITS(total));
324 325 326
		goto formatted;
	}

327 328 329 330 331
	if (die_get_real_type(vr_die, &type) == NULL) {
		pr_warning("Failed to get a type information of %s.\n",
			   dwarf_diename(vr_die));
		return -ENOENT;
	}
332

333 334 335
	pr_debug("%s type is %s.\n",
		 dwarf_diename(vr_die), dwarf_diename(&type));

336 337 338 339 340
	if (cast && strcmp(cast, "string") == 0) {	/* String type */
		ret = dwarf_tag(&type);
		if (ret != DW_TAG_pointer_type &&
		    ret != DW_TAG_array_type) {
			pr_warning("Failed to cast into string: "
M
Masami Hiramatsu 已提交
341
				   "%s(%s) is not a pointer nor array.\n",
342 343 344
				   dwarf_diename(vr_die), dwarf_diename(&type));
			return -EINVAL;
		}
345 346 347 348 349
		if (die_get_real_type(&type, &type) == NULL) {
			pr_warning("Failed to get a type"
				   " information.\n");
			return -ENOENT;
		}
350 351 352 353
		if (ret == DW_TAG_pointer_type) {
			while (*ref_ptr)
				ref_ptr = &(*ref_ptr)->next;
			/* Add new reference with offset +0 */
354
			*ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
355 356 357 358 359
			if (*ref_ptr == NULL) {
				pr_warning("Out of memory error\n");
				return -ENOMEM;
			}
		}
360 361
		if (!die_compare_name(&type, "char") &&
		    !die_compare_name(&type, "unsigned char")) {
362
			pr_warning("Failed to cast into string: "
M
Masami Hiramatsu 已提交
363
				   "%s is not (unsigned) char *.\n",
364 365 366 367 368 369 370
				   dwarf_diename(vr_die));
			return -EINVAL;
		}
		tvar->type = strdup(cast);
		return (tvar->type == NULL) ? -ENOMEM : 0;
	}

371
	if (cast && (strcmp(cast, "u") == 0))
372
		prefix = 'u';
373
	else if (cast && (strcmp(cast, "s") == 0))
374 375 376 377
		prefix = 's';
	else if (cast && (strcmp(cast, "x") == 0) &&
		 probe_type_is_available(PROBE_TYPE_X))
		prefix = 'x';
378
	else
379 380
		prefix = die_is_signed_type(&type) ? 's' :
			 probe_type_is_available(PROBE_TYPE_X) ? 'x' : 'u';
381

382 383
	ret = dwarf_bytesize(&type);
	if (ret <= 0)
384 385
		/* No size ... try to use default type */
		return 0;
386
	ret = BYTES_TO_BITS(ret);
387

388 389 390 391 392
	/* Check the bitwidth */
	if (ret > MAX_BASIC_TYPE_BITS) {
		pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
			dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
		ret = MAX_BASIC_TYPE_BITS;
393
	}
394
	ret = snprintf(buf, 16, "%c%d", prefix, ret);
395 396 397 398 399 400

formatted:
	if (ret < 0 || ret >= 16) {
		if (ret >= 16)
			ret = -E2BIG;
		pr_warning("Failed to convert variable type: %s\n",
401
			   str_error_r(-ret, sbuf, sizeof(sbuf)));
402 403 404 405 406
		return ret;
	}
	tvar->type = strdup(buf);
	if (tvar->type == NULL)
		return -ENOMEM;
407
	return 0;
408 409
}

410
static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
411
				    struct perf_probe_arg_field *field,
412
				    struct probe_trace_arg_ref **ref_ptr,
413
				    Dwarf_Die *die_mem)
414
{
415
	struct probe_trace_arg_ref *ref = *ref_ptr;
416 417
	Dwarf_Die type;
	Dwarf_Word offs;
418
	int ret, tag;
419 420

	pr_debug("converting %s in %s\n", field->name, varname);
421 422 423 424
	if (die_get_real_type(vr_die, &type) == NULL) {
		pr_warning("Failed to get the type of %s.\n", varname);
		return -ENOENT;
	}
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
	pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type));
	tag = dwarf_tag(&type);

	if (field->name[0] == '[' &&
	    (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
		if (field->next)
			/* Save original type for next field */
			memcpy(die_mem, &type, sizeof(*die_mem));
		/* Get the type of this array */
		if (die_get_real_type(&type, &type) == NULL) {
			pr_warning("Failed to get the type of %s.\n", varname);
			return -ENOENT;
		}
		pr_debug2("Array real type: (%x)\n",
			 (unsigned)dwarf_dieoffset(&type));
		if (tag == DW_TAG_pointer_type) {
441
			ref = zalloc(sizeof(struct probe_trace_arg_ref));
442 443 444 445 446 447 448
			if (ref == NULL)
				return -ENOMEM;
			if (*ref_ptr)
				(*ref_ptr)->next = ref;
			else
				*ref_ptr = ref;
		}
449
		ref->offset += dwarf_bytesize(&type) * field->index;
450 451 452 453 454 455
		if (!field->next)
			/* Save vr_die for converting types */
			memcpy(die_mem, vr_die, sizeof(*die_mem));
		goto next;
	} else if (tag == DW_TAG_pointer_type) {
		/* Check the pointer and dereference */
456 457 458 459 460
		if (!field->ref) {
			pr_err("Semantic error: %s must be referred by '->'\n",
			       field->name);
			return -EINVAL;
		}
461
		/* Get the type pointed by this pointer */
462 463 464 465
		if (die_get_real_type(&type, &type) == NULL) {
			pr_warning("Failed to get the type of %s.\n", varname);
			return -ENOENT;
		}
466
		/* Verify it is a data structure  */
467 468
		tag = dwarf_tag(&type);
		if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
469
			pr_warning("%s is not a data structure nor a union.\n",
470
				   varname);
471 472
			return -EINVAL;
		}
473

474
		ref = zalloc(sizeof(struct probe_trace_arg_ref));
475 476
		if (ref == NULL)
			return -ENOMEM;
477 478 479 480 481
		if (*ref_ptr)
			(*ref_ptr)->next = ref;
		else
			*ref_ptr = ref;
	} else {
482
		/* Verify it is a data structure  */
483
		if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
484
			pr_warning("%s is not a data structure nor a union.\n",
485
				   varname);
486 487
			return -EINVAL;
		}
488
		if (field->name[0] == '[') {
489
			pr_err("Semantic error: %s is not a pointer"
M
Masami Hiramatsu 已提交
490
			       " nor array.\n", varname);
491 492
			return -EINVAL;
		}
493 494
		/* While prcessing unnamed field, we don't care about this */
		if (field->ref && dwarf_diename(vr_die)) {
495 496 497 498 499 500 501 502 503
			pr_err("Semantic error: %s must be referred by '.'\n",
			       field->name);
			return -EINVAL;
		}
		if (!ref) {
			pr_warning("Structure on a register is not "
				   "supported yet.\n");
			return -ENOTSUP;
		}
504 505
	}

506
	if (die_find_member(&type, field->name, die_mem) == NULL) {
A
Arnaldo Carvalho de Melo 已提交
507
		pr_warning("%s(type:%s) has no member %s.\n", varname,
508 509 510
			   dwarf_diename(&type), field->name);
		return -EINVAL;
	}
511 512

	/* Get the offset of the field */
513 514 515 516 517 518 519 520 521
	if (tag == DW_TAG_union_type) {
		offs = 0;
	} else {
		ret = die_get_data_member_location(die_mem, &offs);
		if (ret < 0) {
			pr_warning("Failed to get the offset of %s.\n",
				   field->name);
			return ret;
		}
522
	}
523 524
	ref->offset += (long)offs;

525 526 527 528 529
	/* If this member is unnamed, we need to reuse this field */
	if (!dwarf_diename(die_mem))
		return convert_variable_fields(die_mem, varname, field,
						&ref, die_mem);

530
next:
531 532
	/* Converting next field */
	if (field->next)
533
		return convert_variable_fields(die_mem, field->name,
534
					field->next, &ref, die_mem);
535 536
	else
		return 0;
537 538
}

539
/* Show a variables in kprobe event format */
540
static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
541
{
542
	Dwarf_Die die_mem;
543 544
	int ret;

545 546
	pr_debug("Converting variable %s into trace event.\n",
		 dwarf_diename(vr_die));
547

548
	ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
549
					&pf->sp_die, pf->machine, pf->tvar);
550 551 552 553 554 555
	if (ret == -ENOENT || ret == -EINVAL) {
		pr_err("Failed to find the location of the '%s' variable at this address.\n"
		       " Perhaps it has been optimized out.\n"
		       " Use -V with the --range option to show '%s' location range.\n",
		       pf->pvar->var, pf->pvar->var);
	} else if (ret == -ENOTSUP)
556
		pr_err("Sorry, we don't support this variable location yet.\n");
557
	else if (ret == 0 && pf->pvar->field) {
558 559 560
		ret = convert_variable_fields(vr_die, pf->pvar->var,
					      pf->pvar->field, &pf->tvar->ref,
					      &die_mem);
561 562
		vr_die = &die_mem;
	}
563 564
	if (ret == 0)
		ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
565
	/* *expr will be cached in libdw. Don't free it. */
566
	return ret;
567 568
}

569 570
/* Find a variable in a scope DIE */
static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
571
{
572
	Dwarf_Die vr_die;
573
	char *buf, *ptr;
574
	int ret = 0;
575

576 577 578
	/* Copy raw parameters */
	if (!is_c_varname(pf->pvar->var))
		return copy_to_probe_trace_arg(pf->tvar, pf->pvar);
579

580
	if (pf->pvar->name)
581
		pf->tvar->name = strdup(pf->pvar->name);
582
	else {
583 584 585
		buf = synthesize_perf_probe_arg(pf->pvar);
		if (!buf)
			return -ENOMEM;
586 587 588
		ptr = strchr(buf, ':');	/* Change type separator to _ */
		if (ptr)
			*ptr = '_';
589
		pf->tvar->name = buf;
590
	}
591 592
	if (pf->tvar->name == NULL)
		return -ENOMEM;
593

594
	pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
595
	/* Search child die for local variables and parameters. */
596 597
	if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
		/* Search again in global variables */
598 599
		if (!die_find_variable_at(&pf->cu_die, pf->pvar->var,
						0, &vr_die)) {
600 601
			pr_warning("Failed to find '%s' in this function.\n",
				   pf->pvar->var);
602
			ret = -ENOENT;
603
		}
604
	}
605
	if (ret >= 0)
606 607
		ret = convert_variable(&vr_die, pf);

608
	return ret;
609 610
}

611
/* Convert subprogram DIE to trace point */
612 613
static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
				  Dwarf_Addr paddr, bool retprobe,
614
				  const char *function,
615
				  struct probe_trace_point *tp)
616
{
617
	Dwarf_Addr eaddr, highaddr;
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
	GElf_Sym sym;
	const char *symbol;

	/* Verify the address is correct */
	if (dwarf_entrypc(sp_die, &eaddr) != 0) {
		pr_warning("Failed to get entry address of %s\n",
			   dwarf_diename(sp_die));
		return -ENOENT;
	}
	if (dwarf_highpc(sp_die, &highaddr) != 0) {
		pr_warning("Failed to get end address of %s\n",
			   dwarf_diename(sp_die));
		return -ENOENT;
	}
	if (paddr > highaddr) {
		pr_warning("Offset specified is greater than size of %s\n",
			   dwarf_diename(sp_die));
		return -EINVAL;
	}

638
	symbol = dwarf_diename(sp_die);
639
	if (!symbol) {
640 641 642 643 644 645 646 647
		/* Try to get the symbol name from symtab */
		symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
		if (!symbol) {
			pr_warning("Failed to find symbol at 0x%lx\n",
				   (unsigned long)paddr);
			return -ENOENT;
		}
		eaddr = sym.st_value;
648
	}
649
	tp->offset = (unsigned long)(paddr - eaddr);
650
	tp->address = (unsigned long)paddr;
651 652 653
	tp->symbol = strdup(symbol);
	if (!tp->symbol)
		return -ENOMEM;
654

655
	/* Return probe must be on the head of a subprogram */
656 657
	if (retprobe) {
		if (eaddr != paddr) {
658 659 660 661
			pr_warning("Failed to find \"%s%%return\",\n"
				   " because %s is an inlined function and"
				   " has no return point.\n", function,
				   function);
662 663
			return -EINVAL;
		}
664
		tp->retprobe = true;
665 666
	}

667 668 669
	return 0;
}

670 671
/* Call probe_finder callback with scope DIE */
static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
672 673
{
	Dwarf_Attribute fb_attr;
674
	Dwarf_Frame *frame = NULL;
675 676 677
	size_t nops;
	int ret;

678 679 680 681 682 683
	if (!sc_die) {
		pr_err("Caller must pass a scope DIE. Program error.\n");
		return -EINVAL;
	}

	/* If not a real subprogram, find a real one */
684
	if (!die_is_func_def(sc_die)) {
685
		if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
686 687 688 689 690 691 692 693 694
			if (die_find_tailfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
				pr_warning("Ignoring tail call from %s\n",
						dwarf_diename(&pf->sp_die));
				return 0;
			} else {
				pr_warning("Failed to find probe point in any "
					   "functions.\n");
				return -ENOENT;
			}
695
		}
696 697
	} else
		memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
698

699 700
	/* Get the frame base attribute/ops from subprogram */
	dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
701
	ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
702
	if (ret <= 0 || nops == 0) {
703
		pf->fb_ops = NULL;
704
#if _ELFUTILS_PREREQ(0, 142)
705
	} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
706 707 708
		   (pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) {
		if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 &&
		     (dwarf_cfi_addrframe(pf->cfi_dbg, pf->addr, &frame) != 0)) ||
709
		    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
M
Masami Hiramatsu 已提交
710
			pr_warning("Failed to get call frame on 0x%jx\n",
711
				   (uintmax_t)pf->addr);
712 713
			free(frame);
			return -ENOENT;
714
		}
715
#endif
716
	}
717

718
	/* Call finder's callback handler */
719
	ret = pf->callback(sc_die, pf);
720

721 722
	/* Since *pf->fb_ops can be a part of frame. we should free it here. */
	free(frame);
723
	pf->fb_ops = NULL;
724 725

	return ret;
726 727
}

728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
struct find_scope_param {
	const char *function;
	const char *file;
	int line;
	int diff;
	Dwarf_Die *die_mem;
	bool found;
};

static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
{
	struct find_scope_param *fsp = data;
	const char *file;
	int lno;

	/* Skip if declared file name does not match */
	if (fsp->file) {
		file = dwarf_decl_file(fn_die);
		if (!file || strcmp(fsp->file, file) != 0)
			return 0;
	}
	/* If the function name is given, that's what user expects */
	if (fsp->function) {
751
		if (die_match_name(fn_die, fsp->function)) {
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785
			memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
			fsp->found = true;
			return 1;
		}
	} else {
		/* With the line number, find the nearest declared DIE */
		dwarf_decl_line(fn_die, &lno);
		if (lno < fsp->line && fsp->diff > fsp->line - lno) {
			/* Keep a candidate and continue */
			fsp->diff = fsp->line - lno;
			memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
			fsp->found = true;
		}
	}
	return 0;
}

/* Find an appropriate scope fits to given conditions */
static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
{
	struct find_scope_param fsp = {
		.function = pf->pev->point.function,
		.file = pf->fname,
		.line = pf->lno,
		.diff = INT_MAX,
		.die_mem = die_mem,
		.found = false,
	};

	cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp);

	return fsp.found ? die_mem : NULL;
}

786 787
static int probe_point_line_walker(const char *fname, int lineno,
				   Dwarf_Addr addr, void *data)
788
{
789
	struct probe_finder *pf = data;
790
	Dwarf_Die *sc_die, die_mem;
791
	int ret;
792

793 794
	if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
		return 0;
795

796
	pf->addr = addr;
797 798 799 800 801 802 803
	sc_die = find_best_scope(pf, &die_mem);
	if (!sc_die) {
		pr_warning("Failed to find scope of probe point.\n");
		return -ENOENT;
	}

	ret = call_probe_finder(sc_die, pf);
804

805
	/* Continue if no error, because the line will be in inline function */
806
	return ret < 0 ? ret : 0;
807
}
808

809 810 811 812
/* Find probe point from its line number */
static int find_probe_point_by_line(struct probe_finder *pf)
{
	return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf);
813 814
}

815
/* Find lines which match lazy pattern */
816
static int find_lazy_match_lines(struct intlist *list,
817 818
				 const char *fname, const char *pat)
{
819 820 821 822 823
	FILE *fp;
	char *line = NULL;
	size_t line_len;
	ssize_t len;
	int count = 0, linenum = 1;
824
	char sbuf[STRERR_BUFSIZE];
825 826 827

	fp = fopen(fname, "r");
	if (!fp) {
828
		pr_warning("Failed to open %s: %s\n", fname,
829
			   str_error_r(errno, sbuf, sizeof(sbuf)));
830
		return -errno;
831 832
	}

833
	while ((len = getline(&line, &line_len, fp)) > 0) {
834

835 836 837 838
		if (line[len - 1] == '\n')
			line[len - 1] = '\0';

		if (strlazymatch(line, pat)) {
839
			intlist__add(list, linenum);
840
			count++;
841
		}
842
		linenum++;
843
	}
844 845 846 847 848 849 850 851 852

	if (ferror(fp))
		count = -errno;
	free(line);
	fclose(fp);

	if (count == 0)
		pr_debug("No matched lines found in %s.\n", fname);
	return count;
853 854
}

855 856 857 858
static int probe_point_lazy_walker(const char *fname, int lineno,
				   Dwarf_Addr addr, void *data)
{
	struct probe_finder *pf = data;
859
	Dwarf_Die *sc_die, die_mem;
860 861
	int ret;

862
	if (!intlist__has_entry(pf->lcache, lineno) ||
863 864 865 866 867 868
	    strtailcmp(fname, pf->fname) != 0)
		return 0;

	pr_debug("Probe line found: line:%d addr:0x%llx\n",
		 lineno, (unsigned long long)addr);
	pf->addr = addr;
869 870 871 872 873 874 875 876
	pf->lno = lineno;
	sc_die = find_best_scope(pf, &die_mem);
	if (!sc_die) {
		pr_warning("Failed to find scope of probe point.\n");
		return -ENOENT;
	}

	ret = call_probe_finder(sc_die, pf);
877 878 879 880 881

	/*
	 * Continue if no error, because the lazy pattern will match
	 * to other lines
	 */
882
	return ret < 0 ? ret : 0;
883 884
}

885
/* Find probe points from lazy pattern  */
886
static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
887
{
888
	int ret = 0;
889
	char *fpath;
890

891
	if (intlist__empty(pf->lcache)) {
892 893 894 895 896 897 898 899 900
		const char *comp_dir;

		comp_dir = cu_get_comp_dir(&pf->cu_die);
		ret = get_real_path(pf->fname, comp_dir, &fpath);
		if (ret < 0) {
			pr_warning("Failed to find source file path.\n");
			return ret;
		}

901
		/* Matching lazy line pattern */
902
		ret = find_lazy_match_lines(pf->lcache, fpath,
903
					    pf->pev->point.lazy_line);
904
		free(fpath);
905
		if (ret <= 0)
906
			return ret;
907 908
	}

909
	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
910 911
}

912 913 914 915 916 917 918 919 920
static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
{
	struct perf_probe_point *pp = &pf->pev->point;

	/* Not uprobe? */
	if (!pf->pev->uprobes)
		return;

	/* Compiled with optimization? */
921
	if (die_is_optimized_target(&pf->cu_die))
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
		return;

	/* Don't know entrypc? */
	if (!pf->addr)
		return;

	/* Only FUNC and FUNC@SRC are eligible. */
	if (!pp->function || pp->line || pp->retprobe || pp->lazy_line ||
	    pp->offset || pp->abs_address)
		return;

	/* Not interested in func parameter? */
	if (!perf_probe_with_var(pf->pev))
		return;

	pr_info("Target program is compiled without optimization. Skipping prologue.\n"
		"Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
		pf->addr);

941
	die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
942 943
}

944 945
static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
{
946
	struct probe_finder *pf = data;
947
	struct perf_probe_point *pp = &pf->pev->point;
948
	Dwarf_Addr addr;
949
	int ret;
950

951
	if (pp->lazy_line)
952
		ret = find_probe_point_lazy(in_die, pf);
953 954
	else {
		/* Get probe address */
955
		if (dwarf_entrypc(in_die, &addr) != 0) {
M
Masami Hiramatsu 已提交
956
			pr_warning("Failed to get entry address of %s.\n",
957
				   dwarf_diename(in_die));
958
			return -ENOENT;
959
		}
960 961 962 963 964
		if (addr == 0) {
			pr_debug("%s has no valid entry address. skipped.\n",
				 dwarf_diename(in_die));
			return -ENOENT;
		}
965
		pf->addr = addr;
966 967 968 969
		pf->addr += pp->offset;
		pr_debug("found inline addr: 0x%jx\n",
			 (uintmax_t)pf->addr);

970
		ret = call_probe_finder(in_die, pf);
971
	}
972

973
	return ret;
974
}
975

976 977 978 979 980 981
/* Callback parameter with return value for libdw */
struct dwarf_callback_param {
	void *data;
	int retval;
};

982
/* Search function from function name */
983
static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
984
{
985 986
	struct dwarf_callback_param *param = data;
	struct probe_finder *pf = param->data;
987
	struct perf_probe_point *pp = &pf->pev->point;
988

989
	/* Check tag and diename */
990
	if (!die_is_func_def(sp_die) ||
991
	    !die_match_name(sp_die, pp->function))
992
		return DWARF_CB_OK;
993

994 995 996 997
	/* Check declared file */
	if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
		return DWARF_CB_OK;

998 999
	pr_debug("Matched function: %s [%lx]\n", dwarf_diename(sp_die),
		 (unsigned long)dwarf_dieoffset(sp_die));
1000
	pf->fname = dwarf_decl_file(sp_die);
1001 1002 1003
	if (pp->line) { /* Function relative line */
		dwarf_decl_line(sp_die, &pf->lno);
		pf->lno += pp->line;
1004
		param->retval = find_probe_point_by_line(pf);
1005 1006 1007
	} else if (die_is_func_instance(sp_die)) {
		/* Instances always have the entry address */
		dwarf_entrypc(sp_die, &pf->addr);
1008 1009 1010 1011 1012
		/* But in some case the entry address is 0 */
		if (pf->addr == 0) {
			pr_debug("%s has no entry PC. Skipped\n",
				 dwarf_diename(sp_die));
			param->retval = 0;
1013
		/* Real function */
1014
		} else if (pp->lazy_line)
1015
			param->retval = find_probe_point_lazy(sp_die, pf);
1016
		else {
1017
			skip_prologue(sp_die, pf);
1018 1019
			pf->addr += pp->offset;
			/* TODO: Check the address in this function */
1020
			param->retval = call_probe_finder(sp_die, pf);
1021
		}
1022
	} else if (!probe_conf.no_inlines) {
1023
		/* Inlined function: search instances */
1024 1025
		param->retval = die_walk_instances(sp_die,
					probe_point_inline_cb, (void *)pf);
1026
		/* This could be a non-existed inline definition */
1027
		if (param->retval == -ENOENT)
1028 1029 1030 1031 1032 1033 1034 1035
			param->retval = 0;
	}

	/* We need to find other candidates */
	if (strisglob(pp->function) && param->retval >= 0) {
		param->retval = 0;	/* We have to clear the result */
		return DWARF_CB_OK;
	}
1036

1037
	return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
1038 1039
}

1040
static int find_probe_point_by_func(struct probe_finder *pf)
1041
{
1042 1043 1044 1045
	struct dwarf_callback_param _param = {.data = (void *)pf,
					      .retval = 0};
	dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
	return _param.retval;
1046 1047
}

1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
struct pubname_callback_param {
	char *function;
	char *file;
	Dwarf_Die *cu_die;
	Dwarf_Die *sp_die;
	int found;
};

static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
{
	struct pubname_callback_param *param = data;

	if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) {
		if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
			return DWARF_CB_OK;

1064
		if (die_match_name(param->sp_die, param->function)) {
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
			if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
				return DWARF_CB_OK;

			if (param->file &&
			    strtailcmp(param->file, dwarf_decl_file(param->sp_die)))
				return DWARF_CB_OK;

			param->found = 1;
			return DWARF_CB_ABORT;
		}
	}

	return DWARF_CB_OK;
}

1080
static int debuginfo__find_probe_location(struct debuginfo *dbg,
1081
				  struct probe_finder *pf)
1082
{
1083
	struct perf_probe_point *pp = &pf->pev->point;
1084 1085 1086
	Dwarf_Off off, noff;
	size_t cuhl;
	Dwarf_Die *diep;
1087
	int ret = 0;
1088 1089

	off = 0;
1090 1091 1092
	pf->lcache = intlist__new(NULL);
	if (!pf->lcache)
		return -ENOMEM;
1093 1094

	/* Fastpath: lookup by function name from .debug_pubnames section */
1095
	if (pp->function && !strisglob(pp->function)) {
1096 1097 1098 1099 1100
		struct pubname_callback_param pubname_param = {
			.function = pp->function,
			.file	  = pp->file,
			.cu_die	  = &pf->cu_die,
			.sp_die	  = &pf->sp_die,
1101
			.found	  = 0,
1102 1103 1104 1105 1106
		};
		struct dwarf_callback_param probe_param = {
			.data = pf,
		};

1107
		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1108
				  &pubname_param, 0);
1109 1110 1111 1112 1113 1114 1115
		if (pubname_param.found) {
			ret = probe_point_search_cb(&pf->sp_die, &probe_param);
			if (ret)
				goto found;
		}
	}

1116
	/* Loop on CUs (Compilation Unit) */
1117
	while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1118
		/* Get the DIE(Debugging Information Entry) of this CU */
1119
		diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
1120 1121
		if (!diep)
			continue;
1122 1123 1124

		/* Check if target file is included. */
		if (pp->file)
1125
			pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
1126
		else
1127
			pf->fname = NULL;
1128

1129
		if (!pp->file || pf->fname) {
1130
			if (pp->function)
1131
				ret = find_probe_point_by_func(pf);
1132
			else if (pp->lazy_line)
1133
				ret = find_probe_point_lazy(&pf->cu_die, pf);
1134
			else {
1135 1136
				pf->lno = pp->line;
				ret = find_probe_point_by_line(pf);
1137
			}
1138
			if (ret < 0)
1139
				break;
1140
		}
1141
		off = noff;
1142
	}
1143 1144

found:
1145 1146
	intlist__delete(pf->lcache);
	pf->lcache = NULL;
1147

1148 1149 1150
	return ret;
}

1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
/* Find probe points from debuginfo */
static int debuginfo__find_probes(struct debuginfo *dbg,
				  struct probe_finder *pf)
{
	int ret = 0;
	Elf *elf;
	GElf_Ehdr ehdr;

	if (pf->cfi_eh || pf->cfi_dbg)
		return debuginfo__find_probe_location(dbg, pf);

	/* Get the call frame information from this dwarf */
	elf = dwarf_getelf(dbg->dbg);
	if (elf == NULL)
		return -EINVAL;

	if (gelf_getehdr(elf, &ehdr) == NULL)
		return -EINVAL;

1170 1171 1172 1173 1174 1175 1176 1177 1178
	pf->machine = ehdr.e_machine;

#if _ELFUTILS_PREREQ(0, 142)
	do {
		GElf_Shdr shdr;

		if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
		    shdr.sh_type == SHT_PROGBITS)
			pf->cfi_eh = dwarf_getcfi_elf(elf);
1179

1180 1181
		pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
	} while (0);
1182 1183 1184 1185 1186 1187
#endif

	ret = debuginfo__find_probe_location(dbg, pf);
	return ret;
}

1188 1189 1190
struct local_vars_finder {
	struct probe_finder *pf;
	struct perf_probe_arg *args;
1191
	bool vars;
1192 1193 1194 1195 1196 1197 1198 1199 1200
	int max_args;
	int nargs;
	int ret;
};

/* Collect available variables in this scope */
static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
{
	struct local_vars_finder *vf = data;
1201
	struct probe_finder *pf = vf->pf;
1202 1203 1204 1205
	int tag;

	tag = dwarf_tag(die_mem);
	if (tag == DW_TAG_formal_parameter ||
1206
	    (tag == DW_TAG_variable && vf->vars)) {
1207
		if (convert_variable_location(die_mem, vf->pf->addr,
1208
					      vf->pf->fb_ops, &pf->sp_die,
1209
					      pf->machine, NULL) == 0) {
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
			vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
			if (vf->args[vf->nargs].var == NULL) {
				vf->ret = -ENOMEM;
				return DIE_FIND_CB_END;
			}
			pr_debug(" %s", vf->args[vf->nargs].var);
			vf->nargs++;
		}
	}

	if (dwarf_haspc(die_mem, vf->pf->addr))
		return DIE_FIND_CB_CONTINUE;
	else
		return DIE_FIND_CB_SIBLING;
}

static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
			     struct perf_probe_arg *args)
{
	Dwarf_Die die_mem;
	int i;
	int n = 0;
1232
	struct local_vars_finder vf = {.pf = pf, .args = args, .vars = false,
1233 1234 1235 1236
				.max_args = MAX_PROBE_ARGS, .ret = 0};

	for (i = 0; i < pf->pev->nargs; i++) {
		/* var never be NULL */
1237 1238 1239
		if (strcmp(pf->pev->args[i].var, PROBE_ARG_VARS) == 0)
			vf.vars = true;
		else if (strcmp(pf->pev->args[i].var, PROBE_ARG_PARAMS) != 0) {
1240 1241 1242
			/* Copy normal argument */
			args[n] = pf->pev->args[i];
			n++;
1243
			continue;
1244
		}
1245 1246 1247 1248 1249 1250 1251 1252 1253
		pr_debug("Expanding %s into:", pf->pev->args[i].var);
		vf.nargs = n;
		/* Special local variables */
		die_find_child(sc_die, copy_variables_cb, (void *)&vf,
			       &die_mem);
		pr_debug(" (%d)\n", vf.nargs - n);
		if (vf.ret < 0)
			return vf.ret;
		n = vf.nargs;
1254 1255 1256 1257
	}
	return n;
}

1258
/* Add a found probe point into trace event list */
1259
static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1260 1261 1262
{
	struct trace_event_finder *tf =
			container_of(pf, struct trace_event_finder, pf);
1263
	struct perf_probe_point *pp = &pf->pev->point;
1264
	struct probe_trace_event *tev;
1265
	struct perf_probe_arg *args = NULL;
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
	int ret, i;

	/* Check number of tevs */
	if (tf->ntevs == tf->max_tevs) {
		pr_warning("Too many( > %d) probe point found.\n",
			   tf->max_tevs);
		return -ERANGE;
	}
	tev = &tf->tevs[tf->ntevs++];

1276
	/* Trace point should be converted from subprogram DIE */
1277
	ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
1278
				     pp->retprobe, pp->function, &tev->point);
1279
	if (ret < 0)
1280
		goto end;
1281

1282
	tev->point.realname = strdup(dwarf_diename(sc_die));
1283 1284 1285 1286
	if (!tev->point.realname) {
		ret = -ENOMEM;
		goto end;
	}
1287

1288 1289 1290
	pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
		 tev->point.offset);

1291 1292
	/* Expand special probe argument if exist */
	args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
1293 1294 1295 1296
	if (args == NULL) {
		ret = -ENOMEM;
		goto end;
	}
1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311

	ret = expand_probe_args(sc_die, pf, args);
	if (ret < 0)
		goto end;

	tev->nargs = ret;
	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
	if (tev->args == NULL) {
		ret = -ENOMEM;
		goto end;
	}

	/* Find each argument */
	for (i = 0; i < tev->nargs; i++) {
		pf->pvar = &args[i];
1312
		pf->tvar = &tev->args[i];
1313 1314
		/* Variable should be found from scope DIE */
		ret = find_variable(sc_die, pf);
1315
		if (ret != 0)
1316
			break;
1317 1318
	}

1319
end:
1320 1321 1322 1323
	if (ret) {
		clear_probe_trace_event(tev);
		tf->ntevs--;
	}
1324 1325
	free(args);
	return ret;
1326 1327 1328
}

/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1329
int debuginfo__find_trace_events(struct debuginfo *dbg,
1330
				 struct perf_probe_event *pev,
1331
				 struct probe_trace_event **tevs)
1332 1333 1334
{
	struct trace_event_finder tf = {
			.pf = {.pev = pev, .callback = add_probe_trace_event},
1335
			.max_tevs = probe_conf.max_probes, .mod = dbg->mod};
1336
	int ret, i;
1337 1338

	/* Allocate result tevs array */
1339
	*tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
1340 1341 1342 1343 1344 1345
	if (*tevs == NULL)
		return -ENOMEM;

	tf.tevs = *tevs;
	tf.ntevs = 0;

1346
	ret = debuginfo__find_probes(dbg, &tf.pf);
1347
	if (ret < 0) {
1348 1349
		for (i = 0; i < tf.ntevs; i++)
			clear_probe_trace_event(&tf.tevs[i]);
1350
		zfree(tevs);
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361
		return ret;
	}

	return (ret < 0) ? ret : tf.ntevs;
}

/* Collect available variables in this scope */
static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
{
	struct available_var_finder *af = data;
	struct variable_list *vl;
1362
	struct strbuf buf = STRBUF_INIT;
1363 1364 1365 1366 1367 1368 1369 1370
	int tag, ret;

	vl = &af->vls[af->nvls - 1];

	tag = dwarf_tag(die_mem);
	if (tag == DW_TAG_formal_parameter ||
	    tag == DW_TAG_variable) {
		ret = convert_variable_location(die_mem, af->pf.addr,
1371
						af->pf.fb_ops, &af->pf.sp_die,
1372
						af->pf.machine, NULL);
1373 1374 1375
		if (ret == 0 || ret == -ERANGE) {
			int ret2;
			bool externs = !af->child;
1376

1377 1378
			if (strbuf_init(&buf, 64) < 0)
				goto error;
1379 1380

			if (probe_conf.show_location_range) {
1381 1382 1383 1384 1385 1386 1387
				if (!externs)
					ret2 = strbuf_add(&buf,
						ret ? "[INV]\t" : "[VAL]\t", 6);
				else
					ret2 = strbuf_add(&buf, "[EXT]\t", 6);
				if (ret2)
					goto error;
1388 1389 1390 1391 1392 1393
			}

			ret2 = die_get_varname(die_mem, &buf);

			if (!ret2 && probe_conf.show_location_range &&
				!externs) {
1394 1395
				if (strbuf_addch(&buf, '\t') < 0)
					goto error;
1396 1397 1398 1399 1400 1401
				ret2 = die_get_var_range(&af->pf.sp_die,
							die_mem, &buf);
			}

			pr_debug("Add new var: %s\n", buf.buf);
			if (ret2 == 0) {
1402 1403
				strlist__add(vl->vars,
					strbuf_detach(&buf, NULL));
1404 1405
			}
			strbuf_release(&buf);
1406 1407 1408
		}
	}

1409
	if (af->child && dwarf_haspc(die_mem, af->pf.addr))
1410 1411 1412
		return DIE_FIND_CB_CONTINUE;
	else
		return DIE_FIND_CB_SIBLING;
1413 1414 1415 1416
error:
	strbuf_release(&buf);
	pr_debug("Error in strbuf\n");
	return DIE_FIND_CB_END;
1417 1418 1419
}

/* Add a found vars into available variables list */
1420
static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1421 1422 1423
{
	struct available_var_finder *af =
			container_of(pf, struct available_var_finder, pf);
1424
	struct perf_probe_point *pp = &pf->pev->point;
1425
	struct variable_list *vl;
1426 1427
	Dwarf_Die die_mem;
	int ret;
1428 1429 1430 1431 1432 1433 1434 1435

	/* Check number of tevs */
	if (af->nvls == af->max_vls) {
		pr_warning("Too many( > %d) probe point found.\n", af->max_vls);
		return -ERANGE;
	}
	vl = &af->vls[af->nvls++];

1436
	/* Trace point should be converted from subprogram DIE */
1437
	ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
1438
				     pp->retprobe, pp->function, &vl->point);
1439 1440 1441 1442 1443 1444 1445
	if (ret < 0)
		return ret;

	pr_debug("Probe point found: %s+%lu\n", vl->point.symbol,
		 vl->point.offset);

	/* Find local variables */
1446
	vl->vars = strlist__new(NULL, NULL);
1447 1448
	if (vl->vars == NULL)
		return -ENOMEM;
1449
	af->child = true;
1450
	die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
1451

1452
	/* Find external variables */
1453
	if (!probe_conf.show_ext_vars)
1454
		goto out;
1455
	/* Don't need to search child DIE for external vars. */
1456
	af->child = false;
1457
	die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
1458 1459

out:
1460 1461 1462 1463 1464 1465 1466 1467
	if (strlist__empty(vl->vars)) {
		strlist__delete(vl->vars);
		vl->vars = NULL;
	}

	return ret;
}

1468 1469 1470 1471 1472
/*
 * Find available variables at given probe point
 * Return the number of found probe points. Return 0 if there is no
 * matched probe point. Return <0 if an error occurs.
 */
1473
int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1474
				      struct perf_probe_event *pev,
1475
				      struct variable_list **vls)
1476 1477 1478
{
	struct available_var_finder af = {
			.pf = {.pev = pev, .callback = add_available_vars},
1479
			.mod = dbg->mod,
1480
			.max_vls = probe_conf.max_probes};
1481 1482 1483
	int ret;

	/* Allocate result vls array */
1484
	*vls = zalloc(sizeof(struct variable_list) * af.max_vls);
1485 1486 1487 1488 1489 1490
	if (*vls == NULL)
		return -ENOMEM;

	af.vls = *vls;
	af.nvls = 0;

1491
	ret = debuginfo__find_probes(dbg, &af.pf);
1492 1493 1494
	if (ret < 0) {
		/* Free vlist for error */
		while (af.nvls--) {
1495
			zfree(&af.vls[af.nvls].point.symbol);
1496
			strlist__delete(af.vls[af.nvls].vars);
1497
		}
1498
		zfree(vls);
1499 1500 1501 1502
		return ret;
	}

	return (ret < 0) ? ret : af.nvls;
1503 1504
}

1505
/* For the kernel module, we need a special code to get a DIE */
1506 1507
int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
				bool adjust_offset)
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
{
	int n, i;
	Elf32_Word shndx;
	Elf_Scn *scn;
	Elf *elf;
	GElf_Shdr mem, *shdr;
	const char *p;

	elf = dwfl_module_getelf(dbg->mod, &dbg->bias);
	if (!elf)
		return -EINVAL;

	/* Get the number of relocations */
	n = dwfl_module_relocations(dbg->mod);
	if (n < 0)
		return -ENOENT;
	/* Search the relocation related .text section */
	for (i = 0; i < n; i++) {
		p = dwfl_module_relocation_info(dbg->mod, i, &shndx);
		if (strcmp(p, ".text") == 0) {
			/* OK, get the section header */
			scn = elf_getscn(elf, shndx);
			if (!scn)
				return -ENOENT;
			shdr = gelf_getshdr(scn, &mem);
			if (!shdr)
				return -ENOENT;
			*offs = shdr->sh_addr;
1536 1537
			if (adjust_offset)
				*offs -= shdr->sh_offset;
1538 1539 1540 1541 1542
		}
	}
	return 0;
}

1543
/* Reverse search */
1544
int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1545
				struct perf_probe_point *ppt)
1546 1547
{
	Dwarf_Die cudie, spdie, indie;
1548 1549
	Dwarf_Addr _addr = 0, baseaddr = 0;
	const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1550
	int baseline = 0, lineno = 0, ret = 0;
1551

1552
	/* We always need to relocate the address for aranges */
1553
	if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0)
1554
		addr += baseaddr;
1555
	/* Find cu die */
1556
	if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
M
Masami Hiramatsu 已提交
1557 1558
		pr_warning("Failed to find debug information for address %lx\n",
			   addr);
1559 1560 1561
		ret = -EINVAL;
		goto end;
	}
1562

1563 1564 1565
	/* Find a corresponding line (filename and lineno) */
	cu_find_lineinfo(&cudie, addr, &fname, &lineno);
	/* Don't care whether it failed or not */
1566

1567
	/* Find a corresponding function (name, baseline and baseaddr) */
1568
	if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
1569
		/* Get function entry information */
1570 1571
		func = basefunc = dwarf_diename(&spdie);
		if (!func ||
1572
		    dwarf_entrypc(&spdie, &baseaddr) != 0 ||
1573 1574
		    dwarf_decl_line(&spdie, &baseline) != 0) {
			lineno = 0;
1575
			goto post;
1576
		}
1577

1578
		fname = dwarf_decl_file(&spdie);
1579
		if (addr == (unsigned long)baseaddr) {
1580 1581
			/* Function entry - Relative line number is 0 */
			lineno = baseline;
1582 1583 1584 1585 1586 1587 1588
			goto post;
		}

		/* Track down the inline functions step by step */
		while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr,
						&indie)) {
			/* There is an inline function */
1589
			if (dwarf_entrypc(&indie, &_addr) == 0 &&
1590
			    _addr == addr) {
1591 1592 1593
				/*
				 * addr is at an inline function entry.
				 * In this case, lineno should be the call-site
1594
				 * line number. (overwrite lineinfo)
1595 1596
				 */
				lineno = die_get_call_lineno(&indie);
1597 1598 1599
				fname = die_get_call_file(&indie);
				break;
			} else {
1600 1601 1602 1603 1604 1605
				/*
				 * addr is in an inline function body.
				 * Since lineno points one of the lines
				 * of the inline function, baseline should
				 * be the entry line of the inline function.
				 */
1606
				tmp = dwarf_diename(&indie);
1607 1608 1609 1610 1611
				if (!tmp ||
				    dwarf_decl_line(&indie, &baseline) != 0)
					break;
				func = tmp;
				spdie = indie;
1612
			}
1613
		}
1614 1615 1616 1617
		/* Verify the lineno and baseline are in a same file */
		tmp = dwarf_decl_file(&spdie);
		if (!tmp || strcmp(tmp, fname) != 0)
			lineno = 0;
1618 1619 1620 1621 1622 1623
	}

post:
	/* Make a relative line number or an offset */
	if (lineno)
		ppt->line = lineno - baseline;
1624
	else if (basefunc) {
1625
		ppt->offset = addr - (unsigned long)baseaddr;
1626 1627
		func = basefunc;
	}
1628 1629 1630 1631

	/* Duplicate strings */
	if (func) {
		ppt->function = strdup(func);
1632 1633 1634 1635
		if (ppt->function == NULL) {
			ret = -ENOMEM;
			goto end;
		}
1636
	}
1637 1638 1639
	if (fname) {
		ppt->file = strdup(fname);
		if (ppt->file == NULL) {
1640
			zfree(&ppt->function);
1641 1642 1643 1644
			ret = -ENOMEM;
			goto end;
		}
	}
1645
end:
1646 1647
	if (ret == 0 && (fname || func))
		ret = 1;	/* Found a point */
1648 1649 1650
	return ret;
}

1651 1652 1653 1654
/* Add a line and store the src path */
static int line_range_add_line(const char *src, unsigned int lineno,
			       struct line_range *lr)
{
1655
	/* Copy source path */
1656
	if (!lr->path) {
1657 1658 1659
		lr->path = strdup(src);
		if (lr->path == NULL)
			return -ENOMEM;
1660
	}
1661
	return intlist__add(lr->line_list, lineno);
1662 1663
}

1664
static int line_range_walk_cb(const char *fname, int lineno,
1665
			      Dwarf_Addr addr __maybe_unused,
1666
			      void *data)
1667
{
1668
	struct line_finder *lf = data;
1669
	int err;
1670

1671
	if ((strtailcmp(fname, lf->fname) != 0) ||
1672
	    (lf->lno_s > lineno || lf->lno_e < lineno))
1673
		return 0;
1674

1675 1676 1677
	err = line_range_add_line(fname, lineno, lf->lr);
	if (err < 0 && err != -EEXIST)
		return err;
1678

1679
	return 0;
1680
}
1681

1682
/* Find line range from its line number */
1683
static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1684
{
1685
	int ret;
1686

1687
	ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf);
1688

1689
	/* Update status */
1690
	if (ret >= 0)
1691
		if (!intlist__empty(lf->lr->line_list))
1692 1693 1694
			ret = lf->found = 1;
		else
			ret = 0;	/* Lines are not found */
1695
	else {
1696
		zfree(&lf->lr->path);
1697
	}
1698
	return ret;
1699 1700
}

1701 1702
static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
{
1703
	int ret = find_line_range_by_line(in_die, data);
1704 1705 1706 1707

	/*
	 * We have to check all instances of inlined function, because
	 * some execution paths can be optimized out depends on the
1708 1709
	 * function argument of instances. However, if an error occurs,
	 * it should be handled by the caller.
1710
	 */
1711
	return ret < 0 ? ret : 0;
1712 1713
}

1714
/* Search function definition from function name */
1715
static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1716
{
1717 1718
	struct dwarf_callback_param *param = data;
	struct line_finder *lf = param->data;
1719 1720
	struct line_range *lr = lf->lr;

1721 1722 1723 1724
	/* Check declared file */
	if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
		return DWARF_CB_OK;

1725
	if (die_is_func_def(sp_die) &&
1726
	    die_match_name(sp_die, lr->function)) {
1727 1728
		lf->fname = dwarf_decl_file(sp_die);
		dwarf_decl_line(sp_die, &lr->offset);
1729
		pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
1730
		lf->lno_s = lr->offset + lr->start;
1731 1732 1733 1734
		if (lf->lno_s < 0)	/* Overflow */
			lf->lno_s = INT_MAX;
		lf->lno_e = lr->offset + lr->end;
		if (lf->lno_e < 0)	/* Overflow */
1735
			lf->lno_e = INT_MAX;
1736
		pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1737 1738
		lr->start = lf->lno_s;
		lr->end = lf->lno_e;
1739
		if (!die_is_func_instance(sp_die))
1740 1741 1742
			param->retval = die_walk_instances(sp_die,
						line_range_inline_cb, lf);
		else
1743 1744
			param->retval = find_line_range_by_line(sp_die, lf);
		return DWARF_CB_ABORT;
1745
	}
1746
	return DWARF_CB_OK;
1747 1748
}

1749
static int find_line_range_by_func(struct line_finder *lf)
1750
{
1751 1752 1753
	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
	dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
	return param.retval;
1754 1755
}

1756
int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
1757
{
1758
	struct line_finder lf = {.lr = lr, .found = 0};
1759
	int ret = 0;
1760 1761 1762
	Dwarf_Off off = 0, noff;
	size_t cuhl;
	Dwarf_Die *diep;
1763
	const char *comp_dir;
1764

1765 1766 1767 1768 1769 1770 1771 1772
	/* Fastpath: lookup by function name from .debug_pubnames section */
	if (lr->function) {
		struct pubname_callback_param pubname_param = {
			.function = lr->function, .file = lr->file,
			.cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
		struct dwarf_callback_param line_range_param = {
			.data = (void *)&lf, .retval = 0};

1773
		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1774
				  &pubname_param, 0);
1775 1776 1777 1778 1779 1780 1781
		if (pubname_param.found) {
			line_range_search_cb(&lf.sp_die, &line_range_param);
			if (lf.found)
				goto found;
		}
	}

1782
	/* Loop on CUs (Compilation Unit) */
1783
	while (!lf.found && ret >= 0) {
1784
		if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
1785
				 NULL, NULL, NULL) != 0)
1786 1787 1788
			break;

		/* Get the DIE(Debugging Information Entry) of this CU */
1789
		diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
1790 1791
		if (!diep)
			continue;
1792 1793 1794

		/* Check if target file is included. */
		if (lr->file)
1795
			lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
1796
		else
1797
			lf.fname = 0;
1798

1799
		if (!lr->file || lf.fname) {
1800
			if (lr->function)
1801
				ret = find_line_range_by_func(&lf);
1802 1803
			else {
				lf.lno_s = lr->start;
1804
				lf.lno_e = lr->end;
1805
				ret = find_line_range_by_line(NULL, &lf);
1806 1807
			}
		}
1808
		off = noff;
1809
	}
1810

1811
found:
1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
	/* Store comp_dir */
	if (lf.found) {
		comp_dir = cu_get_comp_dir(&lf.cu_die);
		if (comp_dir) {
			lr->comp_dir = strdup(comp_dir);
			if (!lr->comp_dir)
				ret = -ENOMEM;
		}
	}

1822
	pr_debug("path: %s\n", lr->path);
1823
	return (ret < 0) ? ret : lf.found;
1824 1825
}

1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883
/*
 * Find a src file from a DWARF tag path. Prepend optional source path prefix
 * and chop off leading directories that do not exist. Result is passed back as
 * a newly allocated path on success.
 * Return 0 if file was found and readable, -errno otherwise.
 */
int get_real_path(const char *raw_path, const char *comp_dir,
			 char **new_path)
{
	const char *prefix = symbol_conf.source_prefix;

	if (!prefix) {
		if (raw_path[0] != '/' && comp_dir)
			/* If not an absolute path, try to use comp_dir */
			prefix = comp_dir;
		else {
			if (access(raw_path, R_OK) == 0) {
				*new_path = strdup(raw_path);
				return *new_path ? 0 : -ENOMEM;
			} else
				return -errno;
		}
	}

	*new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
	if (!*new_path)
		return -ENOMEM;

	for (;;) {
		sprintf(*new_path, "%s/%s", prefix, raw_path);

		if (access(*new_path, R_OK) == 0)
			return 0;

		if (!symbol_conf.source_prefix) {
			/* In case of searching comp_dir, don't retry */
			zfree(new_path);
			return -errno;
		}

		switch (errno) {
		case ENAMETOOLONG:
		case ENOENT:
		case EROFS:
		case EFAULT:
			raw_path = strchr(++raw_path, '/');
			if (!raw_path) {
				zfree(new_path);
				return -ENOENT;
			}
			continue;

		default:
			zfree(new_path);
			return -errno;
		}
	}
}