diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/probe-event.c | 40 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 86 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.h | 1 |
3 files changed, 26 insertions, 101 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 1ce2cb9845b6..8e34c8d47813 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -248,6 +248,18 @@ static struct debuginfo *open_debuginfo(const char *module) | |||
248 | return debuginfo__new(path); | 248 | return debuginfo__new(path); |
249 | } | 249 | } |
250 | 250 | ||
251 | static struct ref_reloc_sym *__kernel_get_ref_reloc_sym(void) | ||
252 | { | ||
253 | /* kmap->ref_reloc_sym should be set if host_machine is initialized */ | ||
254 | struct kmap *kmap; | ||
255 | |||
256 | if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0) | ||
257 | return NULL; | ||
258 | |||
259 | kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); | ||
260 | return kmap->ref_reloc_sym; | ||
261 | } | ||
262 | |||
251 | /* | 263 | /* |
252 | * Convert trace point to probe point with debuginfo | 264 | * Convert trace point to probe point with debuginfo |
253 | * Currently only handles kprobes. | 265 | * Currently only handles kprobes. |
@@ -256,18 +268,27 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, | |||
256 | struct perf_probe_point *pp) | 268 | struct perf_probe_point *pp) |
257 | { | 269 | { |
258 | struct symbol *sym; | 270 | struct symbol *sym; |
271 | struct ref_reloc_sym *reloc_sym; | ||
259 | struct map *map; | 272 | struct map *map; |
260 | u64 addr; | 273 | u64 addr = 0; |
261 | int ret = -ENOENT; | 274 | int ret = -ENOENT; |
262 | struct debuginfo *dinfo; | 275 | struct debuginfo *dinfo; |
263 | 276 | ||
264 | sym = __find_kernel_function_by_name(tp->symbol, &map); | 277 | /* ref_reloc_sym is just a label. Need a special fix*/ |
265 | if (sym) { | 278 | reloc_sym = __kernel_get_ref_reloc_sym(); |
266 | addr = map->unmap_ip(map, sym->start + tp->offset); | 279 | if (reloc_sym && strcmp(tp->symbol, reloc_sym->name) == 0) |
280 | addr = reloc_sym->unrelocated_addr + tp->offset; | ||
281 | else { | ||
282 | sym = __find_kernel_function_by_name(tp->symbol, &map); | ||
283 | if (sym) | ||
284 | addr = map->unmap_ip(map, sym->start + tp->offset) - | ||
285 | map->reloc; | ||
286 | } | ||
287 | if (addr) { | ||
267 | pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, | 288 | pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, |
268 | tp->offset, addr); | 289 | tp->offset, addr); |
269 | 290 | ||
270 | dinfo = debuginfo__new_online_kernel(addr); | 291 | dinfo = open_debuginfo(tp->module); |
271 | if (dinfo) { | 292 | if (dinfo) { |
272 | ret = debuginfo__find_probe_point(dinfo, | 293 | ret = debuginfo__find_probe_point(dinfo, |
273 | (unsigned long)addr, pp); | 294 | (unsigned long)addr, pp); |
@@ -383,15 +404,6 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | |||
383 | return ret; | 404 | return ret; |
384 | } | 405 | } |
385 | 406 | ||
386 | static struct ref_reloc_sym *__kernel_get_ref_reloc_sym(void) | ||
387 | { | ||
388 | /* kmap->ref_reloc_sym should be set if host_machine is initialized */ | ||
389 | struct kmap *kmap; | ||
390 | |||
391 | kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); | ||
392 | return kmap->ref_reloc_sym; | ||
393 | } | ||
394 | |||
395 | /* Post processing the probe events */ | 407 | /* Post processing the probe events */ |
396 | static int post_process_probe_trace_events(struct probe_trace_event *tevs, | 408 | static int post_process_probe_trace_events(struct probe_trace_event *tevs, |
397 | int ntevs, const char *module, | 409 | int ntevs, const char *module, |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index e5e589fdef9b..4f6e277c457c 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -89,79 +89,6 @@ error: | |||
89 | return -ENOENT; | 89 | return -ENOENT; |
90 | } | 90 | } |
91 | 91 | ||
92 | #if _ELFUTILS_PREREQ(0, 148) | ||
93 | /* This method is buggy if elfutils is older than 0.148 */ | ||
94 | static int __linux_kernel_find_elf(Dwfl_Module *mod, | ||
95 | void **userdata, | ||
96 | const char *module_name, | ||
97 | Dwarf_Addr base, | ||
98 | char **file_name, Elf **elfp) | ||
99 | { | ||
100 | int fd; | ||
101 | const char *path = kernel_get_module_path(module_name); | ||
102 | |||
103 | pr_debug2("Use file %s for %s\n", path, module_name); | ||
104 | if (path) { | ||
105 | fd = open(path, O_RDONLY); | ||
106 | if (fd >= 0) { | ||
107 | *file_name = strdup(path); | ||
108 | return fd; | ||
109 | } | ||
110 | } | ||
111 | /* If failed, try to call standard method */ | ||
112 | return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base, | ||
113 | file_name, elfp); | ||
114 | } | ||
115 | |||
116 | static const Dwfl_Callbacks kernel_callbacks = { | ||
117 | .find_debuginfo = dwfl_standard_find_debuginfo, | ||
118 | .debuginfo_path = &debuginfo_path, | ||
119 | |||
120 | .find_elf = __linux_kernel_find_elf, | ||
121 | .section_address = dwfl_linux_kernel_module_section_address, | ||
122 | }; | ||
123 | |||
124 | /* Get a Dwarf from live kernel image */ | ||
125 | static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg, | ||
126 | Dwarf_Addr addr) | ||
127 | { | ||
128 | dbg->dwfl = dwfl_begin(&kernel_callbacks); | ||
129 | if (!dbg->dwfl) | ||
130 | return -EINVAL; | ||
131 | |||
132 | /* Load the kernel dwarves: Don't care the result here */ | ||
133 | dwfl_linux_kernel_report_kernel(dbg->dwfl); | ||
134 | dwfl_linux_kernel_report_modules(dbg->dwfl); | ||
135 | |||
136 | dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias); | ||
137 | /* Here, check whether we could get a real dwarf */ | ||
138 | if (!dbg->dbg) { | ||
139 | pr_debug("Failed to find kernel dwarf at %lx\n", | ||
140 | (unsigned long)addr); | ||
141 | dwfl_end(dbg->dwfl); | ||
142 | memset(dbg, 0, sizeof(*dbg)); | ||
143 | return -ENOENT; | ||
144 | } | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | #else | ||
149 | /* With older elfutils, this just support kernel module... */ | ||
150 | static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg, | ||
151 | Dwarf_Addr addr __maybe_unused) | ||
152 | { | ||
153 | const char *path = kernel_get_module_path("kernel"); | ||
154 | |||
155 | if (!path) { | ||
156 | pr_err("Failed to find vmlinux path\n"); | ||
157 | return -ENOENT; | ||
158 | } | ||
159 | |||
160 | pr_debug2("Use file %s for debuginfo\n", path); | ||
161 | return debuginfo__init_offline_dwarf(dbg, path); | ||
162 | } | ||
163 | #endif | ||
164 | |||
165 | struct debuginfo *debuginfo__new(const char *path) | 92 | struct debuginfo *debuginfo__new(const char *path) |
166 | { | 93 | { |
167 | struct debuginfo *dbg = zalloc(sizeof(*dbg)); | 94 | struct debuginfo *dbg = zalloc(sizeof(*dbg)); |
@@ -174,19 +101,6 @@ struct debuginfo *debuginfo__new(const char *path) | |||
174 | return dbg; | 101 | return dbg; |
175 | } | 102 | } |
176 | 103 | ||
177 | struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) | ||
178 | { | ||
179 | struct debuginfo *dbg = zalloc(sizeof(*dbg)); | ||
180 | |||
181 | if (!dbg) | ||
182 | return NULL; | ||
183 | |||
184 | if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) | ||
185 | zfree(&dbg); | ||
186 | |||
187 | return dbg; | ||
188 | } | ||
189 | |||
190 | void debuginfo__delete(struct debuginfo *dbg) | 104 | void debuginfo__delete(struct debuginfo *dbg) |
191 | { | 105 | { |
192 | if (dbg) { | 106 | if (dbg) { |
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 592c4dac3be9..3fc597365ce6 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -31,7 +31,6 @@ struct debuginfo { | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | extern struct debuginfo *debuginfo__new(const char *path); | 33 | extern struct debuginfo *debuginfo__new(const char *path); |
34 | extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr); | ||
35 | extern void debuginfo__delete(struct debuginfo *dbg); | 34 | extern void debuginfo__delete(struct debuginfo *dbg); |
36 | 35 | ||
37 | /* Find probe_trace_events specified by perf_probe_event from debuginfo */ | 36 | /* Find probe_trace_events specified by perf_probe_event from debuginfo */ |