probe-finder.c 51.1 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2 3 4 5 6 7
/*
 * probe-finder.c : C expression to kprobe event converter
 *
 * Written by Masami Hiramatsu <mhiramat@redhat.com>
 */

8
#include <inttypes.h>
9 10 11 12 13 14 15 16 17 18
#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>
19
#include <dwarf-regs.h>
20

21
#include <linux/bitops.h>
22
#include <linux/zalloc.h>
23
#include "event.h"
24
#include "dso.h"
25
#include "debug.h"
26
#include "intlist.h"
27
#include "strbuf.h"
28
#include "strlist.h"
29
#include "symbol.h"
30
#include "probe-finder.h"
31
#include "probe-file.h"
32
#include "string2.h"
33

34 35 36 37
#ifdef HAVE_DEBUGINFOD_SUPPORT
#include <elfutils/debuginfod.h>
#endif

38 39 40
/* Kprobe tracer basic type is up to u64 */
#define MAX_BASIC_TYPE_BITS	64

41 42 43 44 45 46 47 48 49 50 51 52 53 54
/* 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 */
55
static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
56
					 const char *path)
57
{
58
	GElf_Addr dummy;
59
	int fd;
60

61 62 63
	fd = open(path, O_RDONLY);
	if (fd < 0)
		return fd;
64

65 66
	dbg->dwfl = dwfl_begin(&offline_callbacks);
	if (!dbg->dwfl)
67
		goto error;
68

69
	dwfl_report_begin(dbg->dwfl);
70 71
	dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
	if (!dbg->mod)
72 73
		goto error;

74 75
	dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
	if (!dbg->dbg)
76 77
		goto error;

78 79
	dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy);

80 81
	dwfl_report_end(dbg->dwfl, NULL, NULL);

82
	return 0;
83
error:
84 85
	if (dbg->dwfl)
		dwfl_end(dbg->dwfl);
86 87
	else
		close(fd);
88
	memset(dbg, 0, sizeof(*dbg));
89 90

	return -ENOENT;
91 92
}

93
static struct debuginfo *__debuginfo__new(const char *path)
94
{
95 96
	struct debuginfo *dbg = zalloc(sizeof(*dbg));
	if (!dbg)
97 98
		return NULL;

99 100
	if (debuginfo__init_offline_dwarf(dbg, path) < 0)
		zfree(&dbg);
101 102
	if (dbg)
		pr_debug("Open Debuginfo file: %s\n", path);
103
	return dbg;
104 105
}

106 107 108 109 110
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,
111
	DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO,
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
	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);
	}
135
	dso__put(dso);
136 137 138 139 140 141

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

142
void debuginfo__delete(struct debuginfo *dbg)
143
{
144 145 146 147
	if (dbg) {
		if (dbg->dwfl)
			dwfl_end(dbg->dwfl);
		free(dbg);
148
	}
149
}
150

151 152 153 154
/*
 * Probe finder related functions
 */

155
static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
156
{
157 158
	struct probe_trace_arg_ref *ref;
	ref = zalloc(sizeof(struct probe_trace_arg_ref));
159 160 161 162 163
	if (ref != NULL)
		ref->offset = offs;
	return ref;
}

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

185 186 187
	if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
		goto static_var;

188 189 190 191 192 193 194 195 196 197 198
	/* Constant value */
	if (dwarf_attr(vr_die, DW_AT_const_value, &attr) &&
	    immediate_value_is_supported()) {
		Dwarf_Sword snum;

		dwarf_formsdata(&attr, &snum);
		ret = asprintf(&tvar->value, "\\%ld", (long)snum);

		return ret < 0 ? -ENOMEM : 0;
	}

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

	if (op->atom == DW_OP_addr) {
235
static_var:
236
		if (!tvar)
237
			return ret2;
238 239 240 241 242 243 244 245 246
		/* 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;
247
		return ret2;
248
	}
249 250

	/* If this is based on frame buffer, set the offset */
251
	if (op->atom == DW_OP_fbreg) {
252
		if (fb_ops == NULL)
253
			return -ENOTSUP;
254
		ref = true;
255
		offs = op->number;
256
		op = &fb_ops[0];
257
	}
258

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

276
	if (!tvar)
277
		return ret2;
278

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

287 288 289 290
	tvar->value = strdup(regs);
	if (tvar->value == NULL)
		return -ENOMEM;

291
	if (ref) {
292
		tvar->ref = alloc_trace_arg_ref((long)offs);
293 294
		if (tvar->ref == NULL)
			return -ENOMEM;
295
	}
296
	return ret2;
297 298
}

299 300
#define BYTES_TO_BITS(nb)	((nb) * BITS_PER_LONG / sizeof(long))

301
static int convert_variable_type(Dwarf_Die *vr_die,
302
				 struct probe_trace_arg *tvar,
303
				 const char *cast, bool user_access)
304
{
305
	struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
306 307
	Dwarf_Die type;
	char buf[16];
308
	char sbuf[STRERR_BUFSIZE];
309
	int bsize, boffs, total;
310
	int ret;
311
	char prefix;
312

313
	/* TODO: check all types */
314 315
	if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "ustring") &&
	    strcmp(cast, "x") != 0 &&
316
	    strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
317
		/* Non string type is OK */
318
		/* and respect signedness/hexadecimal cast */
319 320 321 322
		tvar->type = strdup(cast);
		return (tvar->type == NULL) ? -ENOMEM : 0;
	}

323 324
	bsize = dwarf_bitsize(vr_die);
	if (bsize > 0) {
325
		/* This is a bitfield */
326 327 328 329 330 331
		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));
332 333 334
		goto formatted;
	}

335 336 337 338 339
	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;
	}
340

341 342 343
	pr_debug("%s type is %s.\n",
		 dwarf_diename(vr_die), dwarf_diename(&type));

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

381
	if (cast && (strcmp(cast, "u") == 0))
382
		prefix = 'u';
