xref: /openbmc/linux/tools/perf/util/srcline.c (revision 2cc9d0ef577975abb3ebce7d5978559ec1c73633)
1f048d548SNamhyung Kim #include <stdio.h>
2f048d548SNamhyung Kim #include <stdlib.h>
3f048d548SNamhyung Kim #include <string.h>
4f048d548SNamhyung Kim 
5f048d548SNamhyung Kim #include <linux/kernel.h>
6f048d548SNamhyung Kim 
786c98cabSNamhyung Kim #include "util/dso.h"
8f048d548SNamhyung Kim #include "util/util.h"
9f048d548SNamhyung Kim #include "util/debug.h"
10f048d548SNamhyung Kim 
11f048d548SNamhyung Kim static int addr2line(const char *dso_name, unsigned long addr,
12f048d548SNamhyung Kim 		     char **file, unsigned int *line_nr)
13f048d548SNamhyung Kim {
14f048d548SNamhyung Kim 	FILE *fp;
15f048d548SNamhyung Kim 	char cmd[PATH_MAX];
16f048d548SNamhyung Kim 	char *filename = NULL;
17f048d548SNamhyung Kim 	size_t len;
18f048d548SNamhyung Kim 	char *sep;
19f048d548SNamhyung Kim 	int ret = 0;
20f048d548SNamhyung Kim 
21f048d548SNamhyung Kim 	scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
22f048d548SNamhyung Kim 		  dso_name, addr);
23f048d548SNamhyung Kim 
24f048d548SNamhyung Kim 	fp = popen(cmd, "r");
25f048d548SNamhyung Kim 	if (fp == NULL) {
26f048d548SNamhyung Kim 		pr_warning("popen failed for %s\n", dso_name);
27f048d548SNamhyung Kim 		return 0;
28f048d548SNamhyung Kim 	}
29f048d548SNamhyung Kim 
30f048d548SNamhyung Kim 	if (getline(&filename, &len, fp) < 0 || !len) {
31f048d548SNamhyung Kim 		pr_warning("addr2line has no output for %s\n", dso_name);
32f048d548SNamhyung Kim 		goto out;
33f048d548SNamhyung Kim 	}
34f048d548SNamhyung Kim 
35f048d548SNamhyung Kim 	sep = strchr(filename, '\n');
36f048d548SNamhyung Kim 	if (sep)
37f048d548SNamhyung Kim 		*sep = '\0';
38f048d548SNamhyung Kim 
39f048d548SNamhyung Kim 	if (!strcmp(filename, "??:0")) {
40f048d548SNamhyung Kim 		pr_debug("no debugging info in %s\n", dso_name);
41f048d548SNamhyung Kim 		free(filename);
42f048d548SNamhyung Kim 		goto out;
43f048d548SNamhyung Kim 	}
44f048d548SNamhyung Kim 
45f048d548SNamhyung Kim 	sep = strchr(filename, ':');
46f048d548SNamhyung Kim 	if (sep) {
47f048d548SNamhyung Kim 		*sep++ = '\0';
48f048d548SNamhyung Kim 		*file = filename;
49f048d548SNamhyung Kim 		*line_nr = strtoul(sep, NULL, 0);
50f048d548SNamhyung Kim 		ret = 1;
51f048d548SNamhyung Kim 	}
52f048d548SNamhyung Kim out:
53f048d548SNamhyung Kim 	pclose(fp);
54f048d548SNamhyung Kim 	return ret;
55f048d548SNamhyung Kim }
56f048d548SNamhyung Kim 
5786c98cabSNamhyung Kim char *get_srcline(struct dso *dso, unsigned long addr)
58f048d548SNamhyung Kim {
59f048d548SNamhyung Kim 	char *file;
60f048d548SNamhyung Kim 	unsigned line;
61*2cc9d0efSNamhyung Kim 	char *srcline;
6286c98cabSNamhyung Kim 	char *dso_name = dso->long_name;
63f048d548SNamhyung Kim 	size_t size;
64f048d548SNamhyung Kim 
65*2cc9d0efSNamhyung Kim 	if (!dso->has_srcline)
66*2cc9d0efSNamhyung Kim 		return SRCLINE_UNKNOWN;
67*2cc9d0efSNamhyung Kim 
6858d91a00SNamhyung Kim 	if (dso_name[0] == '[')
6958d91a00SNamhyung Kim 		goto out;
7058d91a00SNamhyung Kim 
7158d91a00SNamhyung Kim 	if (!strncmp(dso_name, "/tmp/perf-", 10))
7258d91a00SNamhyung Kim 		goto out;
7358d91a00SNamhyung Kim 
74f048d548SNamhyung Kim 	if (!addr2line(dso_name, addr, &file, &line))
7558d91a00SNamhyung Kim 		goto out;
76f048d548SNamhyung Kim 
77f048d548SNamhyung Kim 	/* just calculate actual length */
78f048d548SNamhyung Kim 	size = snprintf(NULL, 0, "%s:%u", file, line) + 1;
79f048d548SNamhyung Kim 
80f048d548SNamhyung Kim 	srcline = malloc(size);
81f048d548SNamhyung Kim 	if (srcline)
82f048d548SNamhyung Kim 		snprintf(srcline, size, "%s:%u", file, line);
83f048d548SNamhyung Kim 	else
84f048d548SNamhyung Kim 		srcline = SRCLINE_UNKNOWN;
85f048d548SNamhyung Kim 
86f048d548SNamhyung Kim 	free(file);
87f048d548SNamhyung Kim 	return srcline;
88*2cc9d0efSNamhyung Kim 
89*2cc9d0efSNamhyung Kim out:
90*2cc9d0efSNamhyung Kim 	dso->has_srcline = 0;
91*2cc9d0efSNamhyung Kim 	return SRCLINE_UNKNOWN;
92f048d548SNamhyung Kim }
93f048d548SNamhyung Kim 
94f048d548SNamhyung Kim void free_srcline(char *srcline)
95f048d548SNamhyung Kim {
96f048d548SNamhyung Kim 	if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
97f048d548SNamhyung Kim 		free(srcline);
98f048d548SNamhyung Kim }
99