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