383
	else if (cast && (strcmp(cast, "s") == 0))
384 385 386 387
		prefix = 's';
	else if (cast && (strcmp(cast, "x") == 0) &&
		 probe_type_is_available(PROBE_TYPE_X))
		prefix = 'x';
388
	else
389 390
		prefix = die_is_signed_type(&type) ? 's' :
			 probe_type_is_available(PROBE_TYPE_X) ? 'x' : 'u';
391

392 393
	ret = dwarf_bytesize(&type);
	if (ret <= 0)
394 395
		/* No size ... try to use default type */
		return 0;
396
	ret = BYTES_TO_BITS(ret);
397

398 399 400 401 402
	/* 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;
403
	}
404
	ret = snprintf(buf, 16, "%c%d", prefix, ret);
405 406 407 408 409 410

formatted:
	if (ret < 0 || ret >= 16) {
		if (ret >= 16)
			ret = -E2BIG;
		pr_warning("Failed to convert variable type: %s\n",
411
			   str_error_r(-ret, sbuf, sizeof(sbuf)));
412 413 414 415 416
		return ret;
	}
	tvar->type = strdup(buf);
	if (tvar->type == NULL)
		return -ENOMEM;
417
	return 0;
418 419
}

420
static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
421
				    struct perf_probe_arg_field *field,
422
				    struct probe_trace_arg_ref **ref_ptr,
423
				    Dwarf_Die *die_mem, bool user_access)
424
{
425
	struct probe_trace_arg_ref *ref = *ref_ptr;
426 427
	Dwarf_Die type;
	Dwarf_Word offs;
428
	int ret, tag;
429 430

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

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

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

514
	if (die_find_member(&type, field->name, die_mem) == NULL) {
A
Arnaldo Carvalho de Melo 已提交
515
		pr_warning("%s(type:%s) has no member %s.\n", varname,
516 517 518
			   dwarf_diename(&type), field->name);
		return -EINVAL;
	}
519 520

	/* Get the offset of the field */
521 522 523 524 525 526 527 528 529
	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;
		}
530
	}
531
	ref->offset += (long)offs;
532
	ref->user_access = user_access;
533

534 535 536
	/* If this member is unnamed, we need to reuse this field */
	if (!dwarf_diename(die_mem))
		return convert_variable_fields(die_mem, varname, field,
537
						&ref, die_mem, user_access);
538

539
next:
540 541
	/* Converting next field */
	if (field->next)
542
		return convert_variable_fields(die_mem, field->name,
543
				field->next, &ref, die_mem, user_access);
544 545
	else
		return 0;
546 547
}

548 549 550 551 552 553 554 555
static void print_var_not_found(const char *varname)
{
	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",
		varname, varname);
}

556
/* Show a variables in kprobe event format */
557
static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
558
{
559
	Dwarf_Die die_mem;
560 561
	int ret;

562 563
	pr_debug("Converting variable %s into trace event.\n",
		 dwarf_diename(vr_die));
564

565
	ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
566
					&pf->sp_die, pf->machine, pf->tvar);
567 568 569
	if (ret == -ENOENT && pf->skip_empty_arg)
		/* This can be found in other place. skip it */
		return 0;
570
	if (ret == -ENOENT || ret == -EINVAL) {
571
		print_var_not_found(pf->pvar->var);
572
	} else if (ret == -ENOTSUP)
573
		pr_err("Sorry, we don't support this variable location yet.\n");
574
	else if (ret == 0 && pf->pvar->field) {
575 576
		ret = convert_variable_fields(vr_die, pf->pvar->var,
					      pf->pvar->field, &pf->tvar->ref,
577
					      &die_mem, pf->pvar->user_access);
578 579
		vr_die = &die_mem;
	}
580
	if (ret == 0)
581 582
		ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type,
					    pf->pvar->user_access);
583
	/* *expr will be cached in libdw. Don't free it. */
584
	return ret;
585 586
}

587 588
/* Find a variable in a scope DIE */
static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
589
{
590
	Dwarf_Die vr_die;
591
	char *buf, *ptr;
592
	int ret = 0;
593

594 595 596
	/* Copy raw parameters */
	if (!is_c_varname(pf->pvar->var))
		return copy_to_probe_trace_arg(pf->tvar, pf->pvar);
597

598
	if (pf->pvar->name)
599
		pf->tvar->name = strdup(pf->pvar->name);
600
	else {
601 602 603
		buf = synthesize_perf_probe_arg(pf->pvar);
		if (!buf)
			return -ENOMEM;
604 605 606
		ptr = strchr(buf, ':');	/* Change type separator to _ */
		if (ptr)
			*ptr = '_';
607
		pf->tvar->name = buf;
608
	}
609 610
	if (pf->tvar->name == NULL)
		return -ENOMEM;
611

612
	pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
613
	/* Search child die for local variables and parameters. */
614 615
	if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
		/* Search again in global variables */
616 617
		if (!die_find_variable_at(&pf->cu_die, pf->pvar->var,
						0, &vr_die)) {
618 619
			if (pf->skip_empty_arg)
				return 0;
620 621
			pr_warning("Failed to find '%s' in this function.\n",
				   pf->pvar->var);
622
			ret = -ENOENT;
623
		}
624
	}
625
	if (ret >= 0)
626 627
		ret = convert_variable(&vr_die, pf);

628
	return ret;
629 630
}

631
/* Convert subprogram DIE to trace point */
632 633
static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
				  Dwarf_Addr paddr, bool retprobe,
634
				  const char *function,
635
				  struct probe_trace_point *tp)
