probe-finder.c 41.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * 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.
 *
 */

#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 <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
33
#include <dwarf-regs.h>
34

35
#include <linux/bitops.h>
36 37
#include "event.h"
#include "debug.h"
38
#include "util.h"
39
#include "symbol.h"
40 41
#include "probe-finder.h"

42 43 44
/* Kprobe tracer basic type is up to u64 */
#define MAX_BASIC_TYPE_BITS	64

45 46 47
/* Line number list operations */

/* Add a line to line number list */
48
static int line_list__add_line(struct list_head *head, int line)
49 50 51 52 53 54 55 56 57 58
{
	struct line_node *ln;
	struct list_head *p;

	/* Reverse search, because new line will be the last one */
	list_for_each_entry_reverse(ln, head, list) {
		if (ln->line < line) {
			p = &ln->list;
			goto found;
		} else if (ln->line == line)	/* Already exist */
59
			return 1;
60 61 62 63 64
	}
	/* List is empty, or the smallest entry */
	p = head;
found:
	pr_debug("line list: add a line %u\n", line);
65 66 67
	ln = zalloc(sizeof(struct line_node));
	if (ln == NULL)
		return -ENOMEM;
68 69 70
	ln->line = line;
	INIT_LIST_HEAD(&ln->list);
	list_add(&ln->list, p);
71
	return 0;
72 73 74
}

/* Check if the line in line number list */
75
static int line_list__has_line(struct list_head *head, int line)
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
{
	struct line_node *ln;

	/* Reverse search, because new line will be the last one */
	list_for_each_entry(ln, head, list)
		if (ln->line == line)
			return 1;

	return 0;
}

/* Init line number list */
static void line_list__init(struct list_head *head)
{
	INIT_LIST_HEAD(head);
}

/* Free line number list */
static void line_list__free(struct list_head *head)
{
	struct line_node *ln;
	while (!list_empty(head)) {
		ln = list_first_entry(head, struct line_node, list);
		list_del(&ln->list);
		free(ln);
	}
}

104 105 106 107 108 109 110 111 112 113 114 115 116 117
/* 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 */
118
static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
119
					 const char *path)
120
{
121
	int fd;
122

123 124 125
	fd = open(path, O_RDONLY);
	if (fd < 0)
		return fd;
126

127 128
	dbg->dwfl = dwfl_begin(&offline_callbacks);
	if (!dbg->dwfl)
129
		goto error;
130

131 132
	dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
	if (!dbg->mod)
133 134
		goto error;

135 136
	dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
	if (!dbg->dbg)
137 138 139
		goto error;

	return 0;
140
error:
141 142
	if (dbg->dwfl)
		dwfl_end(dbg->dwfl);
143 144
	else
		close(fd);
145
	memset(dbg, 0, sizeof(*dbg));
146 147

	return -ENOENT;
148 149
}

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
#if _ELFUTILS_PREREQ(0, 148)
/* This method is buggy if elfutils is older than 0.148 */
static int __linux_kernel_find_elf(Dwfl_Module *mod,
				   void **userdata,
				   const char *module_name,
				   Dwarf_Addr base,
				   char **file_name, Elf **elfp)
{
	int fd;
	const char *path = kernel_get_module_path(module_name);

	pr_debug2("Use file %s for %s\n", path, module_name);
	if (path) {
		fd = open(path, O_RDONLY);
		if (fd >= 0) {
			*file_name = strdup(path);
			return fd;
		}
	}
	/* If failed, try to call standard method */
	return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
					  file_name, elfp);
}

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

	.find_elf = __linux_kernel_find_elf,
	.section_address = dwfl_linux_kernel_module_section_address,
};

182
/* Get a Dwarf from live kernel image */
183
static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
184
					       Dwarf_Addr addr)
185
{
186 187
	dbg->dwfl = dwfl_begin(&kernel_callbacks);
	if (!dbg->dwfl)
188
		return -EINVAL;
189 190

	/* Load the kernel dwarves: Don't care the result here */
191 192
	dwfl_linux_kernel_report_kernel(dbg->dwfl);
	dwfl_linux_kernel_report_modules(dbg->dwfl);
193

194
	dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias);
195
	/* Here, check whether we could get a real dwarf */
196
	if (!dbg->dbg) {
197 198
		pr_debug("Failed to find kernel dwarf at %lx\n",
			 (unsigned long)addr);
199 200
		dwfl_end(dbg->dwfl);
		memset(dbg, 0, sizeof(*dbg));
201
		return -ENOENT;
202
	}
203 204

	return 0;
205
}
206 207
#else
/* With older elfutils, this just support kernel module... */
208
static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
209
					       Dwarf_Addr addr __maybe_unused)
210 211 212 213 214
{
	const char *path = kernel_get_module_path("kernel");

	if (!path) {
		pr_err("Failed to find vmlinux path\n");
215
		return -ENOENT;
216 217 218
	}

	pr_debug2("Use file %s for debuginfo\n", path);
219
	return debuginfo__init_offline_dwarf(dbg, path);
220 221 222 223 224
}
#endif

