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