636
{
637
	Dwarf_Addr eaddr;
638 639 640 641
	GElf_Sym sym;
	const char *symbol;

	/* Verify the address is correct */
642 643
	if (!dwarf_haspc(sp_die, paddr)) {
		pr_warning("Specified offset is out of %s\n",
644 645 646 647
			   dwarf_diename(sp_die));
		return -EINVAL;
	}

648 649 650 651 652 653 654 655
	if (dwarf_entrypc(sp_die, &eaddr) == 0) {
		/* If the DIE has entrypc, use it. */
		symbol = dwarf_diename(sp_die);
	} else {
		/* Try to get actual symbol name and address from symtab */
		symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
		eaddr = sym.st_value;
	}
656
	if (!symbol) {
657 658 659
		pr_warning("Failed to find symbol at 0x%lx\n",
			   (unsigned long)paddr);
		return -ENOENT;
660
	}
661

662
	tp->offset = (unsigned long)(paddr - eaddr);
663
	tp->address = (unsigned long)paddr;
664 665 666
	tp->symbol = strdup(symbol);
	if (!tp->symbol)
		return -ENOMEM;
667

668
	/* Return probe must be on the head of a subprogram */
669 670
	if (retprobe) {
		if (eaddr != paddr) {
671 672 673 674
			pr_warning("Failed to find \"%s%%return\",\n"
				   " because %s is an inlined function and"
				   " has no return point.\n", function,
				   function);
675 676
			return -EINVAL;
		}
677
		tp->retprobe = true;
678 679
	}

680 681 682
	return 0;
}

683 684
/* Call probe_finder callback with scope DIE */
static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
685 686
{
	Dwarf_Attribute fb_attr;
687
	Dwarf_Frame *frame = NULL;
688 689 690
	size_t nops;
	int ret;

691 692 693 694 695 696
	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 */
697
	if (!die_is_func_def(sc_die)) {
698
		if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
699 700 701 702 703 704 705 706 707
			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;
			}
708
		}
709 710
	} else
		memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
711

712 713
	/* Get the frame base attribute/ops from subprogram */
	dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
714
	ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
715
	if (ret <= 0 || nops == 0) {
716
		pf->fb_ops = NULL;
717
#if _ELFUTILS_PREREQ(0, 142)
718
	} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
719 720 721
		   (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)) ||
722
		    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
M
Masami Hiramatsu 已提交
723
			pr_warning("Failed to get call frame on 0x%jx\n",
724
				   (uintmax_t)pf->addr);
725 726
			free(frame);
			return -ENOENT;
727
		}
728
#endif
729
	}
730

731
	/* Call finder's callback handler */
732
	ret = pf->callback(sc_die, pf);
733

734 735
	/* Since *pf->fb_ops can be a part of frame. we should free it here. */
	free(frame);
736
	pf->fb_ops = NULL;
737 738

	return ret;
739 740
}

741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
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) {
764
		if (die_match_name(fn_die, fsp->function)) {
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781
			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;
}

782 783 784 785 786 787 788 789 790 791
/* Return innermost DIE */
static int find_inner_scope_cb(Dwarf_Die *fn_die, void *data)
{
	struct find_scope_param *fsp = data;

	memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
	fsp->found = true;
	return 1;
}

792 793 794 795 796 797 798 799 800 801 802
/* 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,
	};
803
	int ret;
804

805 806 807 808 809
	ret = cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb,
				   &fsp);
	if (!ret && !fsp.found)
		cu_walk_functions_at(&pf->cu_die, pf->addr,
				     find_inner_scope_cb, &fsp);
810 811 812 813

	return fsp.found ? die_mem : NULL;
}

814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
static int verify_representive_line(struct probe_finder *pf, const char *fname,
				int lineno, Dwarf_Addr addr)
{
	const char *__fname, *__func = NULL;
	Dwarf_Die die_mem;
	int __lineno;

	/* Verify line number and address by reverse search */
	if (cu_find_lineinfo(&pf->cu_die, addr, &__fname, &__lineno) < 0)
		return 0;

	pr_debug2("Reversed line: %s:%d\n", __fname, __lineno);
	if (strcmp(fname, __fname) || lineno == __lineno)
		return 0;

829
	pr_warning("This line is sharing the address with other lines.\n");
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846

	if (pf->pev->point.function) {
		/* Find best match function name and lines */
		pf->addr = addr;
		if (find_best_scope(pf, &die_mem)
		    && die_match_name(&die_mem, pf->pev->point.function)
		    && dwarf_decl_line(&die_mem, &lineno) == 0) {
			__func = dwarf_diename(&die_mem);
			__lineno -= lineno;
		}
	}
	pr_warning("Please try to probe at %s:%d instead.\n",
		   __func ? : __fname, __lineno);

	return -ENOENT;
}

847 848
static int probe_point_line_walker(const char *fname, int lineno,
				   Dwarf_Addr addr, void *data)
849
{
850
	struct probe_finder *pf = data;
851
	Dwarf_Die *sc_die, die_mem;
852
	int ret;
853

854 855
	if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
		return 0;
856

857 858 859
	if (verify_representive_line(pf, fname, lineno, addr))
		return -ENOENT;

860
	pf->addr = addr;
861 862 863 864 865 866 867
	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);
868

869
	/* Continue if no error, because the line will be in inline function */
870
	return ret < 0 ? ret : 0;
871
}
872

