perf probe: Support DW_OP_plus_uconst in DW_AT_data_member_location
[linux-2.6.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 "string.h"
36 #include "event.h"
37 #include "debug.h"
38 #include "util.h"
39 #include "probe-finder.h"
40
41
42 /*
43  * Generic dwarf analysis helpers
44  */
45
46 #define X86_32_MAX_REGS 8
47 const char *x86_32_regs_table[X86_32_MAX_REGS] = {
48         "%ax",
49         "%cx",
50         "%dx",
51         "%bx",
52         "$stack",       /* Stack address instead of %sp */
53         "%bp",
54         "%si",
55         "%di",
56 };
57
58 #define X86_64_MAX_REGS 16
59 const char *x86_64_regs_table[X86_64_MAX_REGS] = {
60         "%ax",
61         "%dx",
62         "%cx",
63         "%bx",
64         "%si",
65         "%di",
66         "%bp",
67         "%sp",
68         "%r8",
69         "%r9",
70         "%r10",
71         "%r11",
72         "%r12",
73         "%r13",
74         "%r14",
75         "%r15",
76 };
77
78 /* TODO: switching by dwarf address size */
79 #ifdef __x86_64__
80 #define ARCH_MAX_REGS X86_64_MAX_REGS
81 #define arch_regs_table x86_64_regs_table
82 #else
83 #define ARCH_MAX_REGS X86_32_MAX_REGS
84 #define arch_regs_table x86_32_regs_table
85 #endif
86
87 /* Kprobe tracer basic type is up to u64 */
88 #define MAX_BASIC_TYPE_BITS     64
89
90 /* Return architecture dependent register string (for kprobe-tracer) */
91 static const char *get_arch_regstr(unsigned int n)
92 {
93         return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
94 }
95
96 /*
97  * Compare the tail of two strings.
98  * Return 0 if whole of either string is same as another's tail part.
99  */
100 static int strtailcmp(const char *s1, const char *s2)
101 {
102         int i1 = strlen(s1);
103         int i2 = strlen(s2);
104         while (--i1 >= 0 && --i2 >= 0) {
105                 if (s1[i1] != s2[i2])
106                         return s1[i1] - s2[i2];
107         }
108         return 0;
109 }
110
111 /* Line number list operations */
112
113 /* Add a line to line number list */
114 static int line_list__add_line(struct list_head *head, int line)
115 {
116         struct line_node *ln;
117         struct list_head *p;
118
119         /* Reverse search, because new line will be the last one */
120         list_for_each_entry_reverse(ln, head, list) {
121                 if (ln->line < line) {
122                         p = &ln->list;
123                         goto found;
124                 } else if (ln->line == line)    /* Already exist */
125                         return 1;
126         }
127         /* List is empty, or the smallest entry */
128         p = head;
129 found:
130         pr_debug("line list: add a line %u\n", line);
131         ln = zalloc(sizeof(struct line_node));
132         if (ln == NULL)
133                 return -ENOMEM;
134         ln->line = line;
135         INIT_LIST_HEAD(&ln->list);
136         list_add(&ln->list, p);
137         return 0;
138 }
139
140 /* Check if the line in line number list */
141 static int line_list__has_line(struct list_head *head, int line)
142 {
143         struct line_node *ln;
144
145         /* Reverse search, because new line will be the last one */
146         list_for_each_entry(ln, head, list)
147                 if (ln->line == line)
148                         return 1;
149
150         return 0;
151 }
152
153 /* Init line number list */
154 static void line_list__init(struct list_head *head)
155 {
156         INIT_LIST_HEAD(head);
157 }
158
159 /* Free line number list */
160 static void line_list__free(struct list_head *head)
161 {
162         struct line_node *ln;
163         while (!list_empty(head)) {
164                 ln = list_first_entry(head, struct line_node, list);
165                 list_del(&ln->list);
166                 free(ln);
167         }
168 }
169
170 /* Dwarf wrappers */
171
172 /* Find the realpath of the target file. */
173 static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
174 {
175         Dwarf_Files *files;
176         size_t nfiles, i;
177         const char *src = NULL;
178         int ret;
179
180         if (!fname)
181                 return NULL;
182
183         ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
184         if (ret != 0)
185                 return NULL;
186
187         for (i = 0; i < nfiles; i++) {
188                 src = dwarf_filesrc(files, i, NULL, NULL);
189                 if (strtailcmp(src, fname) == 0)
190                         break;
191         }
192         if (i == nfiles)
193                 return NULL;
194         return src;
195 }
196
197 /* Compare diename and tname */
198 static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
199 {
200         const char *name;
201         name = dwarf_diename(dw_die);
202         return name ? strcmp(tname, name) : -1;
203 }
204
205 /* Get type die, but skip qualifiers and typedef */
206 static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
207 {
208         Dwarf_Attribute attr;
209         int tag;
210
211         do {
212                 if (dwarf_attr(vr_die, DW_AT_type, &attr) == NULL ||
213                     dwarf_formref_die(&attr, die_mem) == NULL)
214                         return NULL;
215
216                 tag = dwarf_tag(die_mem);
217                 vr_die = die_mem;
218         } while (tag == DW_TAG_const_type ||
219                  tag == DW_TAG_restrict_type ||
220                  tag == DW_TAG_volatile_type ||
221                  tag == DW_TAG_shared_type ||
222                  tag == DW_TAG_typedef);
223
224         return die_mem;
225 }
226
227 static bool die_is_signed_type(Dwarf_Die *tp_die)
228 {
229         Dwarf_Attribute attr;
230         Dwarf_Word ret;
231
232         if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
233             dwarf_formudata(&attr, &ret) != 0)
234                 return false;
235
236         return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
237                 ret == DW_ATE_signed_fixed);
238 }
239
240 static int die_get_byte_size(Dwarf_Die *tp_die)
241 {
242         Dwarf_Attribute attr;
243         Dwarf_Word ret;
244
245         if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
246             dwarf_formudata(&attr, &ret) != 0)
247                 return 0;
248
249         return (int)ret;
250 }
251
252 /* Get data_member_location offset */
253 static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
254 {
255         Dwarf_Attribute attr;
256         Dwarf_Op *expr;
257         size_t nexpr;
258         int ret;
259
260         if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
261                 return -ENOENT;
262
263         if (dwarf_formudata(&attr, offs) != 0) {
264                 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
265                 ret = dwarf_getlocation(&attr, &expr, &nexpr);
266                 if (ret < 0 || nexpr == 0)
267                         return -ENOENT;
268
269                 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
270                         pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
271                                  expr[0].atom, nexpr);
272                         return -ENOTSUP;
273                 }
274                 *offs = (Dwarf_Word)expr[0].number;
275         }
276         return 0;
277 }
278
279 /* Return values for die_find callbacks */
280 enum {
281         DIE_FIND_CB_FOUND = 0,          /* End of Search */
282         DIE_FIND_CB_CHILD = 1,          /* Search only children */
283         DIE_FIND_CB_SIBLING = 2,        /* Search only siblings */
284         DIE_FIND_CB_CONTINUE = 3,       /* Search children and siblings */
285 };
286
287 /* Search a child die */
288 static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
289                                  int (*callback)(Dwarf_Die *, void *),
290                                  void *data, Dwarf_Die *die_mem)
291 {
292         Dwarf_Die child_die;
293         int ret;
294
295         ret = dwarf_child(rt_die, die_mem);
296         if (ret != 0)
297                 return NULL;
298
299         do {
300                 ret = callback(die_mem, data);
301                 if (ret == DIE_FIND_CB_FOUND)
302                         return die_mem;
303
304                 if ((ret & DIE_FIND_CB_CHILD) &&
305                     die_find_child(die_mem, callback, data, &child_die)) {
306                         memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
307                         return die_mem;
308                 }
309         } while ((ret & DIE_FIND_CB_SIBLING) &&
310                  dwarf_siblingof(die_mem, die_mem) == 0);
311
312         return NULL;
313 }
314
315 struct __addr_die_search_param {
316         Dwarf_Addr      addr;
317         Dwarf_Die       *die_mem;
318 };
319
320 static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
321 {
322         struct __addr_die_search_param *ad = data;
323
324         if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
325             dwarf_haspc(fn_die, ad->addr)) {
326                 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
327                 return DWARF_CB_ABORT;
328         }
329         return DWARF_CB_OK;
330 }
331
332 /* Search a real subprogram including this line, */
333 static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
334                                            Dwarf_Die *die_mem)
335 {
336         struct __addr_die_search_param ad;
337         ad.addr = addr;
338         ad.die_mem = die_mem;
339         /* dwarf_getscopes can't find subprogram. */
340         if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
341                 return NULL;
342         else
343                 return die_mem;
344 }
345
346 /* die_find callback for inline function search */
347 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
348 {
349         Dwarf_Addr *addr = data;
350
351         if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
352             dwarf_haspc(die_mem, *addr))
353                 return DIE_FIND_CB_FOUND;
354
355         return DIE_FIND_CB_CONTINUE;
356 }
357
358 /* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
359 static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
360                                       Dwarf_Die *die_mem)
361 {
362         return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
363 }
364
365 static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
366 {
367         const char *name = data;
368         int tag;
369
370         tag = dwarf_tag(die_mem);
371         if ((tag == DW_TAG_formal_parameter ||
372              tag == DW_TAG_variable) &&
373             (die_compare_name(die_mem, name) == 0))
374                 return DIE_FIND_CB_FOUND;
375
376         return DIE_FIND_CB_CONTINUE;
377 }
378
379 /* Find a variable called 'name' */
380 static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name,
381                                     Dwarf_Die *die_mem)
382 {
383         return die_find_child(sp_die, __die_find_variable_cb, (void *)name,
384                               die_mem);
385 }
386
387 static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
388 {
389         const char *name = data;
390
391         if ((dwarf_tag(die_mem) == DW_TAG_member) &&
392             (die_compare_name(die_mem, name) == 0))
393                 return DIE_FIND_CB_FOUND;
394
395         return DIE_FIND_CB_SIBLING;
396 }
397
398 /* Find a member called 'name' */
399 static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
400                                   Dwarf_Die *die_mem)
401 {
402         return die_find_child(st_die, __die_find_member_cb, (void *)name,
403                               die_mem);
404 }
405
406 /*
407  * Probe finder related functions
408  */
409
410 /* Show a location */
411 static int convert_location(Dwarf_Op *op, struct probe_finder *pf)
412 {
413         unsigned int regn;
414         Dwarf_Word offs = 0;
415         bool ref = false;
416         const char *regs;
417         struct kprobe_trace_arg *tvar = pf->tvar;
418
419         /* If this is based on frame buffer, set the offset */
420         if (op->atom == DW_OP_fbreg) {
421                 if (pf->fb_ops == NULL) {
422                         pr_warning("The attribute of frame base is not "
423                                    "supported.\n");
424                         return -ENOTSUP;
425                 }
426                 ref = true;
427                 offs = op->number;
428                 op = &pf->fb_ops[0];
429         }
430
431         if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
432                 regn = op->atom - DW_OP_breg0;
433                 offs += op->number;
434                 ref = true;
435         } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
436                 regn = op->atom - DW_OP_reg0;
437         } else if (op->atom == DW_OP_bregx) {
438                 regn = op->number;
439                 offs += op->number2;
440                 ref = true;
441         } else if (op->atom == DW_OP_regx) {
442                 regn = op->number;
443         } else {
444                 pr_warning("DW_OP %x is not supported.\n", op->atom);
445                 return -ENOTSUP;
446         }
447
448         regs = get_arch_regstr(regn);
449         if (!regs) {
450                 pr_warning("%u exceeds max register number.\n", regn);
451                 return -ERANGE;
452         }
453
454         tvar->value = strdup(regs);
455         if (tvar->value == NULL)
456                 return -ENOMEM;
457
458         if (ref) {
459                 tvar->ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
460                 if (tvar->ref == NULL)
461                         return -ENOMEM;
462                 tvar->ref->offset = (long)offs;
463         }
464         return 0;
465 }
466
467 static int convert_variable_type(Dwarf_Die *vr_die,
468                                  struct kprobe_trace_arg *targ)
469 {
470         Dwarf_Die type;
471         char buf[16];
472         int ret;
473
474         if (die_get_real_type(vr_die, &type) == NULL) {
475                 pr_warning("Failed to get a type information of %s.\n",
476                            dwarf_diename(vr_die));
477                 return -ENOENT;
478         }
479
480         ret = die_get_byte_size(&type) * 8;
481         if (ret) {
482                 /* Check the bitwidth */
483                 if (ret > MAX_BASIC_TYPE_BITS) {
484                         pr_info("%s exceeds max-bitwidth."
485                                 " Cut down to %d bits.\n",
486                                 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
487                         ret = MAX_BASIC_TYPE_BITS;
488                 }
489
490                 ret = snprintf(buf, 16, "%c%d",
491                                die_is_signed_type(&type) ? 's' : 'u', ret);
492                 if (ret < 0 || ret >= 16) {
493                         if (ret >= 16)
494                                 ret = -E2BIG;
495                         pr_warning("Failed to convert variable type: %s\n",
496                                    strerror(-ret));
497                         return ret;
498                 }
499                 targ->type = strdup(buf);
500                 if (targ->type == NULL)
501                         return -ENOMEM;
502         }
503         return 0;
504 }
505
506 static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
507                                     struct perf_probe_arg_field *field,
508                                     struct kprobe_trace_arg_ref **ref_ptr,
509                                     Dwarf_Die *die_mem)
510 {
511         struct kprobe_trace_arg_ref *ref = *ref_ptr;
512         Dwarf_Die type;
513         Dwarf_Word offs;
514         int ret;
515
516         pr_debug("converting %s in %s\n", field->name, varname);
517         if (die_get_real_type(vr_die, &type) == NULL) {
518                 pr_warning("Failed to get the type of %s.\n", varname);
519                 return -ENOENT;
520         }
521
522         /* Check the pointer and dereference */
523         if (dwarf_tag(&type) == DW_TAG_pointer_type) {
524                 if (!field->ref) {
525                         pr_err("Semantic error: %s must be referred by '->'\n",
526                                field->name);
527                         return -EINVAL;
528                 }
529                 /* Get the type pointed by this pointer */
530                 if (die_get_real_type(&type, &type) == NULL) {
531                         pr_warning("Failed to get the type of %s.\n", varname);
532                         return -ENOENT;
533                 }
534                 /* Verify it is a data structure  */
535                 if (dwarf_tag(&type) != DW_TAG_structure_type) {
536                         pr_warning("%s is not a data structure.\n", varname);
537                         return -EINVAL;
538                 }
539
540                 ref = zalloc(sizeof(struct kprobe_trace_arg_ref));
541                 if (ref == NULL)
542                         return -ENOMEM;
543                 if (*ref_ptr)
544                         (*ref_ptr)->next = ref;
545                 else
546                         *ref_ptr = ref;
547         } else {
548                 /* Verify it is a data structure  */
549                 if (dwarf_tag(&type) != DW_TAG_structure_type) {
550                         pr_warning("%s is not a data structure.\n", varname);
551                         return -EINVAL;
552                 }
553                 if (field->ref) {
554                         pr_err("Semantic error: %s must be referred by '.'\n",
555                                field->name);
556                         return -EINVAL;
557                 }
558                 if (!ref) {
559                         pr_warning("Structure on a register is not "
560                                    "supported yet.\n");
561                         return -ENOTSUP;
562                 }
563         }
564
565         if (die_find_member(&type, field->name, die_mem) == NULL) {
566                 pr_warning("%s(tyep:%s) has no member %s.\n", varname,
567                            dwarf_diename(&type), field->name);
568                 return -EINVAL;
569         }
570
571         /* Get the offset of the field */
572         ret = die_get_data_member_location(die_mem, &offs);
573         if (ret < 0) {
574                 pr_warning("Failed to get the offset of %s.\n", field->name);
575                 return ret;
576         }
577         ref->offset += (long)offs;
578
579         /* Converting next field */
580         if (field->next)
581                 return convert_variable_fields(die_mem, field->name,
582                                         field->next, &ref, die_mem);
583         else
584                 return 0;
585 }
586
587 /* Show a variables in kprobe event format */
588 static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
589 {
590         Dwarf_Attribute attr;
591         Dwarf_Die die_mem;
592         Dwarf_Op *expr;
593         size_t nexpr;
594         int ret;
595
596         if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
597                 goto error;
598         /* TODO: handle more than 1 exprs */
599         ret = dwarf_getlocation_addr(&attr, pf->addr, &expr, &nexpr, 1);
600         if (ret <= 0 || nexpr == 0)
601                 goto error;
602
603         ret = convert_location(expr, pf);
604         if (ret == 0 && pf->pvar->field) {
605                 ret = convert_variable_fields(vr_die, pf->pvar->var,
606                                               pf->pvar->field, &pf->tvar->ref,
607                                               &die_mem);
608                 vr_die = &die_mem;
609         }
610         if (ret == 0) {
611                 if (pf->pvar->type) {
612                         pf->tvar->type = strdup(pf->pvar->type);
613                         if (pf->tvar->type == NULL)
614                                 ret = -ENOMEM;
615                 } else
616                         ret = convert_variable_type(vr_die, pf->tvar);
617         }
618         /* *expr will be cached in libdw. Don't free it. */
619         return ret;
620 error:
621         /* TODO: Support const_value */
622         pr_err("Failed to find the location of %s at this address.\n"
623                " Perhaps, it has been optimized out.\n", pf->pvar->var);
624         return -ENOENT;
625 }
626
627 /* Find a variable in a subprogram die */
628 static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
629 {
630         Dwarf_Die vr_die;
631         char buf[32], *ptr;
632         int ret;
633
634         /* TODO: Support arrays */
635         if (pf->pvar->name)
636                 pf->tvar->name = strdup(pf->pvar->name);
637         else {
638                 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
639                 if (ret < 0)
640                         return ret;
641                 ptr = strchr(buf, ':'); /* Change type separator to _ */
642                 if (ptr)
643                         *ptr = '_';
644                 pf->tvar->name = strdup(buf);
645         }
646         if (pf->tvar->name == NULL)
647                 return -ENOMEM;
648
649         if (!is_c_varname(pf->pvar->var)) {
650                 /* Copy raw parameters */
651                 pf->tvar->value = strdup(pf->pvar->var);
652                 if (pf->tvar->value == NULL)
653                         return -ENOMEM;
654                 else
655                         return 0;
656         }
657
658         pr_debug("Searching '%s' variable in context.\n",
659                  pf->pvar->var);
660         /* Search child die for local variables and parameters. */
661         if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) {
662                 pr_warning("Failed to find '%s' in this function.\n",
663                            pf->pvar->var);
664                 return -ENOENT;
665         }
666         return convert_variable(&vr_die, pf);
667 }
668
669 /* Show a probe point to output buffer */
670 static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
671 {
672         struct kprobe_trace_event *tev;
673         Dwarf_Addr eaddr;
674         Dwarf_Die die_mem;
675         const char *name;
676         int ret, i;
677         Dwarf_Attribute fb_attr;
678         size_t nops;
679
680         if (pf->ntevs == MAX_PROBES) {
681                 pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES);
682                 return -ERANGE;
683         }
684         tev = &pf->tevs[pf->ntevs++];
685
686         /* If no real subprogram, find a real one */
687         if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
688                 sp_die = die_find_real_subprogram(&pf->cu_die,
689                                                  pf->addr, &die_mem);
690                 if (!sp_die) {
691                         pr_warning("Failed to find probe point in any "
692                                    "functions.\n");
693                         return -ENOENT;
694                 }
695         }
696
697         /* Copy the name of probe point */
698         name = dwarf_diename(sp_die);
699         if (name) {
700                 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
701                         pr_warning("Failed to get entry pc of %s\n",
702                                    dwarf_diename(sp_die));
703                         return -ENOENT;
704                 }
705                 tev->point.symbol = strdup(name);
706                 if (tev->point.symbol == NULL)
707                         return -ENOMEM;
708                 tev->point.offset = (unsigned long)(pf->addr - eaddr);
709         } else
710                 /* This function has no name. */
711                 tev->point.offset = (unsigned long)pf->addr;
712
713         pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
714                  tev->point.offset);
715
716         /* Get the frame base attribute/ops */
717         dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
718         ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
719         if (ret <= 0 || nops == 0) {
720                 pf->fb_ops = NULL;
721         } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
722                    pf->cfi != NULL) {
723                 Dwarf_Frame *frame;
724                 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
725                     dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
726                         pr_warning("Failed to get CFA on 0x%jx\n",
727                                    (uintmax_t)pf->addr);
728                         return -ENOENT;
729                 }
730         }
731
732         /* Find each argument */
733         tev->nargs = pf->pev->nargs;
734         tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs);
735         if (tev->args == NULL)
736                 return -ENOMEM;
737         for (i = 0; i < pf->pev->nargs; i++) {
738                 pf->pvar = &pf->pev->args[i];
739                 pf->tvar = &tev->args[i];
740                 ret = find_variable(sp_die, pf);
741                 if (ret != 0)
742                         return ret;
743         }
744
745         /* *pf->fb_ops will be cached in libdw. Don't free it. */
746         pf->fb_ops = NULL;
747         return 0;
748 }
749
750 /* Find probe point from its line number */
751 static int find_probe_point_by_line(struct probe_finder *pf)
752 {
753         Dwarf_Lines *lines;
754         Dwarf_Line *line;
755         size_t nlines, i;
756         Dwarf_Addr addr;
757         int lineno;
758         int ret = 0;
759
760         if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
761                 pr_warning("No source lines found in this CU.\n");
762                 return -ENOENT;
763         }
764
765         for (i = 0; i < nlines && ret == 0; i++) {
766                 line = dwarf_onesrcline(lines, i);
767                 if (dwarf_lineno(line, &lineno) != 0 ||
768                     lineno != pf->lno)
769                         continue;
770
771                 /* TODO: Get fileno from line, but how? */
772                 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
773                         continue;
774
775                 if (dwarf_lineaddr(line, &addr) != 0) {
776                         pr_warning("Failed to get the address of the line.\n");
777                         return -ENOENT;
778                 }
779                 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
780                          (int)i, lineno, (uintmax_t)addr);
781                 pf->addr = addr;
782
783                 ret = convert_probe_point(NULL, pf);
784                 /* Continuing, because target line might be inlined. */
785         }
786         return ret;
787 }
788
789 /* Find lines which match lazy pattern */
790 static int find_lazy_match_lines(struct list_head *head,
791                                  const char *fname, const char *pat)
792 {
793         char *fbuf, *p1, *p2;
794         int fd, ret, line, nlines = 0;
795         struct stat st;
796
797         fd = open(fname, O_RDONLY);
798         if (fd < 0) {
799                 pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
800                 return fd;
801         }
802
803         ret = fstat(fd, &st);
804         if (ret < 0) {
805                 pr_warning("Failed to get the size of %s: %s\n",
806                            fname, strerror(errno));
807                 return ret;
808         }
809         fbuf = xmalloc(st.st_size + 2);
810         ret = read(fd, fbuf, st.st_size);
811         if (ret < 0) {
812                 pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
813                 return ret;
814         }
815         close(fd);
816         fbuf[st.st_size] = '\n';        /* Dummy line */
817         fbuf[st.st_size + 1] = '\0';
818         p1 = fbuf;
819         line = 1;
820         while ((p2 = strchr(p1, '\n')) != NULL) {
821                 *p2 = '\0';
822                 if (strlazymatch(p1, pat)) {
823                         line_list__add_line(head, line);
824                         nlines++;
825                 }
826                 line++;
827                 p1 = p2 + 1;
828         }
829         free(fbuf);
830         return nlines;
831 }
832
833 /* Find probe points from lazy pattern  */
834 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
835 {
836         Dwarf_Lines *lines;
837         Dwarf_Line *line;
838         size_t nlines, i;
839         Dwarf_Addr addr;
840         Dwarf_Die die_mem;
841         int lineno;
842         int ret = 0;
843
844         if (list_empty(&pf->lcache)) {
845                 /* Matching lazy line pattern */
846                 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
847                                             pf->pev->point.lazy_line);
848                 if (ret == 0) {
849                         pr_debug("No matched lines found in %s.\n", pf->fname);
850                         return 0;
851                 } else if (ret < 0)
852                         return ret;
853         }
854
855         if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
856                 pr_warning("No source lines found in this CU.\n");
857                 return -ENOENT;
858         }
859
860         for (i = 0; i < nlines && ret >= 0; i++) {
861                 line = dwarf_onesrcline(lines, i);
862
863                 if (dwarf_lineno(line, &lineno) != 0 ||
864                     !line_list__has_line(&pf->lcache, lineno))
865                         continue;
866
867                 /* TODO: Get fileno from line, but how? */
868                 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
869                         continue;
870
871                 if (dwarf_lineaddr(line, &addr) != 0) {
872                         pr_debug("Failed to get the address of line %d.\n",
873                                  lineno);
874                         continue;
875                 }
876                 if (sp_die) {
877                         /* Address filtering 1: does sp_die include addr? */
878                         if (!dwarf_haspc(sp_die, addr))
879                                 continue;
880                         /* Address filtering 2: No child include addr? */
881                         if (die_find_inlinefunc(sp_die, addr, &die_mem))
882                                 continue;
883                 }
884
885                 pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
886                          (int)i, lineno, (unsigned long long)addr);
887                 pf->addr = addr;
888
889                 ret = convert_probe_point(sp_die, pf);
890                 /* Continuing, because target line might be inlined. */
891         }
892         /* TODO: deallocate lines, but how? */
893         return ret;
894 }
895
896 /* Callback parameter with return value */
897 struct dwarf_callback_param {
898         void *data;
899         int retval;
900 };
901
902 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
903 {
904         struct dwarf_callback_param *param = data;
905         struct probe_finder *pf = param->data;
906         struct perf_probe_point *pp = &pf->pev->point;
907         Dwarf_Addr addr;
908
909         if (pp->lazy_line)
910                 param->retval = find_probe_point_lazy(in_die, pf);
911         else {
912                 /* Get probe address */
913                 if (dwarf_entrypc(in_die, &addr) != 0) {
914                         pr_warning("Failed to get entry pc of %s.\n",
915                                    dwarf_diename(in_die));
916                         param->retval = -ENOENT;
917                         return DWARF_CB_ABORT;
918                 }
919                 pf->addr = addr;
920                 pf->addr += pp->offset;
921                 pr_debug("found inline addr: 0x%jx\n",
922                          (uintmax_t)pf->addr);
923
924                 param->retval = convert_probe_point(in_die, pf);
925         }
926
927         return DWARF_CB_OK;
928 }
929
930 /* Search function from function name */
931 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
932 {
933         struct dwarf_callback_param *param = data;
934         struct probe_finder *pf = param->data;
935         struct perf_probe_point *pp = &pf->pev->point;
936
937         /* Check tag and diename */
938         if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
939             die_compare_name(sp_die, pp->function) != 0)
940                 return DWARF_CB_OK;
941
942         pf->fname = dwarf_decl_file(sp_die);
943         if (pp->line) { /* Function relative line */
944                 dwarf_decl_line(sp_die, &pf->lno);
945                 pf->lno += pp->line;
946                 param->retval = find_probe_point_by_line(pf);
947         } else if (!dwarf_func_inline(sp_die)) {
948                 /* Real function */
949                 if (pp->lazy_line)
950                         param->retval = find_probe_point_lazy(sp_die, pf);
951                 else {
952                         if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
953                                 pr_warning("Failed to get entry pc of %s.\n",
954                                            dwarf_diename(sp_die));
955                                 param->retval = -ENOENT;
956                                 return DWARF_CB_ABORT;
957                         }
958                         pf->addr += pp->offset;
959                         /* TODO: Check the address in this function */
960                         param->retval = convert_probe_point(sp_die, pf);
961                 }
962         } else {
963                 struct dwarf_callback_param _param = {.data = (void *)pf,
964                                                       .retval = 0};
965                 /* Inlined function: search instances */
966                 dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
967                                             &_param);
968                 param->retval = _param.retval;
969         }
970
971         return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
972 }
973
974 static int find_probe_point_by_func(struct probe_finder *pf)
975 {
976         struct dwarf_callback_param _param = {.data = (void *)pf,
977                                               .retval = 0};
978         dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
979         return _param.retval;
980 }
981
982 /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
983 int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
984                              struct kprobe_trace_event **tevs)
985 {
986         struct probe_finder pf = {.pev = pev};
987         struct perf_probe_point *pp = &pev->point;
988         Dwarf_Off off, noff;
989         size_t cuhl;
990         Dwarf_Die *diep;
991         Dwarf *dbg;
992         int ret = 0;
993
994         pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
995         if (pf.tevs == NULL)
996                 return -ENOMEM;
997         *tevs = pf.tevs;
998         pf.ntevs = 0;
999
1000         dbg = dwarf_begin(fd, DWARF_C_READ);
1001         if (!dbg) {
1002                 pr_warning("No dwarf info found in the vmlinux - "
1003                         "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1004                 return -EBADF;
1005         }
1006
1007         /* Get the call frame information from this dwarf */
1008         pf.cfi = dwarf_getcfi(dbg);
1009
1010         off = 0;
1011         line_list__init(&pf.lcache);
1012         /* Loop on CUs (Compilation Unit) */
1013         while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1014                ret >= 0) {
1015                 /* Get the DIE(Debugging Information Entry) of this CU */
1016                 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die);
1017                 if (!diep)
1018                         continue;
1019
1020                 /* Check if target file is included. */
1021                 if (pp->file)
1022                         pf.fname = cu_find_realpath(&pf.cu_die, pp->file);
1023                 else
1024                         pf.fname = NULL;
1025
1026                 if (!pp->file || pf.fname) {
1027                         if (pp->function)
1028                                 ret = find_probe_point_by_func(&pf);
1029                         else if (pp->lazy_line)
1030                                 ret = find_probe_point_lazy(NULL, &pf);
1031                         else {
1032                                 pf.lno = pp->line;
1033                                 ret = find_probe_point_by_line(&pf);
1034                         }
1035                 }
1036                 off = noff;
1037         }
1038         line_list__free(&pf.lcache);
1039         dwarf_end(dbg);
1040
1041         return (ret < 0) ? ret : pf.ntevs;
1042 }
1043
1044 /* Reverse search */
1045 int find_perf_probe_point(int fd, unsigned long addr,
1046                           struct perf_probe_point *ppt)
1047 {
1048         Dwarf_Die cudie, spdie, indie;
1049         Dwarf *dbg;
1050         Dwarf_Line *line;
1051         Dwarf_Addr laddr, eaddr;
1052         const char *tmp;
1053         int lineno, ret = 0;
1054         bool found = false;
1055
1056         dbg = dwarf_begin(fd, DWARF_C_READ);
1057         if (!dbg)
1058                 return -EBADF;
1059
1060         /* Find cu die */
1061         if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) {
1062                 ret = -EINVAL;
1063                 goto end;
1064         }
1065
1066         /* Find a corresponding line */
1067         line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
1068         if (line) {
1069                 if (dwarf_lineaddr(line, &laddr) == 0 &&
1070                     (Dwarf_Addr)addr == laddr &&
1071                     dwarf_lineno(line, &lineno) == 0) {
1072                         tmp = dwarf_linesrc(line, NULL, NULL);
1073                         if (tmp) {
1074                                 ppt->line = lineno;
1075                                 ppt->file = strdup(tmp);
1076                                 if (ppt->file == NULL) {
1077                                         ret = -ENOMEM;
1078                                         goto end;
1079                                 }
1080                                 found = true;
1081                         }
1082                 }
1083         }
1084
1085         /* Find a corresponding function */
1086         if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
1087                 tmp = dwarf_diename(&spdie);
1088                 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
1089                         goto end;
1090
1091                 if (ppt->line) {
1092                         if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
1093                                                 &indie)) {
1094                                 /* addr in an inline function */
1095                                 tmp = dwarf_diename(&indie);
1096                                 if (!tmp)
1097                                         goto end;
1098                                 ret = dwarf_decl_line(&indie, &lineno);
1099                         } else {
1100                                 if (eaddr == addr) {    /* Function entry */
1101                                         lineno = ppt->line;
1102                                         ret = 0;
1103                                 } else
1104                                         ret = dwarf_decl_line(&spdie, &lineno);
1105                         }
1106                         if (ret == 0) {
1107                                 /* Make a relative line number */
1108                                 ppt->line -= lineno;
1109                                 goto found;
1110                         }
1111                 }
1112                 /* We don't have a line number, let's use offset */
1113                 ppt->offset = addr - (unsigned long)eaddr;
1114 found:
1115                 ppt->function = strdup(tmp);
1116                 if (ppt->function == NULL) {
1117                         ret = -ENOMEM;
1118                         goto end;
1119                 }
1120                 found = true;
1121         }
1122
1123 end:
1124         dwarf_end(dbg);
1125         if (ret >= 0)
1126                 ret = found ? 1 : 0;
1127         return ret;
1128 }
1129
1130
1131 /* Find line range from its line number */
1132 static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1133 {
1134         Dwarf_Lines *lines;
1135         Dwarf_Line *line;
1136         size_t nlines, i;
1137         Dwarf_Addr addr;
1138         int lineno;
1139         const char *src;
1140         Dwarf_Die die_mem;
1141
1142         line_list__init(&lf->lr->line_list);
1143         if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1144                 pr_warning("No source lines found in this CU.\n");
1145                 return -ENOENT;
1146         }
1147
1148         for (i = 0; i < nlines; i++) {
1149                 line = dwarf_onesrcline(lines, i);
1150                 if (dwarf_lineno(line, &lineno) != 0 ||
1151                     (lf->lno_s > lineno || lf->lno_e < lineno))
1152                         continue;
1153
1154                 if (sp_die) {
1155                         /* Address filtering 1: does sp_die include addr? */
1156                         if (dwarf_lineaddr(line, &addr) != 0 ||
1157                             !dwarf_haspc(sp_die, addr))
1158                                 continue;
1159
1160                         /* Address filtering 2: No child include addr? */
1161                         if (die_find_inlinefunc(sp_die, addr, &die_mem))
1162                                 continue;
1163                 }
1164
1165                 /* TODO: Get fileno from line, but how? */
1166                 src = dwarf_linesrc(line, NULL, NULL);
1167                 if (strtailcmp(src, lf->fname) != 0)
1168                         continue;
1169
1170                 /* Copy real path */
1171                 if (!lf->lr->path) {
1172                         lf->lr->path = strdup(src);
1173                         if (lf->lr->path == NULL)
1174                                 return -ENOMEM;
1175                 }
1176                 line_list__add_line(&lf->lr->line_list, lineno);
1177         }
1178         /* Update status */
1179         if (!list_empty(&lf->lr->line_list))
1180                 lf->found = 1;
1181         else {
1182                 free(lf->lr->path);
1183                 lf->lr->path = NULL;
1184         }
1185         return lf->found;
1186 }
1187
1188 static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1189 {
1190         struct dwarf_callback_param *param = data;
1191
1192         param->retval = find_line_range_by_line(in_die, param->data);
1193         return DWARF_CB_ABORT;  /* No need to find other instances */
1194 }
1195
1196 /* Search function from function name */
1197 static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1198 {
1199         struct dwarf_callback_param *param = data;
1200         struct line_finder *lf = param->data;
1201         struct line_range *lr = lf->lr;
1202
1203         if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
1204             die_compare_name(sp_die, lr->function) == 0) {
1205                 lf->fname = dwarf_decl_file(sp_die);
1206                 dwarf_decl_line(sp_die, &lr->offset);
1207                 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
1208                 lf->lno_s = lr->offset + lr->start;
1209                 if (lf->lno_s < 0)      /* Overflow */
1210                         lf->lno_s = INT_MAX;
1211                 lf->lno_e = lr->offset + lr->end;
1212                 if (lf->lno_e < 0)      /* Overflow */
1213                         lf->lno_e = INT_MAX;
1214                 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1215                 lr->start = lf->lno_s;
1216                 lr->end = lf->lno_e;
1217                 if (dwarf_func_inline(sp_die)) {
1218                         struct dwarf_callback_param _param;
1219                         _param.data = (void *)lf;
1220                         _param.retval = 0;
1221                         dwarf_func_inline_instances(sp_die,
1222                                                     line_range_inline_cb,
1223                                                     &_param);
1224                         param->retval = _param.retval;
1225                 } else
1226                         param->retval = find_line_range_by_line(sp_die, lf);
1227                 return DWARF_CB_ABORT;
1228         }
1229         return DWARF_CB_OK;
1230 }
1231
1232 static int find_line_range_by_func(struct line_finder *lf)
1233 {
1234         struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1235         dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
1236         return param.retval;
1237 }
1238
1239 int find_line_range(int fd, struct line_range *lr)
1240 {
1241         struct line_finder lf = {.lr = lr, .found = 0};
1242         int ret = 0;
1243         Dwarf_Off off = 0, noff;
1244         size_t cuhl;
1245         Dwarf_Die *diep;
1246         Dwarf *dbg;
1247
1248         dbg = dwarf_begin(fd, DWARF_C_READ);
1249         if (!dbg) {
1250                 pr_warning("No dwarf info found in the vmlinux - "
1251                         "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1252                 return -EBADF;
1253         }
1254
1255         /* Loop on CUs (Compilation Unit) */
1256         while (!lf.found && ret >= 0) {
1257                 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
1258                         break;
1259
1260                 /* Get the DIE(Debugging Information Entry) of this CU */
1261                 diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
1262                 if (!diep)
1263                         continue;
1264
1265                 /* Check if target file is included. */
1266                 if (lr->file)
1267                         lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
1268                 else
1269                         lf.fname = 0;
1270
1271                 if (!lr->file || lf.fname) {
1272                         if (lr->function)
1273                                 ret = find_line_range_by_func(&lf);
1274                         else {
1275                                 lf.lno_s = lr->start;
1276                                 lf.lno_e = lr->end;
1277                                 ret = find_line_range_by_line(NULL, &lf);
1278                         }
1279                 }
1280                 off = noff;
1281         }
1282         pr_debug("path: %lx\n", (unsigned long)lr->path);
1283         dwarf_end(dbg);
1284
1285         return (ret < 0) ? ret : lf.found;
1286 }
1287