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