perf probe: Show accessible local variables
[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 #include <dwarf-regs.h>
35
36 #include "event.h"
37 #include "debug.h"
38 #include "util.h"
39 #include "symbol.h"
40 #include "probe-finder.h"
41
42 /* Kprobe tracer basic type is up to u64 */
43 #define MAX_BASIC_TYPE_BITS     64
44
45 /*
46  * Compare the tail of two strings.
47  * Return 0 if whole of either string is same as another's tail part.
48  */
49 static int strtailcmp(const char *s1, const char *s2)
50 {
51         int i1 = strlen(s1);
52         int i2 = strlen(s2);
53         while (--i1 >= 0 && --i2 >= 0) {
54                 if (s1[i1] != s2[i2])
55                         return s1[i1] - s2[i2];
56         }
57         return 0;
58 }
59
60 /* Line number list operations */
61
62 /* Add a line to line number list */
63 static int line_list__add_line(struct list_head *head, int line)
64 {
65         struct line_node *ln;
66         struct list_head *p;
67
68         /* Reverse search, because new line will be the last one */
69         list_for_each_entry_reverse(ln, head, list) {
70                 if (ln->line < line) {
71                         p = &ln->list;
72                         goto found;
73                 } else if (ln->line == line)    /* Already exist */
74                         return 1;
75         }
76         /* List is empty, or the smallest entry */
77         p = head;
78 found:
79         pr_debug("line list: add a line %u\n", line);
80         ln = zalloc(sizeof(struct line_node));
81         if (ln == NULL)
82                 return -ENOMEM;
83         ln->line = line;
84         INIT_LIST_HEAD(&ln->list);
85         list_add(&ln->list, p);
86         return 0;
87 }
88
89 /* Check if the line in line number list */
90 static int line_list__has_line(struct list_head *head, int line)
91 {
92         struct line_node *ln;
93
94         /* Reverse search, because new line will be the last one */
95         list_for_each_entry(ln, head, list)
96                 if (ln->line == line)
97                         return 1;
98
99         return 0;
100 }
101
102 /* Init line number list */
103 static void line_list__init(struct list_head *head)
104 {
105         INIT_LIST_HEAD(head);
106 }
107
108 /* Free line number list */
109 static void line_list__free(struct list_head *head)
110 {
111         struct line_node *ln;
112         while (!list_empty(head)) {
113                 ln = list_first_entry(head, struct line_node, list);
114                 list_del(&ln->list);
115                 free(ln);
116         }
117 }
118
119 /* Dwarf wrappers */
120
121 /* Find the realpath of the target file. */
122 static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
123 {
124         Dwarf_Files *files;
125         size_t nfiles, i;
126         const char *src = NULL;
127         int ret;
128
129         if (!fname)
130                 return NULL;
131
132         ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
133         if (ret != 0)
134                 return NULL;
135
136         for (i = 0; i < nfiles; i++) {
137                 src = dwarf_filesrc(files, i, NULL, NULL);
138                 if (strtailcmp(src, fname) == 0)
139                         break;
140         }
141         if (i == nfiles)
142                 return NULL;
143         return src;
144 }
145
146 /* Get DW_AT_comp_dir (should be NULL with older gcc) */
147 static const char *cu_get_comp_dir(Dwarf_Die *cu_die)
148 {
149         Dwarf_Attribute attr;
150         if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
151                 return NULL;
152         return dwarf_formstring(&attr);
153 }
154
155 /* Compare diename and tname */
156 static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
157 {
158         const char *name;
159         name = dwarf_diename(dw_die);
160         return name ? (strcmp(tname, name) == 0) : false;
161 }
162
163 /* Get type die */
164 static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
165 {
166         Dwarf_Attribute attr;
167
168         if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
169             dwarf_formref_die(&attr, die_mem))
170                 return die_mem;
171         else
172                 return NULL;
173 }
174
175 /* Get a type die, but skip qualifiers */
176 static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
177 {
178         int tag;
179
180         do {
181                 vr_die = die_get_type(vr_die, die_mem);
182                 if (!vr_die)
183                         break;
184                 tag = dwarf_tag(vr_die);
185         } while (tag == DW_TAG_const_type ||
186                  tag == DW_TAG_restrict_type ||
187                  tag == DW_TAG_volatile_type ||
188                  tag == DW_TAG_shared_type);
189
190         return vr_die;
191 }
192
193 /* Get a type die, but skip qualifiers and typedef */
194 static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
195 {
196         do {
197                 vr_die = __die_get_real_type(vr_die, die_mem);
198         } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
199
200         return vr_die;
201 }
202
203 static bool die_is_signed_type(Dwarf_Die *tp_die)
204 {
205         Dwarf_Attribute attr;
206         Dwarf_Word ret;
207
208         if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
209             dwarf_formudata(&attr, &ret) != 0)
210                 return false;
211
212         return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
213                 ret == DW_ATE_signed_fixed);
214 }
215
216 static int die_get_byte_size(Dwarf_Die *tp_die)
217 {
218         Dwarf_Attribute attr;
219         Dwarf_Word ret;
220
221         if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
222             dwarf_formudata(&attr, &ret) != 0)
223                 return 0;
224
225         return (int)ret;
226 }
227
228 /* Get data_member_location offset */
229 static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
230 {
231         Dwarf_Attribute attr;
232         Dwarf_Op *expr;
233         size_t nexpr;
234         int ret;
235
236         if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
237                 return -ENOENT;
238
239         if (dwarf_formudata(&attr, offs) != 0) {
240                 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
241                 ret = dwarf_getlocation(&attr, &expr, &nexpr);
242                 if (ret < 0 || nexpr == 0)
243                         return -ENOENT;
244
245                 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
246                         pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
247                                  expr[0].atom, nexpr);
248                         return -ENOTSUP;
249                 }
250                 *offs = (Dwarf_Word)expr[0].number;
251         }
252         return 0;
253 }
254
255 /* Return values for die_find callbacks */
256 enum {
257         DIE_FIND_CB_FOUND = 0,          /* End of Search */
258         DIE_FIND_CB_CHILD = 1,          /* Search only children */
259         DIE_FIND_CB_SIBLING = 2,        /* Search only siblings */
260         DIE_FIND_CB_CONTINUE = 3,       /* Search children and siblings */
261 };
262
263 /* Search a child die */
264 static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
265                                  int (*callback)(Dwarf_Die *, void *),
266                                  void *data, Dwarf_Die *die_mem)
267 {
268         Dwarf_Die child_die;
269         int ret;
270
271         ret = dwarf_child(rt_die, die_mem);
272         if (ret != 0)
273                 return NULL;
274
275         do {
276                 ret = callback(die_mem, data);
277                 if (ret == DIE_FIND_CB_FOUND)
278                         return die_mem;
279
280                 if ((ret & DIE_FIND_CB_CHILD) &&
281                     die_find_child(die_mem, callback, data, &child_die)) {
282                         memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
283                         return die_mem;
284                 }
285         } while ((ret & DIE_FIND_CB_SIBLING) &&
286                  dwarf_siblingof(die_mem, die_mem) == 0);
287
288         return NULL;
289 }
290
291 struct __addr_die_search_param {
292         Dwarf_Addr      addr;
293         Dwarf_Die       *die_mem;
294 };
295
296 static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
297 {
298         struct __addr_die_search_param *ad = data;
299
300         if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
301             dwarf_haspc(fn_die, ad->addr)) {
302                 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
303                 return DWARF_CB_ABORT;
304         }
305         return DWARF_CB_OK;
306 }
307
308 /* Search a real subprogram including this line, */
309 static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
310                                            Dwarf_Die *die_mem)
311 {
312         struct __addr_die_search_param ad;
313         ad.addr = addr;
314         ad.die_mem = die_mem;
315         /* dwarf_getscopes can't find subprogram. */
316         if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
317                 return NULL;
318         else
319                 return die_mem;
320 }
321
322 /* die_find callback for inline function search */
323 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
324 {
325         Dwarf_Addr *addr = data;
326
327         if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
328             dwarf_haspc(die_mem, *addr))
329                 return DIE_FIND_CB_FOUND;
330
331         return DIE_FIND_CB_CONTINUE;
332 }
333
334 /* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
335 static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
336                                       Dwarf_Die *die_mem)
337 {
338         return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
339 }
340
341 struct __find_variable_param {
342         const char *name;
343         Dwarf_Addr addr;
344 };
345
346 static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
347 {
348         struct __find_variable_param *fvp = data;
349         int tag;
350
351         tag = dwarf_tag(die_mem);
352         if ((tag == DW_TAG_formal_parameter ||
353              tag == DW_TAG_variable) &&
354             die_compare_name(die_mem, fvp->name))
355                 return DIE_FIND_CB_FOUND;
356
357         if (dwarf_haspc(die_mem, fvp->addr))
358                 return DIE_FIND_CB_CONTINUE;
359         else
360                 return DIE_FIND_CB_SIBLING;
361 }
362
363 /* Find a variable called 'name' at given address */
364 static Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
365                                        Dwarf_Addr addr, Dwarf_Die *die_mem)
366 {
367         struct __find_variable_param fvp = { .name = name, .addr = addr};
368
369         return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
370                               die_mem);
371 }
372
373 static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
374 {
375         const char *name = data;
376
377         if ((dwarf_tag(die_mem) == DW_TAG_member) &&
378             die_compare_name(die_mem, name))
379                 return DIE_FIND_CB_FOUND;
380
381         return DIE_FIND_CB_SIBLING;
382 }
383
384 /* Find a member called 'name' */
385 static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
386                                   Dwarf_Die *die_mem)
387 {
388         return die_find_child(st_die, __die_find_member_cb, (void *)name,
389                               die_mem);
390 }
391
392 /* Get the name of given variable DIE */
393 static int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
394 {
395         Dwarf_Die type;
396         int tag, ret, ret2;
397         const char *tmp = "";
398
399         if (__die_get_real_type(vr_die, &type) == NULL)
400                 return -ENOENT;
401
402         tag = dwarf_tag(&type);
403         if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
404                 tmp = "*";
405         else if (tag == DW_TAG_subroutine_type) {
406                 /* Function pointer */
407                 ret = snprintf(buf, len, "(function_type)");
408                 return (ret >= len) ? -E2BIG : ret;
409         } else {
410                 if (!dwarf_diename(&type))
411                         return -ENOENT;
412                 if (tag == DW_TAG_union_type)
413                         tmp = "union ";
414                 else if (tag == DW_TAG_structure_type)
415                         tmp = "struct ";
416                 /* Write a base name */
417                 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
418                 return (ret >= len) ? -E2BIG : ret;
419         }
420         ret = die_get_typename(&type, buf, len);
421         if (ret > 0) {
422                 ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
423                 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
424         }
425         return ret;
426 }
427
428 /* Get the name and type of given variable DIE, stored as "type\tname" */
429 static int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
430 {
431         int ret, ret2;
432
433         ret = die_get_typename(vr_die, buf, len);
434         if (ret < 0) {
435                 pr_debug("Failed to get type, make it unknown.\n");
436                 ret = snprintf(buf, len, "(unknown_type)");
437         }
438         if (ret > 0) {
439                 ret2 = snprintf(buf + ret, len - ret, "\t%s",
440                                 dwarf_diename(vr_die));
441                 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
442         }
443         return ret;
444 }
445
446 /*
447  * Probe finder related functions
448  */
449
450 static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
451 {
452         struct probe_trace_arg_ref *ref;
453         ref = zalloc(sizeof(struct probe_trace_arg_ref));
454         if (ref != NULL)
455                 ref->offset = offs;
456         return ref;
457 }
458
459 /*
460  * Convert a location into trace_arg.
461  * If tvar == NULL, this just checks variable can be converted.
462  */
463 static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
464                                      Dwarf_Op *fb_ops,
465                                      struct probe_trace_arg *tvar)
466 {
467         Dwarf_Attribute attr;
468         Dwarf_Op *op;
469         size_t nops;
470         unsigned int regn;
471         Dwarf_Word offs = 0;
472         bool ref = false;
473         const char *regs;
474         int ret;
475
476         if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL)
477                 goto static_var;
478
479         /* TODO: handle more than 1 exprs */
480         if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
481             dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
482             nops == 0) {
483                 /* TODO: Support const_value */
484                 return -ENOENT;
485         }
486
487         if (op->atom == DW_OP_addr) {
488 static_var:
489                 if (!tvar)
490                         return 0;
491                 /* Static variables on memory (not stack), make @varname */
492                 ret = strlen(dwarf_diename(vr_die));
493                 tvar->value = zalloc(ret + 2);
494                 if (tvar->value == NULL)
495                         return -ENOMEM;
496                 snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
497                 tvar->ref = alloc_trace_arg_ref((long)offs);
498                 if (tvar->ref == NULL)
499                         return -ENOMEM;
500                 return 0;
501         }
502
503         /* If this is based on frame buffer, set the offset */
504         if (op->atom == DW_OP_fbreg) {
505                 if (fb_ops == NULL)
506                         return -ENOTSUP;
507                 ref = true;
508                 offs = op->number;
509                 op = &fb_ops[0];
510         }
511
512         if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
513                 regn = op->atom - DW_OP_breg0;
514                 offs += op->number;
515                 ref = true;
516         } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
517                 regn = op->atom - DW_OP_reg0;
518         } else if (op->atom == DW_OP_bregx) {
519                 regn = op->number;
520                 offs += op->number2;
521                 ref = true;
522         } else if (op->atom == DW_OP_regx) {
523                 regn = op->number;
524         } else {
525                 pr_debug("DW_OP %x is not supported.\n", op->atom);
526                 return -ENOTSUP;
527         }
528
529         if (!tvar)
530                 return 0;
531
532         regs = get_arch_regstr(regn);
533         if (!regs) {
534                 /* This should be a bug in DWARF or this tool */
535                 pr_warning("Mapping for DWARF register number %u "
536                            "missing on this architecture.", regn);
537                 return -ERANGE;
538         }
539
540         tvar->value = strdup(regs);
541         if (tvar->value == NULL)
542                 return -ENOMEM;
543
544         if (ref) {
545                 tvar->ref = alloc_trace_arg_ref((long)offs);
546                 if (tvar->ref == NULL)
547                         return -ENOMEM;
548         }
549         return 0;
550 }
551
552 static int convert_variable_type(Dwarf_Die *vr_die,
553                                  struct probe_trace_arg *tvar,
554                                  const char *cast)
555 {
556         struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
557         Dwarf_Die type;
558         char buf[16];
559         int ret;
560
561         /* TODO: check all types */
562         if (cast && strcmp(cast, "string") != 0) {
563                 /* Non string type is OK */
564                 tvar->type = strdup(cast);
565                 return (tvar->type == NULL) ? -ENOMEM : 0;
566         }
567
568         if (die_get_real_type(vr_die, &type) == NULL) {
569                 pr_warning("Failed to get a type information of %s.\n",
570                            dwarf_diename(vr_die));
571                 return -ENOENT;
572         }
573
574         pr_debug("%s type is %s.\n",
575                  dwarf_diename(vr_die), dwarf_diename(&type));
576
577         if (cast && strcmp(cast, "string") == 0) {      /* String type */
578                 ret = dwarf_tag(&type);
579                 if (ret != DW_TAG_pointer_type &&
580                     ret != DW_TAG_array_type) {
581                         pr_warning("Failed to cast into string: "
582                                    "%s(%s) is not a pointer nor array.",
583                                    dwarf_diename(vr_die), dwarf_diename(&type));
584                         return -EINVAL;
585                 }
586                 if (ret == DW_TAG_pointer_type) {
587                         if (die_get_real_type(&type, &type) == NULL) {
588                                 pr_warning("Failed to get a type information.");
589                                 return -ENOENT;
590                         }
591                         while (*ref_ptr)
592                                 ref_ptr = &(*ref_ptr)->next;
593                         /* Add new reference with offset +0 */
594                         *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref));
595                         if (*ref_ptr == NULL) {
596                                 pr_warning("Out of memory error\n");
597                                 return -ENOMEM;
598                         }
599                 }
600                 if (!die_compare_name(&type, "char") &&
601                     !die_compare_name(&type, "unsigned char")) {
602                         pr_warning("Failed to cast into string: "
603                                    "%s is not (unsigned) char *.",
604                                    dwarf_diename(vr_die));
605                         return -EINVAL;
606                 }
607                 tvar->type = strdup(cast);
608                 return (tvar->type == NULL) ? -ENOMEM : 0;
609         }
610
611         ret = die_get_byte_size(&type) * 8;
612         if (ret) {
613                 /* Check the bitwidth */
614                 if (ret > MAX_BASIC_TYPE_BITS) {
615                         pr_info("%s exceeds max-bitwidth."
616                                 " Cut down to %d bits.\n",
617                                 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
618                         ret = MAX_BASIC_TYPE_BITS;
619                 }
620
621                 ret = snprintf(buf, 16, "%c%d",
622                                die_is_signed_type(&type) ? 's' : 'u', ret);
623                 if (ret < 0 || ret >= 16) {
624                         if (ret >= 16)
625                                 ret = -E2BIG;
626                         pr_warning("Failed to convert variable type: %s\n",
627                                    strerror(-ret));
628                         return ret;
629                 }
630                 tvar->type = strdup(buf);
631                 if (tvar->type == NULL)
632                         return -ENOMEM;
633         }
634         return 0;
635 }
636
637 static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
638                                     struct perf_probe_arg_field *field,
639                                     struct probe_trace_arg_ref **ref_ptr,
640                                     Dwarf_Die *die_mem)
641 {
642         struct probe_trace_arg_ref *ref = *ref_ptr;
643         Dwarf_Die type;
644         Dwarf_Word offs;
645         int ret, tag;
646
647         pr_debug("converting %s in %s\n", field->name, varname);
648         if (die_get_real_type(vr_die, &type) == NULL) {
649                 pr_warning("Failed to get the type of %s.\n", varname);
650                 return -ENOENT;
651         }
652         pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type));
653         tag = dwarf_tag(&type);
654
655         if (field->name[0] == '[' &&
656             (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) {
657                 if (field->next)
658                         /* Save original type for next field */
659                         memcpy(die_mem, &type, sizeof(*die_mem));
660                 /* Get the type of this array */
661                 if (die_get_real_type(&type, &type) == NULL) {
662                         pr_warning("Failed to get the type of %s.\n", varname);
663                         return -ENOENT;
664                 }
665                 pr_debug2("Array real type: (%x)\n",
666                          (unsigned)dwarf_dieoffset(&type));
667                 if (tag == DW_TAG_pointer_type) {
668                         ref = zalloc(sizeof(struct probe_trace_arg_ref));
669                         if (ref == NULL)
670                                 return -ENOMEM;
671                         if (*ref_ptr)
672                                 (*ref_ptr)->next = ref;
673                         else
674                                 *ref_ptr = ref;
675                 }
676                 ref->offset += die_get_byte_size(&type) * field->index;
677                 if (!field->next)
678                         /* Save vr_die for converting types */
679                         memcpy(die_mem, vr_die, sizeof(*die_mem));
680                 goto next;
681         } else if (tag == DW_TAG_pointer_type) {
682                 /* Check the pointer and dereference */
683                 if (!field->ref) {
684                         pr_err("Semantic error: %s must be referred by '->'\n",
685                                field->name);
686                         return -EINVAL;
687                 }
688                 /* Get the type pointed by this pointer */
689                 if (die_get_real_type(&type, &type) == NULL) {
690                         pr_warning("Failed to get the type of %s.\n", varname);
691                         return -ENOENT;
692                 }
693                 /* Verify it is a data structure  */
694                 if (dwarf_tag(&type) != DW_TAG_structure_type) {
695                         pr_warning("%s is not a data structure.\n", varname);
696                         return -EINVAL;
697                 }
698
699                 ref = zalloc(sizeof(struct probe_trace_arg_ref));
700                 if (ref == NULL)
701                         return -ENOMEM;
702                 if (*ref_ptr)
703                         (*ref_ptr)->next = ref;
704                 else
705                         *ref_ptr = ref;
706         } else {
707                 /* Verify it is a data structure  */
708                 if (tag != DW_TAG_structure_type) {
709                         pr_warning("%s is not a data structure.\n", varname);
710                         return -EINVAL;
711                 }
712                 if (field->name[0] == '[') {
713                         pr_err("Semantic error: %s is not a pointor nor array.",
714                                varname);
715                         return -EINVAL;
716                 }
717                 if (field->ref) {
718                         pr_err("Semantic error: %s must be referred by '.'\n",
719                                field->name);
720                         return -EINVAL;
721                 }
722                 if (!ref) {
723                         pr_warning("Structure on a register is not "
724                                    "supported yet.\n");
725                         return -ENOTSUP;
726                 }
727         }
728
729         if (die_find_member(&type, field->name, die_mem) == NULL) {
730                 pr_warning("%s(tyep:%s) has no member %s.\n", varname,
731                            dwarf_diename(&type), field->name);
732                 return -EINVAL;
733         }
734
735         /* Get the offset of the field */
736         ret = die_get_data_member_location(die_mem, &offs);
737         if (ret < 0) {
738                 pr_warning("Failed to get the offset of %s.\n", field->name);
739                 return ret;
740         }
741         ref->offset += (long)offs;
742
743 next:
744         /* Converting next field */
745         if (field->next)
746                 return convert_variable_fields(die_mem, field->name,
747                                         field->next, &ref, die_mem);
748         else
749                 return 0;
750 }
751
752 /* Show a variables in kprobe event format */
753 static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
754 {
755         Dwarf_Die die_mem;
756         int ret;
757
758         pr_debug("Converting variable %s into trace event.\n",
759                  dwarf_diename(vr_die));
760
761         ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
762                                         pf->tvar);
763         if (ret == -ENOENT)
764                 pr_err("Failed to find the location of %s at this address.\n"
765                        " Perhaps, it has been optimized out.\n", pf->pvar->var);
766         else if (ret == -ENOTSUP)
767                 pr_err("Sorry, we don't support this variable location yet.\n");
768         else if (pf->pvar->field) {
769                 ret = convert_variable_fields(vr_die, pf->pvar->var,
770                                               pf->pvar->field, &pf->tvar->ref,
771                                               &die_mem);
772                 vr_die = &die_mem;
773         }
774         if (ret == 0)
775                 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type);
776         /* *expr will be cached in libdw. Don't free it. */
777         return ret;
778 }
779
780 /* Find a variable in a subprogram die */
781 static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
782 {
783         Dwarf_Die vr_die, *scopes;
784         char buf[32], *ptr;
785         int ret, nscopes;
786
787         if (!is_c_varname(pf->pvar->var)) {
788                 /* Copy raw parameters */
789                 pf->tvar->value = strdup(pf->pvar->var);
790                 if (pf->tvar->value == NULL)
791                         return -ENOMEM;
792                 if (pf->pvar->type) {
793                         pf->tvar->type = strdup(pf->pvar->type);
794                         if (pf->tvar->type == NULL)
795                                 return -ENOMEM;
796                 }
797                 if (pf->pvar->name) {
798                         pf->tvar->name = strdup(pf->pvar->name);
799                         if (pf->tvar->name == NULL)
800                                 return -ENOMEM;
801                 } else
802                         pf->tvar->name = NULL;
803                 return 0;
804         }
805
806         if (pf->pvar->name)
807                 pf->tvar->name = strdup(pf->pvar->name);
808         else {
809                 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);
810                 if (ret < 0)
811                         return ret;
812                 ptr = strchr(buf, ':'); /* Change type separator to _ */
813                 if (ptr)
814                         *ptr = '_';
815                 pf->tvar->name = strdup(buf);
816         }
817         if (pf->tvar->name == NULL)
818                 return -ENOMEM;
819
820         pr_debug("Searching '%s' variable in context.\n",
821                  pf->pvar->var);
822         /* Search child die for local variables and parameters. */
823         if (die_find_variable_at(sp_die, pf->pvar->var, pf->addr, &vr_die))
824                 ret = convert_variable(&vr_die, pf);
825         else {
826                 /* Search upper class */
827                 nscopes = dwarf_getscopes_die(sp_die, &scopes);
828                 while (nscopes-- > 1) {
829                         pr_debug("Searching variables in %s\n",
830                                  dwarf_diename(&scopes[nscopes]));
831                         /* We should check this scope, so give dummy address */
832                         if (die_find_variable_at(&scopes[nscopes],
833                                                  pf->pvar->var, 0,
834                                                  &vr_die)) {
835                                 ret = convert_variable(&vr_die, pf);
836                                 goto found;
837                         }
838                 }
839                 if (scopes)
840                         free(scopes);
841                 ret = -ENOENT;
842         }
843 found:
844         if (ret < 0)
845                 pr_warning("Failed to find '%s' in this function.\n",
846                            pf->pvar->var);
847         return ret;
848 }
849
850 /* Convert subprogram DIE to trace point */
851 static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
852                                   bool retprobe, struct probe_trace_point *tp)
853 {
854         Dwarf_Addr eaddr;
855         const char *name;
856
857         /* Copy the name of probe point */
858         name = dwarf_diename(sp_die);
859         if (name) {
860                 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
861                         pr_warning("Failed to get entry pc of %s\n",
862                                    dwarf_diename(sp_die));
863                         return -ENOENT;
864                 }
865                 tp->symbol = strdup(name);
866                 if (tp->symbol == NULL)
867                         return -ENOMEM;
868                 tp->offset = (unsigned long)(paddr - eaddr);
869         } else
870                 /* This function has no name. */
871                 tp->offset = (unsigned long)paddr;
872
873         /* Return probe must be on the head of a subprogram */
874         if (retprobe) {
875                 if (eaddr != paddr) {
876                         pr_warning("Return probe must be on the head of"
877                                    " a real function\n");
878                         return -EINVAL;
879                 }
880                 tp->retprobe = true;
881         }
882
883         return 0;
884 }
885
886 /* Call probe_finder callback with real subprogram DIE */
887 static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
888 {
889         Dwarf_Die die_mem;
890         Dwarf_Attribute fb_attr;
891         size_t nops;
892         int ret;
893
894         /* If no real subprogram, find a real one */
895         if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) {
896                 sp_die = die_find_real_subprogram(&pf->cu_die,
897                                                   pf->addr, &die_mem);
898                 if (!sp_die) {
899                         pr_warning("Failed to find probe point in any "
900                                    "functions.\n");
901                         return -ENOENT;
902                 }
903         }
904
905         /* Get the frame base attribute/ops */
906         dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
907         ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
908         if (ret <= 0 || nops == 0) {
909                 pf->fb_ops = NULL;
910 #if _ELFUTILS_PREREQ(0, 142)
911         } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
912                    pf->cfi != NULL) {
913                 Dwarf_Frame *frame;
914                 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
915                     dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
916                         pr_warning("Failed to get CFA on 0x%jx\n",
917                                    (uintmax_t)pf->addr);
918                         return -ENOENT;
919                 }
920 #endif
921         }
922
923         /* Call finder's callback handler */
924         ret = pf->callback(sp_die, pf);
925
926         /* *pf->fb_ops will be cached in libdw. Don't free it. */
927         pf->fb_ops = NULL;
928
929         return ret;
930 }
931
932 /* Find probe point from its line number */
933 static int find_probe_point_by_line(struct probe_finder *pf)
934 {
935         Dwarf_Lines *lines;
936         Dwarf_Line *line;
937         size_t nlines, i;
938         Dwarf_Addr addr;
939         int lineno;
940         int ret = 0;
941
942         if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
943                 pr_warning("No source lines found in this CU.\n");
944                 return -ENOENT;
945         }
946
947         for (i = 0; i < nlines && ret == 0; i++) {
948                 line = dwarf_onesrcline(lines, i);
949                 if (dwarf_lineno(line, &lineno) != 0 ||
950                     lineno != pf->lno)
951                         continue;
952
953                 /* TODO: Get fileno from line, but how? */
954                 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
955                         continue;
956
957                 if (dwarf_lineaddr(line, &addr) != 0) {
958                         pr_warning("Failed to get the address of the line.\n");
959                         return -ENOENT;
960                 }
961                 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
962                          (int)i, lineno, (uintmax_t)addr);
963                 pf->addr = addr;
964
965                 ret = call_probe_finder(NULL, pf);
966                 /* Continuing, because target line might be inlined. */
967         }
968         return ret;
969 }
970
971 /* Find lines which match lazy pattern */
972 static int find_lazy_match_lines(struct list_head *head,
973                                  const char *fname, const char *pat)
974 {
975         char *fbuf, *p1, *p2;
976         int fd, line, nlines = -1;
977         struct stat st;
978
979         fd = open(fname, O_RDONLY);
980         if (fd < 0) {
981                 pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
982                 return -errno;
983         }
984
985         if (fstat(fd, &st) < 0) {
986                 pr_warning("Failed to get the size of %s: %s\n",
987                            fname, strerror(errno));
988                 nlines = -errno;
989                 goto out_close;
990         }
991
992         nlines = -ENOMEM;
993         fbuf = malloc(st.st_size + 2);
994         if (fbuf == NULL)
995                 goto out_close;
996         if (read(fd, fbuf, st.st_size) < 0) {
997                 pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
998                 nlines = -errno;
999                 goto out_free_fbuf;
1000         }
1001         fbuf[st.st_size] = '\n';        /* Dummy line */
1002         fbuf[st.st_size + 1] = '\0';
1003         p1 = fbuf;
1004         line = 1;
1005         nlines = 0;
1006         while ((p2 = strchr(p1, '\n')) != NULL) {
1007                 *p2 = '\0';
1008                 if (strlazymatch(p1, pat)) {
1009                         line_list__add_line(head, line);
1010                         nlines++;
1011                 }
1012                 line++;
1013                 p1 = p2 + 1;
1014         }
1015 out_free_fbuf:
1016         free(fbuf);
1017 out_close:
1018         close(fd);
1019         return nlines;
1020 }
1021
1022 /* Find probe points from lazy pattern  */
1023 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1024 {
1025         Dwarf_Lines *lines;
1026         Dwarf_Line *line;
1027         size_t nlines, i;
1028         Dwarf_Addr addr;
1029         Dwarf_Die die_mem;
1030         int lineno;
1031         int ret = 0;
1032
1033         if (list_empty(&pf->lcache)) {
1034                 /* Matching lazy line pattern */
1035                 ret = find_lazy_match_lines(&pf->lcache, pf->fname,
1036                                             pf->pev->point.lazy_line);
1037                 if (ret == 0) {
1038                         pr_debug("No matched lines found in %s.\n", pf->fname);
1039                         return 0;
1040                 } else if (ret < 0)
1041                         return ret;
1042         }
1043
1044         if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1045                 pr_warning("No source lines found in this CU.\n");
1046                 return -ENOENT;
1047         }
1048
1049         for (i = 0; i < nlines && ret >= 0; i++) {
1050                 line = dwarf_onesrcline(lines, i);
1051
1052                 if (dwarf_lineno(line, &lineno) != 0 ||
1053                     !line_list__has_line(&pf->lcache, lineno))
1054                         continue;
1055
1056                 /* TODO: Get fileno from line, but how? */
1057                 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
1058                         continue;
1059
1060                 if (dwarf_lineaddr(line, &addr) != 0) {
1061                         pr_debug("Failed to get the address of line %d.\n",
1062                                  lineno);
1063                         continue;
1064                 }
1065                 if (sp_die) {
1066                         /* Address filtering 1: does sp_die include addr? */
1067                         if (!dwarf_haspc(sp_die, addr))
1068                                 continue;
1069                         /* Address filtering 2: No child include addr? */
1070                         if (die_find_inlinefunc(sp_die, addr, &die_mem))
1071                                 continue;
1072                 }
1073
1074                 pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
1075                          (int)i, lineno, (unsigned long long)addr);
1076                 pf->addr = addr;
1077
1078                 ret = call_probe_finder(sp_die, pf);
1079                 /* Continuing, because target line might be inlined. */
1080         }
1081         /* TODO: deallocate lines, but how? */
1082         return ret;
1083 }
1084
1085 /* Callback parameter with return value */
1086 struct dwarf_callback_param {
1087         void *data;
1088         int retval;
1089 };
1090
1091 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1092 {
1093         struct dwarf_callback_param *param = data;
1094         struct probe_finder *pf = param->data;
1095         struct perf_probe_point *pp = &pf->pev->point;
1096         Dwarf_Addr addr;
1097
1098         if (pp->lazy_line)
1099                 param->retval = find_probe_point_lazy(in_die, pf);
1100         else {
1101                 /* Get probe address */
1102                 if (dwarf_entrypc(in_die, &addr) != 0) {
1103                         pr_warning("Failed to get entry pc of %s.\n",
1104                                    dwarf_diename(in_die));
1105                         param->retval = -ENOENT;
1106                         return DWARF_CB_ABORT;
1107                 }
1108                 pf->addr = addr;
1109                 pf->addr += pp->offset;
1110                 pr_debug("found inline addr: 0x%jx\n",
1111                          (uintmax_t)pf->addr);
1112
1113                 param->retval = call_probe_finder(in_die, pf);
1114                 if (param->retval < 0)
1115                         return DWARF_CB_ABORT;
1116         }
1117
1118         return DWARF_CB_OK;
1119 }
1120
1121 /* Search function from function name */
1122 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1123 {
1124         struct dwarf_callback_param *param = data;
1125         struct probe_finder *pf = param->data;
1126         struct perf_probe_point *pp = &pf->pev->point;
1127
1128         /* Check tag and diename */
1129         if (dwarf_tag(sp_die) != DW_TAG_subprogram ||
1130             !die_compare_name(sp_die, pp->function))
1131                 return DWARF_CB_OK;
1132
1133         pf->fname = dwarf_decl_file(sp_die);
1134         if (pp->line) { /* Function relative line */
1135                 dwarf_decl_line(sp_die, &pf->lno);
1136                 pf->lno += pp->line;
1137                 param->retval = find_probe_point_by_line(pf);
1138         } else if (!dwarf_func_inline(sp_die)) {
1139                 /* Real function */
1140                 if (pp->lazy_line)
1141                         param->retval = find_probe_point_lazy(sp_die, pf);
1142                 else {
1143                         if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1144                                 pr_warning("Failed to get entry pc of %s.\n",
1145                                            dwarf_diename(sp_die));
1146                                 param->retval = -ENOENT;
1147                                 return DWARF_CB_ABORT;
1148                         }
1149                         pf->addr += pp->offset;
1150                         /* TODO: Check the address in this function */
1151                         param->retval = call_probe_finder(sp_die, pf);
1152                 }
1153         } else {
1154                 struct dwarf_callback_param _param = {.data = (void *)pf,
1155                                                       .retval = 0};
1156                 /* Inlined function: search instances */
1157                 dwarf_func_inline_instances(sp_die, probe_point_inline_cb,
1158                                             &_param);
1159                 param->retval = _param.retval;
1160         }
1161
1162         return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
1163 }
1164
1165 static int find_probe_point_by_func(struct probe_finder *pf)
1166 {
1167         struct dwarf_callback_param _param = {.data = (void *)pf,
1168                                               .retval = 0};
1169         dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
1170         return _param.retval;
1171 }
1172
1173 /* Find probe points from debuginfo */
1174 static int find_probes(int fd, struct probe_finder *pf)
1175 {
1176         struct perf_probe_point *pp = &pf->pev->point;
1177         Dwarf_Off off, noff;
1178         size_t cuhl;
1179         Dwarf_Die *diep;
1180         Dwarf *dbg;
1181         int ret = 0;
1182
1183         dbg = dwarf_begin(fd, DWARF_C_READ);
1184         if (!dbg) {
1185                 pr_warning("No dwarf info found in the vmlinux - "
1186                         "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1187                 return -EBADF;
1188         }
1189
1190 #if _ELFUTILS_PREREQ(0, 142)
1191         /* Get the call frame information from this dwarf */
1192         pf->cfi = dwarf_getcfi(dbg);
1193 #endif
1194
1195         off = 0;
1196         line_list__init(&pf->lcache);
1197         /* Loop on CUs (Compilation Unit) */
1198         while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
1199                ret >= 0) {
1200                 /* Get the DIE(Debugging Information Entry) of this CU */
1201                 diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die);
1202                 if (!diep)
1203                         continue;
1204
1205                 /* Check if target file is included. */
1206                 if (pp->file)
1207                         pf->fname = cu_find_realpath(&pf->cu_die, pp->file);
1208                 else
1209                         pf->fname = NULL;
1210
1211                 if (!pp->file || pf->fname) {
1212                         if (pp->function)
1213                                 ret = find_probe_point_by_func(pf);
1214                         else if (pp->lazy_line)
1215                                 ret = find_probe_point_lazy(NULL, pf);
1216                         else {
1217                                 pf->lno = pp->line;
1218                                 ret = find_probe_point_by_line(pf);
1219                         }
1220                 }
1221                 off = noff;
1222         }
1223         line_list__free(&pf->lcache);
1224         dwarf_end(dbg);
1225
1226         return ret;
1227 }
1228
1229 /* Add a found probe point into trace event list */
1230 static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1231 {
1232         struct trace_event_finder *tf =
1233                         container_of(pf, struct trace_event_finder, pf);
1234         struct probe_trace_event *tev;
1235         int ret, i;
1236
1237         /* Check number of tevs */
1238         if (tf->ntevs == tf->max_tevs) {
1239                 pr_warning("Too many( > %d) probe point found.\n",
1240                            tf->max_tevs);
1241                 return -ERANGE;
1242         }
1243         tev = &tf->tevs[tf->ntevs++];
1244
1245         ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
1246                                      &tev->point);
1247         if (ret < 0)
1248                 return ret;
1249
1250         pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1251                  tev->point.offset);
1252
1253         /* Find each argument */
1254         tev->nargs = pf->pev->nargs;
1255         tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1256         if (tev->args == NULL)
1257                 return -ENOMEM;
1258         for (i = 0; i < pf->pev->nargs; i++) {
1259                 pf->pvar = &pf->pev->args[i];
1260                 pf->tvar = &tev->args[i];
1261                 ret = find_variable(sp_die, pf);
1262                 if (ret != 0)
1263                         return ret;
1264         }
1265
1266         return 0;
1267 }
1268
1269 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
1270 int find_probe_trace_events(int fd, struct perf_probe_event *pev,
1271                             struct probe_trace_event **tevs, int max_tevs)
1272 {
1273         struct trace_event_finder tf = {
1274                         .pf = {.pev = pev, .callback = add_probe_trace_event},
1275                         .max_tevs = max_tevs};
1276         int ret;
1277
1278         /* Allocate result tevs array */
1279         *tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
1280         if (*tevs == NULL)
1281                 return -ENOMEM;
1282
1283         tf.tevs = *tevs;
1284         tf.ntevs = 0;
1285
1286         ret = find_probes(fd, &tf.pf);
1287         if (ret < 0) {
1288                 free(*tevs);
1289                 *tevs = NULL;
1290                 return ret;
1291         }
1292
1293         return (ret < 0) ? ret : tf.ntevs;
1294 }
1295
1296 #define MAX_VAR_LEN 64
1297
1298 /* Collect available variables in this scope */
1299 static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1300 {
1301         struct available_var_finder *af = data;
1302         struct variable_list *vl;
1303         char buf[MAX_VAR_LEN];
1304         int tag, ret;
1305
1306         vl = &af->vls[af->nvls - 1];
1307
1308         tag = dwarf_tag(die_mem);
1309         if (tag == DW_TAG_formal_parameter ||
1310             tag == DW_TAG_variable) {
1311                 ret = convert_variable_location(die_mem, af->pf.addr,
1312                                                 af->pf.fb_ops, NULL);
1313                 if (ret == 0) {
1314                         ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
1315                         if (ret > 0)
1316                                 strlist__add(vl->vars, buf);
1317                 }
1318         }
1319
1320         if (dwarf_haspc(die_mem, af->pf.addr))
1321                 return DIE_FIND_CB_CONTINUE;
1322         else
1323                 return DIE_FIND_CB_SIBLING;
1324 }
1325
1326 /* Add a found vars into available variables list */
1327 static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1328 {
1329         struct available_var_finder *af =
1330                         container_of(pf, struct available_var_finder, pf);
1331         struct variable_list *vl;
1332         Dwarf_Die die_mem;
1333         int ret;
1334
1335         /* Check number of tevs */
1336         if (af->nvls == af->max_vls) {
1337                 pr_warning("Too many( > %d) probe point found.\n", af->max_vls);
1338                 return -ERANGE;
1339         }
1340         vl = &af->vls[af->nvls++];
1341
1342         ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe,
1343                                      &vl->point);
1344         if (ret < 0)
1345                 return ret;
1346
1347         pr_debug("Probe point found: %s+%lu\n", vl->point.symbol,
1348                  vl->point.offset);
1349
1350         /* Find local variables */
1351         vl->vars = strlist__new(true, NULL);
1352         if (vl->vars == NULL)
1353                 return -ENOMEM;
1354         die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem);
1355
1356         if (strlist__empty(vl->vars)) {
1357                 strlist__delete(vl->vars);
1358                 vl->vars = NULL;
1359         }
1360
1361         return ret;
1362 }
1363
1364 /* Find available variables at given probe point */
1365 int find_available_vars_at(int fd, struct perf_probe_event *pev,
1366                            struct variable_list **vls, int max_vls)
1367 {
1368         struct available_var_finder af = {
1369                         .pf = {.pev = pev, .callback = add_available_vars},
1370                         .max_vls = max_vls};
1371         int ret;
1372
1373         /* Allocate result vls array */
1374         *vls = zalloc(sizeof(struct variable_list) * max_vls);
1375         if (*vls == NULL)
1376                 return -ENOMEM;
1377
1378         af.vls = *vls;
1379         af.nvls = 0;
1380
1381         ret = find_probes(fd, &af.pf);
1382         if (ret < 0) {
1383                 /* Free vlist for error */
1384                 while (af.nvls--) {
1385                         if (af.vls[af.nvls].point.symbol)
1386                                 free(af.vls[af.nvls].point.symbol);
1387                         if (af.vls[af.nvls].vars)
1388                                 strlist__delete(af.vls[af.nvls].vars);
1389                 }
1390                 free(af.vls);
1391                 *vls = NULL;
1392                 return ret;
1393         }
1394
1395         return (ret < 0) ? ret : af.nvls;
1396 }
1397
1398 /* Reverse search */
1399 int find_perf_probe_point(int fd, unsigned long addr,
1400                           struct perf_probe_point *ppt)
1401 {
1402         Dwarf_Die cudie, spdie, indie;
1403         Dwarf *dbg;
1404         Dwarf_Line *line;
1405         Dwarf_Addr laddr, eaddr;
1406         const char *tmp;
1407         int lineno, ret = 0;
1408         bool found = false;
1409
1410         dbg = dwarf_begin(fd, DWARF_C_READ);
1411         if (!dbg)
1412                 return -EBADF;
1413
1414         /* Find cu die */
1415         if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) {
1416                 ret = -EINVAL;
1417                 goto end;
1418         }
1419
1420         /* Find a corresponding line */
1421         line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
1422         if (line) {
1423                 if (dwarf_lineaddr(line, &laddr) == 0 &&
1424                     (Dwarf_Addr)addr == laddr &&
1425                     dwarf_lineno(line, &lineno) == 0) {
1426                         tmp = dwarf_linesrc(line, NULL, NULL);
1427                         if (tmp) {
1428                                 ppt->line = lineno;
1429                                 ppt->file = strdup(tmp);
1430                                 if (ppt->file == NULL) {
1431                                         ret = -ENOMEM;
1432                                         goto end;
1433                                 }
1434                                 found = true;
1435                         }
1436                 }
1437         }
1438
1439         /* Find a corresponding function */
1440         if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
1441                 tmp = dwarf_diename(&spdie);
1442                 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
1443                         goto end;
1444
1445                 if (ppt->line) {
1446                         if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
1447                                                 &indie)) {
1448                                 /* addr in an inline function */
1449                                 tmp = dwarf_diename(&indie);
1450                                 if (!tmp)
1451                                         goto end;
1452                                 ret = dwarf_decl_line(&indie, &lineno);
1453                         } else {
1454                                 if (eaddr == addr) {    /* Function entry */
1455                                         lineno = ppt->line;
1456                                         ret = 0;
1457                                 } else
1458                                         ret = dwarf_decl_line(&spdie, &lineno);
1459                         }
1460                         if (ret == 0) {
1461                                 /* Make a relative line number */
1462                                 ppt->line -= lineno;
1463                                 goto found;
1464                         }
1465                 }
1466                 /* We don't have a line number, let's use offset */
1467                 ppt->offset = addr - (unsigned long)eaddr;
1468 found:
1469                 ppt->function = strdup(tmp);
1470                 if (ppt->function == NULL) {
1471                         ret = -ENOMEM;
1472                         goto end;
1473                 }
1474                 found = true;
1475         }
1476
1477 end:
1478         dwarf_end(dbg);
1479         if (ret >= 0)
1480                 ret = found ? 1 : 0;
1481         return ret;
1482 }
1483
1484 /* Add a line and store the src path */
1485 static int line_range_add_line(const char *src, unsigned int lineno,
1486                                struct line_range *lr)
1487 {
1488         /* Copy source path */
1489         if (!lr->path) {
1490                 lr->path = strdup(src);
1491                 if (lr->path == NULL)
1492                         return -ENOMEM;
1493         }
1494         return line_list__add_line(&lr->line_list, lineno);
1495 }
1496
1497 /* Search function declaration lines */
1498 static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
1499 {
1500         struct dwarf_callback_param *param = data;
1501         struct line_finder *lf = param->data;
1502         const char *src;
1503         int lineno;
1504
1505         src = dwarf_decl_file(sp_die);
1506         if (src && strtailcmp(src, lf->fname) != 0)
1507                 return DWARF_CB_OK;
1508
1509         if (dwarf_decl_line(sp_die, &lineno) != 0 ||
1510             (lf->lno_s > lineno || lf->lno_e < lineno))
1511                 return DWARF_CB_OK;
1512
1513         param->retval = line_range_add_line(src, lineno, lf->lr);
1514         if (param->retval < 0)
1515                 return DWARF_CB_ABORT;
1516         return DWARF_CB_OK;
1517 }
1518
1519 static int find_line_range_func_decl_lines(struct line_finder *lf)
1520 {
1521         struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1522         dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
1523         return param.retval;
1524 }
1525
1526 /* Find line range from its line number */
1527 static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1528 {
1529         Dwarf_Lines *lines;
1530         Dwarf_Line *line;
1531         size_t nlines, i;
1532         Dwarf_Addr addr;
1533         int lineno, ret = 0;
1534         const char *src;
1535         Dwarf_Die die_mem;
1536
1537         line_list__init(&lf->lr->line_list);
1538         if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1539                 pr_warning("No source lines found in this CU.\n");
1540                 return -ENOENT;
1541         }
1542
1543         /* Search probable lines on lines list */
1544         for (i = 0; i < nlines; i++) {
1545                 line = dwarf_onesrcline(lines, i);
1546                 if (dwarf_lineno(line, &lineno) != 0 ||
1547                     (lf->lno_s > lineno || lf->lno_e < lineno))
1548                         continue;
1549
1550                 if (sp_die) {
1551                         /* Address filtering 1: does sp_die include addr? */
1552                         if (dwarf_lineaddr(line, &addr) != 0 ||
1553                             !dwarf_haspc(sp_die, addr))
1554                                 continue;
1555
1556                         /* Address filtering 2: No child include addr? */
1557                         if (die_find_inlinefunc(sp_die, addr, &die_mem))
1558                                 continue;
1559                 }
1560
1561                 /* TODO: Get fileno from line, but how? */
1562                 src = dwarf_linesrc(line, NULL, NULL);
1563                 if (strtailcmp(src, lf->fname) != 0)
1564                         continue;
1565
1566                 ret = line_range_add_line(src, lineno, lf->lr);
1567                 if (ret < 0)
1568                         return ret;
1569         }
1570
1571         /*
1572          * Dwarf lines doesn't include function declarations. We have to
1573          * check functions list or given function.
1574          */
1575         if (sp_die) {
1576                 src = dwarf_decl_file(sp_die);
1577                 if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
1578                     (lf->lno_s <= lineno && lf->lno_e >= lineno))
1579                         ret = line_range_add_line(src, lineno, lf->lr);
1580         } else
1581                 ret = find_line_range_func_decl_lines(lf);
1582
1583         /* Update status */
1584         if (ret >= 0)
1585                 if (!list_empty(&lf->lr->line_list))
1586                         ret = lf->found = 1;
1587                 else
1588                         ret = 0;        /* Lines are not found */
1589         else {
1590                 free(lf->lr->path);
1591                 lf->lr->path = NULL;
1592         }
1593         return ret;
1594 }
1595
1596 static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1597 {
1598         struct dwarf_callback_param *param = data;
1599
1600         param->retval = find_line_range_by_line(in_die, param->data);
1601         return DWARF_CB_ABORT;  /* No need to find other instances */
1602 }
1603
1604 /* Search function from function name */
1605 static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1606 {
1607         struct dwarf_callback_param *param = data;
1608         struct line_finder *lf = param->data;
1609         struct line_range *lr = lf->lr;
1610
1611         if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
1612             die_compare_name(sp_die, lr->function)) {
1613                 lf->fname = dwarf_decl_file(sp_die);
1614                 dwarf_decl_line(sp_die, &lr->offset);
1615                 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
1616                 lf->lno_s = lr->offset + lr->start;
1617                 if (lf->lno_s < 0)      /* Overflow */
1618                         lf->lno_s = INT_MAX;
1619                 lf->lno_e = lr->offset + lr->end;
1620                 if (lf->lno_e < 0)      /* Overflow */
1621                         lf->lno_e = INT_MAX;
1622                 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1623                 lr->start = lf->lno_s;
1624                 lr->end = lf->lno_e;
1625                 if (dwarf_func_inline(sp_die)) {
1626                         struct dwarf_callback_param _param;
1627                         _param.data = (void *)lf;
1628                         _param.retval = 0;
1629                         dwarf_func_inline_instances(sp_die,
1630                                                     line_range_inline_cb,
1631                                                     &_param);
1632                         param->retval = _param.retval;
1633                 } else
1634                         param->retval = find_line_range_by_line(sp_die, lf);
1635                 return DWARF_CB_ABORT;
1636         }
1637         return DWARF_CB_OK;
1638 }
1639
1640 static int find_line_range_by_func(struct line_finder *lf)
1641 {
1642         struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
1643         dwarf_getfuncs(&lf->cu_die, line_range_search_cb, &param, 0);
1644         return param.retval;
1645 }
1646
1647 int find_line_range(int fd, struct line_range *lr)
1648 {
1649         struct line_finder lf = {.lr = lr, .found = 0};
1650         int ret = 0;
1651         Dwarf_Off off = 0, noff;
1652         size_t cuhl;
1653         Dwarf_Die *diep;
1654         Dwarf *dbg;
1655         const char *comp_dir;
1656
1657         dbg = dwarf_begin(fd, DWARF_C_READ);
1658         if (!dbg) {
1659                 pr_warning("No dwarf info found in the vmlinux - "
1660                         "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1661                 return -EBADF;
1662         }
1663
1664         /* Loop on CUs (Compilation Unit) */
1665         while (!lf.found && ret >= 0) {
1666                 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0)
1667                         break;
1668
1669                 /* Get the DIE(Debugging Information Entry) of this CU */
1670                 diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
1671                 if (!diep)
1672                         continue;
1673
1674                 /* Check if target file is included. */
1675                 if (lr->file)
1676                         lf.fname = cu_find_realpath(&lf.cu_die, lr->file);
1677                 else
1678                         lf.fname = 0;
1679
1680                 if (!lr->file || lf.fname) {
1681                         if (lr->function)
1682                                 ret = find_line_range_by_func(&lf);
1683                         else {
1684                                 lf.lno_s = lr->start;
1685                                 lf.lno_e = lr->end;
1686                                 ret = find_line_range_by_line(NULL, &lf);
1687                         }
1688                 }
1689                 off = noff;
1690         }
1691
1692         /* Store comp_dir */
1693         if (lf.found) {
1694                 comp_dir = cu_get_comp_dir(&lf.cu_die);
1695                 if (comp_dir) {
1696                         lr->comp_dir = strdup(comp_dir);
1697                         if (!lr->comp_dir)
1698                                 ret = -ENOMEM;
1699                 }
1700         }
1701
1702         pr_debug("path: %s\n", lr->path);
1703         dwarf_end(dbg);
1704
1705         return (ret < 0) ? ret : lf.found;
1706 }
1707