Currently, perf script uses host unwind methods to parse perf.data callchain info regardless of the target architecture. So we get wrong result and no promotion when unwinding callchains of x86(32-bit) on x86(64-bit) machine.
This patch shows proper error messages when we do remote unwind x86(32-bit) on other machines. Same thing for other platforms will be added in next patches. Signed-off-by: He Kuang <heku...@huawei.com> --- tools/perf/config/Makefile | 6 ++++++ tools/perf/util/thread.c | 2 ++ tools/perf/util/unwind-libunwind.c | 32 ++++++++++++++++++++++++++++++++ tools/perf/util/unwind.h | 5 +++++ 4 files changed, 45 insertions(+) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 1e46277..a86b864 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -345,6 +345,12 @@ ifeq ($(ARCH),powerpc) endif ifndef NO_LIBUNWIND + ifeq ($(feature-libunwind-x86), 1) + LIBUNWIND_LIBS += -lunwind-x86 + $(call detected,CONFIG_LIBUNWIND_X86) + CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT + endif + ifneq ($(feature-libunwind), 1) msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); NO_LIBUNWIND := 1 diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index dfd00c6..244c4f6 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -186,6 +186,8 @@ void thread__insert_map(struct thread *thread, struct map *map) { map_groups__fixup_overlappings(thread->mg, map, stderr); map_groups__insert(thread->mg, map); + + unwind__get_arch(thread, map); } static int thread__clone_map_groups(struct thread *thread, diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 63687d3..b6eb317 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c @@ -680,3 +680,35 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, return get_entries(&ui, cb, arg, max_stack); } + +void unwind__get_arch(struct thread *thread, struct map *map) +{ + char *arch; + int is_64_bit; + + if (!thread->mg->machine->env) + return; + + is_64_bit = dso_is_64_bit(map->dso, map); + if (is_64_bit < 0) + return; + + if (thread->addr_space) + pr_debug("Thread map already set, 64bit is %d, dso=%s\n", + is_64_bit, map->dso->name); + + arch = thread->mg->machine->env->arch; + + if (!strcmp(arch, "x86_64") + || !strcmp(arch, "x86") + || !strcmp(arch, "i686")) { + pr_debug("Thread map is X86, 64bit is %d\n", is_64_bit); + if (!is_64_bit) +#ifdef HAVE_LIBUNWIND_X86_SUPPORT + pr_err("target platform=%s is not implemented!\n", + arch); +#else + pr_err("target platform=%s is not supported!\n", arch); +#endif + } +} diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index 12790cf..889d630 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -24,6 +24,7 @@ int libunwind__arch_reg_id(int regnum); int unwind__prepare_access(struct thread *thread); void unwind__flush_access(struct thread *thread); void unwind__finish_access(struct thread *thread); +void unwind__get_arch(struct thread *thread, struct map *map); #else static inline int unwind__prepare_access(struct thread *thread __maybe_unused) { @@ -32,6 +33,8 @@ static inline int unwind__prepare_access(struct thread *thread __maybe_unused) static inline void unwind__flush_access(struct thread *thread __maybe_unused) {} static inline void unwind__finish_access(struct thread *thread __maybe_unused) {} +static inline void unwind__get_arch(struct thread *thread __maybe_unused, + struct map *map __maybe_unused) {} #endif #else static inline int @@ -51,5 +54,7 @@ static inline int unwind__prepare_access(struct thread *thread __maybe_unused) static inline void unwind__flush_access(struct thread *thread __maybe_unused) {} static inline void unwind__finish_access(struct thread *thread __maybe_unused) {} +static inline void unwind__get_arch(struct thread *thread __maybe_unused, + struct map *map __maybe_unused) {} #endif /* HAVE_DWARF_UNWIND_SUPPORT */ #endif /* __UNWIND_H */ -- 1.8.5.2