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 "strlist.h"
42
#include "symbol.h"
43
#include "probe-finder.h"
44
#include "probe-file.h"
45
#include "string2.h"
46

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

50 51 52 53 54 55 56 57 58 59 60 61 62 63
/* 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 */
64
static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
65
					 const char *path)
66
{
67
	int fd;
68

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

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

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

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

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

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

	return -ENOENT;
97 98
}

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

105 106
	if (debuginfo__init_offline_dwarf(dbg, path) < 0)
		zfree(&dbg);
107 108
	if (dbg)
		pr_debug("Open Debuginfo file: %s\n", path);
109
	return dbg;
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 139
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);
	}
140
	dso__put(dso);
141 142 143 144 145 146

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

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

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

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

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

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

193
	/* TODO: handle more than 1 exprs */
194 195 196 197
	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);
198 199 200 201 202 203 204 205 206 207 208 209 210
		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)
211 212 213 214 215 216 217 218 219 220
			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;
		}
221 222
		return -ENOENT;
	}
223 224 225 226
found:
	if (nops == 0)
		/* TODO: Support const_value */
		return -ENOENT;
227 228

	if (op->atom == DW_OP_addr) {
229
static_var:
230
		if (!tvar)
231
			return ret2;
232 233 234 235 236 237 238 239 240
		/* 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;
241
		return ret2;
242
	}
243 244

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

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

270
	if (!tvar)
271
		return ret2;
272

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

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

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

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

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

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

316 317
	bsize = dwarf_bitsize(vr_die);
	if (bsize > 0) {
318
		/* This is a bitfield */
319 320 321 322 323 324
		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));
325 326 327
		goto formatted;
	}

328 329 330 331 332
	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;
	}
333

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

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

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

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

389 390 391 392 393
	/* 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;
394
	}
395
	ret = snprintf(buf, 16, "%c%d", prefix, ret);
396 397 398 399 400 401

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

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

	pr_debug("converting %s in %s\n", field->name, varname);
422 423 424 425
	if (die_get_real_type(vr_die, &type) == NULL) {
		pr_warning("Failed to get the type of %s.\n", varname);
		return -ENOENT;
	}
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
	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) {
442
			ref = zalloc(sizeof(struct probe_trace_arg_ref));
443 444 445 446 447 448 449
			if (ref == NULL)
				return -ENOMEM;
			if (*ref_ptr)
				(*ref_ptr)->next = ref;
			else
				*ref_ptr = ref;
		}
450
		ref->offset += dwarf_bytesize(&type) * field->index;
451 452 453 454 455 456
		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 */
457 458 459 460 461
		if (!field->ref) {
			pr_err("Semantic error: %s must be referred by '->'\n",
			       field->name);
			return -EINVAL;
		}
462
		/* Get the type pointed by this pointer */
463 464 465 466
		if (die_get_real_type(&type, &type) == NULL) {
			pr_warning("Failed to get the type of %s.\n", varname);
			return -ENOENT;
		}
467
		/* Verify it is a data structure  */
468 469
		tag = dwarf_tag(&type);
		if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
470
			pr_warning("%s is not a data structure nor a union.\n",
471
				   varname);
472 473
			return -EINVAL;
		}
474

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

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

	/* Get the offset of the field */
514 515 516 517 518 519 520 521 522
	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;
		}
523
	}
524 525
	ref->offset += (long)offs;

526 527 528 529 530
	/* 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);

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

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

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

549
	ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
550
					&pf->sp_die, pf->machine, pf->tvar);
551 552 553 554 555 556
	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)
557
		pr_err("Sorry, we don't support this variable location yet.\n");
558
	else if (ret == 0 && pf->pvar->field) {
559 560 561
		ret = convert_variable_fields(vr_die, pf->pvar->var,
					      pf->pvar->field, &pf->tvar->ref,
					      &die_mem);
562 563
		vr_die = &die_mem;
	}
564 565
	if (ret == 0)
		ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
566
	/* *expr will be cached in libdw. Don't free it. */
567
	return ret;
568 569
}

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

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

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

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

609
	return ret;
610 611
}

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

639
	symbol = dwarf_diename(sp_die);
640
	if (!symbol) {
641 642 643 644 645 646 647 648
		/* 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;
649
	}
650
	tp->offset = (unsigned long)(paddr - eaddr);
651
	tp->address = (unsigned long)paddr;
652 653 654
	tp->symbol = strdup(symbol);
	if (!tp->symbol)
		return -ENOMEM;
655

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

668 669 670
	return 0;
}

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

679 680 681 682 683 684
	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 */
685
	if (!die_is_func_def(sc_die)) {
686
		if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
687 688 689 690 691 692 693 694 695
			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;
			}
696
		}
697 698
	} else
		memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
699

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

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

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

	return ret;
727 728
}

729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
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) {
752
		if (die_match_name(fn_die, fsp->function)) {
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 786
			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;
}

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

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

797
	pf->addr = addr;
798 799 800 801 802 803 804
	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);
805

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

810 811 812 813
/* 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);
814 815
}

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

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

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

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

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

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

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

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

863
	if (!intlist__has_entry(pf->lcache, lineno) ||
864 865 866 867 868 869
	    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;
870 871 872 873 874 875 876 877
	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);
878 879 880 881 882

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

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

892
	if (intlist__empty(pf->lcache)) {
893 894 895 896 897 898 899 900 901
		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;
		}

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

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

913 914 915 916 917 918 919 920 921
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? */
922
	if (die_is_optimized_target(&pf->cu_die))