873 874 875 876
/* 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);
877 878
}

879
/* Find lines which match lazy pattern */
880
static int find_lazy_match_lines(struct intlist *list,
881 882
				 const char *fname, const char *pat)
{
883 884 885 886 887
	FILE *fp;
	char *line = NULL;
	size_t line_len;
	ssize_t len;
	int count = 0, linenum = 1;
888
	char sbuf[STRERR_BUFSIZE];
889 890 891

	fp = fopen(fname, "r");
	if (!fp) {
892
		pr_warning("Failed to open %s: %s\n", fname,
893
			   str_error_r(errno, sbuf, sizeof(sbuf)));
894
		return -errno;
895 896
	}

897
	while ((len = getline(&line, &line_len, fp)) > 0) {
898

899 900 901 902
		if (line[len - 1] == '\n')
			line[len - 1] = '\0';

		if (strlazymatch(line, pat)) {
903
			intlist__add(list, linenum);
904
			count++;
905
		}
906
		linenum++;
907
	}
908 909 910 911 912 913 914 915 916

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

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

919 920 921 922
static int probe_point_lazy_walker(const char *fname, int lineno,
				   Dwarf_Addr addr, void *data)
{
	struct probe_finder *pf = data;
923
	Dwarf_Die *sc_die, die_mem;
924 925
	int ret;

926
	if (!intlist__has_entry(pf->lcache, lineno) ||
927 928 929 930 931 932
	    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;
933 934 935 936 937 938 939 940
	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);
941 942 943 944 945

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

949
/* Find probe points from lazy pattern  */
950
static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
951
{
952
	struct build_id bid;
953
	char sbuild_id[SBUILD_ID_SIZE] = "";
954
	int ret = 0;
955
	char *fpath;
956

957
	if (intlist__empty(pf->lcache)) {
958 959 960
		const char *comp_dir;

		comp_dir = cu_get_comp_dir(&pf->cu_die);
961 962 963 964
		if (pf->dbg->build_id) {
			build_id__init(&bid, pf->dbg->build_id, BUILD_ID_SIZE);
			build_id__sprintf(&bid, sbuild_id);
		}
965
		ret = find_source_path(pf->fname, sbuild_id, comp_dir, &fpath);
966 967 968 969 970
		if (ret < 0) {
			pr_warning("Failed to find source file path.\n");
			return ret;
		}

971
		/* Matching lazy line pattern */
972
		ret = find_lazy_match_lines(pf->lcache, fpath,
973
					    pf->pev->point.lazy_line);
974
		free(fpath);
975
		if (ret <= 0)
976
			return ret;
977 978
	}

979
	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
980 981
}

982 983 984 985 986 987 988 989 990
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? */
991
	if (die_is_optimized_target(&pf->cu_die))
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
		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);

1011
	die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
1012 1013
}

1014 1015
static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
{
1016
	struct probe_finder *pf = data;
1017
	struct perf_probe_point *pp = &pf->pev->point;
1018
	Dwarf_Addr addr;
1019
	int ret;
1020

1021
	if (pp->lazy_line)
1022
		ret = find_probe_point_lazy(in_die, pf);
1023 1024
	else {
		/* Get probe address */
1025
		if (die_entrypc(in_die, &addr) != 0) {
M
Masami Hiramatsu 已提交
1026
			pr_warning("Failed to get entry address of %s.\n",
1027
				   dwarf_diename(in_die));
1028
			return -ENOENT;
1029
		}
1030 1031 1032 1033 1034
		if (addr == 0) {
			pr_debug("%s has no valid entry address. skipped.\n",
				 dwarf_diename(in_die));
			return -ENOENT;
		}
1035
		pf->addr = addr;
1036 1037 1038 1039
		pf->addr += pp->offset;
		pr_debug("found inline addr: 0x%jx\n",
			 (uintmax_t)pf->addr);

1040
		ret = call_probe_finder(in_die, pf);
1041
	}
1042

1043
	return ret;
1044
}
1045

1046 1047 1048 1049 1050 1051
/* Callback parameter with return value for libdw */
struct dwarf_callback_param {
	void *data;
	int retval;
};

1052
/* Search function from function name */
1053
static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1054
{
1055 1056
	struct dwarf_callback_param *param = data;
	struct probe_finder *pf = param->data;
1057
	struct perf_probe_point *pp = &pf->pev->point;
1058

1059
	/* Check tag and diename */
1060
	if (!die_is_func_def(sp_die) ||
1061
	    !die_match_name(sp_die, pp->function))
1062
		return DWARF_CB_OK;
1063

1064 1065 1066 1067
	/* Check declared file */
	if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
		return DWARF_CB_OK;

1068 1069
	pr_debug("Matched function: %s [%lx]\n", dwarf_diename(sp_die),
		 (unsigned long)dwarf_dieoffset(sp_die));
1070
	pf->fname = dwarf_decl_file(sp_die);
1071 1072 1073
	if (pp->line) { /* Function relative line */
		dwarf_decl_line(sp_die, &pf->lno);
		pf->lno += pp->line;
1074
		param->retval = find_probe_point_by_line(pf);
1075 1076
	} else if (die_is_func_instance(sp_die)) {
		/* Instances always have the entry address */
1077
		die_entrypc(sp_die, &pf->addr);
1078 1079 1080 1081 1082
		/* 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;
1083
		/* Real function */
1084
		} else if (pp->lazy_line)
1085
			param->retval = find_probe_point_lazy(sp_die, pf);
1086
		else {
1087
			skip_prologue(sp_die, pf);
1088 1089
			pf->addr += pp->offset;
			/* TODO: Check the address in this function */
1090
			param->retval = call_probe_finder(sp_die, pf);
1091
		}
1092
	} else if (!probe_conf.no_inlines) {
1093
		/* Inlined function: search instances */
1094 1095
		param->retval = die_walk_instances(sp_die,
					probe_point_inline_cb, (void *)pf);
1096
		/* This could be a non-existed inline definition */
1097
		if (param->retval == -ENOENT)
1098 1099 1100 1101 1102 1103 1104 1105
			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;
	}
1106

1107
	return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
1108 1109
}

1110
static int find_probe_point_by_func(struct probe_finder *pf)
1111
{
1112 1113 1114 1115
	struct dwarf_callback_param _param = {.data = (void *)pf,
					      .retval = 0};
	dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
	return _param.retval;
1116 1117
}

1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
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;

1134
		if (die_match_name(param->sp_die, param->function)) {
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
			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;
}

1150
static int debuginfo__find_probe_location(struct debuginfo *dbg,
1151
				  struct probe_finder *pf)
