Currently, perf script uses host unwind methods to parse perf.data
callchain info regardless of the target architecture. So we get wrong
result and no promotion when unwinding callchains of x86(32-bit) on
x86(64-bit) machine.

This patch shows proper error 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         |  6 ++++++
 tools/perf/util/thread.c           |  2 ++
 tools/perf/util/unwind-libunwind.c | 32 ++++++++++++++++++++++++++++++++
 tools/perf/util/unwind.h           |  5 +++++
 4 files changed, 45 insertions(+)

diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 1e46277..a86b864 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -345,6 +345,12 @@ ifeq ($(ARCH),powerpc)
 endif
 
 ifndef NO_LIBUNWIND
+  ifeq ($(feature-libunwind-x86), 1)
+    LIBUNWIND_LIBS += -lunwind-x86
+    $(call detected,CONFIG_LIBUNWIND_X86)
+    CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT
+  endif
+
   ifneq ($(feature-libunwind), 1)
     msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 
1.1 and/or set LIBUNWIND_DIR);
     NO_LIBUNWIND := 1
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index dfd00c6..244c4f6 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -186,6 +186,8 @@ 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__get_arch(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 63687d3..b6eb317 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -680,3 +680,35 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
 
        return get_entries(&ui, cb, arg, max_stack);
 }
+
+void unwind__get_arch(struct thread *thread, struct map *map)
+{
+       char *arch;
+       int is_64_bit;
+
+       if (!thread->mg->machine->env)
+               return;
+
+       is_64_bit = dso_is_64_bit(map->dso, map);
+       if (is_64_bit < 0)
+               return;
+
+       if (thread->addr_space)
+               pr_debug("Thread map already set, 64bit is %d, dso=%s\n",
+                        is_64_bit, map->dso->name);
+
+       arch = thread->mg->machine->env->arch;
+
+       if (!strcmp(arch, "x86_64")
+                  || !strcmp(arch, "x86")
+                  || !strcmp(arch, "i686")) {
+               pr_debug("Thread map is X86, 64bit is %d\n", is_64_bit);
+               if (!is_64_bit)
+#ifdef HAVE_LIBUNWIND_X86_SUPPORT
+                       pr_err("target platform=%s is not implemented!\n",
+                              arch);
+#else
+                       pr_err("target platform=%s is not supported!\n", arch);
+#endif
+       }
+}
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index 12790cf..889d630 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -24,6 +24,7 @@ int libunwind__arch_reg_id(int regnum);
 int unwind__prepare_access(struct thread *thread);
 void unwind__flush_access(struct thread *thread);
 void unwind__finish_access(struct thread *thread);
+void unwind__get_arch(struct thread *thread, struct map *map);
 #else
 static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
 {
@@ -32,6 +33,8 @@ static inline int unwind__prepare_access(struct thread 
*thread __maybe_unused)
 
 static inline void unwind__flush_access(struct thread *thread __maybe_unused) 
{}
 static inline void unwind__finish_access(struct thread *thread __maybe_unused) 
{}
+static inline void unwind__get_arch(struct thread *thread __maybe_unused,
+                                   struct map *map __maybe_unused) {}
 #endif
 #else
 static inline int
@@ -51,5 +54,7 @@ static inline int unwind__prepare_access(struct thread 
*thread __maybe_unused)
 
 static inline void unwind__flush_access(struct thread *thread __maybe_unused) 
{}
 static inline void unwind__finish_access(struct thread *thread __maybe_unused) 
{}
+static inline void unwind__get_arch(struct thread *thread __maybe_unused,
+                                   struct map *map __maybe_unused) {}
 #endif /* HAVE_DWARF_UNWIND_SUPPORT */
 #endif /* __UNWIND_H */
-- 
1.8.5.2

Reply via email to