struct debuginfo *debuginfo__new(const char *path)
{
225 226
	struct debuginfo *dbg = zalloc(sizeof(*dbg));
	if (!dbg)
227 228
		return NULL;

229 230
	if (debuginfo__init_offline_dwarf(dbg, path) < 0)
		zfree(&dbg);
231

232
	return dbg;
233 234 235 236
}

struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
{
237 238 239
	struct debuginfo *dbg = zalloc(sizeof(*dbg));

	if (!dbg)
240 241
		return NULL;

242 243
	if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0)
		zfree(&dbg);
244

245
	return dbg;
246 247
}

248
void debuginfo__delete(struct debuginfo *dbg)
249
{
250 251 252 253
	if (dbg) {
		if (dbg->dwfl)
			dwfl_end(dbg->dwfl);
		free(dbg);
254
	}
255
}
256

257 258 259 260
/*
 * Probe finder related functions
 */

261
static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
262
{
263 264
	struct probe_trace_arg_ref *ref;
	ref = zalloc(sizeof(struct probe_trace_arg_ref));
265 266 267 268 269
	if (ref != NULL)
		ref->offset = offs;
	return ref;
}

270 271 272
/*
 * Convert a location into trace_arg.
 * If tvar == NULL, this just checks variable can be converted.
273 274
 * If fentry == true and vr_die is a parameter, do huristic search
 * for the location fuzzed by function entry mcount.
275 276
 */
static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
277
				     Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
278
				     struct probe_trace_arg *tvar)
279
{
280
	Dwarf_Attribute attr;
281
	Dwarf_Addr tmp = 0;
282 283
	Dwarf_Op *op;
	size_t nops;
284 285
	unsigned int regn;
	Dwarf_Word offs = 0;
286
	bool ref = false;
287
	const char *regs;
288 289
	int ret;

290 291 292
	if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
		goto static_var;

293
	/* TODO: handle more than 1 exprs */
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
	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);
		if (ret || addr != tmp ||
		    dwarf_tag(vr_die) != DW_TAG_formal_parameter ||
		    dwarf_highpc(sp_die, &tmp))
			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;
		}
311 312
		return -ENOENT;
	}
313 314 315 316
found:
	if (nops == 0)
		/* TODO: Support const_value */
		return -ENOENT;
317 318

	if (op->atom == DW_OP_addr) {
319
static_var:
320 321
		if (!tvar)
			return 0;
322 323 324 325 326 327 328 329 330 331 332
		/* 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;
		return 0;
	}
333 334

	/* If this is based on frame buffer, set the offset */
335
	if (op->atom == DW_OP_fbreg) {
336
		if (fb_ops == NULL)
337
			return -ENOTSUP;
338
		ref = true;
339
		offs = op->number;
340
		op = &fb_ops[0];
341
	}
342

343 344 345
	if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
		regn = op->atom - DW_OP_breg0;
		offs += op->number;
346
		ref = true;
347 348 349 350 351
	} 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;
352
		ref = true;
353 354
	} else if (op->atom == DW_OP_regx) {
		regn = op->number;
355
	} else {
356
		pr_debug("DW_OP %x is not supported.\n", op->atom);
357 358
		return -ENOTSUP;
	}
359

360 361 362
	if (!tvar)
		return 0;

363
	regs = get_arch_regstr(regn);
364
	if (!regs) {
365
		/* This should be a bug in DWARF or this tool */
M
Masami Hiramatsu 已提交
366 367
		pr_warning("Mapping for the register number %u "
			   "missing on this architecture.\n", regn);
368 369
		return -ERANGE;
	}
370

371 372 373 374
	tvar->value = strdup(regs);
	if (tvar->value == NULL)
		return -ENOMEM;

375
	if (ref) {
376
		tvar->ref = alloc_trace_arg_ref((long)offs);
377 378
		if (tvar->ref == NULL)
			return -ENOMEM;
379
	}
380
	return 0;
381 382
}

383 384
#define BYTES_TO_BITS(nb)	((nb) * BITS_PER_LONG / sizeof(long))

385
static int convert_variable_type(Dwarf_Die *vr_die,
386
				 struct probe_trace_arg *tvar,
387
				 const char *cast)
388
{
389
	struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
390 391
	Dwarf_Die type;
	char buf[16];
392
	int bsize, boffs, total;
393 394
	int ret;

395 396 397 398 399 400 401
	/* TODO: check all types */
	if (cast && strcmp(cast, "string") != 0) {
		/* Non string type is OK */
		tvar->type = strdup(cast);
		return (tvar->type == NULL) ? -ENOMEM : 0;
	}

402 403
	bsize = dwarf_bitsize(vr_die);
	if (bsize > 0) {
404
		/* This is a bitfield */
405 406 407 408 409 410
		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));
411 412 413
		goto formatted;
	}

414 415 416 417 418
	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;
	}
419

420 421 422
	pr_debug("%s type is %s.\n",
		 dwarf_diename(vr_die), dwarf_diename(&type));

423 424 425 426 427
	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 已提交
428
				   "%s(%s) is not a pointer nor array.\n",
429 430 431
				   dwarf_diename(vr_die), dwarf_diename(&type));
			return -EINVAL;
		}
432 433 434 435 436
		if (die_get_real_type(&type, &type) == NULL) {
			pr_warning("Failed to get a type"
				   " information.\n");
			return -ENOENT;
		}
