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