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