437 438 439 440
		if (ret == DW_TAG_pointer_type) {
			while (*ref_ptr)
				ref_ptr = &(*ref_ptr)->next;
			/* Add new reference with offset +0 */
441
			*ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
442 443 444 445 446
			if (*ref_ptr == NULL) {
				pr_warning("Out of memory error\n");
				return -ENOMEM;
			}
		}
447 448
		if (!die_compare_name(&type, "char") &&
		    !die_compare_name(&type, "unsigned char")) {
449
			pr_warning("Failed to cast into string: "
M
Masami Hiramatsu 已提交
450
				   "%s is not (unsigned) char *.\n",
451 452 453 454 455 456 457
				   dwarf_diename(vr_die));
			return -EINVAL;
		}
		tvar->type = strdup(cast);
		return (tvar->type == NULL) ? -ENOMEM : 0;
	}

458 459
	ret = dwarf_bytesize(&type);
	if (ret <= 0)
460 461
		/* No size ... try to use default type */
		return 0;
462
	ret = BYTES_TO_BITS(ret);
463

464 465 466 467 468
	/* 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;
469
	}
470 471 472 473 474 475 476 477 478 479 480 481 482 483
	ret = snprintf(buf, 16, "%c%d",
		       die_is_signed_type(&type) ? 's' : 'u', ret);

formatted:
	if (ret < 0 || ret >= 16) {
		if (ret >= 16)
			ret = -E2BIG;
		pr_warning("Failed to convert variable type: %s\n",
			   strerror(-ret));
		return ret;
	}
	tvar->type = strdup(buf);
	if (tvar->type == NULL)
		return -ENOMEM;
484
	return 0;
485 486
}

487
static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
488
				    struct perf_probe_arg_field *field,
489
				    struct probe_trace_arg_ref **ref_ptr,
490
				    Dwarf_Die *die_mem)
491
{
492
	struct probe_trace_arg_ref *ref = *ref_ptr;
493 494
	Dwarf_Die type;
	Dwarf_Word offs;
495
	int ret, tag;
496 497

	pr_debug("converting %s in %s\n", field->name, varname);
498 499 500 501
	if (die_get_real_type(vr_die, &type) == NULL) {
		pr_warning("Failed to get the type of %s.\n", varname);
		return -ENOENT;
	}
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
	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) {
518
			ref = zalloc(sizeof(struct probe_trace_arg_ref));
519 520 521 522 523 524 525
			if (ref == NULL)
				return -ENOMEM;
			if (*ref_ptr)
				(*ref_ptr)->next = ref;
			else
				*ref_ptr = ref;
		}
526
		ref->offset += dwarf_bytesize(&type) * field->index;
527 528 529 530 531 532
		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 */
533 534 535 536 537
		if (!field->ref) {
			pr_err("Semantic error: %s must be referred by '->'\n",
			       field->name);
			return -EINVAL;
		}
538
		/* Get the type pointed by this pointer */
539 540 541 542
		if (die_get_real_type(&type, &type) == NULL) {
			pr_warning("Failed to get the type of %s.\n", varname);
			return -ENOENT;
		}
543
		/* Verify it is a data structure  */
544 545 546 547
		tag = dwarf_tag(&type);
		if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
			pr_warning("%s is not a data structure nor an union.\n",
				   varname);
548 549
			return -EINVAL;
		}
550

551
		ref = zalloc(sizeof(struct probe_trace_arg_ref));
552 553
		if (ref == NULL)
			return -ENOMEM;
554 555 556 557 558
		if (*ref_ptr)
			(*ref_ptr)->next = ref;
		else
			*ref_ptr = ref;
	} else {
559
		/* Verify it is a data structure  */
560 561 562
		if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
			pr_warning("%s is not a data structure nor an union.\n",
				   varname);
563 564
			return -EINVAL;
		}
565
		if (field->name[0] == '[') {
M
Masami Hiramatsu 已提交
566 567
			pr_err("Semantic error: %s is not a pointor"
			       " nor array.\n", varname);
568 569
			return -EINVAL;
		}
570 571 572 573 574 575 576 577 578 579
		if (field->ref) {
			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;
		}
580 581
	}

582
	if (die_find_member(&type, field->name, die_mem) == NULL) {
A
Arnaldo Carvalho de Melo 已提交
583
		pr_warning("%s(type:%s) has no member %s.\n", varname,
584 585 586
			   dwarf_diename(&type), field->name);
		return -EINVAL;
	}
587 588

	/* Get the offset of the field */
589 590 591 592 593 594 595 596 597
	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;
		}
598
	}
599 600
	ref->offset += (long)offs;

601
next:
602 603
	/* Converting next field */
	if (field->next)
604
		return convert_variable_fields(die_mem, field->name,
605
					field->next, &ref, die_mem);
606 607
	else
		return 0;
608 609
}

610
/* Show a variables in kprobe event format */
611
static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
612
{
613
	Dwarf_Die die_mem;
614 615
	int ret;

616 617
	pr_debug("Converting variable %s into trace event.\n",
		 dwarf_diename(vr_die));
618

619
	ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
620
					&pf->sp_die, pf->tvar);
