xref: /linux/tools/perf/util/srcline.c (revision bf4afc53b77aeaa48b5409da5c8da6bb4eff7f43)
1 // SPDX-License-Identifier: GPL-2.0
2 #include "srcline.h"
3 #include "addr2line.h"
4 #include "dso.h"
5 #include "callchain.h"
6 #include "libbfd.h"
7 #include "llvm.h"
8 #include "symbol.h"
9 #include "libdw.h"
10 #include "debug.h"
11 
12 #include <inttypes.h>
13 #include <string.h>
14 #include <linux/string.h>
15 
16 bool srcline_full_filename;
17 
18 char *srcline__unknown = (char *)"??:0";
19 
20 static const char *srcline_dso_name(struct dso *dso)
21 {
22 	const char *dso_name;
23 
24 	if (dso__symsrc_filename(dso))
25 		dso_name = dso__symsrc_filename(dso);
26 	else
27 		dso_name = dso__long_name(dso);
28 
29 	if (dso_name[0] == '[')
30 		return NULL;
31 
32 	if (is_perf_pid_map_name(dso_name))
33 		return NULL;
34 
35 	return dso_name;
36 }
37 
38 int inline_list__append(struct symbol *symbol, char *srcline, 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 int inline_list__append_tail(struct symbol *symbol, char *srcline, struct inline_node *node)
58 {
59 	struct inline_list *ilist;
60 
61 	ilist = zalloc(sizeof(*ilist));
62 	if (ilist == NULL)
63 		return -1;
64 
65 	ilist->symbol = symbol;
66 	ilist->srcline = srcline;
67 
68 	if (callchain_param.order == ORDER_CALLEE)
69 		list_add(&ilist->list, &node->val);
70 	else
71 		list_add_tail(&ilist->list, &node->val);
72 
73 	return 0;
74 }
75 
76 /* basename version that takes a const input string */
77 static const char *gnu_basename(const char *path)
78 {
79 	const char *base = strrchr(path, '/');
80 
81 	return base ? base + 1 : path;
82 }
83 
84 char *srcline_from_fileline(const char *file, unsigned int line)
85 {
86 	char *srcline;
87 
88 	if (!file)
89 		return NULL;
90 
91 	if (!srcline_full_filename)
92 		file = gnu_basename(file);
93 
94 	if (asprintf(&srcline, "%s:%u", file, line) < 0)
95 		return NULL;
96 
97 	return srcline;
98 }
99 
100 struct symbol *new_inline_sym(struct dso *dso,
101 			      struct symbol *base_sym,
102 			      const char *funcname)
103 {
104 	struct symbol *inline_sym;
105 	char *demangled = NULL;
106 
107 	if (!funcname)
108 		funcname = "??";
109 
110 	if (dso) {
111 		demangled = dso__demangle_sym(dso, 0, funcname);
112 		if (demangled)
113 			funcname = demangled;
114 	}
115 
116 	if (base_sym && strcmp(funcname, base_sym->name) == 0) {
117 		/* reuse the real, existing symbol */
118 		inline_sym = base_sym;
119 		/* ensure that we don't alias an inlined symbol, which could
120 		 * lead to double frees in inline_node__delete
121 		 */
122 		assert(!base_sym->inlined);
123 	} else {
124 		/* create a fake symbol for the inline frame */
125 		inline_sym = symbol__new(base_sym ? base_sym->start : 0,
126 					 base_sym ? (base_sym->end - base_sym->start) : 0,
127 					 base_sym ? base_sym->binding : 0,
128 					 base_sym ? base_sym->type : 0,
129 					 funcname);
130 		if (inline_sym)
131 			inline_sym->inlined = 1;
132 	}
133 
134 	free(demangled);
135 
136 	return inline_sym;
137 }
138 
139 static int addr2line(const char *dso_name, u64 addr, char **file, unsigned int *line_nr,
140 		     struct dso *dso, bool unwind_inlines, struct inline_node *node,
141 		     struct symbol *sym)
142 {
143 	int ret = 0;
144 
145 	if (symbol_conf.addr2line_style[0] == A2L_STYLE_UNKNOWN) {
146 		int i = 0;
147 
148 		/* Default addr2line fallback order. */
149 #ifdef HAVE_LIBDW_SUPPORT
150 		symbol_conf.addr2line_style[i++] = A2L_STYLE_LIBDW;
151 #endif
152 #ifdef HAVE_LIBLLVM_SUPPORT
153 		symbol_conf.addr2line_style[i++] = A2L_STYLE_LLVM;
154 #endif
155 #ifdef HAVE_LIBBFD_SUPPORT
156 		symbol_conf.addr2line_style[i++] = A2L_STYLE_LIBBFD;
157 #endif
158 		symbol_conf.addr2line_style[i++] = A2L_STYLE_CMD;
159 	}
160 
161 	for (size_t i = 0; i < ARRAY_SIZE(symbol_conf.addr2line_style); i++) {
162 		switch (symbol_conf.addr2line_style[i]) {
163 		case A2L_STYLE_LIBDW:
164 			ret = libdw__addr2line(addr, file, line_nr, dso, unwind_inlines,
165 					       node, sym);
166 			break;
167 		case A2L_STYLE_LLVM:
168 			ret = llvm__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines,
169 					      node, sym);
170 			break;
171 		case A2L_STYLE_LIBBFD:
172 			ret = libbfd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines,
173 						node, sym);
174 			break;
175 		case A2L_STYLE_CMD:
176 			ret = cmd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines,
177 					     node, sym);
178 			break;
179 		case A2L_STYLE_UNKNOWN:
180 		default:
181 			break;
182 		}
183 		if (ret > 0)
184 			return ret;
185 	}
186 
187 	return 0;
188 }
189 
190 int addr2line_configure(const char *var, const char *value, void *cb __maybe_unused)
191 {
192 	static const char * const a2l_style_names[] = {
193 		[A2L_STYLE_LIBDW] = "libdw",
194 		[A2L_STYLE_LLVM] = "llvm",
195 		[A2L_STYLE_LIBBFD] = "libbfd",
196 		[A2L_STYLE_CMD] = "addr2line",
197 		NULL
198 	};
199 
200 	char *s, *p, *saveptr;
201 	size_t i = 0;
202 
203 	if (strcmp(var, "addr2line.style"))
204 		return 0;
205 
206 	if (!value)
207 		return -1;
208 
209 	s = strdup(value);
210 	if (!s)
211 		return -1;
212 
213 	p = strtok_r(s, ",", &saveptr);
214 	while (p && i < ARRAY_SIZE(symbol_conf.addr2line_style)) {
215 		bool found = false;
216 		char *q = strim(p);
217 
218 		for (size_t j = A2L_STYLE_LIBDW; j < MAX_A2L_STYLE; j++) {
219 			if (!strcasecmp(q, a2l_style_names[j])) {
220 				symbol_conf.addr2line_style[i++] = j;
221 				found = true;
222 				break;
223 			}
224 		}
225 		if (!found)
226 			pr_warning("Unknown addr2line style: %s\n", q);
227 		p = strtok_r(NULL, ",", &saveptr);
228 	}
229 
230 	free(s);
231 	return 0;
232 }
233 
234 static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
235 					struct dso *dso, struct symbol *sym)
236 {
237 	struct inline_node *node;
238 
239 	node = zalloc(sizeof(*node));
240 	if (node == NULL) {
241 		perror("not enough memory for the inline node");
242 		return NULL;
243 	}
244 
245 	INIT_LIST_HEAD(&node->val);
246 	node->addr = addr;
247 
248 	addr2line(dso_name, addr, /*file=*/NULL, /*line_nr=*/NULL, dso,
249 		  /*unwind_inlines=*/true, node, sym);
250 
251 	return node;
252 }
253 
254 /*
255  * Number of addr2line failures (without success) before disabling it for that
256  * dso.
257  */
258 #define A2L_FAIL_LIMIT 123
259 
260 char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
261 		  bool show_sym, bool show_addr, bool unwind_inlines,
262 		  u64 ip)
263 {
264 	char *file = NULL;
265 	unsigned line = 0;
266 	char *srcline;
267 	const char *dso_name;
268 
269 	if (!dso__has_srcline(dso))
270 		goto out;
271 
272 	dso_name = srcline_dso_name(dso);
273 	if (dso_name == NULL)
274 		goto out_err;
275 
276 	if (!addr2line(dso_name, addr, &file, &line, dso,
277 		       unwind_inlines, /*node=*/NULL, sym))
278 		goto out_err;
279 
280 	srcline = srcline_from_fileline(file, line);
281 	free(file);
282 
283 	if (!srcline)
284 		goto out_err;
285 
286 	dso__set_a2l_fails(dso, 0);
287 
288 	return srcline;
289 
290 out_err:
291 	dso__set_a2l_fails(dso, dso__a2l_fails(dso) + 1);
292 	if (dso__a2l_fails(dso) > A2L_FAIL_LIMIT) {
293 		dso__set_has_srcline(dso, false);
294 		dso__free_a2l(dso);
295 	}
296 out:
297 	if (!show_addr)
298 		return (show_sym && sym) ?
299 			    strndup(sym->name, sym->namelen) : SRCLINE_UNKNOWN;
300 
301 	if (sym) {
302 		if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
303 					ip - sym->start) < 0)
304 			return SRCLINE_UNKNOWN;
305 	} else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso__short_name(dso), addr) < 0)
306 		return SRCLINE_UNKNOWN;
307 	return srcline;
308 }
309 
310 /* Returns filename and fills in line number in line */
311 char *get_srcline_split(struct dso *dso, u64 addr, unsigned *line)
312 {
313 	char *file = NULL;
314 	const char *dso_name;
315 
316 	if (!dso__has_srcline(dso))
317 		return NULL;
318 
319 	dso_name = srcline_dso_name(dso);
320 	if (dso_name == NULL)
321 		goto out_err;
322 
323 	if (!addr2line(dso_name, addr, &file, line, dso, /*unwind_inlines=*/true,
324 			/*node=*/NULL, /*sym=*/NULL))
325 		goto out_err;
326 
327 	dso__set_a2l_fails(dso, 0);
328 	return file;
329 
330 out_err:
331 	dso__set_a2l_fails(dso, dso__a2l_fails(dso) + 1);
332 	if (dso__a2l_fails(dso) > A2L_FAIL_LIMIT) {
333 		dso__set_has_srcline(dso, false);
334 		dso__free_a2l(dso);
335 	}
336 
337 	return NULL;
338 }
339 
340 void zfree_srcline(char **srcline)
341 {
342 	if (*srcline == NULL)
343 		return;
344 
345 	if (*srcline != SRCLINE_UNKNOWN)
346 		free(*srcline);
347 
348 	*srcline = NULL;
349 }
350 
351 char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
352 		  bool show_sym, bool show_addr, u64 ip)
353 {
354 	return __get_srcline(dso, addr, sym, show_sym, show_addr, false, ip);
355 }
356 
357 struct srcline_node {
358 	u64			addr;
359 	char			*srcline;
360 	struct rb_node		rb_node;
361 };
362 
363 void srcline__tree_insert(struct rb_root_cached *tree, u64 addr, char *srcline)
364 {
365 	struct rb_node **p = &tree->rb_root.rb_node;
366 	struct rb_node *parent = NULL;
367 	struct srcline_node *i, *node;
368 	bool leftmost = true;
369 
370 	node = zalloc(sizeof(struct srcline_node));
371 	if (!node) {
372 		perror("not enough memory for the srcline node");
373 		return;
374 	}
375 
376 	node->addr = addr;
377 	node->srcline = srcline;
378 
379 	while (*p != NULL) {
380 		parent = *p;
381 		i = rb_entry(parent, struct srcline_node, rb_node);
382 		if (addr < i->addr)
383 			p = &(*p)->rb_left;
384 		else {
385 			p = &(*p)->rb_right;
386 			leftmost = false;
387 		}
388 	}
389 	rb_link_node(&node->rb_node, parent, p);
390 	rb_insert_color_cached(&node->rb_node, tree, leftmost);
391 }
392 
393 char *srcline__tree_find(struct rb_root_cached *tree, u64 addr)
394 {
395 	struct rb_node *n = tree->rb_root.rb_node;
396 
397 	while (n) {
398 		struct srcline_node *i = rb_entry(n, struct srcline_node,
399 						  rb_node);
400 
401 		if (addr < i->addr)
402 			n = n->rb_left;
403 		else if (addr > i->addr)
404 			n = n->rb_right;
405 		else
406 			return i->srcline;
407 	}
408 
409 	return NULL;
410 }
411 
412 void srcline__tree_delete(struct rb_root_cached *tree)
413 {
414 	struct srcline_node *pos;
415 	struct rb_node *next = rb_first_cached(tree);
416 
417 	while (next) {
418 		pos = rb_entry(next, struct srcline_node, rb_node);
419 		next = rb_next(&pos->rb_node);
420 		rb_erase_cached(&pos->rb_node, tree);
421 		zfree_srcline(&pos->srcline);
422 		zfree(&pos);
423 	}
424 }
425 
426 struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr,
427 					    struct symbol *sym)
428 {
429 	const char *dso_name;
430 
431 	dso_name = srcline_dso_name(dso);
432 	if (dso_name == NULL)
433 		return NULL;
434 
435 	return addr2inlines(dso_name, addr, dso, sym);
436 }
437 
438 void inline_node__delete(struct inline_node *node)
439 {
440 	struct inline_list *ilist, *tmp;
441 
442 	list_for_each_entry_safe(ilist, tmp, &node->val, list) {
443 		list_del_init(&ilist->list);
444 		zfree_srcline(&ilist->srcline);
445 		/* only the inlined symbols are owned by the list */
446 		if (ilist->symbol && ilist->symbol->inlined)
447 			symbol__delete(ilist->symbol);
448 		free(ilist);
449 	}
450 
451 	free(node);
452 }
453 
454 void inlines__tree_insert(struct rb_root_cached *tree,
455 			  struct inline_node *inlines)
456 {
457 	struct rb_node **p = &tree->rb_root.rb_node;
458 	struct rb_node *parent = NULL;
459 	const u64 addr = inlines->addr;
460 	struct inline_node *i;
461 	bool leftmost = true;
462 
463 	while (*p != NULL) {
464 		parent = *p;
465 		i = rb_entry(parent, struct inline_node, rb_node);
466 		if (addr < i->addr)
467 			p = &(*p)->rb_left;
468 		else {
469 			p = &(*p)->rb_right;
470 			leftmost = false;
471 		}
472 	}
473 	rb_link_node(&inlines->rb_node, parent, p);
474 	rb_insert_color_cached(&inlines->rb_node, tree, leftmost);
475 }
476 
477 struct inline_node *inlines__tree_find(struct rb_root_cached *tree, u64 addr)
478 {
479 	struct rb_node *n = tree->rb_root.rb_node;
480 
481 	while (n) {
482 		struct inline_node *i = rb_entry(n, struct inline_node,
483 						 rb_node);
484 
485 		if (addr < i->addr)
486 			n = n->rb_left;
487 		else if (addr > i->addr)
488 			n = n->rb_right;
489 		else
490 			return i;
491 	}
492 
493 	return NULL;
494 }
495 
496 void inlines__tree_delete(struct rb_root_cached *tree)
497 {
498 	struct inline_node *pos;
499 	struct rb_node *next = rb_first_cached(tree);
500 
501 	while (next) {
502 		pos = rb_entry(next, struct inline_node, rb_node);
503 		next = rb_next(&pos->rb_node);
504 		rb_erase_cached(&pos->rb_node, tree);
505 		inline_node__delete(pos);
506 	}
507 }
508