1152
{
1153
	struct perf_probe_point *pp = &pf->pev->point;
1154 1155 1156
	Dwarf_Off off, noff;
	size_t cuhl;
	Dwarf_Die *diep;
1157
	int ret = 0;
1158 1159

	off = 0;
1160 1161 1162
	pf->lcache = intlist__new(NULL);
	if (!pf->lcache)
		return -ENOMEM;
1163 1164

	/* Fastpath: lookup by function name from .debug_pubnames section */
1165
	if (pp->function && !strisglob(pp->function)) {
1166 1167 1168 1169 1170
		struct pubname_callback_param pubname_param = {
			.function = pp->function,
			.file	  = pp->file,
			.cu_die	  = &pf->cu_die,
			.sp_die	  = &pf->sp_die,
1171
			.found	  = 0,
1172 1173 1174 1175 1176
		};
		struct dwarf_callback_param probe_param = {
			.data = pf,
		};

1177
		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1178
				  &pubname_param, 0);
1179 1180 1181 1182 1183 1184 1185
		if (pubname_param.found) {
			ret = probe_point_search_cb(&pf->sp_die, &probe_param);
			if (ret)
				goto found;
		}
	}

1186
	/* Loop on CUs (Compilation Unit) */
1187
	while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1188
		/* Get the DIE(Debugging Information Entry) of this CU */
1189
		diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
1190 1191
		if (!diep) {
			off = noff;
1192
			continue;
1193
		}
1194 1195 1196

		/* Check if target file is included. */
		if (pp->file)
1197
			pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
1198
		else
1199
			pf->fname = NULL;
1200

1201
		if (!pp->file || pf->fname) {
1202
			if (pp->function)
1203
				ret = find_probe_point_by_func(pf);
1204
			else if (pp->lazy_line)
1205
				ret = find_probe_point_lazy(&pf->cu_die, pf);
1206
			else {
1207 1208
				pf->lno = pp->line;
				ret = find_probe_point_by_line(pf);
1209
			}
1210
			if (ret < 0)
1211
				break;
1212
		}
1213
		off = noff;
1214
	}
1215 1216

found:
1217 1218
	intlist__delete(pf->lcache);
	pf->lcache = NULL;
1219

1220 1221 1222
	return ret;
}

1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
/* 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;

1242 1243 1244 1245 1246 1247 1248 1249 1250
	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);
1251

1252 1253
		pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
	} while (0);
1254 1255 1256 1257 1258 1259
#endif

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

1260 1261 1262
struct local_vars_finder {
	struct probe_finder *pf;
	struct perf_probe_arg *args;
1263
	bool vars;
1264 1265 1266 1267 1268 1269 1270 1271 1272
	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;
1273
	struct probe_finder *pf = vf->pf;
1274 1275 1276 1277
	int tag;

	tag = dwarf_tag(die_mem);
	if (tag == DW_TAG_formal_parameter ||
1278
	    (tag == DW_TAG_variable && vf->vars)) {
1279
		if (convert_variable_location(die_mem, vf->pf->addr,
1280
					      vf->pf->fb_ops, &pf->sp_die,
1281
					      pf->machine, NULL) == 0) {
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
			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;
1304
	struct local_vars_finder vf = {.pf = pf, .args = args, .vars = false,
1305 1306 1307 1308
				.max_args = MAX_PROBE_ARGS, .ret = 0};

	for (i = 0; i < pf->pev->nargs; i++) {
		/* var never be NULL */
1309 1310 1311
		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) {
1312 1313 1314
			/* Copy normal argument */
			args[n] = pf->pev->args[i];
			n++;
1315
			continue;
1316
		}
1317 1318 1319 1320 1321 1322 1323 1324 1325
		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;
1326 1327 1328 1329
	}
	return n;
}

1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
static bool trace_event_finder_overlap(struct trace_event_finder *tf)
{
	int i;

	for (i = 0; i < tf->ntevs; i++) {
		if (tf->pf.addr == tf->tevs[i].point.address)
			return true;
	}
	return false;
}

1341
/* Add a found probe point into trace event list */
1342
static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1343 1344 1345
{
	struct trace_event_finder *tf =
			container_of(pf, struct trace_event_finder, pf);
1346
	struct perf_probe_point *pp = &pf->pev->point;
1347
	struct probe_trace_event *tev;
1348
	struct perf_probe_arg *args = NULL;
1349 1350
	int ret, i;

1351 1352 1353 1354 1355 1356 1357 1358
	/*
	 * For some reason (e.g. different column assigned to same address)
	 * This callback can be called with the address which already passed.
	 * Ignore it first.
	 */
	if (trace_event_finder_overlap(tf))
		return 0;

1359 1360 1361 1362 1363 1364 1365 1366
	/* 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++];

1367
	/* Trace point should be converted from subprogram DIE */
1368
	ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
1369
				     pp->retprobe, pp->function, &tev->point);
1370
	if (ret < 0)
1371
		goto end;
1372

1373
	tev->point.realname = strdup(dwarf_diename(sc_die));
1374 1375 1376 1377
	if (!tev->point.realname) {
		ret = -ENOMEM;
		goto end;
	}
1378

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

1382 1383
	/* Expand special probe argument if exist */
	args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
1384 1385 1386 1387
	if (args == NULL) {
		ret = -ENOMEM;
		goto end;
	}
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402

	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];
1403
		pf->tvar = &tev->args[i];
1404 1405
		/* Variable should be found from scope DIE */
		ret = find_variable(sc_die, pf);
1406
		if (ret != 0)
1407
			break;
1408 1409
	}

1410
end:
1411 1412 1413 1414
	if (ret) {
		clear_probe_trace_event(tev);
		tf->ntevs--;
	}
1415 1416
	free(args);
	return ret;
1417 1418
}