621 622 623 624 625 626
	if (ret == -ENOENT)
		pr_err("Failed to find the location of %s at this address.\n"
		       " Perhaps, it has been optimized out.\n", pf->pvar->var);
	else if (ret == -ENOTSUP)
		pr_err("Sorry, we don't support this variable location yet.\n");
	else if (pf->pvar->field) {
627 628 629
		ret = convert_variable_fields(vr_die, pf->pvar->var,
					      pf->pvar->field, &pf->tvar->ref,
					      &die_mem);
630 631
		vr_die = &die_mem;
	}
632 633
	if (ret == 0)
		ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
634
	/* *expr will be cached in libdw. Don't free it. */
635
	return ret;
636 637
}

638 639
/* Find a variable in a scope DIE */
static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
640
{
641
	Dwarf_Die vr_die;
642
	char buf[32], *ptr;
643
	int ret = 0;
644

645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
	if (!is_c_varname(pf->pvar->var)) {
		/* Copy raw parameters */
		pf->tvar->value = strdup(pf->pvar->var);
		if (pf->tvar->value == NULL)
			return -ENOMEM;
		if (pf->pvar->type) {
			pf->tvar->type = strdup(pf->pvar->type);
			if (pf->tvar->type == NULL)
				return -ENOMEM;
		}
		if (pf->pvar->name) {
			pf->tvar->name = strdup(pf->pvar->name);
			if (pf->tvar->name == NULL)
				return -ENOMEM;
		} else
			pf->tvar->name = NULL;
		return 0;
	}

664
	if (pf->pvar->name)
665
		pf->tvar->name = strdup(pf->pvar->name);
666
	else {
667 668 669
		ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
		if (ret < 0)
			return ret;
670 671 672
		ptr = strchr(buf, ':');	/* Change type separator to _ */
		if (ptr)
			*ptr = '_';
673
		pf->tvar->name = strdup(buf);
674
	}
675 676
	if (pf->tvar->name == NULL)
		return -ENOMEM;
677

678
	pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
679
	/* Search child die for local variables and parameters. */
680 681 682 683
	if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
		/* Search again in global variables */
		if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
			ret = -ENOENT;
684
	}
685
	if (ret >= 0)
686 687
		ret = convert_variable(&vr_die, pf);

688
	if (ret < 0)
689 690
		pr_warning("Failed to find '%s' in this function.\n",
			   pf->pvar->var);
691
	return ret;
692 693
}

694
/* Convert subprogram DIE to trace point */
695 696 697
static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
				  Dwarf_Addr paddr, bool retprobe,
				  struct probe_trace_point *tp)
698
{
699
	Dwarf_Addr eaddr, highaddr;
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
	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;
	}

	/* Get an appropriate symbol 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;
	}
	tp->offset = (unsigned long)(paddr - sym.st_value);
728
	tp->address = (unsigned long)paddr;
729 730 731
	tp->symbol = strdup(symbol);
	if (!tp->symbol)
		return -ENOMEM;
732

733
	/* Return probe must be on the head of a subprogram */
734 735
	if (retprobe) {
		if (eaddr != paddr) {
736
			pr_warning("Return probe must be on the head of"
M
Masami Hiramatsu 已提交
737
				   " a real function.\n");
738 739
			return -EINVAL;
		}
740
		tp->retprobe = true;
741 742
	}

743 744 745
	return 0;
}

746 747
/* Call probe_finder callback with scope DIE */
static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
748 749 750 751 752
{
	Dwarf_Attribute fb_attr;
	size_t nops;
	int ret;

753 754 755 756 757 758
	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 */
759
	if (!die_is_func_def(sc_die)) {
760
		if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
761 762 763 764
			pr_warning("Failed to find probe point in any "
				   "functions.\n");
			return -ENOENT;
		}
765 766
	} else
		memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
767

768 769
	/* Get the frame base attribute/ops from subprogram */
	dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
770
	ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
771
	if (ret <= 0 || nops == 0) {
772
		pf->fb_ops = NULL;
773
#if _ELFUTILS_PREREQ(0, 142)
774 775 776
	} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
		   pf->cfi != NULL) {
		Dwarf_Frame *frame;
777 778
		if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
		    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
M
Masami Hiramatsu 已提交
779
			pr_warning("Failed to get call frame on 0x%jx\n",
780 781 782
				   (uintmax_t)pf->addr);
			return -ENOENT;
		}
783
#endif
784
	}
785

786
	/* Call finder's callback handler */
787
	ret = pf->callback(sc_die, pf);
788 789 790

	/* *pf->fb_ops will be cached in libdw. Don't free it. */
	pf->fb_ops = NULL;
791 792

	return ret;
793 794
}

795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
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) {
		if (die_compare_name(fn_die, fsp->function)) {
			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;
}

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

860 861
	if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
		return 0;
862

863
	pf->addr = addr;
864 865 866 867 868 869 870
	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);
871

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

876 877 878 879
/* 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);
880 881
}

882 883 884 885
/* Find lines which match lazy pattern */
static int find_lazy_match_lines(struct list_head *head,
				 const char *fname, const char *pat)
{
886 887 888 889 890 891 892 893 894
	FILE *fp;
	char *line = NULL;
	size_t line_len;
	ssize_t len;
	int count = 0, linenum = 1;

	fp = fopen(fname, "r");
	if (!fp) {
		pr_warning("Failed to open %s: %s\n", fname, strerror(errno));
895
		return -errno;
896 897
	}

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

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

		if (strlazymatch(line, pat)) {
			line_list__add_line(head, linenum);
			count++;
906
		}
907
		linenum++;
908
	}