923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
		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);

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

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

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

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

974
	return ret;
975
}
976

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

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

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

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

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

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

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

1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
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;

1065
		if (die_match_name(param->sp_die, param->function)) {
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
			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;
}

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

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

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

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

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

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

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

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

1149 1150 1151
	return ret;
}

1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170
/* 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;

1171 1172 1173 1174 1175 1176 1177 1178 1179
	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);
1180

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

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

1189 1190 1191
struct local_vars_finder {
	struct probe_finder *pf;
	struct perf_probe_arg *args;
1192
	bool vars;
1193 1194 1195 1196 1197 1198 1199 1200 1201
	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;
1202
	struct probe_finder *pf = vf->pf;
1203 1204 1205 1206
	int tag;

	tag = dwarf_tag(die_mem);
	if (tag == DW_TAG_formal_parameter ||
1207
	    (tag == DW_TAG_variable && vf->vars)) {
1208
		if (convert_variable_location(die_mem, vf->pf->addr,
1209
					      vf->pf->fb_ops, &pf->sp_die,
1210
					      pf->machine, NULL) == 0) {
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
			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;
1233
	struct local_vars_finder vf = {.pf = pf, .args = args, .vars = false,
1234 1235 1236 1237
				.max_args = MAX_PROBE_ARGS, .ret = 0};

	for (i = 0; i < pf->pev->nargs; i++) {
		/* var never be NULL */
1238 1239 1240
		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) {
1241 1242 1243
			/* Copy normal argument */
			args[n] = pf->pev->args[i];
			n++;
1244
			continue;
1245
		}
1246 1247 1248 1249 1250 1251 1252 1253 1254
		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;
1255 1256 1257 1258
	}
	return n;
}

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

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

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

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

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

	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];
1313
		pf->tvar = &tev->args[i];
1314 1315
		/* Variable should be found from scope DIE */
		ret = find_variable(sc_die, pf);
1316
		if (ret != 0)
1317
			break;
1318 1319
	}

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

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

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

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

1347
	ret = debuginfo__find_probes(dbg, &tf.pf);
1348
	if (ret < 0) {
1349 1350
		for (i = 0; i < tf.ntevs; i++)
			clear_probe_trace_event(&tf.tevs[i]);
1351
		zfree(tevs);
1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
		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;
1363
	struct strbuf buf = STRBUF_INIT;
1364 1365 1366 1367 1368 1369 1370 1371
	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,
1372
						af->pf.fb_ops, &af->pf.sp_die,
1373
						af->pf.machine, NULL);
1374 1375 1376
		if (ret == 0 || ret == -ERANGE) {
			int ret2;
			bool externs = !af->child;
1377

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

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

			ret2 = die_get_varname(die_mem, &buf);

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

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

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

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

	/* 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++];

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

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

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

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

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

	return ret;
}

1469 1470 1471 1472 1473
/*
 * 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.
 */
1474
int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1475
				      struct perf_probe_event *pev,
1476
				      struct variable_list **vls)
1477 1478 1479
{
	struct available_var_finder af = {
			.pf = {.pev = pev, .callback = add_available_vars},
1480
			.mod = dbg->mod,
1481
			.max_vls = probe_conf.max_probes};
1482 1483 1484
	int ret;

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

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

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

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

1506
/* For the kernel module, we need a special code to get a DIE */
1507 1508
int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
				bool adjust_offset)
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 1536
{
	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;
1537 1538
			if (adjust_offset)
				*offs -= shdr->sh_offset;
1539 1540 1541 1542 1543
		}
	}
	return 0;
}

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

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

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

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

1579
		fname = dwarf_decl_file(&spdie);
1580
		if (addr == (unsigned long)baseaddr) {
1581 1582
			/* Function entry - Relative line number is 0 */
			lineno = baseline;
1583 1584 1585 1586 1587 1588 1589
			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 */
1590
			if (dwarf_entrypc(&indie, &_addr) == 0 &&
1591
			    _addr == addr) {
1592 1593 1594
				/*
				 * addr is at an inline function entry.
				 * In this case, lineno should be the call-site
1595
				 * line number. (overwrite lineinfo)
1596 1597
				 */
				lineno = die_get_call_lineno(&indie);
1598 1599 1600
				fname = die_get_call_file(&indie);
				break;
			} else {
1601 1602 1603 1604 1605 1606
				/*
				 * 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.
				 */
1607
				tmp = dwarf_diename(&indie);
1608 1609 1610 1611 1612
				if (!tmp ||
				    dwarf_decl_line(&indie, &baseline) != 0)
					break;
				func = tmp;
				spdie = indie;
1613
			}
1614
		}
1615 1616 1617 1618
		/* Verify the lineno and baseline are in a same file */
		tmp = dwarf_decl_file(&spdie);
		if (!tmp || strcmp(tmp, fname) != 0)
			lineno = 0;
1619 1620 1621 1622 1623 1624
	}

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

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

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

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

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

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

1680
	return 0;
1681
}
1682

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

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

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

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

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

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

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

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

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

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

1766 1767 1768 1769 1770 1771 1772 1773
	/* 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};

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

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

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

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

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

1812
found:
1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
	/* 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;
		}
	}

1823
	pr_debug("path: %s\n", lr->path);
1824
	return (ret < 0) ? ret : lf.found;
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 1884
/*
 * 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;
		}
	}
}