1419 1420 1421 1422 1423 1424 1425
static int fill_empty_trace_arg(struct perf_probe_event *pev,
				struct probe_trace_event *tevs, int ntevs)
{
	char **valp;
	char *type;
	int i, j, ret;

1426 1427 1428
	if (!ntevs)
		return -ENOENT;

1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459
	for (i = 0; i < pev->nargs; i++) {
		type = NULL;
		for (j = 0; j < ntevs; j++) {
			if (tevs[j].args[i].value) {
				type = tevs[j].args[i].type;
				break;
			}
		}
		if (j == ntevs) {
			print_var_not_found(pev->args[i].var);
			return -ENOENT;
		}
		for (j = 0; j < ntevs; j++) {
			valp = &tevs[j].args[i].value;
			if (*valp)
				continue;

			ret = asprintf(valp, "\\%lx", probe_conf.magic_num);
			if (ret < 0)
				return -ENOMEM;
			/* Note that type can be NULL */
			if (type) {
				tevs[j].args[i].type = strdup(type);
				if (!tevs[j].args[i].type)
					return -ENOMEM;
			}
		}
	}
	return 0;
}

1460
/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1461
int debuginfo__find_trace_events(struct debuginfo *dbg,
1462
				 struct perf_probe_event *pev,
1463
				 struct probe_trace_event **tevs)
1464 1465
{
	struct trace_event_finder tf = {
1466
			.pf = {.pev = pev, .dbg = dbg, .callback = add_probe_trace_event},
1467
			.max_tevs = probe_conf.max_probes, .mod = dbg->mod};
1468
	int ret, i;
1469 1470

	/* Allocate result tevs array */
1471
	*tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
1472 1473 1474 1475 1476 1477
	if (*tevs == NULL)
		return -ENOMEM;

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

1478 1479 1480
	if (pev->nargs != 0 && immediate_value_is_supported())
		tf.pf.skip_empty_arg = true;

1481
	ret = debuginfo__find_probes(dbg, &tf.pf);
1482 1483 1484
	if (ret >= 0 && tf.pf.skip_empty_arg)
		ret = fill_empty_trace_arg(pev, tf.tevs, tf.ntevs);

1485
	if (ret < 0 || tf.ntevs == 0) {
1486 1487
		for (i = 0; i < tf.ntevs; i++)
			clear_probe_trace_event(&tf.tevs[i]);
1488
		zfree(tevs);
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499
		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;
1500
	struct strbuf buf = STRBUF_INIT;
1501 1502 1503 1504 1505 1506 1507 1508
	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,
1509
						af->pf.fb_ops, &af->pf.sp_die,
1510
						af->pf.machine, NULL);
1511 1512 1513
		if (ret == 0 || ret == -ERANGE) {
			int ret2;
			bool externs = !af->child;
1514

1515 1516
			if (strbuf_init(&buf, 64) < 0)
				goto error;
1517 1518

			if (probe_conf.show_location_range) {
1519 1520 1521 1522 1523 1524 1525
				if (!externs)
					ret2 = strbuf_add(&buf,
						ret ? "[INV]\t" : "[VAL]\t", 6);
				else
					ret2 = strbuf_add(&buf, "[EXT]\t", 6);
				if (ret2)
					goto error;
1526 1527 1528 1529 1530 1531
			}

			ret2 = die_get_varname(die_mem, &buf);

			if (!ret2 && probe_conf.show_location_range &&
				!externs) {
1532 1533
				if (strbuf_addch(&buf, '\t') < 0)
					goto error;
1534 1535 1536 1537 1538 1539
				ret2 = die_get_var_range(&af->pf.sp_die,
							die_mem, &buf);
			}

			pr_debug("Add new var: %s\n", buf.buf);
			if (ret2 == 0) {
1540 1541
				strlist__add(vl->vars,
					strbuf_detach(&buf, NULL));
1542 1543
			}
			strbuf_release(&buf);
1544 1545 1546
		}
	}

1547
	if (af->child && dwarf_haspc(die_mem, af->pf.addr))
1548 1549 1550
		return DIE_FIND_CB_CONTINUE;
	else
		return DIE_FIND_CB_SIBLING;
1551 1552 1553 1554
error:
	strbuf_release(&buf);
	pr_debug("Error in strbuf\n");
	return DIE_FIND_CB_END;
1555 1556
}

1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568
static bool available_var_finder_overlap(struct available_var_finder *af)
{
	int i;

	for (i = 0; i < af->nvls; i++) {
		if (af->pf.addr == af->vls[i].point.address)
			return true;
	}
	return false;

}

1569
/* Add a found vars into available variables list */
1570
static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1571 1572 1573
{
	struct available_var_finder *af =
			container_of(pf, struct available_var_finder, pf);
1574
	struct perf_probe_point *pp = &pf->pev->point;
1575
	struct variable_list *vl;
1576 1577
	Dwarf_Die die_mem;
	int ret;
1578

1579 1580 1581 1582 1583 1584 1585 1586
	/*
	 * For some reason (e.g. different column assigned to same address),
	 * this callback can be called with the address which already passed.
	 * Ignore it first.
	 */
	if (available_var_finder_overlap(af))
		return 0;

1587 1588 1589 1590 1591 1592 1593
	/* 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++];

1594
	/* Trace point should be converted from subprogram DIE */
1595
	ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
1596
				     pp->retprobe, pp->function, &vl->point);
1597 1598 1599 1600 1601 1602 1603
	if (ret < 0)
		return ret;

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

	/* Find local variables */
1604
	vl->vars = strlist__new(NULL, NULL);
1605 1606
	if (vl->vars == NULL)
		return -ENOMEM;
1607
	af->child = true;
1608
	die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
1609

1610
	/* Find external variables */
1611
	if (!probe_conf.show_ext_vars)
1612
		goto out;
1613
	/* Don't need to search child DIE for external vars. */
1614
	af->child = false;
1615
	die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
1616 1617

out:
1618 1619 1620 1621 1622 1623 1624 1625
	if (strlist__empty(vl->vars)) {
		strlist__delete(vl->vars);
		vl->vars = NULL;
	}

	return ret;
}

1626 1627 1628 1629 1630
/*
 * 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.
 */
1631
int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1632
				      struct perf_probe_event *pev,
1633
				      struct variable_list **vls)
