Support x86(32-bit) cross platform callchain unwind. Signed-off-by: He Kuang <heku...@huawei.com> --- tools/perf/arch/Build | 1 + tools/perf/arch/x86/util/unwind-libunwind.c | 7 ++++--- tools/perf/arch/x86/util/unwind-libunwind_x86_32.c | 21 +++++++++++++++++++++ tools/perf/util/unwind-libunwind-local.c | 4 ++++ tools/perf/util/unwind-libunwind.c | 19 +++++++++++++------ tools/perf/util/unwind.h | 10 ++++++++++ 6 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 tools/perf/arch/x86/util/unwind-libunwind_x86_32.c
diff --git a/tools/perf/arch/Build b/tools/perf/arch/Build index 109eb75..3fc4af1 100644 --- a/tools/perf/arch/Build +++ b/tools/perf/arch/Build @@ -1,2 +1,3 @@ libperf-y += common.o libperf-y += $(ARCH)/ +libperf-$(CONFIG_LIBUNWIND_X86) += x86/util/unwind-libunwind_x86_32.o diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c index db25e93..3b0be69 100644 --- a/tools/perf/arch/x86/util/unwind-libunwind.c +++ b/tools/perf/arch/x86/util/unwind-libunwind.c @@ -1,12 +1,13 @@ - +#ifndef REMOTE_UNWIND_LIBUNWIND #include <errno.h> #include <libunwind.h> #include "perf_regs.h" #include "../../util/unwind.h" #include "../../util/debug.h" +#endif #ifdef HAVE_ARCH_X86_64_SUPPORT -int libunwind__arch_reg_id(int regnum) +int LIBUNWIND__ARCH_REG_ID(int regnum) { int id; @@ -70,7 +71,7 @@ int libunwind__arch_reg_id(int regnum) return id; } #else -int libunwind__arch_reg_id(int regnum) +int LIBUNWIND__ARCH_REG_ID(int regnum) { int id; diff --git a/tools/perf/arch/x86/util/unwind-libunwind_x86_32.c b/tools/perf/arch/x86/util/unwind-libunwind_x86_32.c new file mode 100644 index 0000000..9d5359e --- /dev/null +++ b/tools/perf/arch/x86/util/unwind-libunwind_x86_32.c @@ -0,0 +1,21 @@ +#define REMOTE_UNWIND_LIBUNWIND + +#define LIBUNWIND__ARCH_REG_ID libunwind__x86_reg_id + +#include "unwind.h" +#include "debug.h" +#include "libunwind-x86.h" +#include <../../../../../arch/x86/include/uapi/asm/perf_regs.h> + +#undef HAVE_ARCH_X86_64_SUPPORT +#include "unwind-libunwind.c" + +#undef NO_LIBUNWIND_DEBUG_FRAME +#define NO_LIBUNWIND_DEBUG_FRAME +#include "util/unwind-libunwind-local.c" + +int register_x86_32_unwind_libunwind_ops(struct thread *thread) +{ + thread->unwind_libunwind_ops = &_unwind_libunwind_ops; + return 0; +} diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c index b391e3e..849fec1 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c @@ -5,7 +5,9 @@ #include <unistd.h> #include <sys/mman.h> #include <linux/list.h> +#ifndef REMOTE_UNWIND_LIBUNWIND #include <libunwind.h> +#endif #include "callchain.h" #include "thread.h" #include "session.h" @@ -671,7 +673,9 @@ _unwind_libunwind_ops = { .get_entries = _unwind__get_entries, }; +#ifndef REMOTE_UNWIND_LIBUNWIND void register_local_unwind_libunwind_ops(struct thread *thread) { thread->unwind_libunwind_ops = &_unwind_libunwind_ops; } +#endif diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 037ee72..c1d9d36 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c @@ -8,6 +8,9 @@ int unwind__prepare_access(struct thread *thread, struct map *map) { const char *arch; enum dso_type dso_type; + int use_local_unwind = 1; + int ret; + int (*register_func)(struct thread *thread) = NULL; if (!thread->mg->machine->env) return -1; @@ -22,16 +25,20 @@ int unwind__prepare_access(struct thread *thread, struct map *map) arch = normalize_arch(thread->mg->machine->env->arch); - if (!strcmp(arch, "x86")) { + 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 + register_func = register_x86_32_unwind_libunwind_ops; + + if (register_func) { + ret = register_func(thread); + if (!ret) + use_local_unwind = 0; + else pr_err("unwind: target platform=%s is not supported\n", arch); -#endif } - register_local_unwind_libunwind_ops(thread); + if (use_local_unwind) + 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 9e4f545..43f9f66 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h @@ -46,6 +46,16 @@ static inline void register_local_unwind_libunwind_ops(struct thread *thread __maybe_unused) {} #endif +#ifdef HAVE_LIBUNWIND_X86_SUPPORT +int register_x86_32_unwind_libunwind_ops(struct thread *thread); +#else +static inline int +register_x86_32_unwind_libunwind_ops(struct thread *thread __maybe_unused) +{ + return -1; +} +#endif + #else static inline int unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, -- 1.8.5.2