xref: /openbmc/linux/tools/perf/util/srcline.c (revision cfbb9be8)
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 		  u64 ip)
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 					ip - 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, u64 ip)
555 {
556 	return __get_srcline(dso, addr, sym, show_sym, show_addr, false, ip);
557 }
558 
559 struct srcline_node {
560 	u64			addr;
561 	char			*srcline;
562 	struct rb_node		rb_node;
563 };
564 
565 void srcline__tree_insert(struct rb_root *tree, u64 addr, char *srcline)
566 {
567 	struct rb_node **p = &tree->rb_node;
568 	struct rb_node *parent = NULL;
569 	struct srcline_node *i, *node;
570 
571 	node = zalloc(sizeof(struct srcline_node));
572 	if (!node) {
573 		perror("not enough memory for the srcline node");
574 		return;
575 	}
576 
577 	node->addr = addr;
578 	node->srcline = srcline;
579 
580 	while (*p != NULL) {
581 		parent = *p;
582 		i = rb_entry(parent, struct srcline_node, rb_node);
583 		if (addr < i->addr)
584 			p = &(*p)->rb_left;
585 		else
586 			p = &(*p)->rb_right;
587 	}
588 	rb_link_node(&node->rb_node, parent, p);
589 	rb_insert_color(&node->rb_node, tree);
590 }
591 
592 char *srcline__tree_find(struct rb_root *tree, u64 addr)
593 {
594 	struct rb_node *n = tree->rb_node;
595 
596 	while (n) {
597 		struct srcline_node *i = rb_entry(n, struct srcline_node,
598 						  rb_node);
599 
600 		if (addr < i->addr)
601 			n = n->rb_left;
602 		else if (addr > i->addr)
603 			n = n->rb_right;
604 		else
605 			return i->srcline;
606 	}
607 
608 	return NULL;
609 }
610 
611 void srcline__tree_delete(struct rb_root *tree)
612 {
613 	struct srcline_node *pos;
614 	struct rb_node *next = rb_first(tree);
615 
616 	while (next) {
617 		pos = rb_entry(next, struct srcline_node, rb_node);
618 		next = rb_next(&pos->rb_node);
619 		rb_erase(&pos->rb_node, tree);
620 		free_srcline(pos->srcline);
621 		zfree(&pos);
622 	}
623 }
624 
625 struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr,
626 					    struct symbol *sym)
627 {
628 	const char *dso_name;
629 
630 	dso_name = dso__name(dso);
631 	if (dso_name == NULL)
632 		return NULL;
633 
634 	return addr2inlines(dso_name, addr, dso, sym);
635 }
636 
637 void inline_node__delete(struct inline_node *node)
638 {
639 	struct inline_list *ilist, *tmp;
640 
641 	list_for_each_entry_safe(ilist, tmp, &node->val, list) {
642 		list_del_init(&ilist->list);
643 		free_srcline(ilist->srcline);
644 		/* only the inlined symbols are owned by the list */
645 		if (ilist->symbol && ilist->symbol->inlined)
646 			symbol__delete(ilist->symbol);
647 		free(ilist);
648 	}
649 
650 	free(node);
651 }
652 
653 void inlines__tree_insert(struct rb_root *tree, struct inline_node *inlines)
654 {
655 	struct rb_node **p = &tree->rb_node;
656 	struct rb_node *parent = NULL;
657 	const u64 addr = inlines->addr;
658 	struct inline_node *i;
659 
660 	while (*p != NULL) {
661 		parent = *p;
662 		i = rb_entry(parent, struct inline_node, rb_node);
663 		if (addr < i->addr)
664 			p = &(*p)->rb_left;
665 		else
666 			p = &(*p)->rb_right;
667 	}
668 	rb_link_node(&inlines->rb_node, parent, p);
669 	rb_insert_color(&inlines->rb_node, tree);
670 }
671 
672 struct inline_node *inlines__tree_find(struct rb_root *tree, u64 addr)
673 {
674 	struct rb_node *n = tree->rb_node;
675 
676 	while (n) {
677 		struct inline_node *i = rb_entry(n, struct inline_node,
678 						 rb_node);
679 
680 		if (addr < i->addr)
681 			n = n->rb_left;
682 		else if (addr > i->addr)
683 			n = n->rb_right;
684 		else
685 			return i;
686 	}
687 
688 	return NULL;
689 }
690 
691 void inlines__tree_delete(struct rb_root *tree)
692 {
693 	struct inline_node *pos;
694 	struct rb_node *next = rb_first(tree);
695 
696 	while (next) {
697 		pos = rb_entry(next, struct inline_node, rb_node);
698 		next = rb_next(&pos->rb_node);
699 		rb_erase(&pos->rb_node, tree);
700 		inline_node__delete(pos);
701 	}
702 }
703