]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - tools/perf/util/srcline.c
MAINTAINERS: Update MAX77802 PMIC entry
[mirror_ubuntu-artful-kernel.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(char *filename, char *funcname, int line_nr,
37 struct inline_node *node, struct dso *dso)
38 {
39 struct inline_list *ilist;
40 char *demangled;
41
42 ilist = zalloc(sizeof(*ilist));
43 if (ilist == NULL)
44 return -1;
45
46 ilist->filename = filename;
47 ilist->line_nr = line_nr;
48
49 if (dso != NULL) {
50 demangled = dso__demangle_sym(dso, 0, funcname);
51 if (demangled == NULL) {
52 ilist->funcname = funcname;
53 } else {
54 ilist->funcname = demangled;
55 free(funcname);
56 }
57 }
58
59 list_add_tail(&ilist->list, &node->val);
60
61 return 0;
62 }
63
64 #ifdef HAVE_LIBBFD_SUPPORT
65
66 /*
67 * Implement addr2line using libbfd.
68 */
69 #define PACKAGE "perf"
70 #include <bfd.h>
71
72 struct a2l_data {
73 const char *input;
74 u64 addr;
75
76 bool found;
77 const char *filename;
78 const char *funcname;
79 unsigned line;
80
81 bfd *abfd;
82 asymbol **syms;
83 };
84
85 static int bfd_error(const char *string)
86 {
87 const char *errmsg;
88
89 errmsg = bfd_errmsg(bfd_get_error());
90 fflush(stdout);
91
92 if (string)
93 pr_debug("%s: %s\n", string, errmsg);
94 else
95 pr_debug("%s\n", errmsg);
96
97 return -1;
98 }
99
100 static int slurp_symtab(bfd *abfd, struct a2l_data *a2l)
101 {
102 long storage;
103 long symcount;
104 asymbol **syms;
105 bfd_boolean dynamic = FALSE;
106
107 if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
108 return bfd_error(bfd_get_filename(abfd));
109
110 storage = bfd_get_symtab_upper_bound(abfd);
111 if (storage == 0L) {
112 storage = bfd_get_dynamic_symtab_upper_bound(abfd);
113 dynamic = TRUE;
114 }
115 if (storage < 0L)
116 return bfd_error(bfd_get_filename(abfd));
117
118 syms = malloc(storage);
119 if (dynamic)
120 symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
121 else
122 symcount = bfd_canonicalize_symtab(abfd, syms);
123
124 if (symcount < 0) {
125 free(syms);
126 return bfd_error(bfd_get_filename(abfd));
127 }
128
129 a2l->syms = syms;
130 return 0;
131 }
132
133 static void find_address_in_section(bfd *abfd, asection *section, void *data)
134 {
135 bfd_vma pc, vma;
136 bfd_size_type size;
137 struct a2l_data *a2l = data;
138
139 if (a2l->found)
140 return;
141
142 if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
143 return;
144
145 pc = a2l->addr;
146 vma = bfd_get_section_vma(abfd, section);
147 size = bfd_get_section_size(section);
148
149 if (pc < vma || pc >= vma + size)
150 return;
151
152 a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
153 &a2l->filename, &a2l->funcname,
154 &a2l->line);
155 }
156
157 static struct a2l_data *addr2line_init(const char *path)
158 {
159 bfd *abfd;
160 struct a2l_data *a2l = NULL;
161
162 abfd = bfd_openr(path, NULL);
163 if (abfd == NULL)
164 return NULL;
165
166 if (!bfd_check_format(abfd, bfd_object))
167 goto out;
168
169 a2l = zalloc(sizeof(*a2l));
170 if (a2l == NULL)
171 goto out;
172
173 a2l->abfd = abfd;
174 a2l->input = strdup(path);
175 if (a2l->input == NULL)
176 goto out;
177
178 if (slurp_symtab(abfd, a2l))
179 goto out;
180
181 return a2l;
182
183 out:
184 if (a2l) {
185 zfree((char **)&a2l->input);
186 free(a2l);
187 }
188 bfd_close(abfd);
189 return NULL;
190 }
191
192 static void addr2line_cleanup(struct a2l_data *a2l)
193 {
194 if (a2l->abfd)
195 bfd_close(a2l->abfd);
196 zfree((char **)&a2l->input);
197 zfree(&a2l->syms);
198 free(a2l);
199 }
200
201 #define MAX_INLINE_NEST 1024
202
203 static void inline_list__reverse(struct inline_node *node)
204 {
205 struct inline_list *ilist, *n;
206
207 list_for_each_entry_safe_reverse(ilist, n, &node->val, list)
208 list_move_tail(&ilist->list, &node->val);
209 }
210
211 static int addr2line(const char *dso_name, u64 addr,
212 char **file, unsigned int *line, struct dso *dso,
213 bool unwind_inlines, struct inline_node *node)
214 {
215 int ret = 0;
216 struct a2l_data *a2l = dso->a2l;
217
218 if (!a2l) {
219 dso->a2l = addr2line_init(dso_name);
220 a2l = dso->a2l;
221 }
222
223 if (a2l == NULL) {
224 pr_warning("addr2line_init failed for %s\n", dso_name);
225 return 0;
226 }
227
228 a2l->addr = addr;
229 a2l->found = false;
230
231 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
232
233 if (a2l->found && unwind_inlines) {
234 int cnt = 0;
235
236 while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
237 &a2l->funcname, &a2l->line) &&
238 cnt++ < MAX_INLINE_NEST) {
239
240 if (node != NULL) {
241 if (inline_list__append(strdup(a2l->filename),
242 strdup(a2l->funcname),
243 a2l->line, node,
244 dso) != 0)
245 return 0;
246 }
247 }
248
249 if ((node != NULL) &&
250 (callchain_param.order != ORDER_CALLEE)) {
251 inline_list__reverse(node);
252 }
253 }
254
255 if (a2l->found && a2l->filename) {
256 *file = strdup(a2l->filename);
257 *line = a2l->line;
258
259 if (*file)
260 ret = 1;
261 }
262
263 return ret;
264 }
265
266 void dso__free_a2l(struct dso *dso)
267 {
268 struct a2l_data *a2l = dso->a2l;
269
270 if (!a2l)
271 return;
272
273 addr2line_cleanup(a2l);
274
275 dso->a2l = NULL;
276 }
277
278 static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
279 struct dso *dso)
280 {
281 char *file = NULL;
282 unsigned int line = 0;
283 struct inline_node *node;
284
285 node = zalloc(sizeof(*node));
286 if (node == NULL) {
287 perror("not enough memory for the inline node");
288 return NULL;
289 }
290
291 INIT_LIST_HEAD(&node->val);
292 node->addr = addr;
293
294 if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node))
295 goto out_free_inline_node;
296
297 if (list_empty(&node->val))
298 goto out_free_inline_node;
299
300 return node;
301
302 out_free_inline_node:
303 inline_node__delete(node);
304 return NULL;
305 }
306
307 #else /* HAVE_LIBBFD_SUPPORT */
308
309 static int filename_split(char *filename, unsigned int *line_nr)
310 {
311 char *sep;
312
313 sep = strchr(filename, '\n');
314 if (sep)
315 *sep = '\0';
316
317 if (!strcmp(filename, "??:0"))
318 return 0;
319
320 sep = strchr(filename, ':');
321 if (sep) {
322 *sep++ = '\0';
323 *line_nr = strtoul(sep, NULL, 0);
324 return 1;
325 }
326
327 return 0;
328 }
329
330 static int addr2line(const char *dso_name, u64 addr,
331 char **file, unsigned int *line_nr,
332 struct dso *dso __maybe_unused,
333 bool unwind_inlines __maybe_unused,
334 struct inline_node *node __maybe_unused)
335 {
336 FILE *fp;
337 char cmd[PATH_MAX];
338 char *filename = NULL;
339 size_t len;
340 int ret = 0;
341
342 scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
343 dso_name, addr);
344
345 fp = popen(cmd, "r");
346 if (fp == NULL) {
347 pr_warning("popen failed for %s\n", dso_name);
348 return 0;
349 }
350
351 if (getline(&filename, &len, fp) < 0 || !len) {
352 pr_warning("addr2line has no output for %s\n", dso_name);
353 goto out;
354 }
355
356 ret = filename_split(filename, line_nr);
357 if (ret != 1) {
358 free(filename);
359 goto out;
360 }
361
362 *file = filename;
363
364 out:
365 pclose(fp);
366 return ret;
367 }
368
369 void dso__free_a2l(struct dso *dso __maybe_unused)
370 {
371 }
372
373 static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
374 struct dso *dso __maybe_unused)
375 {
376 FILE *fp;
377 char cmd[PATH_MAX];
378 struct inline_node *node;
379 char *filename = NULL;
380 size_t len;
381 unsigned int line_nr = 0;
382
383 scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64,
384 dso_name, addr);
385
386 fp = popen(cmd, "r");
387 if (fp == NULL) {
388 pr_err("popen failed for %s\n", dso_name);
389 return NULL;
390 }
391
392 node = zalloc(sizeof(*node));
393 if (node == NULL) {
394 perror("not enough memory for the inline node");
395 goto out;
396 }
397
398 INIT_LIST_HEAD(&node->val);
399 node->addr = addr;
400
401 while (getline(&filename, &len, fp) != -1) {
402 if (filename_split(filename, &line_nr) != 1) {
403 free(filename);
404 goto out;
405 }
406
407 if (inline_list__append(filename, NULL, line_nr, node,
408 NULL) != 0)
409 goto out;
410
411 filename = NULL;
412 }
413
414 out:
415 pclose(fp);
416
417 if (list_empty(&node->val)) {
418 inline_node__delete(node);
419 return NULL;
420 }
421
422 return node;
423 }
424
425 #endif /* HAVE_LIBBFD_SUPPORT */
426
427 /*
428 * Number of addr2line failures (without success) before disabling it for that
429 * dso.
430 */
431 #define A2L_FAIL_LIMIT 123
432
433 char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
434 bool show_sym, bool show_addr, bool unwind_inlines)
435 {
436 char *file = NULL;
437 unsigned line = 0;
438 char *srcline;
439 const char *dso_name;
440
441 if (!dso->has_srcline)
442 goto out;
443
444 dso_name = dso__name(dso);
445 if (dso_name == NULL)
446 goto out;
447
448 if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines, NULL))
449 goto out;
450
451 if (asprintf(&srcline, "%s:%u",
452 srcline_full_filename ? file : basename(file),
453 line) < 0) {
454 free(file);
455 goto out;
456 }
457
458 dso->a2l_fails = 0;
459
460 free(file);
461 return srcline;
462
463 out:
464 if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) {
465 dso->has_srcline = 0;
466 dso__free_a2l(dso);
467 }
468
469 if (!show_addr)
470 return (show_sym && sym) ?
471 strndup(sym->name, sym->namelen) : NULL;
472
473 if (sym) {
474 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
475 addr - sym->start) < 0)
476 return SRCLINE_UNKNOWN;
477 } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0)
478 return SRCLINE_UNKNOWN;
479 return srcline;
480 }
481
482 void free_srcline(char *srcline)
483 {
484 if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
485 free(srcline);
486 }
487
488 char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
489 bool show_sym, bool show_addr)
490 {
491 return __get_srcline(dso, addr, sym, show_sym, show_addr, false);
492 }
493
494 struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr)
495 {
496 const char *dso_name;
497
498 dso_name = dso__name(dso);
499 if (dso_name == NULL)
500 return NULL;
501
502 return addr2inlines(dso_name, addr, dso);
503 }
504
505 void inline_node__delete(struct inline_node *node)
506 {
507 struct inline_list *ilist, *tmp;
508
509 list_for_each_entry_safe(ilist, tmp, &node->val, list) {
510 list_del_init(&ilist->list);
511 zfree(&ilist->filename);
512 zfree(&ilist->funcname);
513 free(ilist);
514 }
515
516 free(node);
517 }