diff options
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r-- | tools/perf/util/event.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 70b4aa03b472..233d7ad9bd7f 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -249,3 +249,65 @@ int event__process_task(event_t *self) | |||
249 | 249 | ||
250 | return 0; | 250 | return 0; |
251 | } | 251 | } |
252 | |||
253 | void thread__find_addr_location(struct thread *self, u8 cpumode, | ||
254 | enum map_type type, u64 addr, | ||
255 | struct addr_location *al, | ||
256 | symbol_filter_t filter) | ||
257 | { | ||
258 | struct thread *thread = al->thread = self; | ||
259 | |||
260 | al->addr = addr; | ||
261 | |||
262 | if (cpumode & PERF_RECORD_MISC_KERNEL) { | ||
263 | al->level = 'k'; | ||
264 | thread = kthread; | ||
265 | } else if (cpumode & PERF_RECORD_MISC_USER) | ||
266 | al->level = '.'; | ||
267 | else { | ||
268 | al->level = 'H'; | ||
269 | al->map = NULL; | ||
270 | al->sym = NULL; | ||
271 | return; | ||
272 | } | ||
273 | try_again: | ||
274 | al->map = thread__find_map(thread, type, al->addr); | ||
275 | if (al->map == NULL) { | ||
276 | /* | ||
277 | * If this is outside of all known maps, and is a negative | ||
278 | * address, try to look it up in the kernel dso, as it might be | ||
279 | * a vsyscall or vdso (which executes in user-mode). | ||
280 | * | ||
281 | * XXX This is nasty, we should have a symbol list in the | ||
282 | * "[vdso]" dso, but for now lets use the old trick of looking | ||
283 | * in the whole kernel symbol list. | ||
284 | */ | ||
285 | if ((long long)al->addr < 0 && thread != kthread) { | ||
286 | thread = kthread; | ||
287 | goto try_again; | ||
288 | } | ||
289 | al->sym = NULL; | ||
290 | } else { | ||
291 | al->addr = al->map->map_ip(al->map, al->addr); | ||
292 | al->sym = map__find_symbol(al->map, al->addr, filter); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | int event__preprocess_sample(const event_t *self, struct addr_location *al, | ||
297 | symbol_filter_t filter) | ||
298 | { | ||
299 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
300 | struct thread *thread = threads__findnew(self->ip.pid); | ||
301 | |||
302 | if (thread == NULL) | ||
303 | return -1; | ||
304 | |||
305 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); | ||
306 | |||
307 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, | ||
308 | self->ip.ip, al, filter); | ||
309 | dump_printf(" ...... dso: %s\n", | ||
310 | al->map ? al->map->dso->long_name : | ||
311 | al->level == 'H' ? "[hypervisor]" : "<not found>"); | ||
312 | return 0; | ||
313 | } | ||