Currently, perf script uses host unwind methods to parse perf.data callchain info regardless of the target architecture. So we get wrong result without any warnings when unwinding callchains of x86(32-bit) on x86(64-bit) machine.
This patch shows warning 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 | 8 ++++++++ tools/perf/util/thread.c | 2 +- tools/perf/util/unwind-libunwind.c | 30 +++++++++++++++++++++++++++++- tools/perf/util/unwind.h | 5 +++-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 3a304a3..e156f76 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -355,6 +355,14 @@ endif ifndef NO_LIBUNWIND have_libunwind := + + ifeq ($(feature-libunwind-x86), 1) + $(call detected,CONFIG_LIBUNWIND_X86) + CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT + LDFLAGS += -lunwind-x86 + have_libunwind = 1 + endif + ifneq ($(feature-libunwind), 1) msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); NO_LOCAL_LIBUNWIND := 1 diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 045477d..7ffee25 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -203,7 +203,7 @@ 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__prepare_access(thread); + unwind__prepare_access(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 40d0453..037ee72 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c @@ -1,8 +1,36 @@ #include "unwind.h" #include "thread.h" +#include "session.h" +#include "debug.h" +#include "arch/common.h" -int unwind__prepare_access(struct thread *thread) +int unwind__prepare_access(struct thread *thread, struct map *map) { + const char *arch; + enum dso_type dso_type; + + if (!thread->mg->machine->env) + return -1; + + dso_type = dso__type(map->dso, thread->mg->machine); + if (dso_type == DSO__TYPE_UNKNOWN) + return -1; + + if (thread->addr_space) + pr_debug("unwind: thread map already set, 64bit is %d, dso=%s\n", + dso_type == DSO__TYPE_64BIT, map->dso->name); + + arch = normalize_arch(thread->mg->machine->env->arch); + + if (!strcmp(arch, "x86")) { + if (dso_type != DSO__TYPE_64BIT) +#ifdef HAVE_LIBUNWIND_X86_SUPPORT + pr_err("unwind: target platform=%s is not implemented\n", arch); +#else + pr_err("unwind: target platform=%s is not supported\n", arch); +#endif + } + register_local_unwind_libunwind_ops(thread); return thread->unwind_libunwind_ops->prepare_access(thread); diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index 0122797..4de423c 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -22,11 +22,12 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, /* libunwind specific */ #ifdef HAVE_LIBUNWIND_SUPPORT int libunwind__arch_reg_id(int regnum); -int unwind__prepare_access(struct thread *thread); +int unwind__prepare_access(struct thread *thread, struct map *map); void unwind__flush_access(struct thread *thread); void unwind__finish_access(struct thread *thread); #else -static inline int unwind__prepare_access(struct thread *thread __maybe_unused) +static inline int unwind__prepare_access(struct thread *thread __maybe_unused, + struct map *map __maybe_unused) { return 0; } -- 1.8.5.2