perf probe: Use elfutils-libdw for analyzing debuginfo
[safe/jmp/linux-2.6] / tools / perf / util / probe-finder.c
1 /*
2  * probe-finder.c : C expression to kprobe event converter
3  *
4  * Written by Masami Hiramatsu <mhiramat@redhat.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  */
21
22 #include <sys/utsname.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <getopt.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdarg.h>
33 #include <ctype.h>
34
35 #include "event.h"
36 #include "debug.h"
37 #include "util.h"
38 #include "probe-finder.h"
39
40
41 /* Dwarf_Die Linkage to parent Die */
42 struct die_link {
43         struct die_link *parent;        /* Parent die */
44         Dwarf_Die die;                  /* Current die */
45 };
46
47
48 /*
49  * Generic dwarf analysis helpers
50  */
51
52 #define X86_32_MAX_REGS 8
53 const char *x86_32_regs_table[X86_32_MAX_REGS] = {
54         "%ax",
55         "%cx",
56         "%dx",
57         "%bx",
58         "$stack",       /* Stack address instead of %sp */
59         "%bp",
60         "%si",
61         "%di",
62 };
63
64 #define X86_64_MAX_REGS 16
65 const char *x86_64_regs_table[X86_64_MAX_REGS] = {
66         "%ax",
67         "%dx",
68         "%cx",
69         "%bx",
70         "%si",
71         "%di",
72         "%bp",
73         "%sp",
74         "%r8",
75         "%r9",
76         "%r10",
77         "%r11",
78         "%r12",
79         "%r13",
80         "%r14",
81         "%r15",
82 };
83
84 /* TODO: switching by dwarf address size */
85 #ifdef __x86_64__
86 #define ARCH_MAX_REGS X86_64_MAX_REGS
87 #define arch_regs_table x86_64_regs_table
88 #else
89 #define ARCH_MAX_REGS X86_32_MAX_REGS
90 #define arch_regs_table x86_32_regs_table
91 #endif
92
93 /* Return architecture dependent register string (for kprobe-tracer) */
94 static const char *get_arch_regstr(unsigned int n)
95 {
96         return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL;
97 }
98
99 /*
100  * Compare the tail of two strings.
101  * Return 0 if whole of either string is same as another's tail part.
102  */
103 static int strtailcmp(const char *s1, const char *s2)
104 {
105         int i1 = strlen(s1);
106         int i2 = strlen(s2);
107         while (--i1 >= 0 && --i2 >= 0) {
108                 if (s1[i1] != s2[i2])
109                         return s1[i1] - s2[i2];
110         }
111         return 0;
112 }
113
114 /* Find the fileno of the target file. */
115 static int cu_find_fileno(Dwarf_Die *cu_die, const char *fname)
116 {
117         Dwarf_Files *files;
118         size_t nfiles, i;
119         const char *src;
120         int ret;
121
122         if (!fname)
123                 return -EINVAL;
124
125         ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
126         if (ret == 0) {
127                 for (i = 0; i < nfiles; i++) {
128                         src = dwarf_filesrc(files, i, NULL, NULL);
129                         if (strtailcmp(src, fname) == 0) {
130                                 ret = (int)i;   /*???: +1 or not?*/
131                                 break;
132                         }
133                 }
134                 if (ret)
135                         pr_debug("found fno: %d\n", ret);
136         }
137         return ret;
138 }
139
140 struct __addr_die_search_param {
141         Dwarf_Addr      addr;
142         Dwarf_Die       *die_mem;
143 };
144
145 static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
146 {
147         struct __addr_die_search_param *ad = data;
148
149         if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
150             dwarf_haspc(fn_die, ad->addr)) {
151                 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
152                 return DWARF_CB_ABORT;
153         }
154         return DWARF_CB_OK;
155 }
156
157 /* Search a real subprogram including this line, */
158 static Dwarf_Die *die_get_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
159                                           Dwarf_Die *die_mem)
160 {
161         struct __addr_die_search_param ad;
162         ad.addr = addr;
163         ad.die_mem = die_mem;
164         /* dwarf_getscopes can't find subprogram. */
165         if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
166                 return NULL;
167         else
168                 return die_mem;
169 }
170
171 /* Compare diename and tname */
172 static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
173 {
174         const char *name;
175         name = dwarf_diename(dw_die);
176         DIE_IF(name == NULL);
177         return strcmp(tname, name);
178 }
179
180 /* Check the address is in the subprogram(function). */
181 static bool die_within_subprogram(Dwarf_Die *sp_die, Dwarf_Addr addr,
182                                  size_t *offs)
183 {
184         Dwarf_Addr epc;
185         int ret;
186
187         ret = dwarf_haspc(sp_die, addr);
188         if (ret <= 0)
189                 return false;
190
191         if (offs) {
192                 ret = dwarf_entrypc(sp_die, &epc);
193                 DIE_IF(ret == -1);
194                 *offs = addr - epc;
195         }
196
197         return true;
198 }
199
200 /* Get entry pc(or low pc, 1st entry of ranges)  of the die */
201 static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
202 {
203         Dwarf_Addr epc;
204         int ret;
205
206         ret = dwarf_entrypc(dw_die, &epc);
207         DIE_IF(ret == -1);
208         return epc;
209 }
210
211 /* Check if the abstract origin's address or not */
212 static bool die_compare_abstract_origin(Dwarf_Die *in_die, void *origin_addr)
213 {
214         Dwarf_Attribute attr;
215         Dwarf_Die origin;
216
217         if (!dwarf_attr(in_die, DW_AT_abstract_origin, &attr))
218                 return false;
219         if (!dwarf_formref_die(&attr, &origin))
220                 return false;
221
222         return origin.addr == origin_addr;
223 }
224
225 /*
226  * Search a Die from Die tree.
227  * Note: cur_link->die should be deallocated in this function.
228  */
229 static int __search_die_tree(struct die_link *cur_link,
230                              int (*die_cb)(struct die_link *, void *),
231                              void *data)
232 {
233         struct die_link new_link;
234         int ret;
235
236         if (!die_cb)
237                 return 0;
238
239         /* Check current die */
240         while (!(ret = die_cb(cur_link, data))) {
241                 /* Check child die */
242                 ret = dwarf_child(&cur_link->die, &new_link.die);
243                 if (ret == 0) {
244                         new_link.parent = cur_link;
245                         ret = __search_die_tree(&new_link, die_cb, data);
246                         if (ret)
247                                 break;
248                 }
249
250                 /* Move to next sibling */
251                 ret = dwarf_siblingof(&cur_link->die, &cur_link->die);
252                 if (ret != 0)
253                         return 0;
254         }
255         return ret;
256 }
257
258 /* Search a die in its children's die tree */
259 static int search_die_from_children(Dwarf_Die *parent_die,
260                                     int (*die_cb)(struct die_link *, void *),
261                                     void *data)
262 {
263         struct die_link new_link;
264         int ret;
265
266         new_link.parent = NULL;
267         ret = dwarf_child(parent_die, &new_link.die);
268         if (ret == 0)
269                 return __search_die_tree(&new_link, die_cb, data);
270         else
271                 return 0;
272 }
273
274
275 /*
276  * Probe finder related functions
277  */
278
279 /* Show a location */
280 static void show_location(Dwarf_Op *op, struct probe_finder *pf)
281 {
282         unsigned int regn;
283         Dwarf_Word offs = 0;
284         int deref = 0, ret;
285         const char *regs;
286
287         /* TODO: support CFA */
288         /* If this is based on frame buffer, set the offset */
289         if (op->atom == DW_OP_fbreg) {
290                 if (pf->fb_ops == NULL)
291                         die("The attribute of frame base is not supported.\n");
292                 deref = 1;
293                 offs = op->number;
294                 op = &pf->fb_ops[0];
295         }
296
297         if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
298                 regn = op->atom - DW_OP_breg0;
299                 offs += op->number;
300                 deref = 1;
301         } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
302                 regn = op->atom - DW_OP_reg0;
303         } else if (op->atom == DW_OP_bregx) {
304                 regn = op->number;
305                 offs += op->number2;
306                 deref = 1;
307         } else if (op->atom == DW_OP_regx) {
308                 regn = op->number;
309         } else
310                 die("DW_OP %d is not supported.", op->atom);
311
312         regs = get_arch_regstr(regn);
313         if (!regs)
314                 die("%u exceeds max register number.", regn);
315
316         if (deref)
317                 ret = snprintf(pf->buf, pf->len, " %s=+%ju(%s)",
318                                pf->var, (uintmax_t)offs, regs);
319         else
320                 ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
321         DIE_IF(ret < 0);
322         DIE_IF(ret >= pf->len);
323 }
324
325 /* Show a variables in kprobe event format */
326 static void show_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
327 {
328         Dwarf_Attribute attr;
329         Dwarf_Op *expr;
330         size_t nexpr;
331         int ret;
332
333         if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
334                 goto error;
335         /* TODO: handle more than 1 exprs */
336         ret = dwarf_getlocation_addr(&attr, (pf->addr - pf->cu_base),
337                                      &expr, &nexpr, 1);
338         if (ret <= 0 || nexpr == 0)
339                 goto error;
340
341         show_location(expr, pf);
342         /* *expr will be cached in libdw. Don't free it. */
343         return ;
344 error:
345         /* TODO: Support const_value */
346         die("Failed to find the location of %s at this address.\n"
347             " Perhaps, it has been optimized out.", pf->var);
348 }
349
350 static int variable_search_cb(struct die_link *dlink, void *data)
351 {
352         struct probe_finder *pf = (struct probe_finder *)data;
353         int tag;
354
355         tag = dwarf_tag(&dlink->die);
356         DIE_IF(tag < 0);
357         if ((tag == DW_TAG_formal_parameter ||
358              tag == DW_TAG_variable) &&
359             (die_compare_name(&dlink->die, pf->var) == 0)) {
360                 show_variable(&dlink->die, pf);
361                 return 1;
362         }
363         /* TODO: Support struct members and arrays */
364         return 0;
365 }
366
367 /* Find a variable in a subprogram die */
368 static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
369 {
370         int ret;
371
372         if (!is_c_varname(pf->var)) {
373                 /* Output raw parameters */
374                 ret = snprintf(pf->buf, pf->len, " %s", pf->var);
375                 DIE_IF(ret < 0);
376                 DIE_IF(ret >= pf->len);
377                 return ;
378         }
379
380         pr_debug("Searching '%s' variable in context.\n", pf->var);
381         /* Search child die for local variables and parameters. */
382         ret = search_die_from_children(sp_die, variable_search_cb, pf);
383         if (!ret)
384                 die("Failed to find '%s' in this function.", pf->var);
385 }
386
387 /* Show a probe point to output buffer */
388 static void show_probe_point(Dwarf_Die *sp_die, size_t offs,
389                              struct probe_finder *pf)
390 {
391         struct probe_point *pp = pf->pp;
392         const char *name;
393         char tmp[MAX_PROBE_BUFFER];
394         int ret, i, len;
395         Dwarf_Attribute fb_attr;
396         size_t nops;
397
398         /* Output name of probe point */
399         name = dwarf_diename(sp_die);
400         if (name) {
401                 ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name,
402                                 (unsigned int)offs);
403                 /* Copy the function name if possible */
404                 if (!pp->function) {
405                         pp->function = strdup(name);
406                         pp->offset = offs;
407                 }
408         } else {
409                 /* This function has no name. */
410                 ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%jx",
411                                (uintmax_t)pf->addr);
412                 if (!pp->function) {
413                         /* TODO: Use _stext */
414                         pp->function = strdup("");
415                         pp->offset = (size_t)pf->addr;
416                 }
417         }
418         DIE_IF(ret < 0);
419         DIE_IF(ret >= MAX_PROBE_BUFFER);
420         len = ret;
421         pr_debug("Probe point found: %s\n", tmp);
422
423         /* Get the frame base attribute/ops */
424         dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
425         ret = dwarf_getlocation_addr(&fb_attr, (pf->addr - pf->cu_base),
426                                      &pf->fb_ops, &nops, 1);
427         if (ret <= 0 || nops == 0)
428                 pf->fb_ops = NULL;
429
430         /* Find each argument */
431         /* TODO: use dwarf_cfi_addrframe */
432         for (i = 0; i < pp->nr_args; i++) {
433                 pf->var = pp->args[i];
434                 pf->buf = &tmp[len];
435                 pf->len = MAX_PROBE_BUFFER - len;
436                 find_variable(sp_die, pf);
437                 len += strlen(pf->buf);
438         }
439
440         /* *pf->fb_ops will be cached in libdw. Don't free it. */
441         pf->fb_ops = NULL;
442
443         pp->probes[pp->found] = strdup(tmp);
444         pp->found++;
445 }
446
447 /* Find probe point from its line number */
448 static void find_probe_point_by_line(struct probe_finder *pf)
449 {
450         Dwarf_Lines *lines;
451         Dwarf_Line *line;
452         size_t nlines, i;
453         Dwarf_Addr addr, epc;
454         int lineno;
455         int ret;
456         Dwarf_Die *sp_die, die_mem;
457
458         ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines);
459         DIE_IF(ret != 0);
460
461         for (i = 0; i < nlines; i++) {
462                 line = dwarf_onesrcline(lines, i);
463                 dwarf_lineno(line, &lineno);
464                 if (lineno != pf->lno)
465                         continue;
466
467                 /* TODO: Get fileno from line, but how? */
468                 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
469                         continue;
470
471                 ret = dwarf_lineaddr(line, &addr);
472                 DIE_IF(ret != 0);
473                 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
474                          (int)i, lineno, (uintmax_t)addr);
475                 pf->addr = addr;
476
477                 sp_die = die_get_real_subprogram(&pf->cu_die, addr, &die_mem);
478                 if (!sp_die)
479                         die("Probe point is not found in subprograms.");
480                 dwarf_entrypc(sp_die, &epc);
481                 show_probe_point(sp_die, (size_t)(addr - epc), pf);
482                 /* Continuing, because target line might be inlined. */
483         }
484 }
485
486
487 /* Search function from function name */
488 static int probe_point_search_cb(struct die_link *dlink, void *data)
489 {
490         struct probe_finder *pf = (struct probe_finder *)data;
491         struct probe_point *pp = pf->pp;
492         struct die_link *lk;
493         size_t offs;
494         int tag;
495         int ret;
496
497         tag = dwarf_tag(&dlink->die);
498         if (tag == DW_TAG_subprogram) {
499                 if (die_compare_name(&dlink->die, pp->function) == 0) {
500                         if (pp->line) { /* Function relative line */
501                                 pf->fname = dwarf_decl_file(&dlink->die);
502                                 dwarf_decl_line(&dlink->die, &pf->lno);
503                                 pf->lno += pp->line;
504                                 find_probe_point_by_line(pf);
505                                 return 1;
506                         }
507                         if (dwarf_func_inline(&dlink->die)) {
508                                 /* Inlined function, save it. */
509                                 pf->origin = dlink->die.addr;
510                                 return 0;       /* Continue to search */
511                         }
512                         /* Get probe address */
513                         pf->addr = die_get_entrypc(&dlink->die);
514                         pf->addr += pp->offset;
515                         /* TODO: Check the address in this function */
516                         show_probe_point(&dlink->die, pp->offset, pf);
517                         return 1; /* Exit; no same symbol in this CU. */
518                 }
519         } else if (tag == DW_TAG_inlined_subroutine && pf->origin) {
520                 if (die_compare_abstract_origin(&dlink->die, pf->origin)) {
521                         /* Get probe address */
522                         pf->addr = die_get_entrypc(&dlink->die);
523                         pf->addr += pp->offset;
524                         pr_debug("found inline addr: 0x%jx\n",
525                                  (uintmax_t)pf->addr);
526                         /* Inlined function. Get a real subprogram */
527                         for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
528                                 tag = dwarf_tag(&lk->die);
529                                 if (tag == DW_TAG_subprogram &&
530                                     !dwarf_func_inline(&lk->die))
531                                         goto found;
532                         }
533                         die("Failed to find real subprogram.");
534 found:
535                         /* Get offset from subprogram */
536                         ret = die_within_subprogram(&lk->die, pf->addr, &offs);
537                         DIE_IF(!ret);
538                         show_probe_point(&lk->die, offs, pf);
539                         /* Continue to search */
540                 }
541         }
542         return 0;
543 }
544
545 static void find_probe_point_by_func(struct probe_finder *pf)
546 {
547         search_die_from_children(&pf->cu_die, probe_point_search_cb, pf);
548 }
549
550 /* Find a probe point */
551 int find_probe_point(int fd, struct probe_point *pp)
552 {
553         struct probe_finder pf = {.pp = pp};
554         int ret;
555         Dwarf_Off off, noff;
556         size_t cuhl;
557         Dwarf_Die *diep;
558         Dwarf *dbg;
559         int fno = 0;
560
561         dbg = dwarf_begin(fd, DWARF_C_READ);
562         if (!dbg)
563                 return -ENOENT;
564
565         pp->found = 0;
566         off = 0;
567         /* Loop on CUs (Compilation Unit) */
568         while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
569                 /* Get the DIE(Debugging Information Entry) of this CU */
570                 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die);
571                 if (!diep)
572                         continue;
573
574                 /* Check if target file is included. */
575                 if (pp->file)
576                         fno = cu_find_fileno(&pf.cu_die, pp->file);
577                 else
578                         fno = 0;
579
580                 if (!pp->file || fno) {
581                         /* Save CU base address (for frame_base) */
582                         ret = dwarf_lowpc(&pf.cu_die, &pf.cu_base);
583                         if (ret != 0)
584                                 pf.cu_base = 0;
585                         if (pp->function)
586                                 find_probe_point_by_func(&pf);
587                         else {
588                                 pf.lno = pp->line;
589                                 find_probe_point_by_line(&pf);
590                         }
591                 }
592                 off = noff;
593         }
594         dwarf_end(dbg);
595
596         return pp->found;
597 }
598
599
600 static void line_range_add_line(struct line_range *lr, unsigned int line)
601 {
602         struct line_node *ln;
603         struct list_head *p;
604
605         /* Reverse search, because new line will be the last one */
606         list_for_each_entry_reverse(ln, &lr->line_list, list) {
607                 if (ln->line < line) {
608                         p = &ln->list;
609                         goto found;
610                 } else if (ln->line == line)    /* Already exist */
611                         return ;
612         }
613         /* List is empty, or the smallest entry */
614         p = &lr->line_list;
615 found:
616         pr_debug("Debug: add a line %u\n", line);
617         ln = zalloc(sizeof(struct line_node));
618         DIE_IF(ln == NULL);
619         ln->line = line;
620         INIT_LIST_HEAD(&ln->list);
621         list_add(&ln->list, p);
622 }
623
624 /* Find line range from its line number */
625 static void find_line_range_by_line(struct line_finder *lf)
626 {
627         Dwarf_Lines *lines;
628         Dwarf_Line *line;
629         size_t nlines, i;
630         Dwarf_Addr addr;
631         int lineno;
632         int ret;
633         const char *src;
634
635         INIT_LIST_HEAD(&lf->lr->line_list);
636         ret = dwarf_getsrclines(&lf->cu_die, &lines, &nlines);
637         DIE_IF(ret != 0);
638
639         for (i = 0; i < nlines; i++) {
640                 line = dwarf_onesrcline(lines, i);
641                 dwarf_lineno(line, &lineno);
642                 if (lf->lno_s > lineno || lf->lno_e < lineno)
643                         continue;
644
645                 /* TODO: Get fileno from line, but how? */
646                 src = dwarf_linesrc(line, NULL, NULL);
647                 if (strtailcmp(src, lf->fname) != 0)
648                         continue;
649
650                 /* Filter line in the function address range */
651                 if (lf->addr_s && lf->addr_e) {
652                         ret = dwarf_lineaddr(line, &addr);
653                         DIE_IF(ret != 0);
654                         if (lf->addr_s > addr || lf->addr_e <= addr)
655                                 continue;
656                 }
657                 /* Copy real path */
658                 if (!lf->lr->path)
659                         lf->lr->path = strdup(src);
660                 line_range_add_line(lf->lr, (unsigned int)lineno);
661         }
662         /* Update status */
663         if (!list_empty(&lf->lr->line_list))
664                 lf->found = 1;
665         else {
666                 free(lf->lr->path);
667                 lf->lr->path = NULL;
668         }
669 }
670
671 /* Search function from function name */
672 static int line_range_search_cb(struct die_link *dlink, void *data)
673 {
674         struct line_finder *lf = (struct line_finder *)data;
675         struct line_range *lr = lf->lr;
676         int tag;
677         int ret;
678
679         tag = dwarf_tag(&dlink->die);
680         if (tag == DW_TAG_subprogram &&
681             die_compare_name(&dlink->die, lr->function) == 0) {
682                 /* Get the address range of this function */
683                 ret = dwarf_highpc(&dlink->die, &lf->addr_e);
684                 if (ret == 0)
685                         ret = dwarf_lowpc(&dlink->die, &lf->addr_s);
686                 if (ret != 0) {
687                         lf->addr_s = 0;
688                         lf->addr_e = 0;
689                 }
690
691                 lf->fname = dwarf_decl_file(&dlink->die);
692                 dwarf_decl_line(&dlink->die, &lr->offset);
693                 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
694                 lf->lno_s = lr->offset + lr->start;
695                 if (!lr->end)
696                         lf->lno_e = INT_MAX;
697                 else
698                         lf->lno_e = lr->offset + lr->end;
699                 lr->start = lf->lno_s;
700                 lr->end = lf->lno_e;
701                 find_line_range_by_line(lf);
702                 return 1;
703         }
704         return 0;
705 }
706
707 static void find_line_range_by_func(struct line_finder *lf)
708 {
709         search_die_from_children(&lf->cu_die, line_range_search_cb, lf);
710 }
711
712 int find_line_range(int fd, struct line_range *lr)
713 {
714         struct line_finder lf = {.lr = lr, .found = 0};
715         int ret;
716         Dwarf_Off off = 0, noff;
717         size_t cuhl;
718         Dwarf_Die *diep;
719         Dwarf *dbg;
720         int fno;
721
722         dbg = dwarf_begin(fd, DWARF_C_READ);
723         if (!dbg)
724                 return -ENOENT;
725
726         /* Loop on CUs (Compilation Unit) */
727         while (!lf.found) {
728                 ret = dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL);
729                 if (ret != 0)
730                         break;
731
732                 /* Get the DIE(Debugging Information Entry) of this CU */
733                 diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
734                 if (!diep)
735                         continue;
736
737                 /* Check if target file is included. */
738                 if (lr->file)
739                         fno = cu_find_fileno(&lf.cu_die, lr->file);
740                 else
741                         fno = 0;
742
743                 if (!lr->file || fno) {
744                         if (lr->function)
745                                 find_line_range_by_func(&lf);
746                         else {
747                                 lf.fname = lr->file;
748                                 lf.lno_s = lr->start;
749                                 if (!lr->end)
750                                         lf.lno_e = INT_MAX;
751                                 else
752                                         lf.lno_e = lr->end;
753                                 find_line_range_by_line(&lf);
754                         }
755                 }
756                 off = noff;
757         }
758         pr_debug("path: %lx\n", (unsigned long)lr->path);
759         dwarf_end(dbg);
760         return lf.found;
761 }
762