diff options
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r-- | tools/perf/builtin-report.c | 79 |
1 files changed, 35 insertions, 44 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index c1a54fc8527a..3ed3baf96ffb 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -349,22 +349,17 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm) | |||
349 | 349 | ||
350 | 350 | ||
351 | static struct symbol * | 351 | static struct symbol * |
352 | resolve_symbol(struct thread *thread, struct map **mapp, | 352 | resolve_symbol(struct thread *thread, struct map **mapp, u64 *ipp) |
353 | struct dso **dsop, u64 *ipp) | ||
354 | { | 353 | { |
355 | struct dso *dso = dsop ? *dsop : NULL; | ||
356 | struct map *map = mapp ? *mapp : NULL; | 354 | struct map *map = mapp ? *mapp : NULL; |
357 | u64 ip = *ipp; | 355 | u64 ip = *ipp; |
358 | 356 | ||
359 | if (!thread) | ||
360 | return NULL; | ||
361 | |||
362 | if (dso) | ||
363 | goto got_dso; | ||
364 | |||
365 | if (map) | 357 | if (map) |
366 | goto got_map; | 358 | goto got_map; |
367 | 359 | ||
360 | if (!thread) | ||
361 | return NULL; | ||
362 | |||
368 | map = thread__find_map(thread, ip); | 363 | map = thread__find_map(thread, ip); |
369 | if (map != NULL) { | 364 | if (map != NULL) { |
370 | /* | 365 | /* |
@@ -379,29 +374,29 @@ resolve_symbol(struct thread *thread, struct map **mapp, | |||
379 | *mapp = map; | 374 | *mapp = map; |
380 | got_map: | 375 | got_map: |
381 | ip = map->map_ip(map, ip); | 376 | ip = map->map_ip(map, ip); |
382 | |||
383 | dso = map->dso; | ||
384 | } else { | 377 | } else { |
385 | /* | 378 | /* |
386 | * If this is outside of all known maps, | 379 | * If this is outside of all known maps, |
387 | * and is a negative address, try to look it | 380 | * and is a negative address, try to look it |
388 | * up in the kernel dso, as it might be a | 381 | * up in the kernel dso, as it might be a |
389 | * vsyscall (which executes in user-mode): | 382 | * vsyscall or vdso (which executes in user-mode). |
383 | * | ||
384 | * XXX This is nasty, we should have a symbol list in | ||
385 | * the "[vdso]" dso, but for now lets use the old | ||
386 | * trick of looking in the whole kernel symbol list. | ||
390 | */ | 387 | */ |
391 | if ((long long)ip < 0) | 388 | if ((long long)ip < 0) { |
392 | dso = kernel_dso; | 389 | map = kernel_map; |
390 | if (mapp) | ||
391 | *mapp = map; | ||
392 | } | ||
393 | } | 393 | } |
394 | dump_printf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); | 394 | dump_printf(" ...... dso: %s\n", |
395 | map ? map->dso->long_name : "<not found>"); | ||
395 | dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip); | 396 | dump_printf(" ...... map: %Lx -> %Lx\n", *ipp, ip); |
396 | *ipp = ip; | 397 | *ipp = ip; |
397 | 398 | ||
398 | if (dsop) | 399 | return map ? map->dso->find_symbol(map->dso, ip) : NULL; |
399 | *dsop = dso; | ||
400 | |||
401 | if (!dso) | ||
402 | return NULL; | ||
403 | got_dso: | ||
404 | return dso->find_symbol(dso, ip); | ||
405 | } | 400 | } |
406 | 401 | ||
407 | static int call__match(struct symbol *sym) | 402 | static int call__match(struct symbol *sym) |
@@ -413,7 +408,7 @@ static int call__match(struct symbol *sym) | |||
413 | } | 408 | } |
414 | 409 | ||
415 | static struct symbol ** | 410 | static struct symbol ** |
416 | resolve_callchain(struct thread *thread, struct map *map __used, | 411 | resolve_callchain(struct thread *thread, struct map *map, |
417 | struct ip_callchain *chain, struct hist_entry *entry) | 412 | struct ip_callchain *chain, struct hist_entry *entry) |
418 | { | 413 | { |
419 | u64 context = PERF_CONTEXT_MAX; | 414 | u64 context = PERF_CONTEXT_MAX; |
@@ -430,8 +425,7 @@ resolve_callchain(struct thread *thread, struct map *map __used, | |||
430 | 425 | ||
431 | for (i = 0; i < chain->nr; i++) { | 426 | for (i = 0; i < chain->nr; i++) { |
432 | u64 ip = chain->ips[i]; | 427 | u64 ip = chain->ips[i]; |
433 | struct dso *dso = NULL; | 428 | struct symbol *sym = NULL; |
434 | struct symbol *sym; | ||
435 | 429 | ||
436 | if (ip >= PERF_CONTEXT_MAX) { | 430 | if (ip >= PERF_CONTEXT_MAX) { |
437 | context = ip; | 431 | context = ip; |
@@ -440,17 +434,15 @@ resolve_callchain(struct thread *thread, struct map *map __used, | |||
440 | 434 | ||
441 | switch (context) { | 435 | switch (context) { |
442 | case PERF_CONTEXT_HV: | 436 | case PERF_CONTEXT_HV: |
443 | dso = hypervisor_dso; | ||
444 | break; | 437 | break; |
445 | case PERF_CONTEXT_KERNEL: | 438 | case PERF_CONTEXT_KERNEL: |
446 | dso = kernel_dso; | 439 | sym = kernel_maps__find_symbol(ip, &map); |
447 | break; | 440 | break; |
448 | default: | 441 | default: |
442 | sym = resolve_symbol(thread, &map, &ip); | ||
449 | break; | 443 | break; |
450 | } | 444 | } |
451 | 445 | ||
452 | sym = resolve_symbol(thread, NULL, &dso, &ip); | ||
453 | |||
454 | if (sym) { | 446 | if (sym) { |
455 | if (sort__has_parent && call__match(sym) && | 447 | if (sort__has_parent && call__match(sym) && |
456 | !entry->parent) | 448 | !entry->parent) |
@@ -469,7 +461,7 @@ resolve_callchain(struct thread *thread, struct map *map __used, | |||
469 | */ | 461 | */ |
470 | 462 | ||
471 | static int | 463 | static int |
472 | hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, | 464 | hist_entry__add(struct thread *thread, struct map *map, |
473 | struct symbol *sym, u64 ip, struct ip_callchain *chain, | 465 | struct symbol *sym, u64 ip, struct ip_callchain *chain, |
474 | char level, u64 count) | 466 | char level, u64 count) |
475 | { | 467 | { |
@@ -480,7 +472,6 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, | |||
480 | struct hist_entry entry = { | 472 | struct hist_entry entry = { |
481 | .thread = thread, | 473 | .thread = thread, |
482 | .map = map, | 474 | .map = map, |
483 | .dso = dso, | ||
484 | .sym = sym, | 475 | .sym = sym, |
485 | .ip = ip, | 476 | .ip = ip, |
486 | .level = level, | 477 | .level = level, |
@@ -641,7 +632,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) | |||
641 | { | 632 | { |
642 | char level; | 633 | char level; |
643 | int show = 0; | 634 | int show = 0; |
644 | struct dso *dso = NULL; | 635 | struct symbol *sym = NULL; |
645 | struct thread *thread; | 636 | struct thread *thread; |
646 | u64 ip = event->ip.ip; | 637 | u64 ip = event->ip.ip; |
647 | u64 period = 1; | 638 | u64 period = 1; |
@@ -700,35 +691,35 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) | |||
700 | show = SHOW_KERNEL; | 691 | show = SHOW_KERNEL; |
701 | level = 'k'; | 692 | level = 'k'; |
702 | 693 | ||
703 | dso = kernel_dso; | 694 | sym = kernel_maps__find_symbol(ip, &map); |
704 | 695 | dump_printf(" ...... dso: %s\n", | |
705 | dump_printf(" ...... dso: %s\n", dso->name); | 696 | map ? map->dso->long_name : "<not found>"); |
706 | |||
707 | } else if (cpumode == PERF_RECORD_MISC_USER) { | 697 | } else if (cpumode == PERF_RECORD_MISC_USER) { |
708 | 698 | ||
709 | show = SHOW_USER; | 699 | show = SHOW_USER; |
710 | level = '.'; | 700 | level = '.'; |
701 | sym = resolve_symbol(thread, &map, &ip); | ||
711 | 702 | ||
712 | } else { | 703 | } else { |
713 | show = SHOW_HV; | 704 | show = SHOW_HV; |
714 | level = 'H'; | 705 | level = 'H'; |
715 | 706 | ||
716 | dso = hypervisor_dso; | ||
717 | |||
718 | dump_printf(" ...... dso: [hypervisor]\n"); | 707 | dump_printf(" ...... dso: [hypervisor]\n"); |
719 | } | 708 | } |
720 | 709 | ||
721 | if (show & show_mask) { | 710 | if (show & show_mask) { |
722 | struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); | 711 | if (dso_list && |
723 | 712 | (!map || !map->dso || | |
724 | if (dso_list && (!dso || !dso->name || | 713 | !(strlist__has_entry(dso_list, map->dso->short_name) || |
725 | !strlist__has_entry(dso_list, dso->name))) | 714 | (map->dso->short_name != map->dso->long_name && |
715 | strlist__has_entry(dso_list, map->dso->long_name))))) | ||
726 | return 0; | 716 | return 0; |
727 | 717 | ||
728 | if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name))) | 718 | if (sym_list && sym && !strlist__has_entry(sym_list, sym->name)) |
729 | return 0; | 719 | return 0; |
730 | 720 | ||
731 | if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { | 721 | if (hist_entry__add(thread, map, sym, ip, |
722 | chain, level, period)) { | ||
732 | eprintf("problem incrementing symbol count, skipping event\n"); | 723 | eprintf("problem incrementing symbol count, skipping event\n"); |
733 | return -1; | 724 | return -1; |
734 | } | 725 | } |