Raw File
libunwind-prefer-extbl.patch
From 6b6d4b1ce3dcfdc87a84ee276947d473e84cd39e Mon Sep 17 00:00:00 2001
From: Yichao Yu <yyc1992@gmail.com>
Date: Sat, 1 Oct 2016 16:55:40 +0000
Subject: [PATCH 3/3] Prefer EXTBL unwinding on ARM since it seems to be more
 reliable

---
 include/tdep-arm/libunwind_i.h |  4 ++++
 src/arm/Gex_tables.c           | 18 ++++++++++++++----
 src/arm/Gstep.c                | 29 ++++++++++++++++++-----------
 3 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h
index d3a279c..89a0b72 100644
--- a/include/tdep-arm/libunwind_i.h
+++ b/include/tdep-arm/libunwind_i.h
@@ -250,6 +250,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
 #define tdep_init_done                  UNW_OBJ(init_done)
 #define tdep_init                       UNW_OBJ(init)
 #define arm_find_proc_info              UNW_OBJ(find_proc_info)
+#define arm_find_proc_info2             UNW_OBJ(find_proc_info2)
 #define arm_put_unwind_info             UNW_OBJ(put_unwind_info)
 /* Platforms that support UNW_INFO_FORMAT_TABLE need to define
    tdep_search_unwind_table.  */
@@ -290,6 +291,9 @@ extern void tdep_init (void);
 extern int arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
                                unw_proc_info_t *pi, int need_unwind_info,
                                void *arg);
+extern int arm_find_proc_info2 (unw_addr_space_t as, unw_word_t ip,
+                                unw_proc_info_t *pi, int need_unwind_info,
+                                void *arg, int methods);
 extern void arm_put_unwind_info (unw_addr_space_t as,
                                   unw_proc_info_t *pi, void *arg);
 extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip,
diff --git a/src/arm/Gex_tables.c b/src/arm/Gex_tables.c
index 34706cf..379859a 100644
--- a/src/arm/Gex_tables.c
+++ b/src/arm/Gex_tables.c
@@ -500,15 +500,16 @@ arm_phdr_cb (struct dl_phdr_info *info, size_t size, void *data)
 }
 
 HIDDEN int
-arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
-                    unw_proc_info_t *pi, int need_unwind_info, void *arg)
+arm_find_proc_info2 (unw_addr_space_t as, unw_word_t ip,
+                     unw_proc_info_t *pi, int need_unwind_info, void *arg,
+                     int methods)
 {
   int ret = -1;
   intrmask_t saved_mask;
 
   Debug (14, "looking for IP=0x%lx\n", (long) ip);
 
-  if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF))
+  if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) && (methods & UNW_ARM_METHOD_DWARF))
     {
       struct dwarf_callback_data cb_data;
 
@@ -534,7 +535,8 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
         ret = -UNW_ENOINFO;
     }
 
-  if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
+  if (ret < 0 && UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX) &&
+      (methods & UNW_ARM_METHOD_EXIDX))
     {
       struct arm_cb_data cb_data;
 
@@ -560,6 +562,14 @@ arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
   return ret;
 }
 
+HIDDEN int
+arm_find_proc_info (unw_addr_space_t as, unw_word_t ip,
+                    unw_proc_info_t *pi, int need_unwind_info, void *arg)
+{
+    return arm_find_proc_info2 (as, ip, pi, need_unwind_info, arg,
+                                UNW_ARM_METHOD_ALL);
+}
+
 HIDDEN void
 arm_put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg)
 {
diff --git a/src/arm/Gstep.c b/src/arm/Gstep.c
index 5b2b329..449419b 100644
--- a/src/arm/Gstep.c
+++ b/src/arm/Gstep.c
@@ -50,8 +50,15 @@ arm_exidx_step (struct cursor *c)
                                      c->dwarf.as_arg);
   if (ret == -UNW_ENOINFO)
     {
+#ifdef UNW_LOCAL_ONLY
+        if ((ret = arm_find_proc_info2 (c->dwarf.as, c->dwarf.ip, &c->dwarf.pi,
+                                        1, c->dwarf.as_arg,
+                                        UNW_ARM_METHOD_EXIDX)) < 0)
+        return ret;
+#else
       if ((ret = tdep_find_proc_info (&c->dwarf, c->dwarf.ip, 1)) < 0)
         return ret;
+#endif
     }
 
   if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX)
@@ -184,8 +191,18 @@ unw_step (unw_cursor_t *cursor)
   if (unw_is_signal_frame (cursor))
      return unw_handle_signal_frame (cursor);
 
+  /* First, try extbl-based unwinding. */
+  if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
+    {
+      ret = arm_exidx_step (c);
+      if (ret > 0)
+        return 1;
+      if (ret == -UNW_ESTOPUNWIND || ret == 0)
+        return ret;
+    }
+
 #ifdef CONFIG_DEBUG_FRAME
-  /* First, try DWARF-based unwinding. */
+  /* Second, try DWARF-based unwinding. */
   if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF))
     {
       ret = dwarf_step (&c->dwarf);
@@ -204,16 +221,6 @@ unw_step (unw_cursor_t *cursor)
     }
 #endif /* CONFIG_DEBUG_FRAME */
 
-  /* Next, try extbl-based unwinding. */
-  if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
-    {
-      ret = arm_exidx_step (c);
-      if (ret > 0)
-        return 1;
-      if (ret == -UNW_ESTOPUNWIND || ret == 0)
-        return ret;
-    }
-
   /* Fall back on APCS frame parsing.
      Note: This won't work in case the ARM EABI is used. */
   if (unlikely (ret < 0))
-- 
2.10.0

back to top