Home | History | Annotate | Download | only in util
      1 /*
      2  * probe-finder.c : C expression to kprobe event converter
      3  *
      4  * Written by Masami Hiramatsu <mhiramat (at) redhat.com>
      5  *
      6  * This program is free software; you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License as published by
      8  * the Free Software Foundation; either version 2 of the License, or
      9  * (at your option) any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  * GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with this program; if not, write to the Free Software
     18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     19  *
     20  */
     21 
     22 #include <sys/utsname.h>
     23 #include <sys/types.h>
     24 #include <sys/stat.h>
     25 #include <fcntl.h>
     26 #include <errno.h>
     27 #include <stdio.h>
     28 #include <unistd.h>
     29 #include <getopt.h>
     30 #include <stdlib.h>
     31 #include <string.h>
     32 #include <stdarg.h>
     33 #include <dwarf-regs.h>
     34 
     35 #include <linux/bitops.h>
     36 #include "event.h"
     37 #include "debug.h"
     38 #include "util.h"
     39 #include "symbol.h"
     40 #include "probe-finder.h"
     41 
     42 /* Kprobe tracer basic type is up to u64 */
     43 #define MAX_BASIC_TYPE_BITS	64
     44 
     45 /* Line number list operations */
     46 
     47 /* Add a line to line number list */
     48 static int line_list__add_line(struct list_head *head, int line)
     49 {
     50 	struct line_node *ln;
     51 	struct list_head *p;
     52 
     53 	/* Reverse search, because new line will be the last one */
     54 	list_for_each_entry_reverse(ln, head, list) {
     55 		if (ln->line < line) {
     56 			p = &ln->list;
     57 			goto found;
     58 		} else if (ln->line == line)	/* Already exist */
     59 			return 1;
     60 	}
     61 	/* List is empty, or the smallest entry */
     62 	p = head;
     63 found:
     64 	pr_debug("line list: add a line %u\n", line);
     65 	ln = zalloc(sizeof(struct line_node));
     66 	if (ln == NULL)
     67 		return -ENOMEM;
     68 	ln->line = line;
     69 	INIT_LIST_HEAD(&ln->list);
     70 	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 	struct line_node *ln;
     78 
     79 	/* Reverse search, because new line will be the last one */
     80 	list_for_each_entry(ln, head, list)
     81 		if (ln->line == line)
     82 			return 1;
     83 
     84 	return 0;
     85 }
     86 
     87 /* Init line number list */
     88 static void line_list__init(struct list_head *head)
     89 {
     90 	INIT_LIST_HEAD(head);
     91 }
     92 
     93 /* Free line number list */
     94 static void line_list__free(struct list_head *head)
     95 {
     96 	struct line_node *ln;
     97 	while (!list_empty(head)) {
     98 		ln = list_first_entry(head, struct line_node, list);
     99 		list_del(&ln->list);
    100 		free(ln);
    101 	}
    102 }
    103 
    104 /* Dwarf FL wrappers */
    105 static char *debuginfo_path;	/* Currently dummy */
    106 
    107 static const Dwfl_Callbacks offline_callbacks = {
    108 	.find_debuginfo = dwfl_standard_find_debuginfo,
    109 	.debuginfo_path = &debuginfo_path,
    110 
    111 	.section_address = dwfl_offline_section_address,
    112 
    113 	/* We use this table for core files too.  */
    114 	.find_elf = dwfl_build_id_find_elf,
    115 };
    116 
    117 /* Get a Dwarf from offline image */
    118 static int debuginfo__init_offline_dwarf(struct debuginfo *self,
    119 					 const char *path)
    120 {
    121 	int fd;
    122 
    123 	fd = open(path, O_RDONLY);
    124 	if (fd < 0)
    125 		return fd;
    126 
    127 	self->dwfl = dwfl_begin(&offline_callbacks);
    128 	if (!self->dwfl)
    129 		goto error;
    130 
    131 	self->mod = dwfl_report_offline(self->dwfl, "", "", fd);
    132 	if (!self->mod)
    133 		goto error;
    134 
    135 	self->dbg = dwfl_module_getdwarf(self->mod, &self->bias);
    136 	if (!self->dbg)
    137 		goto error;
    138 
    139 	return 0;
    140 error:
    141 	if (self->dwfl)
    142 		dwfl_end(self->dwfl);
    143 	else
    144 		close(fd);
    145 	memset(self, 0, sizeof(*self));
    146 
    147 	return -ENOENT;
    148 }
    149 
    150 /*
    151  * ANDROID LOCAL PATCH
    152  * Bionic doesn't have stdio_ext.h which is used by dwfl_linux_kernel_find_elf.
    153  * So we just disable the new feature here even though we are pairing perf with
    154  * elfutils 0.153 now.
    155  */
    156 #if _ELFUTILS_PREREQ(0, 148) && 0
    157 /* This method is buggy if elfutils is older than 0.148 */
    158 static int __linux_kernel_find_elf(Dwfl_Module *mod,
    159 				   void **userdata,
    160 				   const char *module_name,
    161 				   Dwarf_Addr base,
    162 				   char **file_name, Elf **elfp)
    163 {
    164 	int fd;
    165 	const char *path = kernel_get_module_path(module_name);
    166 
    167 	pr_debug2("Use file %s for %s\n", path, module_name);
    168 	if (path) {
    169 		fd = open(path, O_RDONLY);
    170 		if (fd >= 0) {
    171 			*file_name = strdup(path);
    172 			return fd;
    173 		}
    174 	}
    175 	/* If failed, try to call standard method */
    176 	return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
    177 					  file_name, elfp);
    178 }
    179 
    180 static const Dwfl_Callbacks kernel_callbacks = {
    181 	.find_debuginfo = dwfl_standard_find_debuginfo,
    182 	.debuginfo_path = &debuginfo_path,
    183 
    184 	.find_elf = __linux_kernel_find_elf,
    185 	.section_address = dwfl_linux_kernel_module_section_address,
    186 };
    187 
    188 /* Get a Dwarf from live kernel image */
    189 static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
    190 					       Dwarf_Addr addr)
    191 {
    192 	self->dwfl = dwfl_begin(&kernel_callbacks);
    193 	if (!self->dwfl)
    194 		return -EINVAL;
    195 
    196 	/* Load the kernel dwarves: Don't care the result here */
    197 	dwfl_linux_kernel_report_kernel(self->dwfl);
    198 	dwfl_linux_kernel_report_modules(self->dwfl);
    199 
    200 	self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
    201 	/* Here, check whether we could get a real dwarf */
    202 	if (!self->dbg) {
    203 		pr_debug("Failed to find kernel dwarf at %lx\n",
    204 			 (unsigned long)addr);
    205 		dwfl_end(self->dwfl);
    206 		memset(self, 0, sizeof(*self));
    207 		return -ENOENT;
    208 	}
    209 
    210 	return 0;
    211 }
    212 #else
    213 /* With older elfutils, this just support kernel module... */
    214 static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
    215 					       Dwarf_Addr addr __maybe_unused)
    216 {
    217 	const char *path = kernel_get_module_path("kernel");
    218 
    219 	if (!path) {
    220 		pr_err("Failed to find vmlinux path\n");
    221 		return -ENOENT;
    222 	}
    223 
    224 	pr_debug2("Use file %s for debuginfo\n", path);
    225 	return debuginfo__init_offline_dwarf(self, path);
    226 }
    227 #endif
    228 
    229 struct debuginfo *debuginfo__new(const char *path)
    230 {
    231 	struct debuginfo *self = zalloc(sizeof(struct debuginfo));
    232 	if (!self)
    233 		return NULL;
    234 
    235 	if (debuginfo__init_offline_dwarf(self, path) < 0) {
    236 		free(self);
    237 		self = NULL;
    238 	}
    239 
    240 	return self;
    241 }
    242 
    243 struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
    244 {
    245 	struct debuginfo *self = zalloc(sizeof(struct debuginfo));
    246 	if (!self)
    247 		return NULL;
    248 
    249 	if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) {
    250 		free(self);
    251 		self = NULL;
    252 	}
    253 
    254 	return self;
    255 }
    256 
    257 void debuginfo__delete(struct debuginfo *self)
    258 {
    259 	if (self) {
    260 		if (self->dwfl)
    261 			dwfl_end(self->dwfl);
    262 		free(self);
    263 	}
    264 }
    265 
    266 /*
    267  * Probe finder related functions
    268  */
    269 
    270 static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
    271 {
    272 	struct probe_trace_arg_ref *ref;
    273 	ref = zalloc(sizeof(struct probe_trace_arg_ref));
    274 	if (ref != NULL)
    275 		ref->offset = offs;
    276 	return ref;
    277 }
    278 
    279 /*
    280  * Convert a location into trace_arg.
    281  * If tvar == NULL, this just checks variable can be converted.
    282  */
    283 static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
    284 				     Dwarf_Op *fb_ops,
    285 				     struct probe_trace_arg *tvar)
    286 {
    287 	Dwarf_Attribute attr;
    288 	Dwarf_Op *op;
    289 	size_t nops;
    290 	unsigned int regn;
    291 	Dwarf_Word offs = 0;
    292 	bool ref = false;
    293 	const char *regs;
    294 	int ret;
    295 
    296 	if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
    297 		goto static_var;
    298 
    299 	/* TODO: handle more than 1 exprs */
    300 	if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
    301 	    dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
    302 	    nops == 0) {
    303 		/* TODO: Support const_value */
    304 		return -ENOENT;
    305 	}
    306 
    307 	if (op->atom == DW_OP_addr) {
    308 static_var:
    309 		if (!tvar)
    310 			return 0;
    311 		/* Static variables on memory (not stack), make @varname */
    312 		ret = strlen(dwarf_diename(vr_die));
    313 		tvar->value = zalloc(ret + 2);
    314 		if (tvar->value == NULL)
    315 			return -ENOMEM;
    316 		snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
    317 		tvar->ref = alloc_trace_arg_ref((long)offs);
    318 		if (tvar->ref == NULL)
    319 			return -ENOMEM;
    320 		return 0;
    321 	}
    322 
    323 	/* If this is based on frame buffer, set the offset */
    324 	if (op->atom == DW_OP_fbreg) {
    325 		if (fb_ops == NULL)
    326 			return -ENOTSUP;
    327 		ref = true;
    328 		offs = op->number;
    329 		op = &fb_ops[0];
    330 	}
    331 
    332 	if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
    333 		regn = op->atom - DW_OP_breg0;
    334 		offs += op->number;
    335 		ref = true;
    336 	} else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
    337 		regn = op->atom - DW_OP_reg0;
    338 	} else if (op->atom == DW_OP_bregx) {
    339 		regn = op->number;
    340 		offs += op->number2;
    341 		ref = true;
    342 	} else if (op->atom == DW_OP_regx) {
    343 		regn = op->number;
    344 	} else {
    345 		pr_debug("DW_OP %x is not supported.\n", op->atom);
    346 		return -ENOTSUP;
    347 	}
    348 
    349 	if (!tvar)
    350 		return 0;
    351 
    352 	regs = get_arch_regstr(regn);
    353 	if (!regs) {
    354 		/* This should be a bug in DWARF or this tool */
    355 		pr_warning("Mapping for the register number %u "
    356 			   "missing on this architecture.\n", regn);
    357 		return -ERANGE;
    358 	}
    359 
    360 	tvar->value = strdup(regs);
    361 	if (tvar->value == NULL)
    362 		return -ENOMEM;
    363 
    364 	if (ref) {
    365 		tvar->ref = alloc_trace_arg_ref((long)offs);
    366 		if (tvar->ref == NULL)
    367 			return -ENOMEM;
    368 	}
    369 	return 0;
    370 }
    371 
    372 #define BYTES_TO_BITS(nb)	((nb) * BITS_PER_LONG / sizeof(long))
    373 
    374 static int convert_variable_type(Dwarf_Die *vr_die,
    375 				 struct probe_trace_arg *tvar,
    376 				 const char *cast)
    377 {
    378 	struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
    379 	Dwarf_Die type;
    380 	char buf[16];
    381 	int bsize, boffs, total;
    382 	int ret;
    383 
    384 	/* TODO: check all types */
    385 	if (cast && strcmp(cast, "string") != 0) {
    386 		/* Non string type is OK */
    387 		tvar->type = strdup(cast);
    388 		return (tvar->type == NULL) ? -ENOMEM : 0;
    389 	}
    390 
    391 	bsize = dwarf_bitsize(vr_die);
    392 	if (bsize > 0) {
    393 		/* This is a bitfield */
    394 		boffs = dwarf_bitoffset(vr_die);
    395 		total = dwarf_bytesize(vr_die);
    396 		if (boffs < 0 || total < 0)
    397 			return -ENOENT;
    398 		ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs,
    399 				BYTES_TO_BITS(total));
    400 		goto formatted;
    401 	}
    402 
    403 	if (die_get_real_type(vr_die, &type) == NULL) {
    404 		pr_warning("Failed to get a type information of %s.\n",
    405 			   dwarf_diename(vr_die));
    406 		return -ENOENT;
    407 	}
    408 
    409 	pr_debug("%s type is %s.\n",
    410 		 dwarf_diename(vr_die), dwarf_diename(&type));
    411 
    412 	if (cast && strcmp(cast, "string") == 0) {	/* String type */
    413 		ret = dwarf_tag(&type);
    414 		if (ret != DW_TAG_pointer_type &&
    415 		    ret != DW_TAG_array_type) {
    416 			pr_warning("Failed to cast into string: "
    417 				   "%s(%s) is not a pointer nor array.\n",
    418 				   dwarf_diename(vr_die), dwarf_diename(&type));
    419 			return -EINVAL;
    420 		}
    421 		if (die_get_real_type(&type, &type) == NULL) {
    422 			pr_warning("Failed to get a type"
    423 				   " information.\n");
    424 			return -ENOENT;
    425 		}
    426 		if (ret == DW_TAG_pointer_type) {
    427 			while (*ref_ptr)
    428 				ref_ptr = &(*ref_ptr)->next;
    429 			/* Add new reference with offset +0 */
    430 			*ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
    431 			if (*ref_ptr == NULL) {
    432 				pr_warning("Out of memory error\n");
    433 				return -ENOMEM;
    434 			}
    435 		}
    436 		if (!die_compare_name(&type, "char") &&
    437 		    !die_compare_name(&type, "unsigned char")) {
    438 			pr_warning("Failed to cast into string: "
    439 				   "%s is not (unsigned) char *.\n",
    440 				   dwarf_diename(vr_die));
    441 			return -EINVAL;
    442 		}
    443 		tvar->type = strdup(cast);
    444 		return (tvar->type == NULL) ? -ENOMEM : 0;
    445 	}
    446 
    447 	ret = dwarf_bytesize(&type);
    448 	if (ret <= 0)
    449 		/* No size ... try to use default type */
    450 		return 0;
    451 	ret = BYTES_TO_BITS(ret);
    452 
    453 	/* Check the bitwidth */
    454 	if (ret > MAX_BASIC_TYPE_BITS) {
    455 		pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
    456 			dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
    457 		ret = MAX_BASIC_TYPE_BITS;
    458 	}
    459 	ret = snprintf(buf, 16, "%c%d",
    460 		       die_is_signed_type(&type) ? 's' : 'u', ret);
    461 
    462 formatted:
    463 	if (ret < 0 || ret >= 16) {
    464 		if (ret >= 16)
    465 			ret = -E2BIG;
    466 		pr_warning("Failed to convert variable type: %s\n",
    467 			   strerror(-ret));
    468 		return ret;
    469 	}
    470 	tvar->type = strdup(buf);
    471 	if (tvar->type == NULL)
    472 		return -ENOMEM;
    473 	return 0;
    474 }
    475 
    476 static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
    477 				    struct perf_probe_arg_field *field,
    478 				    struct probe_trace_arg_ref **ref_ptr,
    479 				    Dwarf_Die *die_mem)
    480 {
    481 	struct probe_trace_arg_ref *ref = *ref_ptr;
    482 	Dwarf_Die type;
    483 	Dwarf_Word offs;
    484 	int ret, tag;
    485 
    486 	pr_debug("converting %s in %s\n", field->name, varname);
    487 	if (die_get_real_type(vr_die, &type) == NULL) {
    488 		pr_warning("Failed to get the type of %s.\n", varname);
    489 		return -ENOENT;
    490 	}
    491 	pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type));
    492 	tag = dwarf_tag(&type);
    493 
    494 	if (field->name[0] == '[' &&
    495 	    (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
    496 		if (field->next)
    497 			/* Save original type for next field */
    498 			memcpy(die_mem, &type, sizeof(*die_mem));
    499 		/* Get the type of this array */
    500 		if (die_get_real_type(&type, &type) == NULL) {
    501 			pr_warning("Failed to get the type of %s.\n", varname);
    502 			return -ENOENT;
    503 		}
    504 		pr_debug2("Array real type: (%x)\n",
    505 			 (unsigned)dwarf_dieoffset(&type));
    506 		if (tag == DW_TAG_pointer_type) {
    507 			ref = zalloc(sizeof(struct probe_trace_arg_ref));
    508 			if (ref == NULL)
    509 				return -ENOMEM;
    510 			if (*ref_ptr)
    511 				(*ref_ptr)->next = ref;
    512 			else
    513 				*ref_ptr = ref;
    514 		}
    515 		ref->offset += dwarf_bytesize(&type) * field->index;
    516 		if (!field->next)
    517 			/* Save vr_die for converting types */
    518 			memcpy(die_mem, vr_die, sizeof(*die_mem));
    519 		goto next;
    520 	} else if (tag == DW_TAG_pointer_type) {
    521 		/* Check the pointer and dereference */
    522 		if (!field->ref) {
    523 			pr_err("Semantic error: %s must be referred by '->'\n",
    524 			       field->name);
    525 			return -EINVAL;
    526 		}
    527 		/* Get the type pointed by this pointer */
    528 		if (die_get_real_type(&type, &type) == NULL) {
    529 			pr_warning("Failed to get the type of %s.\n", varname);
    530 			return -ENOENT;
    531 		}
    532 		/* Verify it is a data structure  */
    533 		tag = dwarf_tag(&type);
    534 		if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
    535 			pr_warning("%s is not a data structure nor an union.\n",
    536 				   varname);
    537 			return -EINVAL;
    538 		}
    539 
    540 		ref = zalloc(sizeof(struct probe_trace_arg_ref));
    541 		if (ref == NULL)
    542 			return -ENOMEM;
    543 		if (*ref_ptr)
    544 			(*ref_ptr)->next = ref;
    545 		else
    546 			*ref_ptr = ref;
    547 	} else {
    548 		/* Verify it is a data structure  */
    549 		if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
    550 			pr_warning("%s is not a data structure nor an union.\n",
    551 				   varname);
    552 			return -EINVAL;
    553 		}
    554 		if (field->name[0] == '[') {
    555 			pr_err("Semantic error: %s is not a pointor"
    556 			       " nor array.\n", varname);
    557 			return -EINVAL;
    558 		}
    559 		if (field->ref) {
    560 			pr_err("Semantic error: %s must be referred by '.'\n",
    561 			       field->name);
    562 			return -EINVAL;
    563 		}
    564 		if (!ref) {
    565 			pr_warning("Structure on a register is not "
    566 				   "supported yet.\n");
    567 			return -ENOTSUP;
    568 		}
    569 	}
    570 
    571 	if (die_find_member(&type, field->name, die_mem) == NULL) {
    572 		pr_warning("%s(tyep:%s) has no member %s.\n", varname,
    573 			   dwarf_diename(&type), field->name);
    574 		return -EINVAL;
    575 	}
    576 
    577 	/* Get the offset of the field */
    578 	if (tag == DW_TAG_union_type) {
    579 		offs = 0;
    580 	} else {
    581 		ret = die_get_data_member_location(die_mem, &offs);
    582 		if (ret < 0) {
    583 			pr_warning("Failed to get the offset of %s.\n",
    584 				   field->name);
    585 			return ret;
    586 		}
    587 	}
    588 	ref->offset += (long)offs;
    589 
    590 next:
    591 	/* Converting next field */
    592 	if (field->next)
    593 		return convert_variable_fields(die_mem, field->name,
    594 					field->next, &ref, die_mem);
    595 	else
    596 		return 0;
    597 }
    598 
    599 /* Show a variables in kprobe event format */
    600 static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
    601 {
    602 	Dwarf_Die die_mem;
    603 	int ret;
    604 
    605 	pr_debug("Converting variable %s into trace event.\n",
    606 		 dwarf_diename(vr_die));
    607 
    608 	ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
    609 					pf->tvar);
    610 	if (ret == -ENOENT)
    611 		pr_err("Failed to find the location of %s at this address.\n"
    612 		       " Perhaps, it has been optimized out.\n", pf->pvar->var);
    613 	else if (ret == -ENOTSUP)
    614 		pr_err("Sorry, we don't support this variable location yet.\n");
    615 	else if (pf->pvar->field) {
    616 		ret = convert_variable_fields(vr_die, pf->pvar->var,
    617 					      pf->pvar->field, &pf->tvar->ref,
    618 					      &die_mem);
    619 		vr_die = &die_mem;
    620 	}
    621 	if (ret == 0)
    622 		ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
    623 	/* *expr will be cached in libdw. Don't free it. */
    624 	return ret;
    625 }
    626 
    627 /* Find a variable in a scope DIE */
    628 static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
    629 {
    630 	Dwarf_Die vr_die;
    631 	char buf[32], *ptr;
    632 	int ret = 0;
    633 
    634 	if (!is_c_varname(pf->pvar->var)) {
    635 		/* Copy raw parameters */
    636 		pf->tvar->value = strdup(pf->pvar->var);
    637 		if (pf->tvar->value == NULL)
    638 			return -ENOMEM;
    639 		if (pf->pvar->type) {
    640 			pf->tvar->type = strdup(pf->pvar->type);
    641 			if (pf->tvar->type == NULL)
    642 				return -ENOMEM;
    643 		}
    644 		if (pf->pvar->name) {
    645 			pf->tvar->name = strdup(pf->pvar->name);
    646 			if (pf->tvar->name == NULL)
    647 				return -ENOMEM;
    648 		} else
    649 			pf->tvar->name = NULL;
    650 		return 0;
    651 	}
    652 
    653 	if (pf->pvar->name)
    654 		pf->tvar->name = strdup(pf->pvar->name);
    655 	else {
    656 		ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
    657 		if (ret < 0)
    658 			return ret;
    659 		ptr = strchr(buf, ':');	/* Change type separator to _ */
    660 		if (ptr)
    661 			*ptr = '_';
    662 		pf->tvar->name = strdup(buf);
    663 	}
    664 	if (pf->tvar->name == NULL)
    665 		return -ENOMEM;
    666 
    667 	pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
    668 	/* Search child die for local variables and parameters. */
    669 	if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
    670 		/* Search again in global variables */
    671 		if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
    672 			ret = -ENOENT;
    673 	}
    674 	if (ret >= 0)
    675 		ret = convert_variable(&vr_die, pf);
    676 
    677 	if (ret < 0)
    678 		pr_warning("Failed to find '%s' in this function.\n",
    679 			   pf->pvar->var);
    680 	return ret;
    681 }
    682 
    683 /* Convert subprogram DIE to trace point */
    684 static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
    685 				  Dwarf_Addr paddr, bool retprobe,
    686 				  struct probe_trace_point *tp)
    687 {
    688 	Dwarf_Addr eaddr, highaddr;
    689 	GElf_Sym sym;
    690 	const char *symbol;
    691 
    692 	/* Verify the address is correct */
    693 	if (dwarf_entrypc(sp_die, &eaddr) != 0) {
    694 		pr_warning("Failed to get entry address of %s\n",
    695 			   dwarf_diename(sp_die));
    696 		return -ENOENT;
    697 	}
    698 	if (dwarf_highpc(sp_die, &highaddr) != 0) {
    699 		pr_warning("Failed to get end address of %s\n",
    700 			   dwarf_diename(sp_die));
    701 		return -ENOENT;
    702 	}
    703 	if (paddr > highaddr) {
    704 		pr_warning("Offset specified is greater than size of %s\n",
    705 			   dwarf_diename(sp_die));
    706 		return -EINVAL;
    707 	}
    708 
    709 	/* Get an appropriate symbol from symtab */
    710 	symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
    711 	if (!symbol) {
    712 		pr_warning("Failed to find symbol at 0x%lx\n",
    713 			   (unsigned long)paddr);
    714 		return -ENOENT;
    715 	}
    716 	tp->offset = (unsigned long)(paddr - sym.st_value);
    717 	tp->symbol = strdup(symbol);
    718 	if (!tp->symbol)
    719 		return -ENOMEM;
    720 
    721 	/* Return probe must be on the head of a subprogram */
    722 	if (retprobe) {
    723 		if (eaddr != paddr) {
    724 			pr_warning("Return probe must be on the head of"
    725 				   " a real function.\n");
    726 			return -EINVAL;
    727 		}
    728 		tp->retprobe = true;
    729 	}
    730 
    731 	return 0;
    732 }
    733 
    734 /* Call probe_finder callback with scope DIE */
    735 static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
    736 {
    737 	Dwarf_Attribute fb_attr;
    738 	size_t nops;
    739 	int ret;
    740 
    741 	if (!sc_die) {
    742 		pr_err("Caller must pass a scope DIE. Program error.\n");
    743 		return -EINVAL;
    744 	}
    745 
    746 	/* If not a real subprogram, find a real one */
    747 	if (!die_is_func_def(sc_die)) {
    748 		if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
    749 			pr_warning("Failed to find probe point in any "
    750 				   "functions.\n");
    751 			return -ENOENT;
    752 		}
    753 	} else
    754 		memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
    755 
    756 	/* Get the frame base attribute/ops from subprogram */
    757 	dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
    758 	ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
    759 	if (ret <= 0 || nops == 0) {
    760 		pf->fb_ops = NULL;
    761 #if _ELFUTILS_PREREQ(0, 142)
    762 	} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
    763 		   pf->cfi != NULL) {
    764 		Dwarf_Frame *frame;
    765 		if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
    766 		    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
    767 			pr_warning("Failed to get call frame on 0x%jx\n",
    768 				   (uintmax_t)pf->addr);
    769 			return -ENOENT;
    770 		}
    771 #endif
    772 	}
    773 
    774 	/* Call finder's callback handler */
    775 	ret = pf->callback(sc_die, pf);
    776 
    777 	/* *pf->fb_ops will be cached in libdw. Don't free it. */
    778 	pf->fb_ops = NULL;
    779 
    780 	return ret;
    781 }
    782 
    783 struct find_scope_param {
    784 	const char *function;
    785 	const char *file;
    786 	int line;
    787 	int diff;
    788 	Dwarf_Die *die_mem;
    789 	bool found;
    790 };
    791 
    792 static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
    793 {
    794 	struct find_scope_param *fsp = data;
    795 	const char *file;
    796 	int lno;
    797 
    798 	/* Skip if declared file name does not match */
    799 	if (fsp->file) {
    800 		file = dwarf_decl_file(fn_die);
    801 		if (!file || strcmp(fsp->file, file) != 0)
    802 			return 0;
    803 	}
    804 	/* If the function name is given, that's what user expects */
    805 	if (fsp->function) {
    806 		if (die_compare_name(fn_die, fsp->function)) {
    807 			memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
    808 			fsp->found = true;
    809 			return 1;
    810 		}
    811 	} else {
    812 		/* With the line number, find the nearest declared DIE */
    813 		dwarf_decl_line(fn_die, &lno);
    814 		if (lno < fsp->line && fsp->diff > fsp->line - lno) {
    815 			/* Keep a candidate and continue */
    816 			fsp->diff = fsp->line - lno;
    817 			memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
    818 			fsp->found = true;
    819 		}
    820 	}
    821 	return 0;
    822 }
    823 
    824 /* Find an appropriate scope fits to given conditions */
    825 static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
    826 {
    827 	struct find_scope_param fsp = {
    828 		.function = pf->pev->point.function,
    829 		.file = pf->fname,
    830 		.line = pf->lno,
    831 		.diff = INT_MAX,
    832 		.die_mem = die_mem,
    833 		.found = false,
    834 	};
    835 
    836 	cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp);
    837 
    838 	return fsp.found ? die_mem : NULL;
    839 }
    840 
    841 static int probe_point_line_walker(const char *fname, int lineno,
    842 				   Dwarf_Addr addr, void *data)
    843 {
    844 	struct probe_finder *pf = data;
    845 	Dwarf_Die *sc_die, die_mem;
    846 	int ret;
    847 
    848 	if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
    849 		return 0;
    850 
    851 	pf->addr = addr;
    852 	sc_die = find_best_scope(pf, &die_mem);
    853 	if (!sc_die) {
    854 		pr_warning("Failed to find scope of probe point.\n");
    855 		return -ENOENT;
    856 	}
    857 
    858 	ret = call_probe_finder(sc_die, pf);
    859 
    860 	/* Continue if no error, because the line will be in inline function */
    861 	return ret < 0 ? ret : 0;
    862 }
    863 
    864 /* Find probe point from its line number */
    865 static int find_probe_point_by_line(struct probe_finder *pf)
    866 {
    867 	return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf);
    868 }
    869 
    870 /* Find lines which match lazy pattern */
    871 static int find_lazy_match_lines(struct list_head *head,
    872 				 const char *fname, const char *pat)
    873 {
    874 	FILE *fp;
    875 	char *line = NULL;
    876 	size_t line_len;
    877 	ssize_t len;
    878 	int count = 0, linenum = 1;
    879 
    880 	fp = fopen(fname, "r");
    881 	if (!fp) {
    882 		pr_warning("Failed to open %s: %s\n", fname, strerror(errno));
    883 		return -errno;
    884 	}
    885 
    886 	while ((len = getline(&line, &line_len, fp)) > 0) {
    887 
    888 		if (line[len - 1] == '\n')
    889 			line[len - 1] = '\0';
    890 
    891 		if (strlazymatch(line, pat)) {
    892 			line_list__add_line(head, linenum);
    893 			count++;
    894 		}
    895 		linenum++;
    896 	}
    897 
    898 	if (ferror(fp))
    899 		count = -errno;
    900 	free(line);
    901 	fclose(fp);
    902 
    903 	if (count == 0)
    904 		pr_debug("No matched lines found in %s.\n", fname);
    905 	return count;
    906 }
    907 
    908 static int probe_point_lazy_walker(const char *fname, int lineno,
    909 				   Dwarf_Addr addr, void *data)
    910 {
    911 	struct probe_finder *pf = data;
    912 	Dwarf_Die *sc_die, die_mem;
    913 	int ret;
    914 
    915 	if (!line_list__has_line(&pf->lcache, lineno) ||
    916 	    strtailcmp(fname, pf->fname) != 0)
    917 		return 0;
    918 
    919 	pr_debug("Probe line found: line:%d addr:0x%llx\n",
    920 		 lineno, (unsigned long long)addr);
    921 	pf->addr = addr;
    922 	pf->lno = lineno;
    923 	sc_die = find_best_scope(pf, &die_mem);
    924 	if (!sc_die) {
    925 		pr_warning("Failed to find scope of probe point.\n");
    926 		return -ENOENT;
    927 	}
    928 
    929 	ret = call_probe_finder(sc_die, pf);
    930 
    931 	/*
    932 	 * Continue if no error, because the lazy pattern will match
    933 	 * to other lines
    934 	 */
    935 	return ret < 0 ? ret : 0;
    936 }
    937 
    938 /* Find probe points from lazy pattern  */
    939 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
    940 {
    941 	int ret = 0;
    942 
    943 	if (list_empty(&pf->lcache)) {
    944 		/* Matching lazy line pattern */
    945 		ret = find_lazy_match_lines(&pf->lcache, pf->fname,
    946 					    pf->pev->point.lazy_line);
    947 		if (ret <= 0)
    948 			return ret;
    949 	}
    950 
    951 	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
    952 }
    953 
    954 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
    955 {
    956 	struct probe_finder *pf = data;
    957 	struct perf_probe_point *pp = &pf->pev->point;
    958 	Dwarf_Addr addr;
    959 	int ret;
    960 
    961 	if (pp->lazy_line)
    962 		ret = find_probe_point_lazy(in_die, pf);
    963 	else {
    964 		/* Get probe address */
    965 		if (dwarf_entrypc(in_die, &addr) != 0) {
    966 			pr_warning("Failed to get entry address of %s.\n",
    967 				   dwarf_diename(in_die));
    968 			return -ENOENT;
    969 		}
    970 		pf->addr = addr;
    971 		pf->addr += pp->offset;
    972 		pr_debug("found inline addr: 0x%jx\n",
    973 			 (uintmax_t)pf->addr);
    974 
    975 		ret = call_probe_finder(in_die, pf);
    976 	}
    977 
    978 	return ret;
    979 }
    980 
    981 /* Callback parameter with return value for libdw */
    982 struct dwarf_callback_param {
    983 	void *data;
    984 	int retval;
    985 };
    986 
    987 /* Search function from function name */
    988 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
    989 {
    990 	struct dwarf_callback_param *param = data;
    991 	struct probe_finder *pf = param->data;
    992 	struct perf_probe_point *pp = &pf->pev->point;
    993 
    994 	/* Check tag and diename */
    995 	if (!die_is_func_def(sp_die) ||
    996 	    !die_compare_name(sp_die, pp->function))
    997 		return DWARF_CB_OK;
    998 
    999 	/* Check declared file */
   1000 	if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
   1001 		return DWARF_CB_OK;
   1002 
   1003 	pf->fname = dwarf_decl_file(sp_die);
   1004 	if (pp->line) { /* Function relative line */
   1005 		dwarf_decl_line(sp_die, &pf->lno);
   1006 		pf->lno += pp->line;
   1007 		param->retval = find_probe_point_by_line(pf);
   1008 	} else if (!dwarf_func_inline(sp_die)) {
   1009 		/* Real function */
   1010 		if (pp->lazy_line)
   1011 			param->retval = find_probe_point_lazy(sp_die, pf);
   1012 		else {
   1013 			if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
   1014 				pr_warning("Failed to get entry address of "
   1015 					   "%s.\n", dwarf_diename(sp_die));
   1016 				param->retval = -ENOENT;
   1017 				return DWARF_CB_ABORT;
   1018 			}
   1019 			pf->addr += pp->offset;
   1020 			/* TODO: Check the address in this function */
   1021 			param->retval = call_probe_finder(sp_die, pf);
   1022 		}
   1023 	} else
   1024 		/* Inlined function: search instances */
   1025 		param->retval = die_walk_instances(sp_die,
   1026 					probe_point_inline_cb, (void *)pf);
   1027 
   1028 	return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
   1029 }
   1030 
   1031 static int find_probe_point_by_func(struct probe_finder *pf)
   1032 {
   1033 	struct dwarf_callback_param _param = {.data = (void *)pf,
   1034 					      .retval = 0};
   1035 	dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
   1036 	return _param.retval;
   1037 }
   1038 
   1039 struct pubname_callback_param {
   1040 	char *function;
   1041 	char *file;
   1042 	Dwarf_Die *cu_die;
   1043 	Dwarf_Die *sp_die;
   1044 	int found;
   1045 };
   1046 
   1047 static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
   1048 {
   1049 	struct pubname_callback_param *param = data;
   1050 
   1051 	if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) {
   1052 		if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
   1053 			return DWARF_CB_OK;
   1054 
   1055 		if (die_compare_name(param->sp_die, param->function)) {
   1056 			if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
   1057 				return DWARF_CB_OK;
   1058 
   1059 			if (param->file &&
   1060 			    strtailcmp(param->file, dwarf_decl_file(param->sp_die)))
   1061 				return DWARF_CB_OK;
   1062 
   1063 			param->found = 1;
   1064 			return DWARF_CB_ABORT;
   1065 		}
   1066 	}
   1067 
   1068 	return DWARF_CB_OK;
   1069 }
   1070 
   1071 /* Find probe points from debuginfo */
   1072 static int debuginfo__find_probes(struct debuginfo *self,
   1073 				  struct probe_finder *pf)
   1074 {
   1075 	struct perf_probe_point *pp = &pf->pev->point;
   1076 	Dwarf_Off off, noff;
   1077 	size_t cuhl;
   1078 	Dwarf_Die *diep;
   1079 	int ret = 0;
   1080 
   1081 #if _ELFUTILS_PREREQ(0, 142)
   1082 	/* Get the call frame information from this dwarf */
   1083 	pf->cfi = dwarf_getcfi(self->dbg);
   1084 #endif
   1085 
   1086 	off = 0;
   1087 	line_list__init(&pf->lcache);
   1088 
   1089 	/* Fastpath: lookup by function name from .debug_pubnames section */
   1090 	if (pp->function) {
   1091 		struct pubname_callback_param pubname_param = {
   1092 			.function = pp->function,
   1093 			.file	  = pp->file,
   1094 			.cu_die	  = &pf->cu_die,
   1095 			.sp_die	  = &pf->sp_die,
   1096 			.found	  = 0,
   1097 		};
   1098 		struct dwarf_callback_param probe_param = {
   1099 			.data = pf,
   1100 		};
   1101 
   1102 		dwarf_getpubnames(self->dbg, pubname_search_cb,
   1103 				  &pubname_param, 0);
   1104 		if (pubname_param.found) {
   1105 			ret = probe_point_search_cb(&pf->sp_die, &probe_param);
   1106 			if (ret)
   1107 				goto found;
   1108 		}
   1109 	}
   1110 
   1111 	/* Loop on CUs (Compilation Unit) */
   1112 	while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
   1113 		/* Get the DIE(Debugging Information Entry) of this CU */
   1114 		diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die);
   1115 		if (!diep)
   1116 			continue;
   1117 
   1118 		/* Check if target file is included. */
   1119 		if (pp->file)
   1120 			pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
   1121 		else
   1122 			pf->fname = NULL;
   1123 
   1124 		if (!pp->file || pf->fname) {
   1125 			if (pp->function)
   1126 				ret = find_probe_point_by_func(pf);
   1127 			else if (pp->lazy_line)
   1128 				ret = find_probe_point_lazy(NULL, pf);
   1129 			else {
   1130 				pf->lno = pp->line;
   1131 				ret = find_probe_point_by_line(pf);
   1132 			}
   1133 			if (ret < 0)
   1134 				break;
   1135 		}
   1136 		off = noff;
   1137 	}
   1138 
   1139 found:
   1140 	line_list__free(&pf->lcache);
   1141 
   1142 	return ret;
   1143 }
   1144 
   1145 /* Add a found probe point into trace event list */
   1146 static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
   1147 {
   1148 	struct trace_event_finder *tf =
   1149 			container_of(pf, struct trace_event_finder, pf);
   1150 	struct probe_trace_event *tev;
   1151 	int ret, i;
   1152 
   1153 	/* Check number of tevs */
   1154 	if (tf->ntevs == tf->max_tevs) {
   1155 		pr_warning("Too many( > %d) probe point found.\n",
   1156 			   tf->max_tevs);
   1157 		return -ERANGE;
   1158 	}
   1159 	tev = &tf->tevs[tf->ntevs++];
   1160 
   1161 	/* Trace point should be converted from subprogram DIE */
   1162 	ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr,
   1163 				     pf->pev->point.retprobe, &tev->point);
   1164 	if (ret < 0)
   1165 		return ret;
   1166 
   1167 	pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
   1168 		 tev->point.offset);
   1169 
   1170 	/* Find each argument */
   1171 	tev->nargs = pf->pev->nargs;
   1172 	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
   1173 	if (tev->args == NULL)
   1174 		return -ENOMEM;
   1175 	for (i = 0; i < pf->pev->nargs; i++) {
   1176 		pf->pvar = &pf->pev->args[i];
   1177 		pf->tvar = &tev->args[i];
   1178 		/* Variable should be found from scope DIE */
   1179 		ret = find_variable(sc_die, pf);
   1180 		if (ret != 0)
   1181 			return ret;
   1182 	}
   1183 
   1184 	return 0;
   1185 }
   1186 
   1187 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
   1188 int debuginfo__find_trace_events(struct debuginfo *self,
   1189 				 struct perf_probe_event *pev,
   1190 				 struct probe_trace_event **tevs, int max_tevs)
   1191 {
   1192 	struct trace_event_finder tf = {
   1193 			.pf = {.pev = pev, .callback = add_probe_trace_event},
   1194 			.mod = self->mod, .max_tevs = max_tevs};
   1195 	int ret;
   1196 
   1197 	/* Allocate result tevs array */
   1198 	*tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
   1199 	if (*tevs == NULL)
   1200 		return -ENOMEM;
   1201 
   1202 	tf.tevs = *tevs;
   1203 	tf.ntevs = 0;
   1204 
   1205 	ret = debuginfo__find_probes(self, &tf.pf);
   1206 	if (ret < 0) {
   1207 		free(*tevs);
   1208 		*tevs = NULL;
   1209 		return ret;
   1210 	}
   1211 
   1212 	return (ret < 0) ? ret : tf.ntevs;
   1213 }
   1214 
   1215 #define MAX_VAR_LEN 64
   1216 
   1217 /* Collect available variables in this scope */
   1218 static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
   1219 {
   1220 	struct available_var_finder *af = data;
   1221 	struct variable_list *vl;
   1222 	char buf[MAX_VAR_LEN];
   1223 	int tag, ret;
   1224 
   1225 	vl = &af->vls[af->nvls - 1];
   1226 
   1227 	tag = dwarf_tag(die_mem);
   1228 	if (tag == DW_TAG_formal_parameter ||
   1229 	    tag == DW_TAG_variable) {
   1230 		ret = convert_variable_location(die_mem, af->pf.addr,
   1231 						af->pf.fb_ops, NULL);
   1232 		if (ret == 0) {
   1233 			ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
   1234 			pr_debug2("Add new var: %s\n", buf);
   1235 			if (ret > 0)
   1236 				strlist__add(vl->vars, buf);
   1237 		}
   1238 	}
   1239 
   1240 	if (af->child && dwarf_haspc(die_mem, af->pf.addr))
   1241 		return DIE_FIND_CB_CONTINUE;
   1242 	else
   1243 		return DIE_FIND_CB_SIBLING;
   1244 }
   1245 
   1246 /* Add a found vars into available variables list */
   1247 static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
   1248 {
   1249 	struct available_var_finder *af =
   1250 			container_of(pf, struct available_var_finder, pf);
   1251 	struct variable_list *vl;
   1252 	Dwarf_Die die_mem;
   1253 	int ret;
   1254 
   1255 	/* Check number of tevs */
   1256 	if (af->nvls == af->max_vls) {
   1257 		pr_warning("Too many( > %d) probe point found.\n", af->max_vls);
   1258 		return -ERANGE;
   1259 	}
   1260 	vl = &af->vls[af->nvls++];
   1261 
   1262 	/* Trace point should be converted from subprogram DIE */
   1263 	ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr,
   1264 				     pf->pev->point.retprobe, &vl->point);
   1265 	if (ret < 0)
   1266 		return ret;
   1267 
   1268 	pr_debug("Probe point found: %s+%lu\n", vl->point.symbol,
   1269 		 vl->point.offset);
   1270 
   1271 	/* Find local variables */
   1272 	vl->vars = strlist__new(true, NULL);
   1273 	if (vl->vars == NULL)
   1274 		return -ENOMEM;
   1275 	af->child = true;
   1276 	die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
   1277 
   1278 	/* Find external variables */
   1279 	if (!af->externs)
   1280 		goto out;
   1281 	/* Don't need to search child DIE for externs. */
   1282 	af->child = false;
   1283 	die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
   1284 
   1285 out:
   1286 	if (strlist__empty(vl->vars)) {
   1287 		strlist__delete(vl->vars);
   1288 		vl->vars = NULL;
   1289 	}
   1290 
   1291 	return ret;
   1292 }
   1293 
   1294 /* Find available variables at given probe point */
   1295 int debuginfo__find_available_vars_at(struct debuginfo *self,
   1296 				      struct perf_probe_event *pev,
   1297 				      struct variable_list **vls,
   1298 				      int max_vls, bool externs)
   1299 {
   1300 	struct available_var_finder af = {
   1301 			.pf = {.pev = pev, .callback = add_available_vars},
   1302 			.mod = self->mod,
   1303 			.max_vls = max_vls, .externs = externs};
   1304 	int ret;
   1305 
   1306 	/* Allocate result vls array */
   1307 	*vls = zalloc(sizeof(struct variable_list) * max_vls);
   1308 	if (*vls == NULL)
   1309 		return -ENOMEM;
   1310 
   1311 	af.vls = *vls;
   1312 	af.nvls = 0;
   1313 
   1314 	ret = debuginfo__find_probes(self, &af.pf);
   1315 	if (ret < 0) {
   1316 		/* Free vlist for error */
   1317 		while (af.nvls--) {
   1318 			if (af.vls[af.nvls].point.symbol)
   1319 				free(af.vls[af.nvls].point.symbol);
   1320 			if (af.vls[af.nvls].vars)
   1321 				strlist__delete(af.vls[af.nvls].vars);
   1322 		}
   1323 		free(af.vls);
   1324 		*vls = NULL;
   1325 		return ret;
   1326 	}
   1327 
   1328 	return (ret < 0) ? ret : af.nvls;
   1329 }
   1330 
   1331 /* Reverse search */
   1332 int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
   1333 				struct perf_probe_point *ppt)
   1334 {
   1335 	Dwarf_Die cudie, spdie, indie;
   1336 	Dwarf_Addr _addr = 0, baseaddr = 0;
   1337 	const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
   1338 	int baseline = 0, lineno = 0, ret = 0;
   1339 
   1340 	/* Adjust address with bias */
   1341 	addr += self->bias;
   1342 
   1343 	/* Find cu die */
   1344 	if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) {
   1345 		pr_warning("Failed to find debug information for address %lx\n",
   1346 			   addr);
   1347 		ret = -EINVAL;
   1348 		goto end;
   1349 	}
   1350 
   1351 	/* Find a corresponding line (filename and lineno) */
   1352 	cu_find_lineinfo(&cudie, addr, &fname, &lineno);
   1353 	/* Don't care whether it failed or not */
   1354 
   1355 	/* Find a corresponding function (name, baseline and baseaddr) */
   1356 	if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
   1357 		/* Get function entry information */
   1358 		func = basefunc = dwarf_diename(&spdie);
   1359 		if (!func ||
   1360 		    dwarf_entrypc(&spdie, &baseaddr) != 0 ||
   1361 		    dwarf_decl_line(&spdie, &baseline) != 0) {
   1362 			lineno = 0;
   1363 			goto post;
   1364 		}
   1365 
   1366 		fname = dwarf_decl_file(&spdie);
   1367 		if (addr == (unsigned long)baseaddr) {
   1368 			/* Function entry - Relative line number is 0 */
   1369 			lineno = baseline;
   1370 			goto post;
   1371 		}
   1372 
   1373 		/* Track down the inline functions step by step */
   1374 		while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr,
   1375 						&indie)) {
   1376 			/* There is an inline function */
   1377 			if (dwarf_entrypc(&indie, &_addr) == 0 &&
   1378 			    _addr == addr) {
   1379 				/*
   1380 				 * addr is at an inline function entry.
   1381 				 * In this case, lineno should be the call-site
   1382 				 * line number. (overwrite lineinfo)
   1383 				 */
   1384 				lineno = die_get_call_lineno(&indie);
   1385 				fname = die_get_call_file(&indie);
   1386 				break;
   1387 			} else {
   1388 				/*
   1389 				 * addr is in an inline function body.
   1390 				 * Since lineno points one of the lines
   1391 				 * of the inline function, baseline should
   1392 				 * be the entry line of the inline function.
   1393 				 */
   1394 				tmp = dwarf_diename(&indie);
   1395 				if (!tmp ||
   1396 				    dwarf_decl_line(&indie, &baseline) != 0)
   1397 					break;
   1398 				func = tmp;
   1399 				spdie = indie;
   1400 			}
   1401 		}
   1402 		/* Verify the lineno and baseline are in a same file */
   1403 		tmp = dwarf_decl_file(&spdie);
   1404 		if (!tmp || strcmp(tmp, fname) != 0)
   1405 			lineno = 0;
   1406 	}
   1407 
   1408 post:
   1409 	/* Make a relative line number or an offset */
   1410 	if (lineno)
   1411 		ppt->line = lineno - baseline;
   1412 	else if (basefunc) {
   1413 		ppt->offset = addr - (unsigned long)baseaddr;
   1414 		func = basefunc;
   1415 	}
   1416 
   1417 	/* Duplicate strings */
   1418 	if (func) {
   1419 		ppt->function = strdup(func);
   1420 		if (ppt->function == NULL) {
   1421 			ret = -ENOMEM;
   1422 			goto end;
   1423 		}
   1424 	}
   1425 	if (fname) {
   1426 		ppt->file = strdup(fname);
   1427 		if (ppt->file == NULL) {
   1428 			if (ppt->function) {
   1429 				free(ppt->function);
   1430 				ppt->function = NULL;
   1431 			}
   1432 			ret = -ENOMEM;
   1433 			goto end;
   1434 		}
   1435 	}
   1436 end:
   1437 	if (ret == 0 && (fname || func))
   1438 		ret = 1;	/* Found a point */
   1439 	return ret;
   1440 }
   1441 
   1442 /* Add a line and store the src path */
   1443 static int line_range_add_line(const char *src, unsigned int lineno,
   1444 			       struct line_range *lr)
   1445 {
   1446 	/* Copy source path */
   1447 	if (!lr->path) {
   1448 		lr->path = strdup(src);
   1449 		if (lr->path == NULL)
   1450 			return -ENOMEM;
   1451 	}
   1452 	return line_list__add_line(&lr->line_list, lineno);
   1453 }
   1454 
   1455 static int line_range_walk_cb(const char *fname, int lineno,
   1456 			      Dwarf_Addr addr __maybe_unused,
   1457 			      void *data)
   1458 {
   1459 	struct line_finder *lf = data;
   1460 
   1461 	if ((strtailcmp(fname, lf->fname) != 0) ||
   1462 	    (lf->lno_s > lineno || lf->lno_e < lineno))
   1463 		return 0;
   1464 
   1465 	if (line_range_add_line(fname, lineno, lf->lr) < 0)
   1466 		return -EINVAL;
   1467 
   1468 	return 0;
   1469 }
   1470 
   1471 /* Find line range from its line number */
   1472 static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
   1473 {
   1474 	int ret;
   1475 
   1476 	ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf);
   1477 
   1478 	/* Update status */
   1479 	if (ret >= 0)
   1480 		if (!list_empty(&lf->lr->line_list))
   1481 			ret = lf->found = 1;
   1482 		else
   1483 			ret = 0;	/* Lines are not found */
   1484 	else {
   1485 		free(lf->lr->path);
   1486 		lf->lr->path = NULL;
   1487 	}
   1488 	return ret;
   1489 }
   1490 
   1491 static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
   1492 {
   1493 	find_line_range_by_line(in_die, data);
   1494 
   1495 	/*
   1496 	 * We have to check all instances of inlined function, because
   1497 	 * some execution paths can be optimized out depends on the
   1498 	 * function argument of instances
   1499 	 */
   1500 	return 0;
   1501 }
   1502 
   1503 /* Search function definition from function name */
   1504 static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
   1505 {
   1506 	struct dwarf_callback_param *param = data;
   1507 	struct line_finder *lf = param->data;
   1508 	struct line_range *lr = lf->lr;
   1509 
   1510 	/* Check declared file */
   1511 	if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
   1512 		return DWARF_CB_OK;
   1513 
   1514 	if (die_is_func_def(sp_die) &&
   1515 	    die_compare_name(sp_die, lr->function)) {
   1516 		lf->fname = dwarf_decl_file(sp_die);
   1517 		dwarf_decl_line(sp_die, &lr->offset);
   1518 		pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
   1519 		lf->lno_s = lr->offset + lr->start;
   1520 		if (lf->lno_s < 0)	/* Overflow */
   1521 			lf->lno_s = INT_MAX;
   1522 		lf->lno_e = lr->offset + lr->end;
   1523 		if (lf->lno_e < 0)	/* Overflow */
   1524 			lf->lno_e = INT_MAX;
   1525 		pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
   1526 		lr->start = lf->lno_s;
   1527 		lr->end = lf->lno_e;
   1528 		if (dwarf_func_inline(sp_die))
   1529 			param->retval = die_walk_instances(sp_die,
   1530 						line_range_inline_cb, lf);
   1531 		else
   1532 			param->retval = find_line_range_by_line(sp_die, lf);
   1533 		return DWARF_CB_ABORT;
   1534 	}
   1535 	return DWARF_CB_OK;
   1536 }
   1537 
   1538 static int find_line_range_by_func(struct line_finder *lf)
   1539 {
   1540 	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
   1541 	dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
   1542 	return param.retval;
   1543 }
   1544 
   1545 int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
   1546 {
   1547 	struct line_finder lf = {.lr = lr, .found = 0};
   1548 	int ret = 0;
   1549 	Dwarf_Off off = 0, noff;
   1550 	size_t cuhl;
   1551 	Dwarf_Die *diep;
   1552 	const char *comp_dir;
   1553 
   1554 	/* Fastpath: lookup by function name from .debug_pubnames section */
   1555 	if (lr->function) {
   1556 		struct pubname_callback_param pubname_param = {
   1557 			.function = lr->function, .file = lr->file,
   1558 			.cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0};
   1559 		struct dwarf_callback_param line_range_param = {
   1560 			.data = (void *)&lf, .retval = 0};
   1561 
   1562 		dwarf_getpubnames(self->dbg, pubname_search_cb,
   1563 				  &pubname_param, 0);
   1564 		if (pubname_param.found) {
   1565 			line_range_search_cb(&lf.sp_die, &line_range_param);
   1566 			if (lf.found)
   1567 				goto found;
   1568 		}
   1569 	}
   1570 
   1571 	/* Loop on CUs (Compilation Unit) */
   1572 	while (!lf.found && ret >= 0) {
   1573 		if (dwarf_nextcu(self->dbg, off, &noff, &cuhl,
   1574 				 NULL, NULL, NULL) != 0)
   1575 			break;
   1576 
   1577 		/* Get the DIE(Debugging Information Entry) of this CU */
   1578 		diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die);
   1579 		if (!diep)
   1580 			continue;
   1581 
   1582 		/* Check if target file is included. */
   1583 		if (lr->file)
   1584 			lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
   1585 		else
   1586 			lf.fname = 0;
   1587 
   1588 		if (!lr->file || lf.fname) {
   1589 			if (lr->function)
   1590 				ret = find_line_range_by_func(&lf);
   1591 			else {
   1592 				lf.lno_s = lr->start;
   1593 				lf.lno_e = lr->end;
   1594 				ret = find_line_range_by_line(NULL, &lf);
   1595 			}
   1596 		}
   1597 		off = noff;
   1598 	}
   1599 
   1600 found:
   1601 	/* Store comp_dir */
   1602 	if (lf.found) {
   1603 		comp_dir = cu_get_comp_dir(&lf.cu_die);
   1604 		if (comp_dir) {
   1605 			lr->comp_dir = strdup(comp_dir);
   1606 			if (!lr->comp_dir)
   1607 				ret = -ENOMEM;
   1608 		}
   1609 	}
   1610 
   1611 	pr_debug("path: %s\n", lr->path);
   1612 	return (ret < 0) ? ret : lf.found;
   1613 }
   1614 
   1615