909 910 911 912 913 914 915 916 917

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

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

920 921 922 923
static int probe_point_lazy_walker(const char *fname, int lineno,
				   Dwarf_Addr addr, void *data)
{
	struct probe_finder *pf = data;
924
	Dwarf_Die *sc_die, die_mem;
925 926 927 928 929 930 931 932 933
	int ret;

	if (!line_list__has_line(&pf->lcache, lineno) ||
	    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;
934 935 936 937 938 939 940 941
	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);
942 943 944 945 946

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

950
/* Find probe points from lazy pattern  */
951
static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
952
{
953
	int ret = 0;
954 955 956 957

	if (list_empty(&pf->lcache)) {
		/* Matching lazy line pattern */
		ret = find_lazy_match_lines(&pf->lcache, pf->fname,
958
					    pf->pev->point.lazy_line);
959
		if (ret <= 0)
960
			return ret;
961 962
	}

963
	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
964 965
}

966 967
static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
{
968
	struct probe_finder *pf = data;
969
	struct perf_probe_point *pp = &pf->pev->point;
970
	Dwarf_Addr addr;
971
	int ret;
972

973
	if (pp->lazy_line)
974
		ret = find_probe_point_lazy(in_die, pf);
975 976
	else {
		/* Get probe address */
977
		if (dwarf_entrypc(in_die, &addr) != 0) {
M
Masami Hiramatsu 已提交
978
			pr_warning("Failed to get entry address of %s.\n",
979
				   dwarf_diename(in_die));
980
			return -ENOENT;
981 982
		}
		pf->addr = addr;
983 984 985 986
		pf->addr += pp->offset;
		pr_debug("found inline addr: 0x%jx\n",
			 (uintmax_t)pf->addr);

987
		ret = call_probe_finder(in_die, pf);
988
	}
989

990
	return ret;
991
}
992

993 994 995 996 997 998
/* Callback parameter with return value for libdw */
struct dwarf_callback_param {
	void *data;
	int retval;
};

999
/* Search function from function name */
1000
static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1001
{
1002 1003
	struct dwarf_callback_param *param = data;
	struct probe_finder *pf = param->data;
1004
	struct perf_probe_point *pp = &pf->pev->point;
1005

1006
	/* Check tag and diename */
1007 1008
	if (!die_is_func_def(sp_die) ||
	    !die_compare_name(sp_die, pp->function))
1009
		return DWARF_CB_OK;
1010

1011 1012 1013 1014
	/* Check declared file */
	if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
		return DWARF_CB_OK;

1015
	pf->fname = dwarf_decl_file(sp_die);
1016 1017 1018
	if (pp->line) { /* Function relative line */
		dwarf_decl_line(sp_die, &pf->lno);
		pf->lno += pp->line;
1019
		param->retval = find_probe_point_by_line(pf);
1020 1021
	} else if (!dwarf_func_inline(sp_die)) {
		/* Real function */
1022
		if (pp->lazy_line)
1023
			param->retval = find_probe_point_lazy(sp_die, pf);
1024
		else {
1025
			if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
M
Masami Hiramatsu 已提交
1026 1027
				pr_warning("Failed to get entry address of "
					   "%s.\n", dwarf_diename(sp_die));
1028 1029 1030
				param->retval = -ENOENT;
				return DWARF_CB_ABORT;
			}
1031 1032
			pf->addr += pp->offset;
			/* TODO: Check the address in this function */
1033
			param->retval = call_probe_finder(sp_die, pf);
1034
		}
1035
	} else
1036
		/* Inlined function: search instances */
1037 1038
		param->retval = die_walk_instances(sp_die,
					probe_point_inline_cb, (void *)pf);
1039

1040
	return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
1041 1042
}

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

1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
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;

		if (die_compare_name(param->sp_die, param->function)) {
			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;
}

1083
/* Find probe points from debuginfo */
1084
static int debuginfo__find_probes(struct debuginfo *dbg,
1085
				  struct probe_finder *pf)
1086
{
1087
	struct perf_probe_point *pp = &pf->pev->point;
1088 1089 1090
	Dwarf_Off off, noff;
	size_t cuhl;
	Dwarf_Die *diep;
1091
	int ret = 0;
1092

1093
#if _ELFUTILS_PREREQ(0, 142)
1094
	/* Get the call frame information from this dwarf */
1095
	pf->cfi = dwarf_getcfi(dbg->dbg);
1096
#endif
1097

1098
	off = 0;
1099
	line_list__init(&pf->lcache);
1100 1101 1102 1103 1104 1105 1106 1107

	/* Fastpath: lookup by function name from .debug_pubnames section */
	if (pp->function) {
		struct pubname_callback_param pubname_param = {
			.function = pp->function,
			.file	  = pp->file,
			.cu_die	  = &pf->cu_die,
			.sp_die	  = &pf->sp_die,
1108
			.found	  = 0,
1109 1110 1111 1112 1113
		};
		struct dwarf_callback_param probe_param = {
			.data = pf,
		};

1114
		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1115
				  &pubname_param, 0);
1116 1117 1118 1119 1120 1121 1122
		if (pubname_param.found) {
			ret = probe_point_search_cb(&pf->sp_die, &probe_param);
			if (ret)
				goto found;
		}
	}

