xref: /openbmc/linux/tools/perf/util/srcline.c (revision f048d548f803b57ee1dbf66702f398ba69657450)
1*f048d548SNamhyung Kim #include <stdio.h>
2*f048d548SNamhyung Kim #include <stdlib.h>
3*f048d548SNamhyung Kim #include <string.h>
4*f048d548SNamhyung Kim 
5*f048d548SNamhyung Kim #include <linux/kernel.h>
6*f048d548SNamhyung Kim 
7*f048d548SNamhyung Kim #include "util/util.h"
8*f048d548SNamhyung Kim #include "util/debug.h"
9*f048d548SNamhyung Kim 
10*f048d548SNamhyung Kim static int addr2line(const char *dso_name, unsigned long addr,
11*f048d548SNamhyung Kim 		     char **file, unsigned int *line_nr)
12*f048d548SNamhyung Kim {
13*f048d548SNamhyung Kim 	FILE *fp;
14*f048d548SNamhyung Kim 	char cmd[PATH_MAX];
15*f048d548SNamhyung Kim 	char *filename = NULL;
16*f048d548SNamhyung Kim 	size_t len;
17*f048d548SNamhyung Kim 	char *sep;
18*f048d548SNamhyung Kim 	int ret = 0;
19*f048d548SNamhyung Kim 
20*f048d548SNamhyung Kim 	scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
21*f048d548SNamhyung Kim 		  dso_name, addr);
22*f048d548SNamhyung Kim 
23*f048d548SNamhyung Kim 	fp = popen(cmd, "r");
24*f048d548SNamhyung Kim 	if (fp == NULL) {
25*f048d548SNamhyung Kim 		pr_warning("popen failed for %s\n", dso_name);
26*f048d548SNamhyung Kim 		return 0;
27*f048d548SNamhyung Kim 	}
28*f048d548SNamhyung Kim 
29*f048d548SNamhyung Kim 	if (getline(&filename, &len, fp) < 0 || !len) {
30*f048d548SNamhyung Kim 		pr_warning("addr2line has no output for %s\n", dso_name);
31*f048d548SNamhyung Kim 		goto out;
32*f048d548SNamhyung Kim 	}
33*f048d548SNamhyung Kim 
34*f048d548SNamhyung Kim 	sep = strchr(filename, '\n');
35*f048d548SNamhyung Kim 	if (sep)
36*f048d548SNamhyung Kim 		*sep = '\0';
37*f048d548SNamhyung Kim 
38*f048d548SNamhyung Kim 	if (!strcmp(filename, "??:0")) {
39*f048d548SNamhyung Kim 		pr_debug("no debugging info in %s\n", dso_name);
40*f048d548SNamhyung Kim 		free(filename);
41*f048d548SNamhyung Kim 		goto out;
42*f048d548SNamhyung Kim 	}
43*f048d548SNamhyung Kim 
44*f048d548SNamhyung Kim 	sep = strchr(filename, ':');
45*f048d548SNamhyung Kim 	if (sep) {
46*f048d548SNamhyung Kim 		*sep++ = '\0';
47*f048d548SNamhyung Kim 		*file = filename;
48*f048d548SNamhyung Kim 		*line_nr = strtoul(sep, NULL, 0);
49*f048d548SNamhyung Kim 		ret = 1;
50*f048d548SNamhyung Kim 	}
51*f048d548SNamhyung Kim out:
52*f048d548SNamhyung Kim 	pclose(fp);
53*f048d548SNamhyung Kim 	return ret;
54*f048d548SNamhyung Kim }
55*f048d548SNamhyung Kim 
56*f048d548SNamhyung Kim char *get_srcline(const char *dso_name, unsigned long addr)
57*f048d548SNamhyung Kim {
58*f048d548SNamhyung Kim 	char *file;
59*f048d548SNamhyung Kim 	unsigned line;
60*f048d548SNamhyung Kim 	char *srcline;
61*f048d548SNamhyung Kim 	size_t size;
62*f048d548SNamhyung Kim 
63*f048d548SNamhyung Kim 	if (!addr2line(dso_name, addr, &file, &line))
64*f048d548SNamhyung Kim 		return SRCLINE_UNKNOWN;
65*f048d548SNamhyung Kim 
66*f048d548SNamhyung Kim 	/* just calculate actual length */
67*f048d548SNamhyung Kim 	size = snprintf(NULL, 0, "%s:%u", file, line) + 1;
68*f048d548SNamhyung Kim 
69*f048d548SNamhyung Kim 	srcline = malloc(size);
70*f048d548SNamhyung Kim 	if (srcline)
71*f048d548SNamhyung Kim 		snprintf(srcline, size, "%s:%u", file, line);
72*f048d548SNamhyung Kim 	else
73*f048d548SNamhyung Kim 		srcline = SRCLINE_UNKNOWN;
74*f048d548SNamhyung Kim 
75*f048d548SNamhyung Kim 	free(file);
76*f048d548SNamhyung Kim 	return srcline;
77*f048d548SNamhyung Kim }
78*f048d548SNamhyung Kim 
79*f048d548SNamhyung Kim void free_srcline(char *srcline)
80*f048d548SNamhyung Kim {
81*f048d548SNamhyung Kim 	if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
82*f048d548SNamhyung Kim 		free(srcline);
83*f048d548SNamhyung Kim }
84