diff options
| author | Adrian Hunter <adrian.hunter@intel.com> | 2013-08-07 07:38:46 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-08-07 16:35:31 -0400 |
| commit | 5b7ba82a75915e739709d0ace4bb559cb280db09 (patch) | |
| tree | cc42fe77866affa6b83dd0945e260427f88761d8 /tools/perf/util | |
| parent | b55ae0a976f2927ea8f15a85c43bbe6d25a68a41 (diff) | |
perf symbols: Load kernel maps before using
In order to use kernel maps to read object code, those maps must be
adjusted to map to the dso file offset. Because lazy-initialization is
used, that is not done until symbols are loaded. However the maps are
first used by thread__find_addr_map() before symbols are loaded. So
this patch changes thread__find_addr() to "load" kernel maps before
using them.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1375875537-4509-3-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
| -rw-r--r-- | tools/perf/util/build-id.c | 2 | ||||
| -rw-r--r-- | tools/perf/util/event.c | 18 | ||||
| -rw-r--r-- | tools/perf/util/thread.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/unwind.c | 4 |
4 files changed, 18 insertions, 8 deletions
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 5295625c0c00..3a0f5089379c 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
| @@ -33,7 +33,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, | |||
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, | 35 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, |
| 36 | event->ip.ip, &al); | 36 | event->ip.ip, &al, NULL); |
| 37 | 37 | ||
| 38 | if (al.map != NULL) | 38 | if (al.map != NULL) |
| 39 | al.map->dso->hit = 1; | 39 | al.map->dso->hit = 1; |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 95412705d0d2..cc7c0c9c9ea6 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -592,9 +592,10 @@ int perf_event__process(struct perf_tool *tool __maybe_unused, | |||
| 592 | void thread__find_addr_map(struct thread *self, | 592 | void thread__find_addr_map(struct thread *self, |
| 593 | struct machine *machine, u8 cpumode, | 593 | struct machine *machine, u8 cpumode, |
| 594 | enum map_type type, u64 addr, | 594 | enum map_type type, u64 addr, |
| 595 | struct addr_location *al) | 595 | struct addr_location *al, symbol_filter_t filter) |
| 596 | { | 596 | { |
| 597 | struct map_groups *mg = &self->mg; | 597 | struct map_groups *mg = &self->mg; |
| 598 | bool load_map = false; | ||
| 598 | 599 | ||
| 599 | al->thread = self; | 600 | al->thread = self; |
| 600 | al->addr = addr; | 601 | al->addr = addr; |
| @@ -609,11 +610,13 @@ void thread__find_addr_map(struct thread *self, | |||
| 609 | if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { | 610 | if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { |
| 610 | al->level = 'k'; | 611 | al->level = 'k'; |
| 611 | mg = &machine->kmaps; | 612 | mg = &machine->kmaps; |
| 613 | load_map = true; | ||
| 612 | } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { | 614 | } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { |
| 613 | al->level = '.'; | 615 | al->level = '.'; |
| 614 | } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { | 616 | } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { |
| 615 | al->level = 'g'; | 617 | al->level = 'g'; |
| 616 | mg = &machine->kmaps; | 618 | mg = &machine->kmaps; |
| 619 | load_map = true; | ||
| 617 | } else { | 620 | } else { |
| 618 | /* | 621 | /* |
| 619 | * 'u' means guest os user space. | 622 | * 'u' means guest os user space. |
| @@ -654,8 +657,15 @@ try_again: | |||
| 654 | mg = &machine->kmaps; | 657 | mg = &machine->kmaps; |
| 655 | goto try_again; | 658 | goto try_again; |
| 656 | } | 659 | } |
| 657 | } else | 660 | } else { |
| 661 | /* | ||
| 662 | * Kernel maps might be changed when loading symbols so loading | ||
| 663 | * must be done prior to using kernel maps. | ||
| 664 | */ | ||
| 665 | if (load_map) | ||
| 666 | map__load(al->map, filter); | ||
| 658 | al->addr = al->map->map_ip(al->map, al->addr); | 667 | al->addr = al->map->map_ip(al->map, al->addr); |
| 668 | } | ||
| 659 | } | 669 | } |
| 660 | 670 | ||
| 661 | void thread__find_addr_location(struct thread *thread, struct machine *machine, | 671 | void thread__find_addr_location(struct thread *thread, struct machine *machine, |
| @@ -663,7 +673,7 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine, | |||
| 663 | struct addr_location *al, | 673 | struct addr_location *al, |
| 664 | symbol_filter_t filter) | 674 | symbol_filter_t filter) |
| 665 | { | 675 | { |
| 666 | thread__find_addr_map(thread, machine, cpumode, type, addr, al); | 676 | thread__find_addr_map(thread, machine, cpumode, type, addr, al, filter); |
| 667 | if (al->map != NULL) | 677 | if (al->map != NULL) |
| 668 | al->sym = map__find_symbol(al->map, al->addr, filter); | 678 | al->sym = map__find_symbol(al->map, al->addr, filter); |
| 669 | else | 679 | else |
| @@ -699,7 +709,7 @@ int perf_event__preprocess_sample(const union perf_event *event, | |||
| 699 | machine__create_kernel_maps(machine); | 709 | machine__create_kernel_maps(machine); |
| 700 | 710 | ||
| 701 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, | 711 | thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, |
| 702 | event->ip.ip, al); | 712 | event->ip.ip, al, filter); |
| 703 | dump_printf(" ...... dso: %s\n", | 713 | dump_printf(" ...... dso: %s\n", |
| 704 | al->map ? al->map->dso->long_name : | 714 | al->map ? al->map->dso->long_name : |
| 705 | al->level == 'H' ? "[hypervisor]" : "<not found>"); | 715 | al->level == 'H' ? "[hypervisor]" : "<not found>"); |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 0fe1f9c05865..f98d1d983547 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
| @@ -41,7 +41,7 @@ static inline struct map *thread__find_map(struct thread *self, | |||
| 41 | 41 | ||
| 42 | void thread__find_addr_map(struct thread *thread, struct machine *machine, | 42 | void thread__find_addr_map(struct thread *thread, struct machine *machine, |
| 43 | u8 cpumode, enum map_type type, u64 addr, | 43 | u8 cpumode, enum map_type type, u64 addr, |
| 44 | struct addr_location *al); | 44 | struct addr_location *al, symbol_filter_t filter); |
| 45 | 45 | ||
| 46 | void thread__find_addr_location(struct thread *thread, struct machine *machine, | 46 | void thread__find_addr_location(struct thread *thread, struct machine *machine, |
| 47 | u8 cpumode, enum map_type type, u64 addr, | 47 | u8 cpumode, enum map_type type, u64 addr, |
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c index 958723ba3d2e..5bbd4947c27d 100644 --- a/tools/perf/util/unwind.c +++ b/tools/perf/util/unwind.c | |||
| @@ -272,7 +272,7 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui) | |||
| 272 | struct addr_location al; | 272 | struct addr_location al; |
| 273 | 273 | ||
| 274 | thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, | 274 | thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, |
| 275 | MAP__FUNCTION, ip, &al); | 275 | MAP__FUNCTION, ip, &al, NULL); |
| 276 | return al.map; | 276 | return al.map; |
| 277 | } | 277 | } |
| 278 | 278 | ||
| @@ -349,7 +349,7 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, | |||
| 349 | ssize_t size; | 349 | ssize_t size; |
| 350 | 350 | ||
| 351 | thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, | 351 | thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, |
| 352 | MAP__FUNCTION, addr, &al); | 352 | MAP__FUNCTION, addr, &al, NULL); |
| 353 | if (!al.map) { | 353 | if (!al.map) { |
| 354 | pr_debug("unwind: no map for %lx\n", (unsigned long)addr); | 354 | pr_debug("unwind: no map for %lx\n", (unsigned long)addr); |
| 355 | return -1; | 355 | return -1; |
