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