c819fd59da9e1a607bbd90af00060abd97463308
[safe/jmp/linux-2.6] / 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 static int cu_get_filename(Dwarf_Die cu_die, Dwarf_Unsigned fno, char **buf)
144 {
145         Dwarf_Signed cnt, i;
146         char **srcs;
147         int ret = 0;
148
149         if (!buf || !fno)
150                 return -EINVAL;
151
152         ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error);
153         if (ret == DW_DLV_OK) {
154                 if ((Dwarf_Unsigned)cnt > fno - 1) {
155                         *buf = strdup(srcs[fno - 1]);
156                         ret = 0;
157                         pr_debug("found filename: %s\n", *buf);
158                 } else
159                         ret = -ENOENT;
160                 for (i = 0; i < cnt; i++)
161                         dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
162                 dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST);
163         } else
164                 ret = -EINVAL;
165         return ret;
166 }
167
168 /* Compare diename and tname */
169 static int die_compare_name(Dwarf_Die dw_die, const char *tname)
170 {
171         char *name;
172         int ret;
173         ret = dwarf_diename(dw_die, &name, &__dw_error);
174         DIE_IF(ret == DW_DLV_ERROR);
175         if (ret == DW_DLV_OK) {
176                 ret = strcmp(tname, name);
177                 dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
178         } else
179                 ret = -1;
180         return ret;
181 }
182
183 /* Check the address is in the subprogram(function). */
184 static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr,
185                                  Dwarf_Signed *offs)
186 {
187         Dwarf_Addr lopc, hipc;
188         int ret;
189
190         /* TODO: check ranges */
191         ret = dwarf_lowpc(sp_die, &lopc, &__dw_error);
192         DIE_IF(ret == DW_DLV_ERROR);
193         if (ret == DW_DLV_NO_ENTRY)
194                 return 0;
195         ret = dwarf_highpc(sp_die, &hipc, &__dw_error);
196         DIE_IF(ret != DW_DLV_OK);
197         if (lopc <= addr && addr < hipc) {
198                 *offs = addr - lopc;
199                 return 1;
200         } else
201                 return 0;
202 }
203
204 /* Check the die is inlined function */
205 static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die)
206 {
207         /* TODO: check strictly */
208         Dwarf_Bool inl;
209         int ret;
210
211         ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error);
212         DIE_IF(ret == DW_DLV_ERROR);
213         return inl;
214 }
215
216 /* Get the offset of abstruct_origin */
217 static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die)
218 {
219         Dwarf_Attribute attr;
220         Dwarf_Off cu_offs;
221         int ret;
222
223         ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error);
224         DIE_IF(ret != DW_DLV_OK);
225         ret = dwarf_formref(attr, &cu_offs, &__dw_error);
226         DIE_IF(ret != DW_DLV_OK);
227         dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
228         return cu_offs;
229 }
230
231 /* Get entry pc(or low pc, 1st entry of ranges)  of the die */
232 static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die)
233 {
234         Dwarf_Attribute attr;
235         Dwarf_Addr addr;
236         Dwarf_Off offs;
237         Dwarf_Ranges *ranges;
238         Dwarf_Signed cnt;
239         int ret;
240
241         /* Try to get entry pc */
242         ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error);
243         DIE_IF(ret == DW_DLV_ERROR);
244         if (ret == DW_DLV_OK) {
245                 ret = dwarf_formaddr(attr, &addr, &__dw_error);
246                 DIE_IF(ret != DW_DLV_OK);
247                 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
248                 return addr;
249         }
250
251         /* Try to get low pc */
252         ret = dwarf_lowpc(dw_die, &addr, &__dw_error);
253         DIE_IF(ret == DW_DLV_ERROR);
254         if (ret == DW_DLV_OK)
255                 return addr;
256
257         /* Try to get ranges */
258         ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error);
259         DIE_IF(ret != DW_DLV_OK);
260         ret = dwarf_formref(attr, &offs, &__dw_error);
261         DIE_IF(ret != DW_DLV_OK);
262         ret = dwarf_get_ranges(__dw_debug, offs, &ranges, &cnt, NULL,
263                                 &__dw_error);
264         DIE_IF(ret != DW_DLV_OK);
265         addr = ranges[0].dwr_addr1;
266         dwarf_ranges_dealloc(__dw_debug, ranges, cnt);
267         return addr;
268 }
269
270 /*
271  * Search a Die from Die tree.
272  * Note: cur_link->die should be deallocated in this function.
273  */
274 static int __search_die_tree(struct die_link *cur_link,
275                              int (*die_cb)(struct die_link *, void *),
276                              void *data)
277 {
278         Dwarf_Die new_die;
279         struct die_link new_link;
280         int ret;
281
282         if (!die_cb)
283                 return 0;
284
285         /* Check current die */
286         while (!(ret = die_cb(cur_link, data))) {
287                 /* Check child die */
288                 ret = dwarf_child(cur_link->die, &new_die, &__dw_error);
289                 DIE_IF(ret == DW_DLV_ERROR);
290                 if (ret == DW_DLV_OK) {
291                         new_link.parent = cur_link;
292                         new_link.die = new_die;
293                         ret = __search_die_tree(&new_link, die_cb, data);
294                         if (ret)
295                                 break;
296                 }
297
298                 /* Move to next sibling */
299                 ret = dwarf_siblingof(__dw_debug, cur_link->die, &new_die,
300                                       &__dw_error);
301                 DIE_IF(ret == DW_DLV_ERROR);
302                 dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
303                 cur_link->die = new_die;
304                 if (ret == DW_DLV_NO_ENTRY)
305                         return 0;
306         }
307         dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
308         return ret;
309 }
310
311 /* Search a die in its children's die tree */
312 static int search_die_from_children(Dwarf_Die parent_die,
313                                     int (*die_cb)(struct die_link *, void *),
314                                     void *data)
315 {
316         struct die_link new_link;
317         int ret;
318
319         new_link.parent = NULL;
320         ret = dwarf_child(parent_die, &new_link.die, &__dw_error);
321         DIE_IF(ret == DW_DLV_ERROR);
322         if (ret == DW_DLV_OK)
323                 return __search_die_tree(&new_link, die_cb, data);
324         else
325                 return 0;
326 }
327
328 /* Find a locdesc corresponding to the address */
329 static int attr_get_locdesc(Dwarf_Attribute attr, Dwarf_Locdesc *desc,
330                             Dwarf_Addr addr)
331 {
332         Dwarf_Signed lcnt;
333         Dwarf_Locdesc **llbuf;
334         int ret, i;
335
336         ret = dwarf_loclist_n(attr, &llbuf, &lcnt, &__dw_error);
337         DIE_IF(ret != DW_DLV_OK);
338         ret = DW_DLV_NO_ENTRY;
339         for (i = 0; i < lcnt; ++i) {
340                 if (llbuf[i]->ld_lopc <= addr &&
341                     llbuf[i]->ld_hipc > addr) {
342                         memcpy(desc, llbuf[i], sizeof(Dwarf_Locdesc));
343                         desc->ld_s =
344                                 malloc(sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
345                         DIE_IF(desc->ld_s == NULL);
346                         memcpy(desc->ld_s, llbuf[i]->ld_s,
347                                 sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
348                         ret = DW_DLV_OK;
349                         break;
350                 }
351                 dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
352                 dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
353         }
354         /* Releasing loop */
355         for (; i < lcnt; ++i) {
356                 dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
357                 dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
358         }
359         dwarf_dealloc(__dw_debug, llbuf, DW_DLA_LIST);
360         return ret;
361 }
362
363 /* Get decl_file attribute value (file number) */
364 static Dwarf_Unsigned die_get_decl_file(Dwarf_Die sp_die)
365 {
366         Dwarf_Attribute attr;
367         Dwarf_Unsigned fno;
368         int ret;
369
370         ret = dwarf_attr(sp_die, DW_AT_decl_file, &attr, &__dw_error);
371         DIE_IF(ret != DW_DLV_OK);
372         dwarf_formudata(attr, &fno, &__dw_error);
373         DIE_IF(ret != DW_DLV_OK);
374         dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
375         return fno;
376 }
377
378 /* Get decl_line attribute value (line number) */
379 static Dwarf_Unsigned die_get_decl_line(Dwarf_Die sp_die)
380 {
381         Dwarf_Attribute attr;
382         Dwarf_Unsigned lno;
383         int ret;
384
385         ret = dwarf_attr(sp_die, DW_AT_decl_line, &attr, &__dw_error);
386         DIE_IF(ret != DW_DLV_OK);
387         dwarf_formudata(attr, &lno, &__dw_error);
388         DIE_IF(ret != DW_DLV_OK);
389         dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
390         return lno;
391 }
392
393 /*
394  * Probe finder related functions
395  */
396
397 /* Show a location */
398 static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
399 {
400         Dwarf_Small op;
401         Dwarf_Unsigned regn;
402         Dwarf_Signed offs;
403         int deref = 0, ret;
404         const char *regs;
405
406         op = loc->lr_atom;
407
408         /* If this is based on frame buffer, set the offset */
409         if (op == DW_OP_fbreg) {
410                 deref = 1;
411                 offs = (Dwarf_Signed)loc->lr_number;
412                 op = pf->fbloc.ld_s[0].lr_atom;
413                 loc = &pf->fbloc.ld_s[0];
414         } else
415                 offs = 0;
416
417         if (op >= DW_OP_breg0 && op <= DW_OP_breg31) {
418                 regn = op - DW_OP_breg0;
419                 offs += (Dwarf_Signed)loc->lr_number;
420                 deref = 1;
421         } else if (op >= DW_OP_reg0 && op <= DW_OP_reg31) {
422                 regn = op - DW_OP_reg0;
423         } else if (op == DW_OP_bregx) {
424                 regn = loc->lr_number;
425                 offs += (Dwarf_Signed)loc->lr_number2;
426                 deref = 1;
427         } else if (op == DW_OP_regx) {
428                 regn = loc->lr_number;
429         } else
430                 die("Dwarf_OP %d is not supported.", op);
431
432         regs = get_arch_regstr(regn);
433         if (!regs)
434                 die("%lld exceeds max register number.", regn);
435
436         if (deref)
437                 ret = snprintf(pf->buf, pf->len,
438                                  " %s=%+lld(%s)", pf->var, offs, regs);
439         else
440                 ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
441         DIE_IF(ret < 0);
442         DIE_IF(ret >= pf->len);
443 }
444
445 /* Show a variables in kprobe event format */
446 static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf)
447 {
448         Dwarf_Attribute attr;
449         Dwarf_Locdesc ld;
450         int ret;
451
452         ret = dwarf_attr(vr_die, DW_AT_location, &attr, &__dw_error);
453         if (ret != DW_DLV_OK)
454                 goto error;
455         ret = attr_get_locdesc(attr, &ld, (pf->addr - pf->cu_base));
456         if (ret != DW_DLV_OK)
457                 goto error;
458         /* TODO? */
459         DIE_IF(ld.ld_cents != 1);
460         show_location(&ld.ld_s[0], pf);
461         free(ld.ld_s);
462         dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
463         return ;
464 error:
465         die("Failed to find the location of %s at this address.\n"
466             " Perhaps, it has been optimized out.", pf->var);
467 }
468
469 static int variable_callback(struct die_link *dlink, void *data)
470 {
471         struct probe_finder *pf = (struct probe_finder *)data;
472         Dwarf_Half tag;
473         int ret;
474
475         ret = dwarf_tag(dlink->die, &tag, &__dw_error);
476         DIE_IF(ret == DW_DLV_ERROR);
477         if ((tag == DW_TAG_formal_parameter ||
478              tag == DW_TAG_variable) &&
479             (die_compare_name(dlink->die, pf->var) == 0)) {
480                 show_variable(dlink->die, pf);
481                 return 1;
482         }
483         /* TODO: Support struct members and arrays */
484         return 0;
485 }
486
487 /* Find a variable in a subprogram die */
488 static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
489 {
490         int ret;
491
492         if (!is_c_varname(pf->var)) {
493                 /* Output raw parameters */
494                 ret = snprintf(pf->buf, pf->len, " %s", pf->var);
495                 DIE_IF(ret < 0);
496                 DIE_IF(ret >= pf->len);
497                 return ;
498         }
499
500         pr_debug("Searching '%s' variable in context.\n", pf->var);
501         /* Search child die for local variables and parameters. */
502         ret = search_die_from_children(sp_die, variable_callback, pf);
503         if (!ret)
504                 die("Failed to find '%s' in this function.", pf->var);
505 }
506
507 /* Get a frame base on the address */
508 static void get_current_frame_base(Dwarf_Die sp_die, struct probe_finder *pf)
509 {
510         Dwarf_Attribute attr;
511         int ret;
512
513         ret = dwarf_attr(sp_die, DW_AT_frame_base, &attr, &__dw_error);
514         DIE_IF(ret != DW_DLV_OK);
515         ret = attr_get_locdesc(attr, &pf->fbloc, (pf->addr - pf->cu_base));
516         DIE_IF(ret != DW_DLV_OK);
517         dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
518 }
519
520 static void free_current_frame_base(struct probe_finder *pf)
521 {
522         free(pf->fbloc.ld_s);
523         memset(&pf->fbloc, 0, sizeof(Dwarf_Locdesc));
524 }
525
526 /* Show a probe point to output buffer */
527 static void show_probe_point(Dwarf_Die sp_die, Dwarf_Signed offs,
528                              struct probe_finder *pf)
529 {
530         struct probe_point *pp = pf->pp;
531         char *name;
532         char tmp[MAX_PROBE_BUFFER];
533         int ret, i, len;
534
535         /* Output name of probe point */
536         ret = dwarf_diename(sp_die, &name, &__dw_error);
537         DIE_IF(ret == DW_DLV_ERROR);
538         if (ret == DW_DLV_OK) {
539                 ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name,
540                                 (unsigned int)offs);
541                 /* Copy the function name if possible */
542                 if (!pp->function) {
543                         pp->function = strdup(name);
544                         pp->offset = offs;
545                 }
546                 dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
547         } else {
548                 /* This function has no name. */
549                 ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%llx", pf->addr);
550                 if (!pp->function) {
551                         /* TODO: Use _stext */
552                         pp->function = strdup("");
553                         pp->offset = (int)pf->addr;
554                 }
555         }
556         DIE_IF(ret < 0);
557         DIE_IF(ret >= MAX_PROBE_BUFFER);
558         len = ret;
559         pr_debug("Probe point found: %s\n", tmp);
560
561         /* Find each argument */
562         get_current_frame_base(sp_die, pf);
563         for (i = 0; i < pp->nr_args; i++) {
564                 pf->var = pp->args[i];
565                 pf->buf = &tmp[len];
566                 pf->len = MAX_PROBE_BUFFER - len;
567                 find_variable(sp_die, pf);
568                 len += strlen(pf->buf);
569         }
570         free_current_frame_base(pf);
571
572         pp->probes[pp->found] = strdup(tmp);
573         pp->found++;
574 }
575
576 static int probeaddr_callback(struct die_link *dlink, void *data)
577 {
578         struct probe_finder *pf = (struct probe_finder *)data;
579         Dwarf_Half tag;
580         Dwarf_Signed offs;
581         int ret;
582
583         ret = dwarf_tag(dlink->die, &tag, &__dw_error);
584         DIE_IF(ret == DW_DLV_ERROR);
585         /* Check the address is in this subprogram */
586         if (tag == DW_TAG_subprogram &&
587             die_within_subprogram(dlink->die, pf->addr, &offs)) {
588                 show_probe_point(dlink->die, offs, pf);
589                 return 1;
590         }
591         return 0;
592 }
593
594 /* Find probe point from its line number */
595 static void find_probe_point_by_line(struct probe_finder *pf)
596 {
597         Dwarf_Signed cnt, i, clm;
598         Dwarf_Line *lines;
599         Dwarf_Unsigned lineno = 0;
600         Dwarf_Addr addr;
601         Dwarf_Unsigned fno;
602         int ret;
603
604         ret = dwarf_srclines(pf->cu_die, &lines, &cnt, &__dw_error);
605         DIE_IF(ret != DW_DLV_OK);
606
607         for (i = 0; i < cnt; i++) {
608                 ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
609                 DIE_IF(ret != DW_DLV_OK);
610                 if (fno != pf->fno)
611                         continue;
612
613                 ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
614                 DIE_IF(ret != DW_DLV_OK);
615                 if (lineno != pf->lno)
616                         continue;
617
618                 ret = dwarf_lineoff(lines[i], &clm, &__dw_error);
619                 DIE_IF(ret != DW_DLV_OK);
620
621                 ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
622                 DIE_IF(ret != DW_DLV_OK);
623                 pr_debug("Probe line found: line[%d]:%u,%d addr:0x%llx\n",
624                          (int)i, (unsigned)lineno, (int)clm, addr);
625                 pf->addr = addr;
626                 /* Search a real subprogram including this line, */
627                 ret = search_die_from_children(pf->cu_die,
628                                                probeaddr_callback, pf);
629                 if (ret == 0)
630                         die("Probe point is not found in subprograms.");
631                 /* Continuing, because target line might be inlined. */
632         }
633         dwarf_srclines_dealloc(__dw_debug, lines, cnt);
634 }
635
636 /* Search function from function name */
637 static int probefunc_callback(struct die_link *dlink, void *data)
638 {
639         struct probe_finder *pf = (struct probe_finder *)data;
640         struct probe_point *pp = pf->pp;
641         struct die_link *lk;
642         Dwarf_Signed offs;
643         Dwarf_Half tag;
644         int ret;
645
646         ret = dwarf_tag(dlink->die, &tag, &__dw_error);
647         DIE_IF(ret == DW_DLV_ERROR);
648         if (tag == DW_TAG_subprogram) {
649                 if (die_compare_name(dlink->die, pp->function) == 0) {
650                         if (pp->line) { /* Function relative line */
651                                 pf->fno = die_get_decl_file(dlink->die);
652                                 pf->lno = die_get_decl_line(dlink->die)
653                                          + pp->line;
654                                 find_probe_point_by_line(pf);
655                                 return 1;
656                         }
657                         if (die_inlined_subprogram(dlink->die)) {
658                                 /* Inlined function, save it. */
659                                 ret = dwarf_die_CU_offset(dlink->die,
660                                                           &pf->inl_offs,
661                                                           &__dw_error);
662                                 DIE_IF(ret != DW_DLV_OK);
663                                 pr_debug("inline definition offset %lld\n",
664                                          pf->inl_offs);
665                                 return 0;       /* Continue to search */
666                         }
667                         /* Get probe address */
668                         pf->addr = die_get_entrypc(dlink->die);
669                         pf->addr += pp->offset;
670                         /* TODO: Check the address in this function */
671                         show_probe_point(dlink->die, pp->offset, pf);
672                         return 1; /* Exit; no same symbol in this CU. */
673                 }
674         } else if (tag == DW_TAG_inlined_subroutine && pf->inl_offs) {
675                 if (die_get_abstract_origin(dlink->die) == pf->inl_offs) {
676                         /* Get probe address */
677                         pf->addr = die_get_entrypc(dlink->die);
678                         pf->addr += pp->offset;
679                         pr_debug("found inline addr: 0x%llx\n", pf->addr);
680                         /* Inlined function. Get a real subprogram */
681                         for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
682                                 tag = 0;
683                                 dwarf_tag(lk->die, &tag, &__dw_error);
684                                 DIE_IF(ret == DW_DLV_ERROR);
685                                 if (tag == DW_TAG_subprogram &&
686                                     !die_inlined_subprogram(lk->die))
687                                         goto found;
688                         }
689                         die("Failed to find real subprogram.");
690 found:
691                         /* Get offset from subprogram */
692                         ret = die_within_subprogram(lk->die, pf->addr, &offs);
693                         DIE_IF(!ret);
694                         show_probe_point(lk->die, offs, pf);
695                         /* Continue to search */
696                 }
697         }
698         return 0;
699 }
700
701 static void find_probe_point_by_func(struct probe_finder *pf)
702 {
703         search_die_from_children(pf->cu_die, probefunc_callback, pf);
704 }
705
706 /* Find a probe point */
707 int find_probe_point(int fd, struct probe_point *pp)
708 {
709         Dwarf_Half addr_size = 0;
710         Dwarf_Unsigned next_cuh = 0;
711         int cu_number = 0, ret;
712         struct probe_finder pf = {.pp = pp};
713
714         ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
715         if (ret != DW_DLV_OK)
716                 return -ENOENT;
717
718         pp->found = 0;
719         while (++cu_number) {
720                 /* Search CU (Compilation Unit) */
721                 ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
722                         &addr_size, &next_cuh, &__dw_error);
723                 DIE_IF(ret == DW_DLV_ERROR);
724                 if (ret == DW_DLV_NO_ENTRY)
725                         break;
726
727                 /* Get the DIE(Debugging Information Entry) of this CU */
728                 ret = dwarf_siblingof(__dw_debug, 0, &pf.cu_die, &__dw_error);
729                 DIE_IF(ret != DW_DLV_OK);
730
731                 /* Check if target file is included. */
732                 if (pp->file)
733                         pf.fno = cu_find_fileno(pf.cu_die, pp->file);
734
735                 if (!pp->file || pf.fno) {
736                         /* Save CU base address (for frame_base) */
737                         ret = dwarf_lowpc(pf.cu_die, &pf.cu_base, &__dw_error);
738                         DIE_IF(ret == DW_DLV_ERROR);
739                         if (ret == DW_DLV_NO_ENTRY)
740                                 pf.cu_base = 0;
741                         if (pp->function)
742                                 find_probe_point_by_func(&pf);
743                         else {
744                                 pf.lno = pp->line;
745                                 find_probe_point_by_line(&pf);
746                         }
747                 }
748                 dwarf_dealloc(__dw_debug, pf.cu_die, DW_DLA_DIE);
749         }
750         ret = dwarf_finish(__dw_debug, &__dw_error);
751         DIE_IF(ret != DW_DLV_OK);
752
753         return pp->found;
754 }
755
756
757 static void line_range_add_line(struct line_range *lr, unsigned int line)
758 {
759         struct line_node *ln;
760         struct list_head *p;
761
762         /* Reverse search, because new line will be the last one */
763         list_for_each_entry_reverse(ln, &lr->line_list, list) {
764                 if (ln->line < line) {
765                         p = &ln->list;
766                         goto found;
767                 } else if (ln->line == line)    /* Already exist */
768                         return ;
769         }
770         /* List is empty, or the smallest entry */
771         p = &lr->line_list;
772 found:
773         pr_debug("Debug: add a line %u\n", line);
774         ln = zalloc(sizeof(struct line_node));
775         DIE_IF(ln == NULL);
776         ln->line = line;
777         INIT_LIST_HEAD(&ln->list);
778         list_add(&ln->list, p);
779 }
780
781 /* Find line range from its line number */
782 static void find_line_range_by_line(struct line_finder *lf)
783 {
784         Dwarf_Signed cnt, i;
785         Dwarf_Line *lines;
786         Dwarf_Unsigned lineno = 0;
787         Dwarf_Unsigned fno;
788         Dwarf_Addr addr;
789         int ret;
790
791         INIT_LIST_HEAD(&lf->lr->line_list);
792         ret = dwarf_srclines(lf->cu_die, &lines, &cnt, &__dw_error);
793         DIE_IF(ret != DW_DLV_OK);
794
795         for (i = 0; i < cnt; i++) {
796                 ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
797                 DIE_IF(ret != DW_DLV_OK);
798                 if (fno != lf->fno)
799                         continue;
800
801                 ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
802                 DIE_IF(ret != DW_DLV_OK);
803                 if (lf->lno_s > lineno || lf->lno_e < lineno)
804                         continue;
805
806                 /* Filter line in the function address range */
807                 if (lf->addr_s && lf->addr_e) {
808                         ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
809                         DIE_IF(ret != DW_DLV_OK);
810                         if (lf->addr_s > addr || lf->addr_e <= addr)
811                                 continue;
812                 }
813                 line_range_add_line(lf->lr, (unsigned int)lineno);
814         }
815         dwarf_srclines_dealloc(__dw_debug, lines, cnt);
816         if (!list_empty(&lf->lr->line_list))
817                 lf->found = 1;
818 }
819
820 /* Search function from function name */
821 static int linefunc_callback(struct die_link *dlink, void *data)
822 {
823         struct line_finder *lf = (struct line_finder *)data;
824         struct line_range *lr = lf->lr;
825         Dwarf_Half tag;
826         int ret;
827
828         ret = dwarf_tag(dlink->die, &tag, &__dw_error);
829         DIE_IF(ret == DW_DLV_ERROR);
830         if (tag == DW_TAG_subprogram &&
831             die_compare_name(dlink->die, lr->function) == 0) {
832                 /* Get the address range of this function */
833                 ret = dwarf_highpc(dlink->die, &lf->addr_e, &__dw_error);
834                 if (ret == DW_DLV_OK)
835                         ret = dwarf_lowpc(dlink->die, &lf->addr_s, &__dw_error);
836                 DIE_IF(ret == DW_DLV_ERROR);
837                 if (ret == DW_DLV_NO_ENTRY) {
838                         lf->addr_s = 0;
839                         lf->addr_e = 0;
840                 }
841
842                 lf->fno = die_get_decl_file(dlink->die);
843                 lr->offset = die_get_decl_line(dlink->die);;
844                 lf->lno_s = lr->offset + lr->start;
845                 if (!lr->end)
846                         lf->lno_e = (Dwarf_Unsigned)-1;
847                 else
848                         lf->lno_e = lr->offset + lr->end;
849                 lr->start = lf->lno_s;
850                 lr->end = lf->lno_e;
851                 find_line_range_by_line(lf);
852                 return 1;
853         }
854         return 0;
855 }
856
857 static void find_line_range_by_func(struct line_finder *lf)
858 {
859         search_die_from_children(lf->cu_die, linefunc_callback, lf);
860 }
861
862 int find_line_range(int fd, struct line_range *lr)
863 {
864         Dwarf_Half addr_size = 0;
865         Dwarf_Unsigned next_cuh = 0;
866         int ret;
867         struct line_finder lf = {.lr = lr};
868
869         ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
870         if (ret != DW_DLV_OK)
871                 return -ENOENT;
872
873         while (!lf.found) {
874                 /* Search CU (Compilation Unit) */
875                 ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
876                         &addr_size, &next_cuh, &__dw_error);
877                 DIE_IF(ret == DW_DLV_ERROR);
878                 if (ret == DW_DLV_NO_ENTRY)
879                         break;
880
881                 /* Get the DIE(Debugging Information Entry) of this CU */
882                 ret = dwarf_siblingof(__dw_debug, 0, &lf.cu_die, &__dw_error);
883                 DIE_IF(ret != DW_DLV_OK);
884
885                 /* Check if target file is included. */
886                 if (lr->file)
887                         lf.fno = cu_find_fileno(lf.cu_die, lr->file);
888
889                 if (!lr->file || lf.fno) {
890                         if (lr->function)
891                                 find_line_range_by_func(&lf);
892                         else {
893                                 lf.lno_s = lr->start;
894                                 if (!lr->end)
895                                         lf.lno_e = (Dwarf_Unsigned)-1;
896                                 else
897                                         lf.lno_e = lr->end;
898                                 find_line_range_by_line(&lf);
899                         }
900                         /* Get the real file path */
901                         if (lf.found)
902                                 cu_get_filename(lf.cu_die, lf.fno, &lr->path);
903                 }
904                 dwarf_dealloc(__dw_debug, lf.cu_die, DW_DLA_DIE);
905         }
906         ret = dwarf_finish(__dw_debug, &__dw_error);
907         DIE_IF(ret != DW_DLV_OK);
908         return lf.found;
909 }
910