1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
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
|