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

Reply via email to