1123
	/* Loop on CUs (Compilation Unit) */
1124
	while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1125
		/* Get the DIE(Debugging Information Entry) of this CU */
1126
		diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
1127 1128
		if (!diep)
			continue;
1129 1130 1131

		/* Check if target file is included. */
		if (pp->file)
1132
			pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
1133
		else
1134
			pf->fname = NULL;
1135

1136
		if (!pp->file || pf->fname) {
1137
			if (pp->function)
1138
				ret = find_probe_point_by_func(pf);
1139
			else if (pp->lazy_line)
1140
				ret = find_probe_point_lazy(NULL, pf);
1141
			else {
1142 1143
				pf->lno = pp->line;
				ret = find_probe_point_by_line(pf);
1144
			}
1145
			if (ret < 0)
1146
				break;
1147
		}
1148
		off = noff;
1149
	}
1150 1151

found:
1152
	line_list__free(&pf->lcache);
1153

1154 1155 1156
	return ret;
}

1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
struct local_vars_finder {
	struct probe_finder *pf;
	struct perf_probe_arg *args;
	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;
1169
	struct probe_finder *pf = vf->pf;
1170 1171 1172 1173 1174 1175
	int tag;

	tag = dwarf_tag(die_mem);
	if (tag == DW_TAG_formal_parameter ||
	    tag == DW_TAG_variable) {
		if (convert_variable_location(die_mem, vf->pf->addr,
1176 1177
					      vf->pf->fb_ops, &pf->sp_die,
					      NULL) == 0) {
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
			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;
	struct local_vars_finder vf = {.pf = pf, .args = args,
				.max_args = MAX_PROBE_ARGS, .ret = 0};

	for (i = 0; i < pf->pev->nargs; i++) {
		/* var never be NULL */
		if (strcmp(pf->pev->args[i].var, "$vars") == 0) {
			pr_debug("Expanding $vars into:");
			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;
		} else {
			/* Copy normal argument */
			args[n] = pf->pev->args[i];
			n++;
		}
	}
	return n;
}

1224
/* Add a found probe point into trace event list */
1225
static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1226 1227 1228 1229
{
	struct trace_event_finder *tf =
			container_of(pf, struct trace_event_finder, pf);
	struct probe_trace_event *tev;
1230
	struct perf_probe_arg *args;
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240
	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++];

1241
	/* Trace point should be converted from subprogram DIE */
1242
	ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
1243
				     pf->pev->point.retprobe, &tev->point);
1244 1245 1246 1247 1248 1249
	if (ret < 0)
		return ret;

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

1250 1251 1252
	/* Expand special probe argument if exist */
	args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
	if (args == NULL)
1253
		return -ENOMEM;
1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268

	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];
1269
		pf->tvar = &tev->args[i];
1270 1271
		/* Variable should be found from scope DIE */
		ret = find_variable(sc_die, pf);
1272
		if (ret != 0)
1273
			break;
1274 1275
	}

1276 1277 1278
end:
	free(args);
	return ret;
1279 1280 1281
}

/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1282
int debuginfo__find_trace_events(struct debuginfo *dbg,
1283 1284
				 struct perf_probe_event *pev,
				 struct probe_trace_event **tevs, int max_tevs)
1285 1286 1287
{
	struct trace_event_finder tf = {
			.pf = {.pev = pev, .callback = add_probe_trace_event},
1288
			.mod = dbg->mod, .max_tevs = max_tevs};
1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
	int ret;

	/* Allocate result tevs array */
	*tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
	if (*tevs == NULL)
		return -ENOMEM;

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

1299
	ret = debuginfo__find_probes(dbg, &tf.pf);
1300
	if (ret < 0) {
1301
		zfree(tevs);
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
		return ret;
	}

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

#define MAX_VAR_LEN 64

/* 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;
	char buf[MAX_VAR_LEN];
	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,
1324 1325
						af->pf.fb_ops, &af->pf.sp_die,
						NULL);
1326 1327
		if (ret == 0) {
			ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
1328
			pr_debug2("Add new var: %s\n", buf);
1329 1330 1331 1332 1333
			if (ret > 0)
				strlist__add(vl->vars, buf);
		}
	}

1334
	if (af->child && dwarf_haspc(die_mem, af->pf.addr))
1335 1336 1337 1338 1339 1340
		return DIE_FIND_CB_CONTINUE;
	else
		return DIE_FIND_CB_SIBLING;
}

/* Add a found vars into available variables list */
1341
static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1342 1343 1344 1345
{
	struct available_var_finder *af =
			container_of(pf, struct available_var_finder, pf);
	struct variable_list *vl;
1346 1347
	Dwarf_Die die_mem;
	int ret;
1348 1349 1350 1351 1352 1353 1354 1355

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

1356
	/* Trace point should be converted from subprogram DIE */
1357
	ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
1358
				     pf->pev->point.retprobe, &vl->point);
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368
	if (ret < 0)
		return ret;

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

	/* Find local variables */
	vl->vars = strlist__new(true, NULL);
	if (vl->vars == NULL)
		return -ENOMEM;
1369
	af->child = true;
1370
	die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
1371

1372 1373 1374 1375 1376
	/* Find external variables */
	if (!af->externs)
		goto out;
	/* Don't need to search child DIE for externs. */
	af->child = false;
1377
	die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
1378 1379

out:
1380 1381 1382 1383 1384 1385 1386 1387 1388
	if (strlist__empty(vl->vars)) {
		strlist__delete(vl->vars);
		vl->vars = NULL;
	}

	return ret;
}

