xref: /linux/tools/perf/util/srcline.c (revision 11ea2515f32e783b9a7984c148e742c377383915)
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 }
586 
587 void inlines__tree_insert(struct rb_root *tree, struct inline_node *inlines)
588 {
589 	struct rb_node **p = &tree->rb_node;
590 	struct rb_node *parent = NULL;
591 	const u64 addr = inlines->addr;
592 	struct inline_node *i;
593 
594 	while (*p != NULL) {
595 		parent = *p;
596 		i = rb_entry(parent, struct inline_node, rb_node);
597 		if (addr < i->addr)
598 			p = &(*p)->rb_left;
599 		else
600 			p = &(*p)->rb_right;
601 	}
602 	rb_link_node(&inlines->rb_node, parent, p);
603 	rb_insert_color(&inlines->rb_node, tree);
604 }
605 
606 struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr)
607 {
608 	struct rb_node *n = tree->rb_node;
609 
610 	while (n) {
611 		struct inline_node *i = rb_entry(n, struct inline_node,
612 						 rb_node);
613 
614 		if (addr < i->addr)
615 			n = n->rb_left;
616 		else if (addr > i->addr)
617 			n = n->rb_right;
618 		else
619 			return i;
620 	}
621 
622 	return NULL;
623 }
624 
625 void inlines__tree_delete(struct rb_root *tree)
626 {
627 	struct inline_node *pos;
628 	struct rb_node *next = rb_first(tree);
629 
630 	while (next) {
631 		pos = rb_entry(next, struct inline_node, rb_node);
632 		next = rb_next(&pos->rb_node);
633 		rb_erase(&pos->rb_node, tree);
634 		inline_node__delete(pos);
635 	}
636 }
637