perf callchain: Refactor inline_list to store srcline string directly
[linux-2.6-microblaze.git] / tools / perf / util / srcline.c
1 #include <inttypes.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include <linux/kernel.h>
7
8 #include "util/dso.h"
9 #include "util/util.h"
10 #include "util/debug.h"
11 #include "util/callchain.h"
12 #include "srcline.h"
13
14 #include "symbol.h"
15
16 bool srcline_full_filename;
17
18 static const char *dso__name(struct dso *dso)
19 {
20         const char *dso_name;
21
22         if (dso->symsrc_filename)
23                 dso_name = dso->symsrc_filename;
24         else
25                 dso_name = dso->long_name;
26
27         if (dso_name[0] == '[')
28                 return NULL;
29
30         if (!strncmp(dso_name, "/tmp/perf-", 10))
31                 return NULL;
32
33         return dso_name;
34 }
35
36 static int inline_list__append(struct symbol *symbol, char *srcline,
37                                struct inline_node *node)
38 {
39         struct inline_list *ilist;
40
41         ilist = zalloc(sizeof(*ilist));
42         if (ilist == NULL)
43                 return -1;
44
45         ilist->symbol = symbol;
46         ilist->srcline = srcline;
47
48         if (callchain_param.order == ORDER_CALLEE)
49                 list_add_tail(&ilist->list, &node->val);
50         else
51                 list_add(&ilist->list, &node->val);
52
53         return 0;
54 }
55
56 /* basename version that takes a const input string */
57 static const char *gnu_basename(const char *path)
58 {
59         const char *base = strrchr(path, '/');
60
61         return base ? base + 1 : path;
62 }
63
64 static char *srcline_from_fileline(const char *file, unsigned int line)
65 {
66         char *srcline;
67
68         if (!file)
69                 return NULL;
70
71         if (!srcline_full_filename)
72                 file = gnu_basename(file);
73
74         if (asprintf(&srcline, "%s:%u", file, line) < 0)
75                 return NULL;
76
77         return srcline;
78 }
79
80 #ifdef HAVE_LIBBFD_SUPPORT
81
82 /*
83  * Implement addr2line using libbfd.
84  */
85 #define PACKAGE "perf"
86 #include <bfd.h>
87
88 struct a2l_data {
89         const char      *input;
90         u64             addr;
91
92         bool            found;
93         const char      *filename;
94         const char      *funcname;
95         unsigned        line;
96
97         bfd             *abfd;
98         asymbol         **syms;
99 };
100
101 static int bfd_error(const char *string)
102 {
103         const char *errmsg;
104
105         errmsg = bfd_errmsg(bfd_get_error());
106         fflush(stdout);
107
108         if (string)
109                 pr_debug("%s: %s\n", string, errmsg);
110         else
111                 pr_debug("%s\n", errmsg);
112
113         return -1;
114 }
115
116 static int slurp_symtab(bfd *abfd, struct a2l_data *a2l)
117 {
118         long storage;
119         long symcount;
120         asymbol **syms;
121         bfd_boolean dynamic = FALSE;
122
123         if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
124                 return bfd_error(bfd_get_filename(abfd));
125
126         storage = bfd_get_symtab_upper_bound(abfd);
127         if (storage == 0L) {
128                 storage = bfd_get_dynamic_symtab_upper_bound(abfd);
129                 dynamic = TRUE;
130         }
131         if (storage < 0L)
132                 return bfd_error(bfd_get_filename(abfd));
133
134         syms = malloc(storage);
135         if (dynamic)
136                 symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
137         else
138                 symcount = bfd_canonicalize_symtab(abfd, syms);
139
140         if (symcount < 0) {
141                 free(syms);
142                 return bfd_error(bfd_get_filename(abfd));
143         }
144
145         a2l->syms = syms;
146         return 0;
147 }
148
149 static void find_address_in_section(bfd *abfd, asection *section, void *data)
150 {
151         bfd_vma pc, vma;
152         bfd_size_type size;
153         struct a2l_data *a2l = data;
154
155         if (a2l->found)
156                 return;
157
158         if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
159                 return;
160
161         pc = a2l->addr;
162         vma = bfd_get_section_vma(abfd, section);
163         size = bfd_get_section_size(section);
164
165         if (pc < vma || pc >= vma + size)
166                 return;
167
168         a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
169                                            &a2l->filename, &a2l->funcname,
170                                            &a2l->line);
171
172         if (a2l->filename && !strlen(a2l->filename))
173                 a2l->filename = NULL;
174 }
175
176 static struct a2l_data *addr2line_init(const char *path)
177 {
178         bfd *abfd;
179         struct a2l_data *a2l = NULL;
180
181         abfd = bfd_openr(path, NULL);
182         if (abfd == NULL)
183                 return NULL;
184
185         if (!bfd_check_format(abfd, bfd_object))
186                 goto out;
187
188         a2l = zalloc(sizeof(*a2l));
189         if (a2l == NULL)
190                 goto out;
191
192         a2l->abfd = abfd;
193         a2l->input = strdup(path);
194         if (a2l->input == NULL)
195                 goto out;
196
197         if (slurp_symtab(abfd, a2l))
198                 goto out;
199
200         return a2l;
201
202 out:
203         if (a2l) {
204                 zfree((char **)&a2l->input);
205                 free(a2l);
206         }
207         bfd_close(abfd);
208         return NULL;
209 }
210
211 static void addr2line_cleanup(struct a2l_data *a2l)
212 {
213         if (a2l->abfd)
214                 bfd_close(a2l->abfd);
215         zfree((char **)&a2l->input);
216         zfree(&a2l->syms);
217         free(a2l);
218 }
219
220 #define MAX_INLINE_NEST 1024
221
222 static struct symbol *new_inline_sym(struct dso *dso,
223                                      struct symbol *base_sym,
224                                      const char *funcname)
225 {
226         struct symbol *inline_sym;
227         char *demangled = NULL;
228
229         if (dso) {
230                 demangled = dso__demangle_sym(dso, 0, funcname);
231                 if (demangled)
232                         funcname = demangled;
233         }
234
235         if (base_sym && strcmp(funcname, base_sym->name) == 0) {
236                 /* reuse the real, existing symbol */
237                 inline_sym = base_sym;
238                 /* ensure that we don't alias an inlined symbol, which could
239                  * lead to double frees in inline_node__delete
240                  */
241                 assert(!base_sym->inlined);
242         } else {
243                 /* create a fake symbol for the inline frame */
244                 inline_sym = symbol__new(base_sym ? base_sym->start : 0,
245                                          base_sym ? base_sym->end : 0,
246                                          base_sym ? base_sym->binding : 0,
247                                          funcname);
248                 if (inline_sym)
249                         inline_sym->inlined = 1;
250         }
251
252         free(demangled);
253
254         return inline_sym;
255 }
256
257 static int inline_list__append_dso_a2l(struct dso *dso,
258                                        struct inline_node *node,
259                                        struct symbol *sym)
260 {
261         struct a2l_data *a2l = dso->a2l;
262         struct symbol *inline_sym = new_inline_sym(dso, sym, a2l->funcname);
263         char *srcline = NULL;
264
265         if (a2l->filename)
266                 srcline = srcline_from_fileline(a2l->filename, a2l->line);
267
268         return inline_list__append(inline_sym, srcline, node);
269 }
270
271 static int addr2line(const char *dso_name, u64 addr,
272                      char **file, unsigned int *line, struct dso *dso,
273                      bool unwind_inlines, struct inline_node *node,
274                      struct symbol *sym)
275 {
276         int ret = 0;
277         struct a2l_data *a2l = dso->a2l;
278
279         if (!a2l) {
280                 dso->a2l = addr2line_init(dso_name);
281                 a2l = dso->a2l;
282         }
283
284         if (a2l == NULL) {
285                 pr_warning("addr2line_init failed for %s\n", dso_name);
286                 return 0;
287         }
288
289         a2l->addr = addr;
290         a2l->found = false;
291
292         bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
293
294         if (!a2l->found)
295                 return 0;
296
297         if (unwind_inlines) {
298                 int cnt = 0;
299
300                 if (node && inline_list__append_dso_a2l(dso, node, sym))
301                         return 0;
302
303                 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
304                                              &a2l->funcname, &a2l->line) &&
305                        cnt++ < MAX_INLINE_NEST) {
306
307                         if (a2l->filename && !strlen(a2l->filename))
308                                 a2l->filename = NULL;
309
310                         if (node != NULL) {
311                                 if (inline_list__append_dso_a2l(dso, node, sym))
312                                         return 0;
313                                 // found at least one inline frame
314                                 ret = 1;
315                         }
316                 }
317         }
318
319         if (file) {
320                 *file = a2l->filename ? strdup(a2l->filename) : NULL;
321                 ret = *file ? 1 : 0;
322         }
323
324         if (line)
325                 *line = a2l->line;
326
327         return ret;
328 }
329
330 void dso__free_a2l(struct dso *dso)
331 {
332         struct a2l_data *a2l = dso->a2l;
333
334         if (!a2l)
335                 return;
336
337         addr2line_cleanup(a2l);
338
339         dso->a2l = NULL;
340 }
341
342 static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
343                                         struct dso *dso, struct symbol *sym)
344 {
345         struct inline_node *node;
346
347         node = zalloc(sizeof(*node));
348         if (node == NULL) {
349                 perror("not enough memory for the inline node");
350                 return NULL;
351         }
352
353         INIT_LIST_HEAD(&node->val);
354         node->addr = addr;
355
356         if (!addr2line(dso_name, addr, NULL, NULL, dso, TRUE, node, sym))
357                 goto out_free_inline_node;
358
359         if (list_empty(&node->val))
360                 goto out_free_inline_node;
361
362         return node;
363
364 out_free_inline_node:
365         inline_node__delete(node);
366         return NULL;
367 }
368
369 #else /* HAVE_LIBBFD_SUPPORT */
370
371 static int filename_split(char *filename, unsigned int *line_nr)
372 {
373         char *sep;
374
375         sep = strchr(filename, '\n');
376         if (sep)
377                 *sep = '\0';
378
379         if (!strcmp(filename, "??:0"))
380                 return 0;
381
382         sep = strchr(filename, ':');
383         if (sep) {
384                 *sep++ = '\0';
385                 *line_nr = strtoul(sep, NULL, 0);
386                 return 1;
387         }
388
389         return 0;
390 }
391
392 static int addr2line(const char *dso_name, u64 addr,
393                      char **file, unsigned int *line_nr,
394                      struct dso *dso __maybe_unused,
395                      bool unwind_inlines __maybe_unused,
396                      struct inline_node *node __maybe_unused,
397                      struct symbol *sym __maybe_unused)
398 {
399         FILE *fp;
400         char cmd[PATH_MAX];
401         char *filename = NULL;
402         size_t len;
403         int ret = 0;
404
405         scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
406                   dso_name, addr);
407
408         fp = popen(cmd, "r");
409         if (fp == NULL) {
410                 pr_warning("popen failed for %s\n", dso_name);
411                 return 0;
412         }
413
414         if (getline(&filename, &len, fp) < 0 || !len) {
415                 pr_warning("addr2line has no output for %s\n", dso_name);
416                 goto out;
417         }
418
419         ret = filename_split(filename, line_nr);
420         if (ret != 1) {
421                 free(filename);
422                 goto out;
423         }
424
425         *file = filename;
426
427 out:
428         pclose(fp);
429         return ret;
430 }
431
432 void dso__free_a2l(struct dso *dso __maybe_unused)
433 {
434 }
435
436 static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
437                                         struct dso *dso __maybe_unused,
438                                         struct symbol *sym)
439 {
440         FILE *fp;
441         char cmd[PATH_MAX];
442         struct inline_node *node;
443         char *filename = NULL;
444         size_t len;
445         unsigned int line_nr = 0;
446
447         scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64,
448                   dso_name, addr);
449
450         fp = popen(cmd, "r");
451         if (fp == NULL) {
452                 pr_err("popen failed for %s\n", dso_name);
453                 return NULL;
454         }
455
456         node = zalloc(sizeof(*node));
457         if (node == NULL) {
458                 perror("not enough memory for the inline node");
459                 goto out;
460         }
461
462         INIT_LIST_HEAD(&node->val);
463         node->addr = addr;
464
465         while (getline(&filename, &len, fp) != -1) {
466                 char *srcline;
467
468                 if (filename_split(filename, &line_nr) != 1) {
469                         free(filename);
470                         goto out;
471                 }
472
473                 srcline = srcline_from_fileline(filename, line_nr);
474                 if (inline_list__append(sym, srcline, node) != 0)
475                         goto out;
476
477                 filename = NULL;
478         }
479
480 out:
481         pclose(fp);
482
483         if (list_empty(&node->val)) {
484                 inline_node__delete(node);
485                 return NULL;
486         }
487
488         return node;
489 }
490
491 #endif /* HAVE_LIBBFD_SUPPORT */
492
493 /*
494  * Number of addr2line failures (without success) before disabling it for that
495  * dso.
496  */
497 #define A2L_FAIL_LIMIT 123
498
499 char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
500                   bool show_sym, bool show_addr, bool unwind_inlines)
501 {
502         char *file = NULL;
503         unsigned line = 0;
504         char *srcline;
505         const char *dso_name;
506
507         if (!dso->has_srcline)
508                 goto out;
509
510         dso_name = dso__name(dso);
511         if (dso_name == NULL)
512                 goto out;
513
514         if (!addr2line(dso_name, addr, &file, &line, dso,
515                        unwind_inlines, NULL, sym))
516                 goto out;
517
518         srcline = srcline_from_fileline(file, line);
519         free(file);
520
521         if (!srcline)
522                 goto out;
523
524         dso->a2l_fails = 0;
525
526         return srcline;
527
528 out:
529         if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) {
530                 dso->has_srcline = 0;
531                 dso__free_a2l(dso);
532         }
533
534         if (!show_addr)
535                 return (show_sym && sym) ?
536                             strndup(sym->name, sym->namelen) : NULL;
537
538         if (sym) {
539                 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
540                                         addr - sym->start) < 0)
541                         return SRCLINE_UNKNOWN;
542         } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0)
543                 return SRCLINE_UNKNOWN;
544         return srcline;
545 }
546
547 void free_srcline(char *srcline)
548 {
549         if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
550                 free(srcline);
551 }
552
553 char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
554                   bool show_sym, bool show_addr)
555 {
556         return __get_srcline(dso, addr, sym, show_sym, show_addr, false);
557 }
558
559 struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr,
560                                             struct symbol *sym)
561 {
562         const char *dso_name;
563
564         dso_name = dso__name(dso);
565         if (dso_name == NULL)
566                 return NULL;
567
568         return addr2inlines(dso_name, addr, dso, sym);
569 }
570
571 void inline_node__delete(struct inline_node *node)
572 {
573         struct inline_list *ilist, *tmp;
574
575         list_for_each_entry_safe(ilist, tmp, &node->val, list) {
576                 list_del_init(&ilist->list);
577                 free_srcline(ilist->srcline);
578                 /* only the inlined symbols are owned by the list */
579                 if (ilist->symbol && ilist->symbol->inlined)
580                         symbol__delete(ilist->symbol);
581                 free(ilist);
582         }
583
584         free(node);
585 }