/* Find available variables at given probe point */
1389
int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1390 1391 1392
				      struct perf_probe_event *pev,
				      struct variable_list **vls,
				      int max_vls, bool externs)
1393 1394 1395
{
	struct available_var_finder af = {
			.pf = {.pev = pev, .callback = add_available_vars},
1396
			.mod = dbg->mod,
1397
			.max_vls = max_vls, .externs = externs};
1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
	int ret;

	/* Allocate result vls array */
	*vls = zalloc(sizeof(struct variable_list) * max_vls);
	if (*vls == NULL)
		return -ENOMEM;

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

1408
	ret = debuginfo__find_probes(dbg, &af.pf);
1409 1410 1411
	if (ret < 0) {
		/* Free vlist for error */
		while (af.nvls--) {
1412 1413
			free(af.vls[af.nvls].point.symbol);
			strlist__delete(af.vls[af.nvls].vars);
1414
		}
1415
		zfree(vls);
1416 1417 1418 1419
		return ret;
	}

	return (ret < 0) ? ret : af.nvls;
1420 1421
}

1422
/* Reverse search */
1423
int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1424
				struct perf_probe_point *ppt)
1425 1426
{
	Dwarf_Die cudie, spdie, indie;
1427 1428
	Dwarf_Addr _addr = 0, baseaddr = 0;
	const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1429
	int baseline = 0, lineno = 0, ret = 0;
1430

1431
	/* Adjust address with bias */
1432
	addr += dbg->bias;
1433

1434
	/* Find cu die */
1435
	if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) {
M
Masami Hiramatsu 已提交
1436 1437
		pr_warning("Failed to find debug information for address %lx\n",
			   addr);
1438 1439 1440
		ret = -EINVAL;
		goto end;
	}
1441

1442 1443 1444
	/* Find a corresponding line (filename and lineno) */
	cu_find_lineinfo(&cudie, addr, &fname, &lineno);
	/* Don't care whether it failed or not */
1445

1446
	/* Find a corresponding function (name, baseline and baseaddr) */
1447
	if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
1448
		/* Get function entry information */
1449 1450
		func = basefunc = dwarf_diename(&spdie);
		if (!func ||
1451
		    dwarf_entrypc(&spdie, &baseaddr) != 0 ||
1452 1453
		    dwarf_decl_line(&spdie, &baseline) != 0) {
			lineno = 0;
1454
			goto post;
1455
		}
1456

1457
		fname = dwarf_decl_file(&spdie);
1458
		if (addr == (unsigned long)baseaddr) {
1459 1460
			/* Function entry - Relative line number is 0 */
			lineno = baseline;
1461 1462 1463 1464 1465 1466 1467
			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 */
1468
			if (dwarf_entrypc(&indie, &_addr) == 0 &&
1469
			    _addr == addr) {
1470 1471 1472
				/*
				 * addr is at an inline function entry.
				 * In this case, lineno should be the call-site
1473
				 * line number. (overwrite lineinfo)
1474 1475
				 */
				lineno = die_get_call_lineno(&indie);
1476 1477 1478
				fname = die_get_call_file(&indie);
				break;
			} else {
1479 1480 1481 1482 1483 1484
				/*
				 * 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.
				 */
1485
				tmp = dwarf_diename(&indie);
1486 1487 1488 1489 1490
				if (!tmp ||
				    dwarf_decl_line(&indie, &baseline) != 0)
					break;
				func = tmp;
				spdie = indie;
1491
			}
1492
		}
1493 1494 1495 1496
		/* Verify the lineno and baseline are in a same file */
		tmp = dwarf_decl_file(&spdie);
		if (!tmp || strcmp(tmp, fname) != 0)
			lineno = 0;
1497 1498 1499 1500 1501 1502
	}

post:
	/* Make a relative line number or an offset */
	if (lineno)
		ppt->line = lineno - baseline;
1503
	else if (basefunc) {
1504
		ppt->offset = addr - (unsigned long)baseaddr;
1505 1506
		func = basefunc;
	}
1507 1508 1509 1510

	/* Duplicate strings */
	if (func) {
		ppt->function = strdup(func);
1511 1512 1513 1514
		if (ppt->function == NULL) {
			ret = -ENOMEM;
			goto end;
		}
1515
	}
1516 1517 1518
	if (fname) {
		ppt->file = strdup(fname);
		if (ppt->file == NULL) {
1519
			zfree(&ppt->function);
1520 1521 1522 1523
			ret = -ENOMEM;
			goto end;
		}
	}
