xref: /openbmc/linux/tools/perf/util/srcline.c (revision d236d361)
1 #include <inttypes.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #include <linux/kernel.h>
7 
8 #include "util/dso.h"
9 #include "util/util.h"
10 #include "util/debug.h"
11 #include "util/callchain.h"
12 #include "srcline.h"
13 
14 #include "symbol.h"
15 
16 bool srcline_full_filename;
17 
18 static const char *dso__name(struct dso *dso)
19 {
20 	const char *dso_name;
21 
22 	if (dso->symsrc_filename)
23 		dso_name = dso->symsrc_filename;
24 	else
25 		dso_name = dso->long_name;
26 
27 	if (dso_name[0] == '[')
28 		return NULL;
29 
30 	if (!strncmp(dso_name, "/tmp/perf-", 10))
31 		return NULL;
32 
33 	return dso_name;
34 }
35 
36 static int inline_list__append(char *filename, char *funcname, int line_nr,
37 			       struct inline_node *node, struct dso *dso)
38 {
39 	struct inline_list *ilist;
40 	char *demangled;
41 
42 	ilist = zalloc(sizeof(*ilist));
43 	if (ilist == NULL)
44 		return -1;
45 
46 	ilist->filename = filename;
47 	ilist->line_nr = line_nr;
48 
49 	if (dso != NULL) {
50 		demangled = dso__demangle_sym(dso, 0, funcname);
51 		if (demangled == NULL) {
52 			ilist->funcname = funcname;
53 		} else {
54 			ilist->funcname = demangled;
55 			free(funcname);
56 		}
57 	}
58 
59 	list_add_tail(&ilist->list, &node->val);
60 
61 	return 0;
62 }
63 
64 #ifdef HAVE_LIBBFD_SUPPORT
65 
66 /*
67  * Implement addr2line using libbfd.
68  */
69 #define PACKAGE "perf"
70 #include <bfd.h>
71 
72 struct a2l_data {
73 	const char 	*input;
74 	u64	 	addr;
75 
76 	bool 		found;
77 	const char 	*filename;
78 	const char 	*funcname;
79 	unsigned 	line;
80 
81 	bfd 		*abfd;
82 	asymbol 	**syms;
83 };
84 
85 static int bfd_error(const char *string)
86 {
87 	const char *errmsg;
88 
89 	errmsg = bfd_errmsg(bfd_get_error());
90 	fflush(stdout);
91 
92 	if (string)
93 		pr_debug("%s: %s\n", string, errmsg);
94 	else
95 		pr_debug("%s\n", errmsg);
96 
97 	return -1;
98 }
99 
100 static int slurp_symtab(bfd *abfd, struct a2l_data *a2l)
101 {
102 	long storage;
103 	long symcount;
104 	asymbol **syms;
105 	bfd_boolean dynamic = FALSE;
106 
107 	if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
108 		return bfd_error(bfd_get_filename(abfd));
109 
110 	storage = bfd_get_symtab_upper_bound(abfd);
111 	if (storage == 0L) {
112 		storage = bfd_get_dynamic_symtab_upper_bound(abfd);
113 		dynamic = TRUE;
114 	}
115 	if (storage < 0L)
116 		return bfd_error(bfd_get_filename(abfd));
117 
118 	syms = malloc(storage);
119 	if (dynamic)
120 		symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
121 	else
122 		symcount = bfd_canonicalize_symtab(abfd, syms);
123 
124 	if (symcount < 0) {
125 		free(syms);
126 		return bfd_error(bfd_get_filename(abfd));
127 	}
128 
129 	a2l->syms = syms;
130 	return 0;
131 }
132 
133 static void find_address_in_section(bfd *abfd, asection *section, void *data)
134 {
135 	bfd_vma pc, vma;
136 	bfd_size_type size;
137 	struct a2l_data *a2l = data;
138 
139 	if (a2l->found)
140 		return;
141 
142 	if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
143 		return;
144 
145 	pc = a2l->addr;
146 	vma = bfd_get_section_vma(abfd, section);
147 	size = bfd_get_section_size(section);
148 
149 	if (pc < vma || pc >= vma + size)
150 		return;
151 
152 	a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
153 					   &a2l->filename, &a2l->funcname,
154 					   &a2l->line);
155 }
156 
157 static struct a2l_data *addr2line_init(const char *path)
158 {
159 	bfd *abfd;
160 	struct a2l_data *a2l = NULL;
161 
162 	abfd = bfd_openr(path, NULL);
163 	if (abfd == NULL)
164 		return NULL;
165 
166 	if (!bfd_check_format(abfd, bfd_object))
167 		goto out;
168 
169 	a2l = zalloc(sizeof(*a2l));
170 	if (a2l == NULL)
171 		goto out;
172 
173 	a2l->abfd = abfd;
174 	a2l->input = strdup(path);
175 	if (a2l->input == NULL)
176 		goto out;
177 
178 	if (slurp_symtab(abfd, a2l))
179 		goto out;
180 
181 	return a2l;
182 
183 out:
184 	if (a2l) {
185 		zfree((char **)&a2l->input);
186 		free(a2l);
187 	}
188 	bfd_close(abfd);
189 	return NULL;
190 }
191 
192 static void addr2line_cleanup(struct a2l_data *a2l)
193 {
194 	if (a2l->abfd)
195 		bfd_close(a2l->abfd);
196 	zfree((char **)&a2l->input);
197 	zfree(&a2l->syms);
198 	free(a2l);
199 }
200 
201 #define MAX_INLINE_NEST 1024
202 
203 static void inline_list__reverse(struct inline_node *node)
204 {
205 	struct inline_list *ilist, *n;
206 
207 	list_for_each_entry_safe_reverse(ilist, n, &node->val, list)
208 		list_move_tail(&ilist->list, &node->val);
209 }
210 
211 static int addr2line(const char *dso_name, u64 addr,
212 		     char **file, unsigned int *line, struct dso *dso,
213 		     bool unwind_inlines, struct inline_node *node)
214 {
215 	int ret = 0;
216 	struct a2l_data *a2l = dso->a2l;
217 
218 	if (!a2l) {
219 		dso->a2l = addr2line_init(dso_name);
220 		a2l = dso->a2l;
221 	}
222 
223 	if (a2l == NULL) {
224 		pr_warning("addr2line_init failed for %s\n", dso_name);
225 		return 0;
226 	}
227 
228 	a2l->addr = addr;
229 	a2l->found = false;
230 
231 	bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
232 
233 	if (a2l->found && unwind_inlines) {
234 		int cnt = 0;
235 
236 		while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
237 					     &a2l->funcname, &a2l->line) &&
238 		       cnt++ < MAX_INLINE_NEST) {
239 
240 			if (node != NULL) {
241 				if (inline_list__append(strdup(a2l->filename),
242 							strdup(a2l->funcname),
243 							a2l->line, node,
244 							dso) != 0)
245 					return 0;
246 			}
247 		}
248 
249 		if ((node != NULL) &&
250 		    (callchain_param.order != ORDER_CALLEE)) {
251 			inline_list__reverse(node);
252 		}
253 	}
254 
255 	if (a2l->found && a2l->filename) {
256 		*file = strdup(a2l->filename);
257 		*line = a2l->line;
258 
259 		if (*file)
260 			ret = 1;
261 	}
262 
263 	return ret;
264 }
265 
266 void dso__free_a2l(struct dso *dso)
267 {
268 	struct a2l_data *a2l = dso->a2l;
269 
270 	if (!a2l)
271 		return;
272 
273 	addr2line_cleanup(a2l);
274 
275 	dso->a2l = NULL;
276 }
277 
278 static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
279 	struct dso *dso)
280 {
281 	char *file = NULL;
282 	unsigned int line = 0;
283 	struct inline_node *node;
284 
285 	node = zalloc(sizeof(*node));
286 	if (node == NULL) {
287 		perror("not enough memory for the inline node");
288 		return NULL;
289 	}
290 
291 	INIT_LIST_HEAD(&node->val);
292 	node->addr = addr;
293 
294 	if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node))
295 		goto out_free_inline_node;
296 
297 	if (list_empty(&node->val))
298 		goto out_free_inline_node;
299 
300 	return node;
301 
302 out_free_inline_node:
303 	inline_node__delete(node);
304 	return NULL;
305 }
306 
307 #else /* HAVE_LIBBFD_SUPPORT */
308 
309 static int filename_split(char *filename, unsigned int *line_nr)
310 {
311 	char *sep;
312 
313 	sep = strchr(filename, '\n');
314 	if (sep)
315 		*sep = '\0';
316 
317 	if (!strcmp(filename, "??:0"))
318 		return 0;
319 
320 	sep = strchr(filename, ':');
321 	if (sep) {
322 		*sep++ = '\0';
323 		*line_nr = strtoul(sep, NULL, 0);
324 		return 1;
325 	}
326 
327 	return 0;
328 }
329 
330 static int addr2line(const char *dso_name, u64 addr,
331 		     char **file, unsigned int *line_nr,
332 		     struct dso *dso __maybe_unused,
333 		     bool unwind_inlines __maybe_unused,
334 		     struct inline_node *node __maybe_unused)
335 {
336 	FILE *fp;
337 	char cmd[PATH_MAX];
338 	char *filename = NULL;
339 	size_t len;
340 	int ret = 0;
341 
342 	scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
343 		  dso_name, addr);
344 
345 	fp = popen(cmd, "r");
346 	if (fp == NULL) {
347 		pr_warning("popen failed for %s\n", dso_name);
348 		return 0;
349 	}
350 
351 	if (getline(&filename, &len, fp) < 0 || !len) {
352 		pr_warning("addr2line has no output for %s\n", dso_name);
353 		goto out;
354 	}
355 
356 	ret = filename_split(filename, line_nr);
357 	if (ret != 1) {
358 		free(filename);
359 		goto out;
360 	}
361 
362 	*file = filename;
363 
364 out:
365 	pclose(fp);
366 	return ret;
367 }
368 
369 void dso__free_a2l(struct dso *dso __maybe_unused)
370 {
371 }
372 
373 static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
374 	struct dso *dso __maybe_unused)
375 {
376 	FILE *fp;
377 	char cmd[PATH_MAX];
378 	struct inline_node *node;
379 	char *filename = NULL;
380 	size_t len;
381 	unsigned int line_nr = 0;
382 
383 	scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64,
384 		  dso_name, addr);
385 
386 	fp = popen(cmd, "r");
387 	if (fp == NULL) {
388 		pr_err("popen failed for %s\n", dso_name);
389 		return NULL;
390 	}
391 
392 	node = zalloc(sizeof(*node));
393 	if (node == NULL) {
394 		perror("not enough memory for the inline node");
395 		goto out;
396 	}
397 
398 	INIT_LIST_HEAD(&node->val);
399 	node->addr = addr;
400 
401 	while (getline(&filename, &len, fp) != -1) {
402 		if (filename_split(filename, &line_nr) != 1) {
403 			free(filename);
404 			goto out;
405 		}
406 
407 		if (inline_list__append(filename, NULL, line_nr, node,
408 					NULL) != 0)
409 			goto out;
410 
411 		filename = NULL;
412 	}
413 
414 out:
415 	pclose(fp);
416 
417 	if (list_empty(&node->val)) {
418 		inline_node__delete(node);
419 		return NULL;
420 	}
421 
422 	return node;
423 }
424 
425 #endif /* HAVE_LIBBFD_SUPPORT */
426 
427 /*
428  * Number of addr2line failures (without success) before disabling it for that
429  * dso.
430  */
431 #define A2L_FAIL_LIMIT 123
432 
433 char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
434 		  bool show_sym, bool show_addr, bool unwind_inlines)
435 {
436 	char *file = NULL;
437 	unsigned line = 0;
438 	char *srcline;
439 	const char *dso_name;
440 
441 	if (!dso->has_srcline)
442 		goto out;
443 
444 	dso_name = dso__name(dso);
445 	if (dso_name == NULL)
446 		goto out;
447 
448 	if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines, NULL))
449 		goto out;
450 
451 	if (asprintf(&srcline, "%s:%u",
452 				srcline_full_filename ? file : basename(file),
453 				line) < 0) {
454 		free(file);
455 		goto out;
456 	}
457 
458 	dso->a2l_fails = 0;
459 
460 	free(file);
461 	return srcline;
462 
463 out:
464 	if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) {
465 		dso->has_srcline = 0;
466 		dso__free_a2l(dso);
467 	}
468 
469 	if (!show_addr)
470 		return (show_sym && sym) ?
471 			    strndup(sym->name, sym->namelen) : NULL;
472 
473 	if (sym) {
474 		if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
475 					addr - sym->start) < 0)
476 			return SRCLINE_UNKNOWN;
477 	} else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0)
478 		return SRCLINE_UNKNOWN;
479 	return srcline;
480 }
481 
482 void free_srcline(char *srcline)
483 {
484 	if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
485 		free(srcline);
486 }
487 
488 char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
489 		  bool show_sym, bool show_addr)
490 {
491 	return __get_srcline(dso, addr, sym, show_sym, show_addr, false);
492 }
493 
494 struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr)
495 {
496 	const char *dso_name;
497 
498 	dso_name = dso__name(dso);
499 	if (dso_name == NULL)
500 		return NULL;
501 
502 	return addr2inlines(dso_name, addr, dso);
503 }
504 
505 void inline_node__delete(struct inline_node *node)
506 {
507 	struct inline_list *ilist, *tmp;
508 
509 	list_for_each_entry_safe(ilist, tmp, &node->val, list) {
510 		list_del_init(&ilist->list);
511 		zfree(&ilist->filename);
512 		zfree(&ilist->funcname);
513 		free(ilist);
514 	}
515 
516 	free(node);
517 }
518