forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
libunwind-prefer-extbl.patch
144 lines (132 loc) · 5.21 KB
/
libunwind-prefer-extbl.patch
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 bc7b50355cb37cfa56f6131b2f9174b499053188 Mon Sep 17 00:00:00 2001
From: Yichao Yu <[email protected]>
Date: Sat, 1 Oct 2016 16:55:40 +0000
Subject: [PATCH] Prefer EXTBL unwinding on ARM
It is part of the C++ ABI so a EXTBL unwind info that's not `CANT_UNWIND`
should always be reliable/correct.
Ignore `ESTOPUNWIND` so that a `CANT_UNWIND` info can fallback to unwinding
using the debug info instead.
---
include/tdep-arm/libunwind_i.h | 4 ++++
src/arm/Gex_tables.c | 18 ++++++++++++++----
src/arm/Gstep.c | 35 +++++++++++++++++++++--------------
3 files changed, 39 insertions(+), 18 deletions(-)
diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h
index 2602f41c..074fc8cb 100644
--- a/include/tdep-arm/libunwind_i.h
+++ b/include/tdep-arm/libunwind_i.h
@@ -253,6 +253,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. */
@@ -294,6 +295,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 d6573a65..a895e0cc 100644
--- a/src/arm/Gex_tables.c
+++ b/src/arm/Gex_tables.c
@@ -506,18 +506,20 @@ 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))
ret = dwarf_find_proc_info (as, ip, pi, need_unwind_info, arg);
- 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;
@@ -540,6 +542,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 adec02e0..c43daa1c 100644
--- a/src/arm/Gstep.c
+++ b/src/arm/Gstep.c
@@ -53,8 +53,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, 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, ip, 1)) < 0)
return ret;
+#endif
}
if (c->dwarf.pi.format != UNW_INFO_FORMAT_ARM_EXIDX)
@@ -94,8 +101,21 @@ unw_step (unw_cursor_t *cursor)
if (unw_is_signal_frame (cursor) > 0)
return arm_handle_signal_frame (cursor);
+ /* First, try extbl-based unwinding. */
+ if (UNW_TRY_METHOD (UNW_ARM_METHOD_EXIDX))
+ {
+ Debug (13, "%s(ret=%d), trying extbl\n",
+ UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF) ? "dwarf_step() failed " : "",
+ ret);
+ ret = arm_exidx_step (c);
+ if (ret > 0)
+ return 1;
+ if (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);
@@ -114,16 +129,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. */
#ifdef __FreeBSD__
--
2.16.1