Support aarch64 cross platform callchain unwind.

Signed-off-by: He Kuang <heku...@huawei.com>
---
 .../perf/arch/arm64/include/libunwind/libunwind-arch.h | 18 ++++++++++++++++++
 tools/perf/arch/arm64/util/unwind-libunwind.c          |  5 ++++-
 tools/perf/config/Makefile                             | 12 ++++++++++++
 tools/perf/util/Build                                  |  4 ++++
 tools/perf/util/thread.c                               | 12 ++++++++++++
 tools/perf/util/unwind.h                               |  3 +++
 6 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/arch/arm64/include/libunwind/libunwind-arch.h

diff --git a/tools/perf/arch/arm64/include/libunwind/libunwind-arch.h 
b/tools/perf/arch/arm64/include/libunwind/libunwind-arch.h
new file mode 100644
index 0000000..7bc8a00
--- /dev/null
+++ b/tools/perf/arch/arm64/include/libunwind/libunwind-arch.h
@@ -0,0 +1,18 @@
+#ifndef _LIBUNWIND_ARCH_H
+#define _LIBUNWIND_ARCH_H
+
+#include <libunwind-aarch64.h>
+#include <../perf_regs.h>
+#include <../../../../../../arch/arm64/include/uapi/asm/perf_regs.h>
+
+#define LIBUNWIND_AARCH64
+int libunwind__aarch64_reg_id(int regnum);
+
+#include <../../../arm64/util/unwind-libunwind.c>
+
+#define LIBUNWIND__ARCH_REG_ID libunwind__aarch64_reg_id
+
+#define UNWT_PREFIX    UNW_PASTE(UNW_PASTE(_U, aarch64), _)
+#define UNWT_OBJ(fn)   UNW_PASTE(UNWT_PREFIX, fn)
+
+#endif /* _LIBUNWIND_ARCH_H */
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c 
b/tools/perf/arch/arm64/util/unwind-libunwind.c
index a87afa9..5b557a5 100644
--- a/tools/perf/arch/arm64/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm64/util/unwind-libunwind.c
@@ -1,11 +1,14 @@
 
 #include <errno.h>
-#include <libunwind.h>
 #include "perf_regs.h"
 #include "../../util/unwind.h"
 #include "../../util/debug.h"
 
+#ifndef LIBUNWIND_AARCH64
 int libunwind__arch_reg_id(int regnum)
+#else
+int libunwind__aarch64_reg_id(int regnum)
+#endif
 {
        switch (regnum) {
        case UNW_AARCH64_X0:
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 16f14b1..c1bfc5e 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -353,6 +353,18 @@ ifndef NO_LIBUNWIND
     have_libunwind = 1
   endif
 
+  ifeq ($(feature-libunwind-aarch64), 1)
+    $(call detected,CONFIG_LIBUNWIND_AARCH64)
+    CFLAGS += -DHAVE_LIBUNWIND_AARCH64_SUPPORT
+    LDFLAGS += -lunwind -lunwind-aarch64
+    have_libunwind = 1
+    $(call feature_check,libunwind-debug-frame-aarch64)
+    ifneq ($(feature-libunwind-debug-frame-aarch64), 1)
+      msg := $(warning No debug_frame support found in libunwind-aarch64);
+      CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_AARCH64
+    endif
+  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/Build b/tools/perf/util/Build
index 2dd3939..10e42ad 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -102,10 +102,14 @@ libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
 libperf-$(CONFIG_LOCAL_LIBUNWIND)    += unwind-libunwind.o
 libperf-$(CONFIG_LIBUNWIND)          += unwind-libunwind_common.o
 libperf-$(CONFIG_LIBUNWIND_X86)      += unwind-libunwind_x86_32.o
+libperf-$(CONFIG_LIBUNWIND_AARCH64)  += unwind-libunwind_arm64.o
 
 $(OUTPUT)util/unwind-libunwind_x86_32.o: util/unwind-libunwind.c 
arch/x86/util/unwind-libunwind.c
        $(QUIET_CC)$(CC) $(CFLAGS) -DARCH_UNWIND_LIBUNWIND 
-Iarch/x86/include/libunwind -c -o $@ util/unwind-libunwind.c
 
+$(OUTPUT)util/unwind-libunwind_arm64.o: util/unwind-libunwind.c 
arch/arm64/util/unwind-libunwind.c
+       $(QUIET_CC)$(CC) $(CFLAGS) -DARCH_UNWIND_LIBUNWIND 
-Iarch/arm64/include/libunwind -c -o $@ util/unwind-libunwind.c
+
 libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
 
 libperf-y += scripting-engines/
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 2b93856..ba3e597 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -221,6 +221,18 @@ void thread__insert_map(struct thread *thread, struct map 
*map)
                        goto err;
 #endif
                }
+       } else if (!strcmp(arch, "aarch64") || !strncmp(arch, "arm", 3)) {
+               pr_debug("Thread map is ARM, 64bit is %d, dso=%s\n",
+                        is_64_bit, map->dso->name);
+               if (is_64_bit) {
+#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT
+                       register_unwind_libunwind_ops(
+                               &_Uaarch64_unwind_libunwind_ops, thread);
+#else
+                       register_null_unwind_libunwind_ops(thread);
+                       goto err;
+#endif
+               }
        } else {
                register_local_unwind_libunwind_ops(thread);
        }
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index 98d40bd..d215717 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -59,6 +59,9 @@ static inline void unwind__finish_access(struct thread 
*thread __maybe_unused) {
 #ifdef HAVE_LIBUNWIND_X86_SUPPORT
 extern struct unwind_libunwind_ops _Ux86_unwind_libunwind_ops;
 #endif
+#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT
+extern struct unwind_libunwind_ops _Uaarch64_unwind_libunwind_ops;
+#endif
 
 #else
 static inline int
-- 
1.8.5.2

Reply via email to