1524
end:
1525 1526
	if (ret == 0 && (fname || func))
		ret = 1;	/* Found a point */
1527 1528 1529
	return ret;
}

1530 1531 1532 1533
/* Add a line and store the src path */
static int line_range_add_line(const char *src, unsigned int lineno,
			       struct line_range *lr)
{
1534
	/* Copy source path */
1535
	if (!lr->path) {
1536 1537 1538
		lr->path = strdup(src);
		if (lr->path == NULL)
			return -ENOMEM;
1539 1540 1541 1542
	}
	return line_list__add_line(&lr->line_list, lineno);
}

1543
static int line_range_walk_cb(const char *fname, int lineno,
1544
			      Dwarf_Addr addr __maybe_unused,
1545
			      void *data)
1546
{
1547
	struct line_finder *lf = data;
1548

1549
	if ((strtailcmp(fname, lf->fname) != 0) ||
1550
	    (lf->lno_s > lineno || lf->lno_e < lineno))
1551
		return 0;
1552

1553 1554
	if (line_range_add_line(fname, lineno, lf->lr) < 0)
		return -EINVAL;
1555

1556
	return 0;
1557
}
1558

1559
/* Find line range from its line number */
1560
static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1561
{
1562
	int ret;
1563

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

1566
	/* Update status */
1567 1568 1569 1570 1571
	if (ret >= 0)
		if (!list_empty(&lf->lr->line_list))
			ret = lf->found = 1;
		else
			ret = 0;	/* Lines are not found */
1572
	else {
1573
		zfree(&lf->lr->path);
1574
	}
1575
	return ret;
1576 1577
}

1578 1579
static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
{
1580
	find_line_range_by_line(in_die, data);
1581 1582 1583 1584 1585 1586

	/*
	 * We have to check all instances of inlined function, because
	 * some execution paths can be optimized out depends on the
	 * function argument of instances
	 */
1587
	return 0;
1588 1589
}

1590
/* Search function definition from function name */
1591
static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1592
{
1593 1594
	struct dwarf_callback_param *param = data;
	struct line_finder *lf = param->data;
1595 1596
	struct line_range *lr = lf->lr;

1597 1598 1599 1600
	/* Check declared file */
	if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
		return DWARF_CB_OK;

1601
	if (die_is_func_def(sp_die) &&
1602
	    die_compare_name(sp_die, lr->function)) {
1603 1604
		lf->fname = dwarf_decl_file(sp_die);
		dwarf_decl_line(sp_die, &lr->offset);
1605
		pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
1606
		lf->lno_s = lr->offset + lr->start;
1607 1608 1609 1610
		if (lf->lno_s < 0)	/* Overflow */
			lf->lno_s = INT_MAX;
		lf->lno_e = lr->offset + lr->end;
		if (lf->lno_e < 0)	/* Overflow */
1611
			lf->lno_e = INT_MAX;
1612
		pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1613 1614
		lr->start = lf->lno_s;
		lr->end = lf->lno_e;
1615 1616 1617 1618
		if (dwarf_func_inline(sp_die))
			param->retval = die_walk_instances(sp_die,
						line_range_inline_cb, lf);
		else
1619 1620
			param->retval = find_line_range_by_line(sp_die, lf);
		return DWARF_CB_ABORT;
1621
	}
1622
	return DWARF_CB_OK;
1623 1624
}

1625
static int find_line_range_by_func(struct line_finder *lf)
1626
{
1627 1628 1629
	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
	dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
	return param.retval;
1630 1631
}

1632
int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
1633
{
1634
	struct line_finder lf = {.lr = lr, .found = 0};
1635
	int ret = 0;
1636 1637 1638
	Dwarf_Off off = 0, noff;
	size_t cuhl;
	Dwarf_Die *diep;
1639
	const char *comp_dir;
1640

1641 1642 1643 1644 1645 1646 1647 1648
	/* 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};

1649
		dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1650
				  &pubname_param, 0);
1651 1652 1653 1654 1655 1656 1657
		if (pubname_param.found) {
			line_range_search_cb(&lf.sp_die, &line_range_param);
			if (lf.found)
				goto found;
		}
	}

1658
	/* Loop on CUs (Compilation Unit) */
1659
	while (!lf.found && ret >= 0) {
1660
		if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
1661
				 NULL, NULL, NULL) != 0)
1662 1663 1664
			break;

		/* Get the DIE(Debugging Information Entry) of this CU */
1665
		diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
1666 1667
		if (!diep)
			continue;
1668 1669 1670

		/* Check if target file is included. */
		if (lr->file)
1671
			lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
1672
		else
1673
			lf.fname = 0;
1674

1675
		if (!lr->file || lf.fname) {
1676
			if (lr->function)
1677
				ret = find_line_range_by_func(&lf);
1678 1679
			else {
				lf.lno_s = lr->start;
1680
				lf.lno_e = lr->end;
1681
				ret = find_line_range_by_line(NULL, &lf);
1682 1683
			}
		}
1684
		off = noff;
1685
	}
1686

1687
found:
1688 1689 1690 1691 1692 1693 1694 1695 1696 1697
	/* 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;
		}
	}

1698
	pr_debug("path: %s\n", lr->path);
1699
	return (ret < 0) ? ret : lf.found;
1700 1701
}