diff options
| author | He Kuang <hekuang@huawei.com> | 2016-06-02 23:33:22 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-06-07 14:13:27 -0400 |
| commit | 52ffe0ff02fc053a025c381d5808e9ecd3206dfe (patch) | |
| tree | 9b89d84dc668b112c7cf581be7eee13cd1dd656c | |
| parent | 19473e7ba8f8f443f09d4187791de9d6f95fdc1d (diff) | |
perf callchain: Support x86 target platform
Support x86(32-bit) cross platform callchain unwind.
Signed-off-by: He Kuang <hekuang@huawei.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Ekaterina Tumanova <tumanova@linux.vnet.ibm.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1464924803-22214-14-git-send-email-hekuang@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/perf/arch/x86/util/unwind-libunwind.c | 6 | ||||
| -rw-r--r-- | tools/perf/config/Makefile | 8 | ||||
| -rw-r--r-- | tools/perf/util/Build | 1 | ||||
| -rw-r--r-- | tools/perf/util/libunwind/x86_32.c | 37 | ||||
| -rw-r--r-- | tools/perf/util/unwind-libunwind.c | 15 |
5 files changed, 63 insertions, 4 deletions
diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c index db25e93d989c..4f16661cbdbb 100644 --- a/tools/perf/arch/x86/util/unwind-libunwind.c +++ b/tools/perf/arch/x86/util/unwind-libunwind.c | |||
| @@ -1,12 +1,14 @@ | |||
| 1 | 1 | ||
| 2 | #ifndef REMOTE_UNWIND_LIBUNWIND | ||
| 2 | #include <errno.h> | 3 | #include <errno.h> |
| 3 | #include <libunwind.h> | 4 | #include <libunwind.h> |
| 4 | #include "perf_regs.h" | 5 | #include "perf_regs.h" |
| 5 | #include "../../util/unwind.h" | 6 | #include "../../util/unwind.h" |
| 6 | #include "../../util/debug.h" | 7 | #include "../../util/debug.h" |
| 8 | #endif | ||
| 7 | 9 | ||
| 8 | #ifdef HAVE_ARCH_X86_64_SUPPORT | 10 | #ifdef HAVE_ARCH_X86_64_SUPPORT |
| 9 | int libunwind__arch_reg_id(int regnum) | 11 | int LIBUNWIND__ARCH_REG_ID(int regnum) |
| 10 | { | 12 | { |
| 11 | int id; | 13 | int id; |
| 12 | 14 | ||
| @@ -70,7 +72,7 @@ int libunwind__arch_reg_id(int regnum) | |||
| 70 | return id; | 72 | return id; |
| 71 | } | 73 | } |
| 72 | #else | 74 | #else |
| 73 | int libunwind__arch_reg_id(int regnum) | 75 | int LIBUNWIND__ARCH_REG_ID(int regnum) |
| 74 | { | 76 | { |
| 75 | int id; | 77 | int id; |
| 76 | 78 | ||
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 3918687e7816..34999fb19358 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
| @@ -354,6 +354,14 @@ endif | |||
| 354 | 354 | ||
| 355 | ifndef NO_LIBUNWIND | 355 | ifndef NO_LIBUNWIND |
| 356 | have_libunwind := | 356 | have_libunwind := |
| 357 | |||
| 358 | ifeq ($(feature-libunwind-x86), 1) | ||
| 359 | $(call detected,CONFIG_LIBUNWIND_X86) | ||
| 360 | CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT | ||
| 361 | LDFLAGS += -lunwind-x86 | ||
| 362 | have_libunwind = 1 | ||
| 363 | endif | ||
| 364 | |||
| 357 | ifneq ($(feature-libunwind), 1) | 365 | ifneq ($(feature-libunwind), 1) |
| 358 | msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); | 366 | msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); |
| 359 | NO_LOCAL_LIBUNWIND := 1 | 367 | NO_LOCAL_LIBUNWIND := 1 |
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 004fb1d1d0ad..7746e0932768 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
| @@ -101,6 +101,7 @@ libperf-$(CONFIG_DWARF) += dwarf-aux.o | |||
| 101 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o | 101 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o |
| 102 | libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o | 102 | libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o |
| 103 | libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o | 103 | libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o |
| 104 | libperf-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o | ||
| 104 | 105 | ||
| 105 | libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o | 106 | libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o |
| 106 | 107 | ||
diff --git a/tools/perf/util/libunwind/x86_32.c b/tools/perf/util/libunwind/x86_32.c new file mode 100644 index 000000000000..d98c17e19a2b --- /dev/null +++ b/tools/perf/util/libunwind/x86_32.c | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | * This file setups defines to compile arch specific binary from the | ||
| 3 | * generic one. | ||
| 4 | * | ||
| 5 | * The function 'LIBUNWIND__ARCH_REG_ID' name is set according to arch | ||
| 6 | * name and the defination of this function is included directly from | ||
| 7 | * 'arch/x86/util/unwind-libunwind.c', to make sure that this function | ||
| 8 | * is defined no matter what arch the host is. | ||
| 9 | * | ||
| 10 | * Finally, the arch specific unwind methods are exported which will | ||
| 11 | * be assigned to each x86 thread. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #define REMOTE_UNWIND_LIBUNWIND | ||
| 15 | #define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__x86_reg_id(regnum) | ||
| 16 | |||
| 17 | #include "unwind.h" | ||
| 18 | #include "debug.h" | ||
| 19 | #include "libunwind-x86.h" | ||
| 20 | #include <../../../../arch/x86/include/uapi/asm/perf_regs.h> | ||
| 21 | |||
| 22 | /* HAVE_ARCH_X86_64_SUPPORT is used in'arch/x86/util/unwind-libunwind.c' | ||
| 23 | * for x86_32, we undef it to compile code for x86_32 only. | ||
| 24 | */ | ||
| 25 | #undef HAVE_ARCH_X86_64_SUPPORT | ||
| 26 | #include "../../arch/x86/util/unwind-libunwind.c" | ||
| 27 | |||
| 28 | /* Explicitly define NO_LIBUNWIND_DEBUG_FRAME, because non-ARM has no | ||
| 29 | * dwarf_find_debug_frame() function. | ||
| 30 | */ | ||
| 31 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | ||
| 32 | #define NO_LIBUNWIND_DEBUG_FRAME | ||
| 33 | #endif | ||
| 34 | #include "util/unwind-libunwind-local.c" | ||
| 35 | |||
| 36 | struct unwind_libunwind_ops * | ||
| 37 | x86_32_unwind_libunwind_ops = &_unwind_libunwind_ops; | ||
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 0086726e00e0..e65515aa61d9 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include "arch/common.h" | 5 | #include "arch/common.h" |
| 6 | 6 | ||
| 7 | struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops; | 7 | struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops; |
| 8 | struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops; | ||
| 8 | 9 | ||
| 9 | static void unwind__register_ops(struct thread *thread, | 10 | static void unwind__register_ops(struct thread *thread, |
| 10 | struct unwind_libunwind_ops *ops) | 11 | struct unwind_libunwind_ops *ops) |
| @@ -16,6 +17,7 @@ int unwind__prepare_access(struct thread *thread, struct map *map) | |||
| 16 | { | 17 | { |
| 17 | const char *arch; | 18 | const char *arch; |
| 18 | enum dso_type dso_type; | 19 | enum dso_type dso_type; |
| 20 | struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops; | ||
| 19 | 21 | ||
| 20 | if (thread->addr_space) { | 22 | if (thread->addr_space) { |
| 21 | pr_debug("unwind: thread map already set, dso=%s\n", | 23 | pr_debug("unwind: thread map already set, dso=%s\n", |
| @@ -32,9 +34,18 @@ int unwind__prepare_access(struct thread *thread, struct map *map) | |||
| 32 | return 0; | 34 | return 0; |
| 33 | 35 | ||
| 34 | arch = normalize_arch(thread->mg->machine->env->arch); | 36 | arch = normalize_arch(thread->mg->machine->env->arch); |
| 35 | pr_debug("unwind: target platform=%s\n", arch); | 37 | |
| 38 | if (!strcmp(arch, "x86")) { | ||
| 39 | if (dso_type != DSO__TYPE_64BIT) | ||
| 40 | ops = x86_32_unwind_libunwind_ops; | ||
| 41 | } | ||
| 42 | |||
| 43 | if (!ops) { | ||
| 44 | pr_err("unwind: target platform=%s is not supported\n", arch); | ||
| 45 | return -1; | ||
| 46 | } | ||
| 36 | out_register: | 47 | out_register: |
| 37 | unwind__register_ops(thread, local_unwind_libunwind_ops); | 48 | unwind__register_ops(thread, ops); |
| 38 | 49 | ||
| 39 | return thread->unwind_libunwind_ops->prepare_access(thread); | 50 | return thread->unwind_libunwind_ops->prepare_access(thread); |
| 40 | } | 51 | } |