1634 1635
{
	struct available_var_finder af = {
1636
			.pf = {.pev = pev, .dbg = dbg, .callback = add_available_vars},
1637
			.mod = dbg->mod,
1638
			.max_vls = probe_conf.max_probes};
1639 1640 1641
	int ret;

	/* Allocate result vls array */
1642
	*vls = zalloc(sizeof(struct variable_list) * af.max_vls);
1643 1644 1645 1646 1647 1648
	if (*vls == NULL)
		return -ENOMEM;

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

1649
	ret = debuginfo__find_probes(dbg, &af.pf);
1650 1651 1652
	if (ret < 0) {
		/* Free vlist for error */
		while (af.nvls--) {
1653
			zfree(&af.vls[af.nvls].point.symbol);
1654
			strlist__delete(af.vls[af.nvls].vars);
1655
		}
1656
		zfree(vls);
1657 1658 1659 1660
		return ret;
	}

	return (ret < 0) ? ret : af.nvls;
1661 1662
}

1663
/* For the kernel module, we need a special code to get a DIE */
1664 1665
int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
				bool adjust_offset)
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693
{
	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;
1694 1695
			if (adjust_offset)
				*offs -= shdr->sh_offset;
1696 1697 1698 1699 1700
		}
	}
	return 0;
}

1701
/* Reverse search */
1702
int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1703
				struct perf_probe_point *ppt)
1704 1705
{
	Dwarf_Die cudie, spdie, indie;
1706 1707
	Dwarf_Addr _addr = 0, baseaddr = 0;
	const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1708
	int baseline = 0, lineno = 0, ret = 0;
1709

1710
	/* We always need to relocate the address for aranges */
1711
	if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0)
1712
		addr += baseaddr;
1713
	/* Find cu die */
1714
	if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
M
Masami Hiramatsu 已提交
1715 1716
		pr_warning("Failed to find debug information for address %lx\n",
			   addr);
1717 1718 1719
		ret = -EINVAL;
		goto end;
	}
1720

1721 1722 1723
	/* Find a corresponding line (filename and lineno) */
	cu_find_lineinfo(&cudie, addr, &fname, &lineno);
	/* Don't care whether it failed or not */
1724

1725
	/* Find a corresponding function (name, baseline and baseaddr) */
1726
	if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
1727
		/* Get function entry information */
1728 1729
		func = basefunc = dwarf_diename(&spdie);
		if (!func ||
1730
		    die_entrypc(&spdie, &baseaddr) != 0 ||
1731 1732
		    dwarf_decl_line(&spdie, &baseline) != 0) {
			lineno = 0;
1733
			goto post;
1734
		}
1735

1736
		fname = dwarf_decl_file(&spdie);
1737
		if (addr == (unsigned long)baseaddr) {
1738 1739
			/* Function entry - Relative line number is 0 */
			lineno = baseline;
1740 1741 1742 1743 1744 1745 1746
			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 */
1747
			if (die_entrypc(&indie, &_addr) == 0 &&
1748
			    _addr == addr) {
1749 1750 1751
				/*
				 * addr is at an inline function entry.
				 * In this case, lineno should be the call-site
1752
				 * line number. (overwrite lineinfo)
1753 1754
				 */
				lineno = die_get_call_lineno(&indie);
1755 1756 1757
				fname = die_get_call_file(&indie);
				break;
			} else {
1758 1759 1760 1761 1762 1763
				/*
				 * 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.
				 */
1764
				tmp = dwarf_diename(&indie);
1765 1766 1767 1768 1769
				if (!tmp ||
				    dwarf_decl_line(&indie, &baseline) != 0)
					break;
				func = tmp;
				spdie = indie;
1770
			}
1771
		}
1772 1773 1774 1775
		/* Verify the lineno and baseline are in a same file */
		tmp = dwarf_decl_file(&spdie);
		if (!tmp || strcmp(tmp, fname) != 0)
			lineno = 0;
1776 1777 1778 1779 1780 1781
	}

post:
	/* Make a relative line number or an offset */
	if (lineno)
		ppt->line = lineno - baseline;
1782
	else if (basefunc) {
1783
		ppt->offset = addr - (unsigned long)baseaddr;
1784 1785
		func = basefunc;
	}
1786 1787 1788 1789

	/* Duplicate strings */
	if (func) {
		ppt->function = strdup(func);
1790 1791 1792 1793
		if (ppt->function == NULL) {
			ret = -ENOMEM;
			goto end;
		}
1794
	}
1795 1796 1797
	if (fname) {
		ppt->file = strdup(fname);
		if (ppt->file == NULL) {
1798
			zfree(&ppt->function);
1799 1800 1801 1802
			ret = -ENOMEM;
			goto end;
		}
	}
1803
end:
1804 1805
	if (ret == 0 && (fname || func))
		ret = 1;	/* Found a point */
1806 1807 1808
	return ret;
}

1809 1810 1811 1812
/* Add a line and store the src path */
static int line_range_add_line(const char *src, unsigned int lineno,
			       struct line_range *lr)
{
1813
	/* Copy source path */
1814
	if (!lr->path) {
1815 1816 1817
		lr->path = strdup(src);
		if (lr->path == NULL)
			return -ENOMEM;
1818
	}
1819
	return intlist__add(lr->line_list, lineno);
1820 1821
}

1822
static int line_range_walk_cb(const char *fname, int lineno,
1823
			      Dwarf_Addr addr __maybe_unused,
1824
			      void *data)
1825
{
1826
	struct line_finder *lf = data;
1827 1828
	const char *__fname;
	int __lineno;
1829
	int err;
1830

1831
	if ((strtailcmp(fname, lf->fname) != 0) ||
1832
	    (lf->lno_s > lineno || lf->lno_e < lineno))
1833
		return 0;
1834

1835 1836 1837 1838 1839
	/* Make sure this line can be reversable */
	if (cu_find_lineinfo(&lf->cu_die, addr, &__fname, &__lineno) > 0
	    && (lineno != __lineno || strcmp(fname, __fname)))
		return 0;

1840 1841 1842
	err = line_range_add_line(fname, lineno, lf->lr);
	if (err < 0 && err != -EEXIST)
		return err;
1843

1844
	return 0;
1845
}
1846

