Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[pandora-kernel.git] / tools / perf / util / probe-finder.c
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