xref: /openbmc/linux/tools/perf/util/probe-finder.c (revision 7dd65feb)
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 <ctype.h>
34 
35 #include "event.h"
36 #include "debug.h"
37 #include "util.h"
38 #include "probe-finder.h"
39 
40 
41 /* Dwarf_Die Linkage to parent Die */
42 struct die_link {
43 	struct die_link *parent;	/* Parent die */
44 	Dwarf_Die die;			/* Current die */
45 };
46 
47 static Dwarf_Debug __dw_debug;
48 static Dwarf_Error __dw_error;
49 
50 /*
51  * Generic dwarf analysis helpers
52  */
53 
54 #define X86_32_MAX_REGS 8
55 const char *x86_32_regs_table[X86_32_MAX_REGS] = {
56 	"%ax",
57 	"%cx",
58 	"%dx",
59 	"%bx",
60 	"$stack",	/* Stack address instead of %sp */
61 	"%bp",
62 	"%si",
63 	"%di",
64 };
65 
66 #define X86_64_MAX_REGS 16
67 const char *x86_64_regs_table[X86_64_MAX_REGS] = {
68 	"%ax",
69 	"%dx",
70 	"%cx",
71 	"%bx",
72 	"%si",
73 	"%di",
74 	"%bp",
75 	"%sp",
76 	"%r8",
77 	"%r9",
78 	"%r10",
79 	"%r11",
80 	"%r12",
81 	"%r13",
82 	"%r14",
83 	"%r15",
84 };
85 
86 /* TODO: switching by dwarf address size */
87 #ifdef __x86_64__
88 #define ARCH_MAX_REGS X86_64_MAX_REGS
89 #define arch_regs_table x86_64_regs_table
90 #else
91 #define ARCH_MAX_REGS X86_32_MAX_REGS
92 #define arch_regs_table x86_32_regs_table
93 #endif
94 
95 /* Return architecture dependent register string (for kprobe-tracer) */
96 static const char *get_arch_regstr(unsigned int n)
97 {
98 	return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
99 }
100 
101 /*
102  * Compare the tail of two strings.
103  * Return 0 if whole of either string is same as another's tail part.
104  */
105 static int strtailcmp(const char *s1, const char *s2)
106 {
107 	int i1 = strlen(s1);
108 	int i2 = strlen(s2);
109 	while (--i1 >= 0 && --i2 >= 0) {
110 		if (s1[i1] != s2[i2])
111 			return s1[i1] - s2[i2];
112 	}
113 	return 0;
114 }
115 
116 /* Find the fileno of the target file. */
117 static Dwarf_Unsigned cu_find_fileno(Dwarf_Die cu_die, const char *fname)
118 {
119 	Dwarf_Signed cnt, i;
120 	Dwarf_Unsigned found = 0;
121 	char **srcs;
122 	int ret;
123 
124 	if (!fname)
125 		return 0;
126 
127 	ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error);
128 	if (ret == DW_DLV_OK) {
129 		for (i = 0; i < cnt && !found; i++) {
130 			if (strtailcmp(srcs[i], fname) == 0)
131 				found = i + 1;
132 			dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
133 		}
134 		for (; i < cnt; i++)
135 			dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
136 		dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST);
137 	}
138 	if (found)
139 		pr_debug("found fno: %d\n", (int)found);
140 	return found;
141 }
142 
143 /* Compare diename and tname */
144 static int die_compare_name(Dwarf_Die dw_die, const char *tname)
145 {
146 	char *name;
147 	int ret;
148 	ret = dwarf_diename(dw_die, &name, &__dw_error);
149 	DIE_IF(ret == DW_DLV_ERROR);
150 	if (ret == DW_DLV_OK) {
151 		ret = strcmp(tname, name);
152 		dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
153 	} else
154 		ret = -1;
155 	return ret;
156 }
157 
158 /* Check the address is in the subprogram(function). */
159 static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr,
160 				 Dwarf_Signed *offs)
161 {
162 	Dwarf_Addr lopc, hipc;
163 	int ret;
164 
165 	/* TODO: check ranges */
166 	ret = dwarf_lowpc(sp_die, &lopc, &__dw_error);
167 	DIE_IF(ret == DW_DLV_ERROR);
168 	if (ret == DW_DLV_NO_ENTRY)
169 		return 0;
170 	ret = dwarf_highpc(sp_die, &hipc, &__dw_error);
171 	DIE_IF(ret != DW_DLV_OK);
172 	if (lopc <= addr && addr < hipc) {
173 		*offs = addr - lopc;
174 		return 1;
175 	} else
176 		return 0;
177 }
178 
179 /* Check the die is inlined function */
180 static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die)
181 {
182 	/* TODO: check strictly */
183 	Dwarf_Bool inl;
184 	int ret;
185 
186 	ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error);
187 	DIE_IF(ret == DW_DLV_ERROR);
188 	return inl;
189 }
190 
191 /* Get the offset of abstruct_origin */
192 static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die)
193 {
194 	Dwarf_Attribute attr;
195 	Dwarf_Off cu_offs;
196 	int ret;
197 
198 	ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error);
199 	DIE_IF(ret != DW_DLV_OK);
200 	ret = dwarf_formref(attr, &cu_offs, &__dw_error);
201 	DIE_IF(ret != DW_DLV_OK);
202 	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
203 	return cu_offs;
204 }
205 
206 /* Get entry pc(or low pc, 1st entry of ranges)  of the die */
207 static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die)
208 {
209 	Dwarf_Attribute attr;
210 	Dwarf_Addr addr;
211 	Dwarf_Off offs;
212 	Dwarf_Ranges *ranges;
213 	Dwarf_Signed cnt;
214 	int ret;
215 
216 	/* Try to get entry pc */
217 	ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error);
218 	DIE_IF(ret == DW_DLV_ERROR);
219 	if (ret == DW_DLV_OK) {
220 		ret = dwarf_formaddr(attr, &addr, &__dw_error);
221 		DIE_IF(ret != DW_DLV_OK);
222 		dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
223 		return addr;
224 	}
225 
226 	/* Try to get low pc */
227 	ret = dwarf_lowpc(dw_die, &addr, &__dw_error);
228 	DIE_IF(ret == DW_DLV_ERROR);
229 	if (ret == DW_DLV_OK)
230 		return addr;
231 
232 	/* Try to get ranges */
233 	ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error);
234 	DIE_IF(ret != DW_DLV_OK);
235 	ret = dwarf_formref(attr, &offs, &__dw_error);
236 	DIE_IF(ret != DW_DLV_OK);
237 	ret = dwarf_get_ranges(__dw_debug, offs, &ranges, &cnt, NULL,
238 				&__dw_error);
239 	DIE_IF(ret != DW_DLV_OK);
240 	addr = ranges[0].dwr_addr1;
241 	dwarf_ranges_dealloc(__dw_debug, ranges, cnt);
242 	return addr;
243 }
244 
245 /*
246  * Search a Die from Die tree.
247  * Note: cur_link->die should be deallocated in this function.
248  */
249 static int __search_die_tree(struct die_link *cur_link,
250 			     int (*die_cb)(struct die_link *, void *),
251 			     void *data)
252 {
253 	Dwarf_Die new_die;
254 	struct die_link new_link;
255 	int ret;
256 
257 	if (!die_cb)
258 		return 0;
259 
260 	/* Check current die */
261 	while (!(ret = die_cb(cur_link, data))) {
262 		/* Check child die */
263 		ret = dwarf_child(cur_link->die, &new_die, &__dw_error);
264 		DIE_IF(ret == DW_DLV_ERROR);
265 		if (ret == DW_DLV_OK) {
266 			new_link.parent = cur_link;
267 			new_link.die = new_die;
268 			ret = __search_die_tree(&new_link, die_cb, data);
269 			if (ret)
270 				break;
271 		}
272 
273 		/* Move to next sibling */
274 		ret = dwarf_siblingof(__dw_debug, cur_link->die, &new_die,
275 				      &__dw_error);
276 		DIE_IF(ret == DW_DLV_ERROR);
277 		dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
278 		cur_link->die = new_die;
279 		if (ret == DW_DLV_NO_ENTRY)
280 			return 0;
281 	}
282 	dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
283 	return ret;
284 }
285 
286 /* Search a die in its children's die tree */
287 static int search_die_from_children(Dwarf_Die parent_die,
288 				    int (*die_cb)(struct die_link *, void *),
289 				    void *data)
290 {
291 	struct die_link new_link;
292 	int ret;
293 
294 	new_link.parent = NULL;
295 	ret = dwarf_child(parent_die, &new_link.die, &__dw_error);
296 	DIE_IF(ret == DW_DLV_ERROR);
297 	if (ret == DW_DLV_OK)
298 		return __search_die_tree(&new_link, die_cb, data);
299 	else
300 		return 0;
301 }
302 
303 /* Find a locdesc corresponding to the address */
304 static int attr_get_locdesc(Dwarf_Attribute attr, Dwarf_Locdesc *desc,
305 			    Dwarf_Addr addr)
306 {
307 	Dwarf_Signed lcnt;
308 	Dwarf_Locdesc **llbuf;
309 	int ret, i;
310 
311 	ret = dwarf_loclist_n(attr, &llbuf, &lcnt, &__dw_error);
312 	DIE_IF(ret != DW_DLV_OK);
313 	ret = DW_DLV_NO_ENTRY;
314 	for (i = 0; i < lcnt; ++i) {
315 		if (llbuf[i]->ld_lopc <= addr &&
316 		    llbuf[i]->ld_hipc > addr) {
317 			memcpy(desc, llbuf[i], sizeof(Dwarf_Locdesc));
318 			desc->ld_s =
319 				malloc(sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
320 			DIE_IF(desc->ld_s == NULL);
321 			memcpy(desc->ld_s, llbuf[i]->ld_s,
322 				sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
323 			ret = DW_DLV_OK;
324 			break;
325 		}
326 		dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
327 		dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
328 	}
329 	/* Releasing loop */
330 	for (; i < lcnt; ++i) {
331 		dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
332 		dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
333 	}
334 	dwarf_dealloc(__dw_debug, llbuf, DW_DLA_LIST);
335 	return ret;
336 }
337 
338 /* Get decl_file attribute value (file number) */
339 static Dwarf_Unsigned die_get_decl_file(Dwarf_Die sp_die)
340 {
341 	Dwarf_Attribute attr;
342 	Dwarf_Unsigned fno;
343 	int ret;
344 
345 	ret = dwarf_attr(sp_die, DW_AT_decl_file, &attr, &__dw_error);
346 	DIE_IF(ret != DW_DLV_OK);
347 	dwarf_formudata(attr, &fno, &__dw_error);
348 	DIE_IF(ret != DW_DLV_OK);
349 	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
350 	return fno;
351 }
352 
353 /* Get decl_line attribute value (line number) */
354 static Dwarf_Unsigned die_get_decl_line(Dwarf_Die sp_die)
355 {
356 	Dwarf_Attribute attr;
357 	Dwarf_Unsigned lno;
358 	int ret;
359 
360 	ret = dwarf_attr(sp_die, DW_AT_decl_line, &attr, &__dw_error);
361 	DIE_IF(ret != DW_DLV_OK);
362 	dwarf_formudata(attr, &lno, &__dw_error);
363 	DIE_IF(ret != DW_DLV_OK);
364 	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
365 	return lno;
366 }
367 
368 /*
369  * Probe finder related functions
370  */
371 
372 /* Show a location */
373 static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
374 {
375 	Dwarf_Small op;
376 	Dwarf_Unsigned regn;
377 	Dwarf_Signed offs;
378 	int deref = 0, ret;
379 	const char *regs;
380 
381 	op = loc->lr_atom;
382 
383 	/* If this is based on frame buffer, set the offset */
384 	if (op == DW_OP_fbreg) {
385 		deref = 1;
386 		offs = (Dwarf_Signed)loc->lr_number;
387 		op = pf->fbloc.ld_s[0].lr_atom;
388 		loc = &pf->fbloc.ld_s[0];
389 	} else
390 		offs = 0;
391 
392 	if (op >= DW_OP_breg0 && op <= DW_OP_breg31) {
393 		regn = op - DW_OP_breg0;
394 		offs += (Dwarf_Signed)loc->lr_number;
395 		deref = 1;
396 	} else if (op >= DW_OP_reg0 && op <= DW_OP_reg31) {
397 		regn = op - DW_OP_reg0;
398 	} else if (op == DW_OP_bregx) {
399 		regn = loc->lr_number;
400 		offs += (Dwarf_Signed)loc->lr_number2;
401 		deref = 1;
402 	} else if (op == DW_OP_regx) {
403 		regn = loc->lr_number;
404 	} else
405 		die("Dwarf_OP %d is not supported.\n", op);
406 
407 	regs = get_arch_regstr(regn);
408 	if (!regs)
409 		die("%lld exceeds max register number.\n", regn);
410 
411 	if (deref)
412 		ret = snprintf(pf->buf, pf->len,
413 				 " %s=%+lld(%s)", pf->var, offs, regs);
414 	else
415 		ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
416 	DIE_IF(ret < 0);
417 	DIE_IF(ret >= pf->len);
418 }
419 
420 /* Show a variables in kprobe event format */
421 static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf)
422 {
423 	Dwarf_Attribute attr;
424 	Dwarf_Locdesc ld;
425 	int ret;
426 
427 	ret = dwarf_attr(vr_die, DW_AT_location, &attr, &__dw_error);
428 	if (ret != DW_DLV_OK)
429 		goto error;
430 	ret = attr_get_locdesc(attr, &ld, (pf->addr - pf->cu_base));
431 	if (ret != DW_DLV_OK)
432 		goto error;
433 	/* TODO? */
434 	DIE_IF(ld.ld_cents != 1);
435 	show_location(&ld.ld_s[0], pf);
436 	free(ld.ld_s);
437 	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
438 	return ;
439 error:
440 	die("Failed to find the location of %s at this address.\n"
441 	    " Perhaps, it has been optimized out.\n", pf->var);
442 }
443 
444 static int variable_callback(struct die_link *dlink, void *data)
445 {
446 	struct probe_finder *pf = (struct probe_finder *)data;
447 	Dwarf_Half tag;
448 	int ret;
449 
450 	ret = dwarf_tag(dlink->die, &tag, &__dw_error);
451 	DIE_IF(ret == DW_DLV_ERROR);
452 	if ((tag == DW_TAG_formal_parameter ||
453 	     tag == DW_TAG_variable) &&
454 	    (die_compare_name(dlink->die, pf->var) == 0)) {
455 		show_variable(dlink->die, pf);
456 		return 1;
457 	}
458 	/* TODO: Support struct members and arrays */
459 	return 0;
460 }
461 
462 /* Find a variable in a subprogram die */
463 static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
464 {
465 	int ret;
466 
467 	if (!is_c_varname(pf->var)) {
468 		/* Output raw parameters */
469 		ret = snprintf(pf->buf, pf->len, " %s", pf->var);
470 		DIE_IF(ret < 0);
471 		DIE_IF(ret >= pf->len);
472 		return ;
473 	}
474 
475 	pr_debug("Searching '%s' variable in context.\n", pf->var);
476 	/* Search child die for local variables and parameters. */
477 	ret = search_die_from_children(sp_die, variable_callback, pf);
478 	if (!ret)
479 		die("Failed to find '%s' in this function.\n", pf->var);
480 }
481 
482 /* Get a frame base on the address */
483 static void get_current_frame_base(Dwarf_Die sp_die, struct probe_finder *pf)
484 {
485 	Dwarf_Attribute attr;
486 	int ret;
487 
488 	ret = dwarf_attr(sp_die, DW_AT_frame_base, &attr, &__dw_error);
489 	DIE_IF(ret != DW_DLV_OK);
490 	ret = attr_get_locdesc(attr, &pf->fbloc, (pf->addr - pf->cu_base));
491 	DIE_IF(ret != DW_DLV_OK);
492 	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
493 }
494 
495 static void free_current_frame_base(struct probe_finder *pf)
496 {
497 	free(pf->fbloc.ld_s);
498 	memset(&pf->fbloc, 0, sizeof(Dwarf_Locdesc));
499 }
500 
501 /* Show a probe point to output buffer */
502 static void show_probepoint(Dwarf_Die sp_die, Dwarf_Signed offs,
503 			    struct probe_finder *pf)
504 {
505 	struct probe_point *pp = pf->pp;
506 	char *name;
507 	char tmp[MAX_PROBE_BUFFER];
508 	int ret, i, len;
509 
510 	/* Output name of probe point */
511 	ret = dwarf_diename(sp_die, &name, &__dw_error);
512 	DIE_IF(ret == DW_DLV_ERROR);
513 	if (ret == DW_DLV_OK) {
514 		ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name,
515 				(unsigned int)offs);
516 		/* Copy the function name if possible */
517 		if (!pp->function) {
518 			pp->function = strdup(name);
519 			pp->offset = offs;
520 		}
521 		dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
522 	} else {
523 		/* This function has no name. */
524 		ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%llx", pf->addr);
525 		if (!pp->function) {
526 			/* TODO: Use _stext */
527 			pp->function = strdup("");
528 			pp->offset = (int)pf->addr;
529 		}
530 	}
531 	DIE_IF(ret < 0);
532 	DIE_IF(ret >= MAX_PROBE_BUFFER);
533 	len = ret;
534 	pr_debug("Probe point found: %s\n", tmp);
535 
536 	/* Find each argument */
537 	get_current_frame_base(sp_die, pf);
538 	for (i = 0; i < pp->nr_args; i++) {
539 		pf->var = pp->args[i];
540 		pf->buf = &tmp[len];
541 		pf->len = MAX_PROBE_BUFFER - len;
542 		find_variable(sp_die, pf);
543 		len += strlen(pf->buf);
544 	}
545 	free_current_frame_base(pf);
546 
547 	pp->probes[pp->found] = strdup(tmp);
548 	pp->found++;
549 }
550 
551 static int probeaddr_callback(struct die_link *dlink, void *data)
552 {
553 	struct probe_finder *pf = (struct probe_finder *)data;
554 	Dwarf_Half tag;
555 	Dwarf_Signed offs;
556 	int ret;
557 
558 	ret = dwarf_tag(dlink->die, &tag, &__dw_error);
559 	DIE_IF(ret == DW_DLV_ERROR);
560 	/* Check the address is in this subprogram */
561 	if (tag == DW_TAG_subprogram &&
562 	    die_within_subprogram(dlink->die, pf->addr, &offs)) {
563 		show_probepoint(dlink->die, offs, pf);
564 		return 1;
565 	}
566 	return 0;
567 }
568 
569 /* Find probe point from its line number */
570 static void find_by_line(struct probe_finder *pf)
571 {
572 	Dwarf_Signed cnt, i, clm;
573 	Dwarf_Line *lines;
574 	Dwarf_Unsigned lineno = 0;
575 	Dwarf_Addr addr;
576 	Dwarf_Unsigned fno;
577 	int ret;
578 
579 	ret = dwarf_srclines(pf->cu_die, &lines, &cnt, &__dw_error);
580 	DIE_IF(ret != DW_DLV_OK);
581 
582 	for (i = 0; i < cnt; i++) {
583 		ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
584 		DIE_IF(ret != DW_DLV_OK);
585 		if (fno != pf->fno)
586 			continue;
587 
588 		ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
589 		DIE_IF(ret != DW_DLV_OK);
590 		if (lineno != pf->lno)
591 			continue;
592 
593 		ret = dwarf_lineoff(lines[i], &clm, &__dw_error);
594 		DIE_IF(ret != DW_DLV_OK);
595 
596 		ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
597 		DIE_IF(ret != DW_DLV_OK);
598 		pr_debug("Probe line found: line[%d]:%u,%d addr:0x%llx\n",
599 			 (int)i, (unsigned)lineno, (int)clm, addr);
600 		pf->addr = addr;
601 		/* Search a real subprogram including this line, */
602 		ret = search_die_from_children(pf->cu_die,
603 					       probeaddr_callback, pf);
604 		if (ret == 0)
605 			die("Probe point is not found in subprograms.\n");
606 		/* Continuing, because target line might be inlined. */
607 	}
608 	dwarf_srclines_dealloc(__dw_debug, lines, cnt);
609 }
610 
611 /* Search function from function name */
612 static int probefunc_callback(struct die_link *dlink, void *data)
613 {
614 	struct probe_finder *pf = (struct probe_finder *)data;
615 	struct probe_point *pp = pf->pp;
616 	struct die_link *lk;
617 	Dwarf_Signed offs;
618 	Dwarf_Half tag;
619 	int ret;
620 
621 	ret = dwarf_tag(dlink->die, &tag, &__dw_error);
622 	DIE_IF(ret == DW_DLV_ERROR);
623 	if (tag == DW_TAG_subprogram) {
624 		if (die_compare_name(dlink->die, pp->function) == 0) {
625 			if (pp->line) {	/* Function relative line */
626 				pf->fno = die_get_decl_file(dlink->die);
627 				pf->lno = die_get_decl_line(dlink->die)
628 					 + pp->line;
629 				find_by_line(pf);
630 				return 1;
631 			}
632 			if (die_inlined_subprogram(dlink->die)) {
633 				/* Inlined function, save it. */
634 				ret = dwarf_die_CU_offset(dlink->die,
635 							  &pf->inl_offs,
636 							  &__dw_error);
637 				DIE_IF(ret != DW_DLV_OK);
638 				pr_debug("inline definition offset %lld\n",
639 					 pf->inl_offs);
640 				return 0;	/* Continue to search */
641 			}
642 			/* Get probe address */
643 			pf->addr = die_get_entrypc(dlink->die);
644 			pf->addr += pp->offset;
645 			/* TODO: Check the address in this function */
646 			show_probepoint(dlink->die, pp->offset, pf);
647 			return 1; /* Exit; no same symbol in this CU. */
648 		}
649 	} else if (tag == DW_TAG_inlined_subroutine && pf->inl_offs) {
650 		if (die_get_abstract_origin(dlink->die) == pf->inl_offs) {
651 			/* Get probe address */
652 			pf->addr = die_get_entrypc(dlink->die);
653 			pf->addr += pp->offset;
654 			pr_debug("found inline addr: 0x%llx\n", pf->addr);
655 			/* Inlined function. Get a real subprogram */
656 			for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
657 				tag = 0;
658 				dwarf_tag(lk->die, &tag, &__dw_error);
659 				DIE_IF(ret == DW_DLV_ERROR);
660 				if (tag == DW_TAG_subprogram &&
661 				    !die_inlined_subprogram(lk->die))
662 					goto found;
663 			}
664 			die("Failed to find real subprogram.\n");
665 found:
666 			/* Get offset from subprogram */
667 			ret = die_within_subprogram(lk->die, pf->addr, &offs);
668 			DIE_IF(!ret);
669 			show_probepoint(lk->die, offs, pf);
670 			/* Continue to search */
671 		}
672 	}
673 	return 0;
674 }
675 
676 static void find_by_func(struct probe_finder *pf)
677 {
678 	search_die_from_children(pf->cu_die, probefunc_callback, pf);
679 }
680 
681 /* Find a probe point */
682 int find_probepoint(int fd, struct probe_point *pp)
683 {
684 	Dwarf_Half addr_size = 0;
685 	Dwarf_Unsigned next_cuh = 0;
686 	int cu_number = 0, ret;
687 	struct probe_finder pf = {.pp = pp};
688 
689 	ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
690 	if (ret != DW_DLV_OK)
691 		return -ENOENT;
692 
693 	pp->found = 0;
694 	while (++cu_number) {
695 		/* Search CU (Compilation Unit) */
696 		ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
697 			&addr_size, &next_cuh, &__dw_error);
698 		DIE_IF(ret == DW_DLV_ERROR);
699 		if (ret == DW_DLV_NO_ENTRY)
700 			break;
701 
702 		/* Get the DIE(Debugging Information Entry) of this CU */
703 		ret = dwarf_siblingof(__dw_debug, 0, &pf.cu_die, &__dw_error);
704 		DIE_IF(ret != DW_DLV_OK);
705 
706 		/* Check if target file is included. */
707 		if (pp->file)
708 			pf.fno = cu_find_fileno(pf.cu_die, pp->file);
709 
710 		if (!pp->file || pf.fno) {
711 			/* Save CU base address (for frame_base) */
712 			ret = dwarf_lowpc(pf.cu_die, &pf.cu_base, &__dw_error);
713 			DIE_IF(ret == DW_DLV_ERROR);
714 			if (ret == DW_DLV_NO_ENTRY)
715 				pf.cu_base = 0;
716 			if (pp->function)
717 				find_by_func(&pf);
718 			else {
719 				pf.lno = pp->line;
720 				find_by_line(&pf);
721 			}
722 		}
723 		dwarf_dealloc(__dw_debug, pf.cu_die, DW_DLA_DIE);
724 	}
725 	ret = dwarf_finish(__dw_debug, &__dw_error);
726 	DIE_IF(ret != DW_DLV_OK);
727 
728 	return pp->found;
729 }
730 
731