1847
/* Find line range from its line number */
1848
static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1849
{
1850
	int ret;
1851

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

1854
	/* Update status */
1855
	if (ret >= 0)
1856
		if (!intlist__empty(lf->lr->line_list))
1857 1858 1859
			ret = lf->found = 1;
		else
			ret = 0;	/* Lines are not found */
1860
	else {
1861
		zfree(&lf->lr->path);
1862
	}
1863
	return ret;
1864 1865
}

1866 1867
static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
{
1868
	int ret = find_line_range_by_line(in_die, data);
1869 1870 1871 1872

	/*
	 * We have to check all instances of inlined function, because
	 * some execution paths can be optimized out depends on the
1873 1874
	 * function argument of instances. However, if an error occurs,
	 * it should be handled by the caller.
1875
	 */
1876
	return ret < 0 ? ret : 0;
1877 1878
}

1879
/* Search function definition from function name */
1880
static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1881
{
1882 1883
	struct dwarf_callback_param *param = data;
	struct line_finder *lf = param->data;
1884 1885
	struct line_range *lr = lf->lr;

1886 1887 1888 1889
	/* Check declared file */
	if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
		return DWARF_CB_OK;

1890
	if (die_match_name(sp_die, lr->function) && die_is_func_def(sp_die)) {
1891 1892
		lf->fname = dwarf_decl_file(sp_die);
		dwarf_decl_line(sp_die, &lr->offset);
1893
		pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
1894
		lf->lno_s = lr->offset + lr->start;
1895 1896 1897 1898
		if (lf->lno_s < 0)	/* Overflow */
			lf->lno_s = INT_MAX;
		lf->lno_e = lr->offset + lr->end;
		if (lf->lno_e < 0)	/* Overflow */
1899
			lf->lno_e = INT_MAX;
1900
		pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1901 1902
		lr->start = lf->lno_s;
		lr->end = lf->lno_e;
1903
		if (!die_is_func_instance(sp_die))
1904 1905 1906
			param->retval = die_walk_instances(sp_die,
						line_range_inline_cb, lf);
		else
1907 1908
			param->retval = find_line_range_by_line(sp_die, lf);
		return DWARF_CB_ABORT;
1909
	}
1910
	return DWARF_CB_OK;
1911 1912
}

1913
static int find_line_range_by_func(struct line_finder *lf)
1914
{
1915 1916 1917
	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
	dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
	return param.retval;
1918 1919
}

1920
int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
1921
{
1922
	struct line_finder lf = {.lr = lr, .found = 0};
1923
	int ret = 0;
1924 1925 1926
	Dwarf_Off off = 0, noff;
	size_t cuhl;
	Dwarf_Die *diep;
1927
	const char *comp_dir;
1928

1929 1930 1931 1932 1933 1934 1935 1936
	/* 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};

1937
		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1938
				  &pubname_param, 0);
1939 1940 1941 1942 1943 1944 1945
		if (pubname_param.found) {
			line_range_search_cb(&lf.sp_die, &line_range_param);
			if (lf.found)
				goto found;
		}
	}

1946
	/* Loop on CUs (Compilation Unit) */
1947
	while (!lf.found && ret >= 0) {
1948
		if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
1949
				 NULL, NULL, NULL) != 0)
1950 1951 1952
			break;

		/* Get the DIE(Debugging Information Entry) of this CU */
1953
		diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
1954 1955
		if (!diep) {
			off = noff;
1956
			continue;
1957
		}
1958 1959 1960

		/* Check if target file is included. */
		if (lr->file)
1961
			lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
1962
		else
1963
			lf.fname = 0;
1964

1965
		if (!lr->file || lf.fname) {
1966
			if (lr->function)
1967
				ret = find_line_range_by_func(&lf);
1968 1969
			else {
				lf.lno_s = lr->start;
1970
				lf.lno_e = lr->end;
1971
				ret = find_line_range_by_line(NULL, &lf);
1972 1973
			}
		}
1974
		off = noff;
1975
	}
1976

1977
found:
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987
	/* 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;
		}
	}

1988
	pr_debug("path: %s\n", lr->path);
1989
	return (ret < 0) ? ret : lf.found;
1990 1991
}

1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026
#ifdef HAVE_DEBUGINFOD_SUPPORT
/* debuginfod doesn't require the comp_dir but buildid is required */
static int get_source_from_debuginfod(const char *raw_path,
				const char *sbuild_id, char **new_path)
{
	debuginfod_client *c = debuginfod_begin();
	const char *p = raw_path;
	int fd;

	if (!c)
		return -ENOMEM;

	fd = debuginfod_find_source(c, (const unsigned char *)sbuild_id,
				0, p, new_path);
	pr_debug("Search %s from debuginfod -> %d\n", p, fd);
	if (fd >= 0)
		close(fd);
	debuginfod_end(c);
	if (fd < 0) {
		pr_debug("Failed to find %s in debuginfod (%s)\n",
			raw_path, sbuild_id);
		return -ENOENT;
	}
	pr_debug("Got a source %s\n", *new_path);

	return 0;
}
#else
static inline int get_source_from_debuginfod(const char *raw_path __maybe_unused,
				const char *sbuild_id __maybe_unused,
				char **new_path __maybe_unused)
{
	return -ENOTSUP;
}
#endif
2027 2028 2029 2030 2031 2032
/*
 * 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.
 */
2033 2034
int find_source_path(const char *raw_path, const char *sbuild_id,
		const char *comp_dir, char **new_path)
2035 2036 2037
{
	const char *prefix = symbol_conf.source_prefix;

2038 2039 2040 2041 2042
	if (sbuild_id && !prefix) {
		if (!get_source_from_debuginfod(raw_path, sbuild_id, new_path))
			return 0;
	}

2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089
	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;
		}
	}
}