authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-05 22:42:14-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-05 22:42:14-05:00
logbc8c4ec608ad541264994e62800679cdc5781760
tree960a8c4cda24c08a2ae9e282031df0df49ffeb2a
parent4c386436ea5c5b3c98d91cb9b007e373faa8a257
signature Commit is signed but in an unrecognized format.

libunwind 8.0.0rc3


26 files changed, 16684 insertions(+), 0 deletions(-)

libunwind/include/__libunwind_config.h created+141
...@@ -0,0 +1,141 @@
1//===------------------------- __libunwind_config.h -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef ____LIBUNWIND_CONFIG_H__
11#define ____LIBUNWIND_CONFIG_H__
12
13#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
14 !defined(__ARM_DWARF_EH__)
15#define _LIBUNWIND_ARM_EHABI
16#endif
17
18#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8
19#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 32
20#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 112
21#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 116
22#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 95
23#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM 287
24#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32
25#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65
26#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31
27
28#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
29# if defined(__i386__)
30# define _LIBUNWIND_TARGET_I386
31# define _LIBUNWIND_CONTEXT_SIZE 8
32# define _LIBUNWIND_CURSOR_SIZE 15
33# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86
34# elif defined(__x86_64__)
35# define _LIBUNWIND_TARGET_X86_64 1
36# if defined(_WIN64)
37# define _LIBUNWIND_CONTEXT_SIZE 54
38# ifdef __SEH__
39# define _LIBUNWIND_CURSOR_SIZE 204
40# else
41# define _LIBUNWIND_CURSOR_SIZE 66
42# endif
43# else
44# define _LIBUNWIND_CONTEXT_SIZE 21
45# define _LIBUNWIND_CURSOR_SIZE 33
46# endif
47# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64
48# elif defined(__powerpc64__)
49# define _LIBUNWIND_TARGET_PPC64 1
50# define _LIBUNWIND_CONTEXT_SIZE 167
51# define _LIBUNWIND_CURSOR_SIZE 179
52# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64
53# elif defined(__ppc__)
54# define _LIBUNWIND_TARGET_PPC 1
55# define _LIBUNWIND_CONTEXT_SIZE 117
56# define _LIBUNWIND_CURSOR_SIZE 124
57# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC
58# elif defined(__aarch64__)
59# define _LIBUNWIND_TARGET_AARCH64 1
60# define _LIBUNWIND_CONTEXT_SIZE 66
61# if defined(__SEH__)
62# define _LIBUNWIND_CURSOR_SIZE 164
63# else
64# define _LIBUNWIND_CURSOR_SIZE 78
65# endif
66# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
67# elif defined(__arm__)
68# define _LIBUNWIND_TARGET_ARM 1
69# if defined(__SEH__)
70# define _LIBUNWIND_CONTEXT_SIZE 42
71# define _LIBUNWIND_CURSOR_SIZE 80
72# elif defined(__ARM_WMMX)
73# define _LIBUNWIND_CONTEXT_SIZE 61
74# define _LIBUNWIND_CURSOR_SIZE 68
75# else
76# define _LIBUNWIND_CONTEXT_SIZE 42
77# define _LIBUNWIND_CURSOR_SIZE 49
78# endif
79# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM
80# elif defined(__or1k__)
81# define _LIBUNWIND_TARGET_OR1K 1
82# define _LIBUNWIND_CONTEXT_SIZE 16
83# define _LIBUNWIND_CURSOR_SIZE 24
84# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K
85# elif defined(__mips__)
86# if defined(_ABIO32) && _MIPS_SIM == _ABIO32
87# define _LIBUNWIND_TARGET_MIPS_O32 1
88# if defined(__mips_hard_float)
89# define _LIBUNWIND_CONTEXT_SIZE 50
90# define _LIBUNWIND_CURSOR_SIZE 57
91# else
92# define _LIBUNWIND_CONTEXT_SIZE 18
93# define _LIBUNWIND_CURSOR_SIZE 24
94# endif
95# elif defined(_ABIN32) && _MIPS_SIM == _ABIN32
96# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
97# if defined(__mips_hard_float)
98# define _LIBUNWIND_CONTEXT_SIZE 67
99# define _LIBUNWIND_CURSOR_SIZE 74
100# else
101# define _LIBUNWIND_CONTEXT_SIZE 35
102# define _LIBUNWIND_CURSOR_SIZE 42
103# endif
104# elif defined(_ABI64) && _MIPS_SIM == _ABI64
105# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
106# if defined(__mips_hard_float)
107# define _LIBUNWIND_CONTEXT_SIZE 67
108# define _LIBUNWIND_CURSOR_SIZE 79
109# else
110# define _LIBUNWIND_CONTEXT_SIZE 35
111# define _LIBUNWIND_CURSOR_SIZE 47
112# endif
113# else
114# error "Unsupported MIPS ABI and/or environment"
115# endif
116# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
117# elif defined(__sparc__)
118 #define _LIBUNWIND_TARGET_SPARC 1
119 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
120 #define _LIBUNWIND_CONTEXT_SIZE 16
121 #define _LIBUNWIND_CURSOR_SIZE 23
122# else
123# error "Unsupported architecture."
124# endif
125#else // !_LIBUNWIND_IS_NATIVE_ONLY
126# define _LIBUNWIND_TARGET_I386
127# define _LIBUNWIND_TARGET_X86_64 1
128# define _LIBUNWIND_TARGET_PPC 1
129# define _LIBUNWIND_TARGET_PPC64 1
130# define _LIBUNWIND_TARGET_AARCH64 1
131# define _LIBUNWIND_TARGET_ARM 1
132# define _LIBUNWIND_TARGET_OR1K 1
133# define _LIBUNWIND_TARGET_MIPS_O32 1
134# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
135# define _LIBUNWIND_TARGET_SPARC 1
136# define _LIBUNWIND_CONTEXT_SIZE 167
137# define _LIBUNWIND_CURSOR_SIZE 179
138# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
139#endif // _LIBUNWIND_IS_NATIVE_ONLY
140
141#endif // ____LIBUNWIND_CONFIG_H__
libunwind/include/libunwind.h created+862
...@@ -0,0 +1,862 @@
1//===---------------------------- libunwind.h -----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Compatible with libunwind API documented at:
10// http://www.nongnu.org/libunwind/man/libunwind(3).html
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef __LIBUNWIND__
15#define __LIBUNWIND__
16
17#include <__libunwind_config.h>
18
19#include <stdint.h>
20#include <stddef.h>
21
22#ifdef __APPLE__
23 #if __clang__
24 #if __has_include(<Availability.h>)
25 #include <Availability.h>
26 #endif
27 #elif __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
28 #include <Availability.h>
29 #endif
30
31 #ifdef __arm__
32 #define LIBUNWIND_AVAIL __attribute__((unavailable))
33 #elif defined(__OSX_AVAILABLE_STARTING)
34 #define LIBUNWIND_AVAIL __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_5_0)
35 #else
36 #include <AvailabilityMacros.h>
37 #ifdef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
38 #define LIBUNWIND_AVAIL AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
39 #else
40 #define LIBUNWIND_AVAIL __attribute__((unavailable))
41 #endif
42 #endif
43#else
44 #define LIBUNWIND_AVAIL
45#endif
46
47/* error codes */
48enum {
49 UNW_ESUCCESS = 0, /* no error */
50 UNW_EUNSPEC = -6540, /* unspecified (general) error */
51 UNW_ENOMEM = -6541, /* out of memory */
52 UNW_EBADREG = -6542, /* bad register number */
53 UNW_EREADONLYREG = -6543, /* attempt to write read-only register */
54 UNW_ESTOPUNWIND = -6544, /* stop unwinding */
55 UNW_EINVALIDIP = -6545, /* invalid IP */
56 UNW_EBADFRAME = -6546, /* bad frame */
57 UNW_EINVAL = -6547, /* unsupported operation or bad value */
58 UNW_EBADVERSION = -6548, /* unwind info has unsupported version */
59 UNW_ENOINFO = -6549 /* no unwind info found */
60#if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY)
61 , UNW_ECROSSRASIGNING = -6550 /* cross unwind with return address signing */
62#endif
63};
64
65struct unw_context_t {
66 uint64_t data[_LIBUNWIND_CONTEXT_SIZE];
67};
68typedef struct unw_context_t unw_context_t;
69
70struct unw_cursor_t {
71 uint64_t data[_LIBUNWIND_CURSOR_SIZE];
72};
73typedef struct unw_cursor_t unw_cursor_t;
74
75typedef struct unw_addr_space *unw_addr_space_t;
76
77typedef int unw_regnum_t;
78typedef uintptr_t unw_word_t;
79#if defined(__arm__)
80typedef uint64_t unw_fpreg_t;
81#else
82typedef double unw_fpreg_t;
83#endif
84
85struct unw_proc_info_t {
86 unw_word_t start_ip; /* start address of function */
87 unw_word_t end_ip; /* address after end of function */
88 unw_word_t lsda; /* address of language specific data area, */
89 /* or zero if not used */
90 unw_word_t handler; /* personality routine, or zero if not used */
91 unw_word_t gp; /* not used */
92 unw_word_t flags; /* not used */
93 uint32_t format; /* compact unwind encoding, or zero if none */
94 uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */
95 unw_word_t unwind_info; /* address of DWARF unwind info, or zero */
96 unw_word_t extra; /* mach_header of mach-o image containing func */
97};
98typedef struct unw_proc_info_t unw_proc_info_t;
99
100#ifdef __cplusplus
101extern "C" {
102#endif
103
104extern int unw_getcontext(unw_context_t *) LIBUNWIND_AVAIL;
105extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL;
106extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL;
107extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL;
108extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL;
109extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t) LIBUNWIND_AVAIL;
110extern int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL;
111extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL;
112
113#ifdef __arm__
114/* Save VFP registers in FSTMX format (instead of FSTMD). */
115extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL;
116#endif
117
118
119extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;
120extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL;
121extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;
122extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL;
123extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL;
124//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*);
125
126extern unw_addr_space_t unw_local_addr_space;
127
128#ifdef UNW_REMOTE
129/*
130 * Mac OS X "remote" API for unwinding other processes on same machine
131 *
132 */
133extern unw_addr_space_t unw_create_addr_space_for_task(task_t);
134extern void unw_destroy_addr_space(unw_addr_space_t);
135extern int unw_init_remote_thread(unw_cursor_t *, unw_addr_space_t, thread_t *);
136#endif /* UNW_REMOTE */
137
138/*
139 * traditional libunwind "remote" API
140 * NOT IMPLEMENTED on Mac OS X
141 *
142 * extern int unw_init_remote(unw_cursor_t*, unw_addr_space_t,
143 * thread_t*);
144 * extern unw_accessors_t unw_get_accessors(unw_addr_space_t);
145 * extern unw_addr_space_t unw_create_addr_space(unw_accessors_t, int);
146 * extern void unw_flush_cache(unw_addr_space_t, unw_word_t,
147 * unw_word_t);
148 * extern int unw_set_caching_policy(unw_addr_space_t,
149 * unw_caching_policy_t);
150 * extern void _U_dyn_register(unw_dyn_info_t*);
151 * extern void _U_dyn_cancel(unw_dyn_info_t*);
152 */
153
154#ifdef __cplusplus
155}
156#endif
157
158// architecture independent register numbers
159enum {
160 UNW_REG_IP = -1, // instruction pointer
161 UNW_REG_SP = -2, // stack pointer
162};
163
164// 32-bit x86 registers
165enum {
166 UNW_X86_EAX = 0,
167 UNW_X86_ECX = 1,
168 UNW_X86_EDX = 2,
169 UNW_X86_EBX = 3,
170 UNW_X86_EBP = 4,
171 UNW_X86_ESP = 5,
172 UNW_X86_ESI = 6,
173 UNW_X86_EDI = 7
174};
175
176// 64-bit x86_64 registers
177enum {
178 UNW_X86_64_RAX = 0,
179 UNW_X86_64_RDX = 1,
180 UNW_X86_64_RCX = 2,
181 UNW_X86_64_RBX = 3,
182 UNW_X86_64_RSI = 4,
183 UNW_X86_64_RDI = 5,
184 UNW_X86_64_RBP = 6,
185 UNW_X86_64_RSP = 7,
186 UNW_X86_64_R8 = 8,
187 UNW_X86_64_R9 = 9,
188 UNW_X86_64_R10 = 10,
189 UNW_X86_64_R11 = 11,
190 UNW_X86_64_R12 = 12,
191 UNW_X86_64_R13 = 13,
192 UNW_X86_64_R14 = 14,
193 UNW_X86_64_R15 = 15,
194 UNW_X86_64_RIP = 16,
195 UNW_X86_64_XMM0 = 17,
196 UNW_X86_64_XMM1 = 18,
197 UNW_X86_64_XMM2 = 19,
198 UNW_X86_64_XMM3 = 20,
199 UNW_X86_64_XMM4 = 21,
200 UNW_X86_64_XMM5 = 22,
201 UNW_X86_64_XMM6 = 23,
202 UNW_X86_64_XMM7 = 24,
203 UNW_X86_64_XMM8 = 25,
204 UNW_X86_64_XMM9 = 26,
205 UNW_X86_64_XMM10 = 27,
206 UNW_X86_64_XMM11 = 28,
207 UNW_X86_64_XMM12 = 29,
208 UNW_X86_64_XMM13 = 30,
209 UNW_X86_64_XMM14 = 31,
210 UNW_X86_64_XMM15 = 32,
211};
212
213
214// 32-bit ppc register numbers
215enum {
216 UNW_PPC_R0 = 0,
217 UNW_PPC_R1 = 1,
218 UNW_PPC_R2 = 2,
219 UNW_PPC_R3 = 3,
220 UNW_PPC_R4 = 4,
221 UNW_PPC_R5 = 5,
222 UNW_PPC_R6 = 6,
223 UNW_PPC_R7 = 7,
224 UNW_PPC_R8 = 8,
225 UNW_PPC_R9 = 9,
226 UNW_PPC_R10 = 10,
227 UNW_PPC_R11 = 11,
228 UNW_PPC_R12 = 12,
229 UNW_PPC_R13 = 13,
230 UNW_PPC_R14 = 14,
231 UNW_PPC_R15 = 15,
232 UNW_PPC_R16 = 16,
233 UNW_PPC_R17 = 17,
234 UNW_PPC_R18 = 18,
235 UNW_PPC_R19 = 19,
236 UNW_PPC_R20 = 20,
237 UNW_PPC_R21 = 21,
238 UNW_PPC_R22 = 22,
239 UNW_PPC_R23 = 23,
240 UNW_PPC_R24 = 24,
241 UNW_PPC_R25 = 25,
242 UNW_PPC_R26 = 26,
243 UNW_PPC_R27 = 27,
244 UNW_PPC_R28 = 28,
245 UNW_PPC_R29 = 29,
246 UNW_PPC_R30 = 30,
247 UNW_PPC_R31 = 31,
248 UNW_PPC_F0 = 32,
249 UNW_PPC_F1 = 33,
250 UNW_PPC_F2 = 34,
251 UNW_PPC_F3 = 35,
252 UNW_PPC_F4 = 36,
253 UNW_PPC_F5 = 37,
254 UNW_PPC_F6 = 38,
255 UNW_PPC_F7 = 39,
256 UNW_PPC_F8 = 40,
257 UNW_PPC_F9 = 41,
258 UNW_PPC_F10 = 42,
259 UNW_PPC_F11 = 43,
260 UNW_PPC_F12 = 44,
261 UNW_PPC_F13 = 45,
262 UNW_PPC_F14 = 46,
263 UNW_PPC_F15 = 47,
264 UNW_PPC_F16 = 48,
265 UNW_PPC_F17 = 49,
266 UNW_PPC_F18 = 50,
267 UNW_PPC_F19 = 51,
268 UNW_PPC_F20 = 52,
269 UNW_PPC_F21 = 53,
270 UNW_PPC_F22 = 54,
271 UNW_PPC_F23 = 55,
272 UNW_PPC_F24 = 56,
273 UNW_PPC_F25 = 57,
274 UNW_PPC_F26 = 58,
275 UNW_PPC_F27 = 59,
276 UNW_PPC_F28 = 60,
277 UNW_PPC_F29 = 61,
278 UNW_PPC_F30 = 62,
279 UNW_PPC_F31 = 63,
280 UNW_PPC_MQ = 64,
281 UNW_PPC_LR = 65,
282 UNW_PPC_CTR = 66,
283 UNW_PPC_AP = 67,
284 UNW_PPC_CR0 = 68,
285 UNW_PPC_CR1 = 69,
286 UNW_PPC_CR2 = 70,
287 UNW_PPC_CR3 = 71,
288 UNW_PPC_CR4 = 72,
289 UNW_PPC_CR5 = 73,
290 UNW_PPC_CR6 = 74,
291 UNW_PPC_CR7 = 75,
292 UNW_PPC_XER = 76,
293 UNW_PPC_V0 = 77,
294 UNW_PPC_V1 = 78,
295 UNW_PPC_V2 = 79,
296 UNW_PPC_V3 = 80,
297 UNW_PPC_V4 = 81,
298 UNW_PPC_V5 = 82,
299 UNW_PPC_V6 = 83,
300 UNW_PPC_V7 = 84,
301 UNW_PPC_V8 = 85,
302 UNW_PPC_V9 = 86,
303 UNW_PPC_V10 = 87,
304 UNW_PPC_V11 = 88,
305 UNW_PPC_V12 = 89,
306 UNW_PPC_V13 = 90,
307 UNW_PPC_V14 = 91,
308 UNW_PPC_V15 = 92,
309 UNW_PPC_V16 = 93,
310 UNW_PPC_V17 = 94,
311 UNW_PPC_V18 = 95,
312 UNW_PPC_V19 = 96,
313 UNW_PPC_V20 = 97,
314 UNW_PPC_V21 = 98,
315 UNW_PPC_V22 = 99,
316 UNW_PPC_V23 = 100,
317 UNW_PPC_V24 = 101,
318 UNW_PPC_V25 = 102,
319 UNW_PPC_V26 = 103,
320 UNW_PPC_V27 = 104,
321 UNW_PPC_V28 = 105,
322 UNW_PPC_V29 = 106,
323 UNW_PPC_V30 = 107,
324 UNW_PPC_V31 = 108,
325 UNW_PPC_VRSAVE = 109,
326 UNW_PPC_VSCR = 110,
327 UNW_PPC_SPE_ACC = 111,
328 UNW_PPC_SPEFSCR = 112
329};
330
331// 64-bit ppc register numbers
332enum {
333 UNW_PPC64_R0 = 0,
334 UNW_PPC64_R1 = 1,
335 UNW_PPC64_R2 = 2,
336 UNW_PPC64_R3 = 3,
337 UNW_PPC64_R4 = 4,
338 UNW_PPC64_R5 = 5,
339 UNW_PPC64_R6 = 6,
340 UNW_PPC64_R7 = 7,
341 UNW_PPC64_R8 = 8,
342 UNW_PPC64_R9 = 9,
343 UNW_PPC64_R10 = 10,
344 UNW_PPC64_R11 = 11,
345 UNW_PPC64_R12 = 12,
346 UNW_PPC64_R13 = 13,
347 UNW_PPC64_R14 = 14,
348 UNW_PPC64_R15 = 15,
349 UNW_PPC64_R16 = 16,
350 UNW_PPC64_R17 = 17,
351 UNW_PPC64_R18 = 18,
352 UNW_PPC64_R19 = 19,
353 UNW_PPC64_R20 = 20,
354 UNW_PPC64_R21 = 21,
355 UNW_PPC64_R22 = 22,
356 UNW_PPC64_R23 = 23,
357 UNW_PPC64_R24 = 24,
358 UNW_PPC64_R25 = 25,
359 UNW_PPC64_R26 = 26,
360 UNW_PPC64_R27 = 27,
361 UNW_PPC64_R28 = 28,
362 UNW_PPC64_R29 = 29,
363 UNW_PPC64_R30 = 30,
364 UNW_PPC64_R31 = 31,
365 UNW_PPC64_F0 = 32,
366 UNW_PPC64_F1 = 33,
367 UNW_PPC64_F2 = 34,
368 UNW_PPC64_F3 = 35,
369 UNW_PPC64_F4 = 36,
370 UNW_PPC64_F5 = 37,
371 UNW_PPC64_F6 = 38,
372 UNW_PPC64_F7 = 39,
373 UNW_PPC64_F8 = 40,
374 UNW_PPC64_F9 = 41,
375 UNW_PPC64_F10 = 42,
376 UNW_PPC64_F11 = 43,
377 UNW_PPC64_F12 = 44,
378 UNW_PPC64_F13 = 45,
379 UNW_PPC64_F14 = 46,
380 UNW_PPC64_F15 = 47,
381 UNW_PPC64_F16 = 48,
382 UNW_PPC64_F17 = 49,
383 UNW_PPC64_F18 = 50,
384 UNW_PPC64_F19 = 51,
385 UNW_PPC64_F20 = 52,
386 UNW_PPC64_F21 = 53,
387 UNW_PPC64_F22 = 54,
388 UNW_PPC64_F23 = 55,
389 UNW_PPC64_F24 = 56,
390 UNW_PPC64_F25 = 57,
391 UNW_PPC64_F26 = 58,
392 UNW_PPC64_F27 = 59,
393 UNW_PPC64_F28 = 60,
394 UNW_PPC64_F29 = 61,
395 UNW_PPC64_F30 = 62,
396 UNW_PPC64_F31 = 63,
397 // 64: reserved
398 UNW_PPC64_LR = 65,
399 UNW_PPC64_CTR = 66,
400 // 67: reserved
401 UNW_PPC64_CR0 = 68,
402 UNW_PPC64_CR1 = 69,
403 UNW_PPC64_CR2 = 70,
404 UNW_PPC64_CR3 = 71,
405 UNW_PPC64_CR4 = 72,
406 UNW_PPC64_CR5 = 73,
407 UNW_PPC64_CR6 = 74,
408 UNW_PPC64_CR7 = 75,
409 UNW_PPC64_XER = 76,
410 UNW_PPC64_V0 = 77,
411 UNW_PPC64_V1 = 78,
412 UNW_PPC64_V2 = 79,
413 UNW_PPC64_V3 = 80,
414 UNW_PPC64_V4 = 81,
415 UNW_PPC64_V5 = 82,
416 UNW_PPC64_V6 = 83,
417 UNW_PPC64_V7 = 84,
418 UNW_PPC64_V8 = 85,
419 UNW_PPC64_V9 = 86,
420 UNW_PPC64_V10 = 87,
421 UNW_PPC64_V11 = 88,
422 UNW_PPC64_V12 = 89,
423 UNW_PPC64_V13 = 90,
424 UNW_PPC64_V14 = 91,
425 UNW_PPC64_V15 = 92,
426 UNW_PPC64_V16 = 93,
427 UNW_PPC64_V17 = 94,
428 UNW_PPC64_V18 = 95,
429 UNW_PPC64_V19 = 96,
430 UNW_PPC64_V20 = 97,
431 UNW_PPC64_V21 = 98,
432 UNW_PPC64_V22 = 99,
433 UNW_PPC64_V23 = 100,
434 UNW_PPC64_V24 = 101,
435 UNW_PPC64_V25 = 102,
436 UNW_PPC64_V26 = 103,
437 UNW_PPC64_V27 = 104,
438 UNW_PPC64_V28 = 105,
439 UNW_PPC64_V29 = 106,
440 UNW_PPC64_V30 = 107,
441 UNW_PPC64_V31 = 108,
442 // 109, 111-113: OpenPOWER ELF V2 ABI: reserved
443 // Borrowing VRSAVE number from PPC32.
444 UNW_PPC64_VRSAVE = 109,
445 UNW_PPC64_VSCR = 110,
446 UNW_PPC64_TFHAR = 114,
447 UNW_PPC64_TFIAR = 115,
448 UNW_PPC64_TEXASR = 116,
449 UNW_PPC64_VS0 = UNW_PPC64_F0,
450 UNW_PPC64_VS1 = UNW_PPC64_F1,
451 UNW_PPC64_VS2 = UNW_PPC64_F2,
452 UNW_PPC64_VS3 = UNW_PPC64_F3,
453 UNW_PPC64_VS4 = UNW_PPC64_F4,
454 UNW_PPC64_VS5 = UNW_PPC64_F5,
455 UNW_PPC64_VS6 = UNW_PPC64_F6,
456 UNW_PPC64_VS7 = UNW_PPC64_F7,
457 UNW_PPC64_VS8 = UNW_PPC64_F8,
458 UNW_PPC64_VS9 = UNW_PPC64_F9,
459 UNW_PPC64_VS10 = UNW_PPC64_F10,
460 UNW_PPC64_VS11 = UNW_PPC64_F11,
461 UNW_PPC64_VS12 = UNW_PPC64_F12,
462 UNW_PPC64_VS13 = UNW_PPC64_F13,
463 UNW_PPC64_VS14 = UNW_PPC64_F14,
464 UNW_PPC64_VS15 = UNW_PPC64_F15,
465 UNW_PPC64_VS16 = UNW_PPC64_F16,
466 UNW_PPC64_VS17 = UNW_PPC64_F17,
467 UNW_PPC64_VS18 = UNW_PPC64_F18,
468 UNW_PPC64_VS19 = UNW_PPC64_F19,
469 UNW_PPC64_VS20 = UNW_PPC64_F20,
470 UNW_PPC64_VS21 = UNW_PPC64_F21,
471 UNW_PPC64_VS22 = UNW_PPC64_F22,
472 UNW_PPC64_VS23 = UNW_PPC64_F23,
473 UNW_PPC64_VS24 = UNW_PPC64_F24,
474 UNW_PPC64_VS25 = UNW_PPC64_F25,
475 UNW_PPC64_VS26 = UNW_PPC64_F26,
476 UNW_PPC64_VS27 = UNW_PPC64_F27,
477 UNW_PPC64_VS28 = UNW_PPC64_F28,
478 UNW_PPC64_VS29 = UNW_PPC64_F29,
479 UNW_PPC64_VS30 = UNW_PPC64_F30,
480 UNW_PPC64_VS31 = UNW_PPC64_F31,
481 UNW_PPC64_VS32 = UNW_PPC64_V0,
482 UNW_PPC64_VS33 = UNW_PPC64_V1,
483 UNW_PPC64_VS34 = UNW_PPC64_V2,
484 UNW_PPC64_VS35 = UNW_PPC64_V3,
485 UNW_PPC64_VS36 = UNW_PPC64_V4,
486 UNW_PPC64_VS37 = UNW_PPC64_V5,
487 UNW_PPC64_VS38 = UNW_PPC64_V6,
488 UNW_PPC64_VS39 = UNW_PPC64_V7,
489 UNW_PPC64_VS40 = UNW_PPC64_V8,
490 UNW_PPC64_VS41 = UNW_PPC64_V9,
491 UNW_PPC64_VS42 = UNW_PPC64_V10,
492 UNW_PPC64_VS43 = UNW_PPC64_V11,
493 UNW_PPC64_VS44 = UNW_PPC64_V12,
494 UNW_PPC64_VS45 = UNW_PPC64_V13,
495 UNW_PPC64_VS46 = UNW_PPC64_V14,
496 UNW_PPC64_VS47 = UNW_PPC64_V15,
497 UNW_PPC64_VS48 = UNW_PPC64_V16,
498 UNW_PPC64_VS49 = UNW_PPC64_V17,
499 UNW_PPC64_VS50 = UNW_PPC64_V18,
500 UNW_PPC64_VS51 = UNW_PPC64_V19,
501 UNW_PPC64_VS52 = UNW_PPC64_V20,
502 UNW_PPC64_VS53 = UNW_PPC64_V21,
503 UNW_PPC64_VS54 = UNW_PPC64_V22,
504 UNW_PPC64_VS55 = UNW_PPC64_V23,
505 UNW_PPC64_VS56 = UNW_PPC64_V24,
506 UNW_PPC64_VS57 = UNW_PPC64_V25,
507 UNW_PPC64_VS58 = UNW_PPC64_V26,
508 UNW_PPC64_VS59 = UNW_PPC64_V27,
509 UNW_PPC64_VS60 = UNW_PPC64_V28,
510 UNW_PPC64_VS61 = UNW_PPC64_V29,
511 UNW_PPC64_VS62 = UNW_PPC64_V30,
512 UNW_PPC64_VS63 = UNW_PPC64_V31
513};
514
515// 64-bit ARM64 registers
516enum {
517 UNW_ARM64_X0 = 0,
518 UNW_ARM64_X1 = 1,
519 UNW_ARM64_X2 = 2,
520 UNW_ARM64_X3 = 3,
521 UNW_ARM64_X4 = 4,
522 UNW_ARM64_X5 = 5,
523 UNW_ARM64_X6 = 6,
524 UNW_ARM64_X7 = 7,
525 UNW_ARM64_X8 = 8,
526 UNW_ARM64_X9 = 9,
527 UNW_ARM64_X10 = 10,
528 UNW_ARM64_X11 = 11,
529 UNW_ARM64_X12 = 12,
530 UNW_ARM64_X13 = 13,
531 UNW_ARM64_X14 = 14,
532 UNW_ARM64_X15 = 15,
533 UNW_ARM64_X16 = 16,
534 UNW_ARM64_X17 = 17,
535 UNW_ARM64_X18 = 18,
536 UNW_ARM64_X19 = 19,
537 UNW_ARM64_X20 = 20,
538 UNW_ARM64_X21 = 21,
539 UNW_ARM64_X22 = 22,
540 UNW_ARM64_X23 = 23,
541 UNW_ARM64_X24 = 24,
542 UNW_ARM64_X25 = 25,
543 UNW_ARM64_X26 = 26,
544 UNW_ARM64_X27 = 27,
545 UNW_ARM64_X28 = 28,
546 UNW_ARM64_X29 = 29,
547 UNW_ARM64_FP = 29,
548 UNW_ARM64_X30 = 30,
549 UNW_ARM64_LR = 30,
550 UNW_ARM64_X31 = 31,
551 UNW_ARM64_SP = 31,
552 // reserved block
553 UNW_ARM64_RA_SIGN_STATE = 34,
554 // reserved block
555 UNW_ARM64_D0 = 64,
556 UNW_ARM64_D1 = 65,
557 UNW_ARM64_D2 = 66,
558 UNW_ARM64_D3 = 67,
559 UNW_ARM64_D4 = 68,
560 UNW_ARM64_D5 = 69,
561 UNW_ARM64_D6 = 70,
562 UNW_ARM64_D7 = 71,
563 UNW_ARM64_D8 = 72,
564 UNW_ARM64_D9 = 73,
565 UNW_ARM64_D10 = 74,
566 UNW_ARM64_D11 = 75,
567 UNW_ARM64_D12 = 76,
568 UNW_ARM64_D13 = 77,
569 UNW_ARM64_D14 = 78,
570 UNW_ARM64_D15 = 79,
571 UNW_ARM64_D16 = 80,
572 UNW_ARM64_D17 = 81,
573 UNW_ARM64_D18 = 82,
574 UNW_ARM64_D19 = 83,
575 UNW_ARM64_D20 = 84,
576 UNW_ARM64_D21 = 85,
577 UNW_ARM64_D22 = 86,
578 UNW_ARM64_D23 = 87,
579 UNW_ARM64_D24 = 88,
580 UNW_ARM64_D25 = 89,
581 UNW_ARM64_D26 = 90,
582 UNW_ARM64_D27 = 91,
583 UNW_ARM64_D28 = 92,
584 UNW_ARM64_D29 = 93,
585 UNW_ARM64_D30 = 94,
586 UNW_ARM64_D31 = 95,
587};
588
589// 32-bit ARM registers. Numbers match DWARF for ARM spec #3.1 Table 1.
590// Naming scheme uses recommendations given in Note 4 for VFP-v2 and VFP-v3.
591// In this scheme, even though the 64-bit floating point registers D0-D31
592// overlap physically with the 32-bit floating pointer registers S0-S31,
593// they are given a non-overlapping range of register numbers.
594//
595// Commented out ranges are not preserved during unwinding.
596enum {
597 UNW_ARM_R0 = 0,
598 UNW_ARM_R1 = 1,
599 UNW_ARM_R2 = 2,
600 UNW_ARM_R3 = 3,
601 UNW_ARM_R4 = 4,
602 UNW_ARM_R5 = 5,
603 UNW_ARM_R6 = 6,
604 UNW_ARM_R7 = 7,
605 UNW_ARM_R8 = 8,
606 UNW_ARM_R9 = 9,
607 UNW_ARM_R10 = 10,
608 UNW_ARM_R11 = 11,
609 UNW_ARM_R12 = 12,
610 UNW_ARM_SP = 13, // Logical alias for UNW_REG_SP
611 UNW_ARM_R13 = 13,
612 UNW_ARM_LR = 14,
613 UNW_ARM_R14 = 14,
614 UNW_ARM_IP = 15, // Logical alias for UNW_REG_IP
615 UNW_ARM_R15 = 15,
616 // 16-63 -- OBSOLETE. Used in VFP1 to represent both S0-S31 and D0-D31.
617 UNW_ARM_S0 = 64,
618 UNW_ARM_S1 = 65,
619 UNW_ARM_S2 = 66,
620 UNW_ARM_S3 = 67,
621 UNW_ARM_S4 = 68,
622 UNW_ARM_S5 = 69,
623 UNW_ARM_S6 = 70,
624 UNW_ARM_S7 = 71,
625 UNW_ARM_S8 = 72,
626 UNW_ARM_S9 = 73,
627 UNW_ARM_S10 = 74,
628 UNW_ARM_S11 = 75,
629 UNW_ARM_S12 = 76,
630 UNW_ARM_S13 = 77,
631 UNW_ARM_S14 = 78,
632 UNW_ARM_S15 = 79,
633 UNW_ARM_S16 = 80,
634 UNW_ARM_S17 = 81,
635 UNW_ARM_S18 = 82,
636 UNW_ARM_S19 = 83,
637 UNW_ARM_S20 = 84,
638 UNW_ARM_S21 = 85,
639 UNW_ARM_S22 = 86,
640 UNW_ARM_S23 = 87,
641 UNW_ARM_S24 = 88,
642 UNW_ARM_S25 = 89,
643 UNW_ARM_S26 = 90,
644 UNW_ARM_S27 = 91,
645 UNW_ARM_S28 = 92,
646 UNW_ARM_S29 = 93,
647 UNW_ARM_S30 = 94,
648 UNW_ARM_S31 = 95,
649 // 96-103 -- OBSOLETE. F0-F7. Used by the FPA system. Superseded by VFP.
650 // 104-111 -- wCGR0-wCGR7, ACC0-ACC7 (Intel wireless MMX)
651 UNW_ARM_WR0 = 112,
652 UNW_ARM_WR1 = 113,
653 UNW_ARM_WR2 = 114,
654 UNW_ARM_WR3 = 115,
655 UNW_ARM_WR4 = 116,
656 UNW_ARM_WR5 = 117,
657 UNW_ARM_WR6 = 118,
658 UNW_ARM_WR7 = 119,
659 UNW_ARM_WR8 = 120,
660 UNW_ARM_WR9 = 121,
661 UNW_ARM_WR10 = 122,
662 UNW_ARM_WR11 = 123,
663 UNW_ARM_WR12 = 124,
664 UNW_ARM_WR13 = 125,
665 UNW_ARM_WR14 = 126,
666 UNW_ARM_WR15 = 127,
667 // 128-133 -- SPSR, SPSR_{FIQ|IRQ|ABT|UND|SVC}
668 // 134-143 -- Reserved
669 // 144-150 -- R8_USR-R14_USR
670 // 151-157 -- R8_FIQ-R14_FIQ
671 // 158-159 -- R13_IRQ-R14_IRQ
672 // 160-161 -- R13_ABT-R14_ABT
673 // 162-163 -- R13_UND-R14_UND
674 // 164-165 -- R13_SVC-R14_SVC
675 // 166-191 -- Reserved
676 UNW_ARM_WC0 = 192,
677 UNW_ARM_WC1 = 193,
678 UNW_ARM_WC2 = 194,
679 UNW_ARM_WC3 = 195,
680 // 196-199 -- wC4-wC7 (Intel wireless MMX control)
681 // 200-255 -- Reserved
682 UNW_ARM_D0 = 256,
683 UNW_ARM_D1 = 257,
684 UNW_ARM_D2 = 258,
685 UNW_ARM_D3 = 259,
686 UNW_ARM_D4 = 260,
687 UNW_ARM_D5 = 261,
688 UNW_ARM_D6 = 262,
689 UNW_ARM_D7 = 263,
690 UNW_ARM_D8 = 264,
691 UNW_ARM_D9 = 265,
692 UNW_ARM_D10 = 266,
693 UNW_ARM_D11 = 267,
694 UNW_ARM_D12 = 268,
695 UNW_ARM_D13 = 269,
696 UNW_ARM_D14 = 270,
697 UNW_ARM_D15 = 271,
698 UNW_ARM_D16 = 272,
699 UNW_ARM_D17 = 273,
700 UNW_ARM_D18 = 274,
701 UNW_ARM_D19 = 275,
702 UNW_ARM_D20 = 276,
703 UNW_ARM_D21 = 277,
704 UNW_ARM_D22 = 278,
705 UNW_ARM_D23 = 279,
706 UNW_ARM_D24 = 280,
707 UNW_ARM_D25 = 281,
708 UNW_ARM_D26 = 282,
709 UNW_ARM_D27 = 283,
710 UNW_ARM_D28 = 284,
711 UNW_ARM_D29 = 285,
712 UNW_ARM_D30 = 286,
713 UNW_ARM_D31 = 287,
714 // 288-319 -- Reserved for VFP/Neon
715 // 320-8191 -- Reserved
716 // 8192-16383 -- Unspecified vendor co-processor register.
717};
718
719// OpenRISC1000 register numbers
720enum {
721 UNW_OR1K_R0 = 0,
722 UNW_OR1K_R1 = 1,
723 UNW_OR1K_R2 = 2,
724 UNW_OR1K_R3 = 3,
725 UNW_OR1K_R4 = 4,
726 UNW_OR1K_R5 = 5,
727 UNW_OR1K_R6 = 6,
728 UNW_OR1K_R7 = 7,
729 UNW_OR1K_R8 = 8,
730 UNW_OR1K_R9 = 9,
731 UNW_OR1K_R10 = 10,
732 UNW_OR1K_R11 = 11,
733 UNW_OR1K_R12 = 12,
734 UNW_OR1K_R13 = 13,
735 UNW_OR1K_R14 = 14,
736 UNW_OR1K_R15 = 15,
737 UNW_OR1K_R16 = 16,
738 UNW_OR1K_R17 = 17,
739 UNW_OR1K_R18 = 18,
740 UNW_OR1K_R19 = 19,
741 UNW_OR1K_R20 = 20,
742 UNW_OR1K_R21 = 21,
743 UNW_OR1K_R22 = 22,
744 UNW_OR1K_R23 = 23,
745 UNW_OR1K_R24 = 24,
746 UNW_OR1K_R25 = 25,
747 UNW_OR1K_R26 = 26,
748 UNW_OR1K_R27 = 27,
749 UNW_OR1K_R28 = 28,
750 UNW_OR1K_R29 = 29,
751 UNW_OR1K_R30 = 30,
752 UNW_OR1K_R31 = 31,
753 UNW_OR1K_EPCR = 32,
754};
755
756// MIPS registers
757enum {
758 UNW_MIPS_R0 = 0,
759 UNW_MIPS_R1 = 1,
760 UNW_MIPS_R2 = 2,
761 UNW_MIPS_R3 = 3,
762 UNW_MIPS_R4 = 4,
763 UNW_MIPS_R5 = 5,
764 UNW_MIPS_R6 = 6,
765 UNW_MIPS_R7 = 7,
766 UNW_MIPS_R8 = 8,
767 UNW_MIPS_R9 = 9,
768 UNW_MIPS_R10 = 10,
769 UNW_MIPS_R11 = 11,
770 UNW_MIPS_R12 = 12,
771 UNW_MIPS_R13 = 13,
772 UNW_MIPS_R14 = 14,
773 UNW_MIPS_R15 = 15,
774 UNW_MIPS_R16 = 16,
775 UNW_MIPS_R17 = 17,
776 UNW_MIPS_R18 = 18,
777 UNW_MIPS_R19 = 19,
778 UNW_MIPS_R20 = 20,
779 UNW_MIPS_R21 = 21,
780 UNW_MIPS_R22 = 22,
781 UNW_MIPS_R23 = 23,
782 UNW_MIPS_R24 = 24,
783 UNW_MIPS_R25 = 25,
784 UNW_MIPS_R26 = 26,
785 UNW_MIPS_R27 = 27,
786 UNW_MIPS_R28 = 28,
787 UNW_MIPS_R29 = 29,
788 UNW_MIPS_R30 = 30,
789 UNW_MIPS_R31 = 31,
790 UNW_MIPS_F0 = 32,
791 UNW_MIPS_F1 = 33,
792 UNW_MIPS_F2 = 34,
793 UNW_MIPS_F3 = 35,
794 UNW_MIPS_F4 = 36,
795 UNW_MIPS_F5 = 37,
796 UNW_MIPS_F6 = 38,
797 UNW_MIPS_F7 = 39,
798 UNW_MIPS_F8 = 40,
799 UNW_MIPS_F9 = 41,
800 UNW_MIPS_F10 = 42,
801 UNW_MIPS_F11 = 43,
802 UNW_MIPS_F12 = 44,
803 UNW_MIPS_F13 = 45,
804 UNW_MIPS_F14 = 46,
805 UNW_MIPS_F15 = 47,
806 UNW_MIPS_F16 = 48,
807 UNW_MIPS_F17 = 49,
808 UNW_MIPS_F18 = 50,
809 UNW_MIPS_F19 = 51,
810 UNW_MIPS_F20 = 52,
811 UNW_MIPS_F21 = 53,
812 UNW_MIPS_F22 = 54,
813 UNW_MIPS_F23 = 55,
814 UNW_MIPS_F24 = 56,
815 UNW_MIPS_F25 = 57,
816 UNW_MIPS_F26 = 58,
817 UNW_MIPS_F27 = 59,
818 UNW_MIPS_F28 = 60,
819 UNW_MIPS_F29 = 61,
820 UNW_MIPS_F30 = 62,
821 UNW_MIPS_F31 = 63,
822 UNW_MIPS_HI = 64,
823 UNW_MIPS_LO = 65,
824};
825
826// SPARC registers
827enum {
828 UNW_SPARC_G0 = 0,
829 UNW_SPARC_G1 = 1,
830 UNW_SPARC_G2 = 2,
831 UNW_SPARC_G3 = 3,
832 UNW_SPARC_G4 = 4,
833 UNW_SPARC_G5 = 5,
834 UNW_SPARC_G6 = 6,
835 UNW_SPARC_G7 = 7,
836 UNW_SPARC_O0 = 8,
837 UNW_SPARC_O1 = 9,
838 UNW_SPARC_O2 = 10,
839 UNW_SPARC_O3 = 11,
840 UNW_SPARC_O4 = 12,
841 UNW_SPARC_O5 = 13,
842 UNW_SPARC_O6 = 14,
843 UNW_SPARC_O7 = 15,
844 UNW_SPARC_L0 = 16,
845 UNW_SPARC_L1 = 17,
846 UNW_SPARC_L2 = 18,
847 UNW_SPARC_L3 = 19,
848 UNW_SPARC_L4 = 20,
849 UNW_SPARC_L5 = 21,
850 UNW_SPARC_L6 = 22,
851 UNW_SPARC_L7 = 23,
852 UNW_SPARC_I0 = 24,
853 UNW_SPARC_I1 = 25,
854 UNW_SPARC_I2 = 26,
855 UNW_SPARC_I3 = 27,
856 UNW_SPARC_I4 = 28,
857 UNW_SPARC_I5 = 29,
858 UNW_SPARC_I6 = 30,
859 UNW_SPARC_I7 = 31,
860};
861
862#endif
libunwind/include/mach-o/compact_unwind_encoding.h created+478
...@@ -0,0 +1,478 @@
1//===------------------ mach-o/compact_unwind_encoding.h ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Darwin's alternative to DWARF based unwind encodings.
10//
11//===----------------------------------------------------------------------===//
12
13
14#ifndef __COMPACT_UNWIND_ENCODING__
15#define __COMPACT_UNWIND_ENCODING__
16
17#include <stdint.h>
18
19//
20// Compilers can emit standard DWARF FDEs in the __TEXT,__eh_frame section
21// of object files. Or compilers can emit compact unwind information in
22// the __LD,__compact_unwind section.
23//
24// When the linker creates a final linked image, it will create a
25// __TEXT,__unwind_info section. This section is a small and fast way for the
26// runtime to access unwind info for any given function. If the compiler
27// emitted compact unwind info for the function, that compact unwind info will
28// be encoded in the __TEXT,__unwind_info section. If the compiler emitted
29// DWARF unwind info, the __TEXT,__unwind_info section will contain the offset
30// of the FDE in the __TEXT,__eh_frame section in the final linked image.
31//
32// Note: Previously, the linker would transform some DWARF unwind infos into
33// compact unwind info. But that is fragile and no longer done.
34
35
36//
37// The compact unwind endoding is a 32-bit value which encoded in an
38// architecture specific way, which registers to restore from where, and how
39// to unwind out of the function.
40//
41typedef uint32_t compact_unwind_encoding_t;
42
43
44// architecture independent bits
45enum {
46 UNWIND_IS_NOT_FUNCTION_START = 0x80000000,
47 UNWIND_HAS_LSDA = 0x40000000,
48 UNWIND_PERSONALITY_MASK = 0x30000000,
49};
50
51
52
53
54//
55// x86
56//
57// 1-bit: start
58// 1-bit: has lsda
59// 2-bit: personality index
60//
61// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=DWARF
62// ebp based:
63// 15-bits (5*3-bits per reg) register permutation
64// 8-bits for stack offset
65// frameless:
66// 8-bits stack size
67// 3-bits stack adjust
68// 3-bits register count
69// 10-bits register permutation
70//
71enum {
72 UNWIND_X86_MODE_MASK = 0x0F000000,
73 UNWIND_X86_MODE_EBP_FRAME = 0x01000000,
74 UNWIND_X86_MODE_STACK_IMMD = 0x02000000,
75 UNWIND_X86_MODE_STACK_IND = 0x03000000,
76 UNWIND_X86_MODE_DWARF = 0x04000000,
77
78 UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF,
79 UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000,
80
81 UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000,
82 UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000,
83 UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
84 UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
85
86 UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF,
87};
88
89enum {
90 UNWIND_X86_REG_NONE = 0,
91 UNWIND_X86_REG_EBX = 1,
92 UNWIND_X86_REG_ECX = 2,
93 UNWIND_X86_REG_EDX = 3,
94 UNWIND_X86_REG_EDI = 4,
95 UNWIND_X86_REG_ESI = 5,
96 UNWIND_X86_REG_EBP = 6,
97};
98
99//
100// For x86 there are four modes for the compact unwind encoding:
101// UNWIND_X86_MODE_EBP_FRAME:
102// EBP based frame where EBP is push on stack immediately after return address,
103// then ESP is moved to EBP. Thus, to unwind ESP is restored with the current
104// EPB value, then EBP is restored by popping off the stack, and the return
105// is done by popping the stack once more into the pc.
106// All non-volatile registers that need to be restored must have been saved
107// in a small range in the stack that starts EBP-4 to EBP-1020. The offset/4
108// is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits. The registers saved
109// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
110// Each entry contains which register to restore.
111// UNWIND_X86_MODE_STACK_IMMD:
112// A "frameless" (EBP not used as frame pointer) function with a small
113// constant stack size. To return, a constant (encoded in the compact
114// unwind encoding) is added to the ESP. Then the return is done by
115// popping the stack into the pc.
116// All non-volatile registers that need to be restored must have been saved
117// on the stack immediately after the return address. The stack_size/4 is
118// encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024).
119// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT.
120// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
121// saved and their order.
122// UNWIND_X86_MODE_STACK_IND:
123// A "frameless" (EBP not used as frame pointer) function large constant
124// stack size. This case is like the previous, except the stack size is too
125// large to encode in the compact unwind encoding. Instead it requires that
126// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact
127// encoding contains the offset to the nnnnnnnn value in the function in
128// UNWIND_X86_FRAMELESS_STACK_SIZE.
129// UNWIND_X86_MODE_DWARF:
130// No compact unwind encoding is available. Instead the low 24-bits of the
131// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
132// This mode is never used in object files. It is only generated by the
133// linker in final linked images which have only DWARF unwind info for a
134// function.
135//
136// The permutation encoding is a Lehmer code sequence encoded into a
137// single variable-base number so we can encode the ordering of up to
138// six registers in a 10-bit space.
139//
140// The following is the algorithm used to create the permutation encoding used
141// with frameless stacks. It is passed the number of registers to be saved and
142// an array of the register numbers saved.
143//
144//uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6])
145//{
146// uint32_t renumregs[6];
147// for (int i=6-registerCount; i < 6; ++i) {
148// int countless = 0;
149// for (int j=6-registerCount; j < i; ++j) {
150// if ( registers[j] < registers[i] )
151// ++countless;
152// }
153// renumregs[i] = registers[i] - countless -1;
154// }
155// uint32_t permutationEncoding = 0;
156// switch ( registerCount ) {
157// case 6:
158// permutationEncoding |= (120*renumregs[0] + 24*renumregs[1]
159// + 6*renumregs[2] + 2*renumregs[3]
160// + renumregs[4]);
161// break;
162// case 5:
163// permutationEncoding |= (120*renumregs[1] + 24*renumregs[2]
164// + 6*renumregs[3] + 2*renumregs[4]
165// + renumregs[5]);
166// break;
167// case 4:
168// permutationEncoding |= (60*renumregs[2] + 12*renumregs[3]
169// + 3*renumregs[4] + renumregs[5]);
170// break;
171// case 3:
172// permutationEncoding |= (20*renumregs[3] + 4*renumregs[4]
173// + renumregs[5]);
174// break;
175// case 2:
176// permutationEncoding |= (5*renumregs[4] + renumregs[5]);
177// break;
178// case 1:
179// permutationEncoding |= (renumregs[5]);
180// break;
181// }
182// return permutationEncoding;
183//}
184//
185
186
187
188
189//
190// x86_64
191//
192// 1-bit: start
193// 1-bit: has lsda
194// 2-bit: personality index
195//
196// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=DWARF
197// rbp based:
198// 15-bits (5*3-bits per reg) register permutation
199// 8-bits for stack offset
200// frameless:
201// 8-bits stack size
202// 3-bits stack adjust
203// 3-bits register count
204// 10-bits register permutation
205//
206enum {
207 UNWIND_X86_64_MODE_MASK = 0x0F000000,
208 UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000,
209 UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000,
210 UNWIND_X86_64_MODE_STACK_IND = 0x03000000,
211 UNWIND_X86_64_MODE_DWARF = 0x04000000,
212
213 UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF,
214 UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000,
215
216 UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000,
217 UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000,
218 UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
219 UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
220
221 UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
222};
223
224enum {
225 UNWIND_X86_64_REG_NONE = 0,
226 UNWIND_X86_64_REG_RBX = 1,
227 UNWIND_X86_64_REG_R12 = 2,
228 UNWIND_X86_64_REG_R13 = 3,
229 UNWIND_X86_64_REG_R14 = 4,
230 UNWIND_X86_64_REG_R15 = 5,
231 UNWIND_X86_64_REG_RBP = 6,
232};
233//
234// For x86_64 there are four modes for the compact unwind encoding:
235// UNWIND_X86_64_MODE_RBP_FRAME:
236// RBP based frame where RBP is push on stack immediately after return address,
237// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
238// EPB value, then RBP is restored by popping off the stack, and the return
239// is done by popping the stack once more into the pc.
240// All non-volatile registers that need to be restored must have been saved
241// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8
242// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved
243// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
244// Each entry contains which register to restore.
245// UNWIND_X86_64_MODE_STACK_IMMD:
246// A "frameless" (RBP not used as frame pointer) function with a small
247// constant stack size. To return, a constant (encoded in the compact
248// unwind encoding) is added to the RSP. Then the return is done by
249// popping the stack into the pc.
250// All non-volatile registers that need to be restored must have been saved
251// on the stack immediately after the return address. The stack_size/8 is
252// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
253// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
254// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
255// saved and their order.
256// UNWIND_X86_64_MODE_STACK_IND:
257// A "frameless" (RBP not used as frame pointer) function large constant
258// stack size. This case is like the previous, except the stack size is too
259// large to encode in the compact unwind encoding. Instead it requires that
260// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact
261// encoding contains the offset to the nnnnnnnn value in the function in
262// UNWIND_X86_64_FRAMELESS_STACK_SIZE.
263// UNWIND_X86_64_MODE_DWARF:
264// No compact unwind encoding is available. Instead the low 24-bits of the
265// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
266// This mode is never used in object files. It is only generated by the
267// linker in final linked images which have only DWARF unwind info for a
268// function.
269//
270
271
272// ARM64
273//
274// 1-bit: start
275// 1-bit: has lsda
276// 2-bit: personality index
277//
278// 4-bits: 4=frame-based, 3=DWARF, 2=frameless
279// frameless:
280// 12-bits of stack size
281// frame-based:
282// 4-bits D reg pairs saved
283// 5-bits X reg pairs saved
284// DWARF:
285// 24-bits offset of DWARF FDE in __eh_frame section
286//
287enum {
288 UNWIND_ARM64_MODE_MASK = 0x0F000000,
289 UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
290 UNWIND_ARM64_MODE_DWARF = 0x03000000,
291 UNWIND_ARM64_MODE_FRAME = 0x04000000,
292
293 UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
294 UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
295 UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
296 UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
297 UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
298 UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
299 UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
300 UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
301 UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800,
302
303 UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000,
304 UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
305};
306// For arm64 there are three modes for the compact unwind encoding:
307// UNWIND_ARM64_MODE_FRAME:
308// This is a standard arm64 prolog where FP/LR are immediately pushed on the
309// stack, then SP is copied to FP. If there are any non-volatile registers
310// saved, then are copied into the stack frame in pairs in a contiguous
311// range right below the saved FP/LR pair. Any subset of the five X pairs
312// and four D pairs can be saved, but the memory layout must be in register
313// number order.
314// UNWIND_ARM64_MODE_FRAMELESS:
315// A "frameless" leaf function, where FP/LR are not saved. The return address
316// remains in LR throughout the function. If any non-volatile registers
317// are saved, they must be pushed onto the stack before any stack space is
318// allocated for local variables. The stack sized (including any saved
319// non-volatile registers) divided by 16 is encoded in the bits
320// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
321// UNWIND_ARM64_MODE_DWARF:
322// No compact unwind encoding is available. Instead the low 24-bits of the
323// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
324// This mode is never used in object files. It is only generated by the
325// linker in final linked images which have only DWARF unwind info for a
326// function.
327//
328
329
330
331
332
333////////////////////////////////////////////////////////////////////////////////
334//
335// Relocatable Object Files: __LD,__compact_unwind
336//
337////////////////////////////////////////////////////////////////////////////////
338
339//
340// A compiler can generated compact unwind information for a function by adding
341// a "row" to the __LD,__compact_unwind section. This section has the
342// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
343// It is removed by the new linker, so never ends up in final executables.
344// This section is a table, initially with one row per function (that needs
345// unwind info). The table columns and some conceptual entries are:
346//
347// range-start pointer to start of function/range
348// range-length
349// compact-unwind-encoding 32-bit encoding
350// personality-function or zero if no personality function
351// lsda or zero if no LSDA data
352//
353// The length and encoding fields are 32-bits. The other are all pointer sized.
354//
355// In x86_64 assembly, these entry would look like:
356//
357// .section __LD,__compact_unwind,regular,debug
358//
359// #compact unwind for _foo
360// .quad _foo
361// .set L1,LfooEnd-_foo
362// .long L1
363// .long 0x01010001
364// .quad 0
365// .quad 0
366//
367// #compact unwind for _bar
368// .quad _bar
369// .set L2,LbarEnd-_bar
370// .long L2
371// .long 0x01020011
372// .quad __gxx_personality
373// .quad except_tab1
374//
375//
376// Notes: There is no need for any labels in the the __compact_unwind section.
377// The use of the .set directive is to force the evaluation of the
378// range-length at assembly time, instead of generating relocations.
379//
380// To support future compiler optimizations where which non-volatile registers
381// are saved changes within a function (e.g. delay saving non-volatiles until
382// necessary), there can by multiple lines in the __compact_unwind table for one
383// function, each with a different (non-overlapping) range and each with
384// different compact unwind encodings that correspond to the non-volatiles
385// saved at that range of the function.
386//
387// If a particular function is so wacky that there is no compact unwind way
388// to encode it, then the compiler can emit traditional DWARF unwind info.
389// The runtime will use which ever is available.
390//
391// Runtime support for compact unwind encodings are only available on 10.6
392// and later. So, the compiler should not generate it when targeting pre-10.6.
393
394
395
396
397////////////////////////////////////////////////////////////////////////////////
398//
399// Final Linked Images: __TEXT,__unwind_info
400//
401////////////////////////////////////////////////////////////////////////////////
402
403//
404// The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
405// The header of the section contains a coarse index that maps function address
406// to the page (4096 byte block) containing the unwind info for that function.
407//
408
409#define UNWIND_SECTION_VERSION 1
410struct unwind_info_section_header
411{
412 uint32_t version; // UNWIND_SECTION_VERSION
413 uint32_t commonEncodingsArraySectionOffset;
414 uint32_t commonEncodingsArrayCount;
415 uint32_t personalityArraySectionOffset;
416 uint32_t personalityArrayCount;
417 uint32_t indexSectionOffset;
418 uint32_t indexCount;
419 // compact_unwind_encoding_t[]
420 // uint32_t personalities[]
421 // unwind_info_section_header_index_entry[]
422 // unwind_info_section_header_lsda_index_entry[]
423};
424
425struct unwind_info_section_header_index_entry
426{
427 uint32_t functionOffset;
428 uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page
429 uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range
430};
431
432struct unwind_info_section_header_lsda_index_entry
433{
434 uint32_t functionOffset;
435 uint32_t lsdaOffset;
436};
437
438//
439// There are two kinds of second level index pages: regular and compressed.
440// A compressed page can hold up to 1021 entries, but it cannot be used
441// if too many different encoding types are used. The regular page holds
442// 511 entries.
443//
444
445struct unwind_info_regular_second_level_entry
446{
447 uint32_t functionOffset;
448 compact_unwind_encoding_t encoding;
449};
450
451#define UNWIND_SECOND_LEVEL_REGULAR 2
452struct unwind_info_regular_second_level_page_header
453{
454 uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR
455 uint16_t entryPageOffset;
456 uint16_t entryCount;
457 // entry array
458};
459
460#define UNWIND_SECOND_LEVEL_COMPRESSED 3
461struct unwind_info_compressed_second_level_page_header
462{
463 uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED
464 uint16_t entryPageOffset;
465 uint16_t entryCount;
466 uint16_t encodingsPageOffset;
467 uint16_t encodingsCount;
468 // 32-bit entry array
469 // encodings array
470};
471
472#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF)
473#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF)
474
475
476
477#endif
478
libunwind/include/unwind.h created+401
...@@ -0,0 +1,401 @@
1//===------------------------------- unwind.h -----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// C++ ABI Level 1 ABI documented at:
10// http://mentorembedded.github.io/cxx-abi/abi-eh.html
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef __UNWIND_H__
15#define __UNWIND_H__
16
17#include <__libunwind_config.h>
18
19#include <stdint.h>
20#include <stddef.h>
21
22#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) && defined(_WIN32)
23#include <windows.h>
24#include <ntverp.h>
25#endif
26
27#if defined(__APPLE__)
28#define LIBUNWIND_UNAVAIL __attribute__ (( unavailable ))
29#else
30#define LIBUNWIND_UNAVAIL
31#endif
32
33typedef enum {
34 _URC_NO_REASON = 0,
35 _URC_OK = 0,
36 _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
37 _URC_FATAL_PHASE2_ERROR = 2,
38 _URC_FATAL_PHASE1_ERROR = 3,
39 _URC_NORMAL_STOP = 4,
40 _URC_END_OF_STACK = 5,
41 _URC_HANDLER_FOUND = 6,
42 _URC_INSTALL_CONTEXT = 7,
43 _URC_CONTINUE_UNWIND = 8,
44#if defined(_LIBUNWIND_ARM_EHABI)
45 _URC_FAILURE = 9
46#endif
47} _Unwind_Reason_Code;
48
49typedef enum {
50 _UA_SEARCH_PHASE = 1,
51 _UA_CLEANUP_PHASE = 2,
52 _UA_HANDLER_FRAME = 4,
53 _UA_FORCE_UNWIND = 8,
54 _UA_END_OF_STACK = 16 // gcc extension to C++ ABI
55} _Unwind_Action;
56
57typedef struct _Unwind_Context _Unwind_Context; // opaque
58
59#if defined(_LIBUNWIND_ARM_EHABI)
60typedef uint32_t _Unwind_State;
61
62static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0;
63static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1;
64static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2;
65static const _Unwind_State _US_ACTION_MASK = 3;
66/* Undocumented flag for force unwinding. */
67static const _Unwind_State _US_FORCE_UNWIND = 8;
68
69typedef uint32_t _Unwind_EHT_Header;
70
71struct _Unwind_Control_Block;
72typedef struct _Unwind_Control_Block _Unwind_Control_Block;
73typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */
74
75struct _Unwind_Control_Block {
76 uint64_t exception_class;
77 void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*);
78
79 /* Unwinder cache, private fields for the unwinder's use */
80 struct {
81 uint32_t reserved1; /* init reserved1 to 0, then don't touch */
82 uint32_t reserved2;
83 uint32_t reserved3;
84 uint32_t reserved4;
85 uint32_t reserved5;
86 } unwinder_cache;
87
88 /* Propagation barrier cache (valid after phase 1): */
89 struct {
90 uint32_t sp;
91 uint32_t bitpattern[5];
92 } barrier_cache;
93
94 /* Cleanup cache (preserved over cleanup): */
95 struct {
96 uint32_t bitpattern[4];
97 } cleanup_cache;
98
99 /* Pr cache (for pr's benefit): */
100 struct {
101 uint32_t fnstart; /* function start address */
102 _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */
103 uint32_t additional;
104 uint32_t reserved1;
105 } pr_cache;
106
107 long long int :0; /* Enforce the 8-byte alignment */
108} __attribute__((__aligned__(8)));
109
110typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
111 (_Unwind_State state,
112 _Unwind_Exception* exceptionObject,
113 struct _Unwind_Context* context);
114
115typedef _Unwind_Reason_Code (*__personality_routine)
116 (_Unwind_State state,
117 _Unwind_Exception* exceptionObject,
118 struct _Unwind_Context* context);
119#else
120struct _Unwind_Context; // opaque
121struct _Unwind_Exception; // forward declaration
122typedef struct _Unwind_Exception _Unwind_Exception;
123
124struct _Unwind_Exception {
125 uint64_t exception_class;
126 void (*exception_cleanup)(_Unwind_Reason_Code reason,
127 _Unwind_Exception *exc);
128#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
129 uintptr_t private_[6];
130#else
131 uintptr_t private_1; // non-zero means forced unwind
132 uintptr_t private_2; // holds sp that phase1 found for phase2 to use
133#endif
134#if __SIZEOF_POINTER__ == 4
135 // The implementation of _Unwind_Exception uses an attribute mode on the
136 // above fields which has the side effect of causing this whole struct to
137 // round up to 32 bytes in size (48 with SEH). To be more explicit, we add
138 // pad fields added for binary compatibility.
139 uint32_t reserved[3];
140#endif
141 // The Itanium ABI requires that _Unwind_Exception objects are "double-word
142 // aligned". GCC has interpreted this to mean "use the maximum useful
143 // alignment for the target"; so do we.
144} __attribute__((__aligned__));
145
146typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
147 (int version,
148 _Unwind_Action actions,
149 uint64_t exceptionClass,
150 _Unwind_Exception* exceptionObject,
151 struct _Unwind_Context* context,
152 void* stop_parameter );
153
154typedef _Unwind_Reason_Code (*__personality_routine)
155 (int version,
156 _Unwind_Action actions,
157 uint64_t exceptionClass,
158 _Unwind_Exception* exceptionObject,
159 struct _Unwind_Context* context);
160#endif
161
162#ifdef __cplusplus
163extern "C" {
164#endif
165
166//
167// The following are the base functions documented by the C++ ABI
168//
169#ifdef __USING_SJLJ_EXCEPTIONS__
170extern _Unwind_Reason_Code
171 _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object);
172extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object);
173#else
174extern _Unwind_Reason_Code
175 _Unwind_RaiseException(_Unwind_Exception *exception_object);
176extern void _Unwind_Resume(_Unwind_Exception *exception_object);
177#endif
178extern void _Unwind_DeleteException(_Unwind_Exception *exception_object);
179
180#if defined(_LIBUNWIND_ARM_EHABI)
181typedef enum {
182 _UVRSC_CORE = 0, /* integer register */
183 _UVRSC_VFP = 1, /* vfp */
184 _UVRSC_WMMXD = 3, /* Intel WMMX data register */
185 _UVRSC_WMMXC = 4 /* Intel WMMX control register */
186} _Unwind_VRS_RegClass;
187
188typedef enum {
189 _UVRSD_UINT32 = 0,
190 _UVRSD_VFPX = 1,
191 _UVRSD_UINT64 = 3,
192 _UVRSD_FLOAT = 4,
193 _UVRSD_DOUBLE = 5
194} _Unwind_VRS_DataRepresentation;
195
196typedef enum {
197 _UVRSR_OK = 0,
198 _UVRSR_NOT_IMPLEMENTED = 1,
199 _UVRSR_FAILED = 2
200} _Unwind_VRS_Result;
201
202extern void _Unwind_Complete(_Unwind_Exception* exception_object);
203
204extern _Unwind_VRS_Result
205_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
206 uint32_t regno, _Unwind_VRS_DataRepresentation representation,
207 void *valuep);
208
209extern _Unwind_VRS_Result
210_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
211 uint32_t regno, _Unwind_VRS_DataRepresentation representation,
212 void *valuep);
213
214extern _Unwind_VRS_Result
215_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
216 uint32_t discriminator,
217 _Unwind_VRS_DataRepresentation representation);
218#endif
219
220#if !defined(_LIBUNWIND_ARM_EHABI)
221
222extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index);
223extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
224 uintptr_t new_value);
225extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
226extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value);
227
228#else // defined(_LIBUNWIND_ARM_EHABI)
229
230#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)
231#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern
232#else
233#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__
234#endif
235
236// These are de facto helper functions for ARM, which delegate the function
237// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI
238// specification, thus these function MUST be inlined. Please don't replace
239// these with the "extern" function declaration; otherwise, the program
240// including this <unwind.h> header won't be ABI compatible and will result in
241// link error when we are linking the program with libgcc.
242
243_LIBUNWIND_EXPORT_UNWIND_LEVEL1
244uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
245 uintptr_t value = 0;
246 _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
247 return value;
248}
249
250_LIBUNWIND_EXPORT_UNWIND_LEVEL1
251void _Unwind_SetGR(struct _Unwind_Context *context, int index,
252 uintptr_t value) {
253 _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
254}
255
256_LIBUNWIND_EXPORT_UNWIND_LEVEL1
257uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
258 // remove the thumb-bit before returning
259 return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1);
260}
261
262_LIBUNWIND_EXPORT_UNWIND_LEVEL1
263void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) {
264 uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
265 _Unwind_SetGR(context, 15, value | thumb_bit);
266}
267#endif // defined(_LIBUNWIND_ARM_EHABI)
268
269extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context);
270extern uintptr_t
271 _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context);
272#ifdef __USING_SJLJ_EXCEPTIONS__
273extern _Unwind_Reason_Code
274 _Unwind_SjLj_ForcedUnwind(_Unwind_Exception *exception_object,
275 _Unwind_Stop_Fn stop, void *stop_parameter);
276#else
277extern _Unwind_Reason_Code
278 _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
279 _Unwind_Stop_Fn stop, void *stop_parameter);
280#endif
281
282#ifdef __USING_SJLJ_EXCEPTIONS__
283typedef struct _Unwind_FunctionContext *_Unwind_FunctionContext_t;
284extern void _Unwind_SjLj_Register(_Unwind_FunctionContext_t fc);
285extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc);
286#endif
287
288//
289// The following are semi-suppoted extensions to the C++ ABI
290//
291
292//
293// called by __cxa_rethrow().
294//
295#ifdef __USING_SJLJ_EXCEPTIONS__
296extern _Unwind_Reason_Code
297 _Unwind_SjLj_Resume_or_Rethrow(_Unwind_Exception *exception_object);
298#else
299extern _Unwind_Reason_Code
300 _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object);
301#endif
302
303// _Unwind_Backtrace() is a gcc extension that walks the stack and calls the
304// _Unwind_Trace_Fn once per frame until it reaches the bottom of the stack
305// or the _Unwind_Trace_Fn function returns something other than _URC_NO_REASON.
306typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *,
307 void *);
308extern _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn, void *);
309
310// _Unwind_GetCFA is a gcc extension that can be called from within a
311// personality handler to get the CFA (stack pointer before call) of
312// current frame.
313extern uintptr_t _Unwind_GetCFA(struct _Unwind_Context *);
314
315
316// _Unwind_GetIPInfo is a gcc extension that can be called from within a
317// personality handler. Similar to _Unwind_GetIP() but also returns in
318// *ipBefore a non-zero value if the instruction pointer is at or before the
319// instruction causing the unwind. Normally, in a function call, the IP returned
320// is the return address which is after the call instruction and may be past the
321// end of the function containing the call instruction.
322extern uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
323 int *ipBefore);
324
325
326// __register_frame() is used with dynamically generated code to register the
327// FDE for a generated (JIT) code. The FDE must use pc-rel addressing to point
328// to its function and optional LSDA.
329// __register_frame() has existed in all versions of Mac OS X, but in 10.4 and
330// 10.5 it was buggy and did not actually register the FDE with the unwinder.
331// In 10.6 and later it does register properly.
332extern void __register_frame(const void *fde);
333extern void __deregister_frame(const void *fde);
334
335// _Unwind_Find_FDE() will locate the FDE if the pc is in some function that has
336// an associated FDE. Note, Mac OS X 10.6 and later, introduces "compact unwind
337// info" which the runtime uses in preference to DWARF unwind info. This
338// function will only work if the target function has an FDE but no compact
339// unwind info.
340struct dwarf_eh_bases {
341 uintptr_t tbase;
342 uintptr_t dbase;
343 uintptr_t func;
344};
345extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *);
346
347
348// This function attempts to find the start (address of first instruction) of
349// a function given an address inside the function. It only works if the
350// function has an FDE (DWARF unwind info).
351// This function is unimplemented on Mac OS X 10.6 and later. Instead, use
352// _Unwind_Find_FDE() and look at the dwarf_eh_bases.func result.
353extern void *_Unwind_FindEnclosingFunction(void *pc);
354
355// Mac OS X does not support text-rel and data-rel addressing so these functions
356// are unimplemented
357extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context)
358 LIBUNWIND_UNAVAIL;
359extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context)
360 LIBUNWIND_UNAVAIL;
361
362// Mac OS X 10.4 and 10.5 had implementations of these functions in
363// libgcc_s.dylib, but they never worked.
364/// These functions are no longer available on Mac OS X.
365extern void __register_frame_info_bases(const void *fde, void *ob, void *tb,
366 void *db) LIBUNWIND_UNAVAIL;
367extern void __register_frame_info(const void *fde, void *ob)
368 LIBUNWIND_UNAVAIL;
369extern void __register_frame_info_table_bases(const void *fde, void *ob,
370 void *tb, void *db)
371 LIBUNWIND_UNAVAIL;
372extern void __register_frame_info_table(const void *fde, void *ob)
373 LIBUNWIND_UNAVAIL;
374extern void __register_frame_table(const void *fde)
375 LIBUNWIND_UNAVAIL;
376extern void *__deregister_frame_info(const void *fde)
377 LIBUNWIND_UNAVAIL;
378extern void *__deregister_frame_info_bases(const void *fde)
379 LIBUNWIND_UNAVAIL;
380
381#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
382#ifndef _WIN32
383typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD;
384typedef struct _CONTEXT CONTEXT;
385typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT;
386#elif !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
387typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT;
388#endif
389// This is the common wrapper for GCC-style personality functions with SEH.
390extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc,
391 void *frame,
392 CONTEXT *ctx,
393 DISPATCHER_CONTEXT *disp,
394 __personality_routine pers);
395#endif
396
397#ifdef __cplusplus
398}
399#endif
400
401#endif // __UNWIND_H__
libunwind/src/AddressSpace.hpp created+738
...@@ -0,0 +1,738 @@
1//===------------------------- AddressSpace.hpp ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Abstracts accessing local vs remote address spaces.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef __ADDRESSSPACE_HPP__
14#define __ADDRESSSPACE_HPP__
15
16#include <stdint.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#ifndef _LIBUNWIND_USE_DLADDR
22 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
23 #define _LIBUNWIND_USE_DLADDR 1
24 #else
25 #define _LIBUNWIND_USE_DLADDR 0
26 #endif
27#endif
28
29#if _LIBUNWIND_USE_DLADDR
30#include <dlfcn.h>
31#endif
32
33#ifdef __APPLE__
34#include <mach-o/getsect.h>
35namespace libunwind {
36 bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde);
37}
38#endif
39
40#include "libunwind.h"
41#include "config.h"
42#include "dwarf2.h"
43#include "EHHeaderParser.hpp"
44#include "Registers.hpp"
45
46#ifdef __APPLE__
47
48 struct dyld_unwind_sections
49 {
50 const struct mach_header* mh;
51 const void* dwarf_section;
52 uintptr_t dwarf_section_length;
53 const void* compact_unwind_section;
54 uintptr_t compact_unwind_section_length;
55 };
56 #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \
57 && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \
58 || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
59 // In 10.7.0 or later, libSystem.dylib implements this function.
60 extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
61 #else
62 // In 10.6.x and earlier, we need to implement this functionality. Note
63 // that this requires a newer version of libmacho (from cctools) than is
64 // present in libSystem on 10.6.x (for getsectiondata).
65 static inline bool _dyld_find_unwind_sections(void* addr,
66 dyld_unwind_sections* info) {
67 // Find mach-o image containing address.
68 Dl_info dlinfo;
69 if (!dladdr(addr, &dlinfo))
70 return false;
71#if __LP64__
72 const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase;
73#else
74 const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase;
75#endif
76
77 // Initialize the return struct
78 info->mh = (const struct mach_header *)mh;
79 info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length);
80 info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length);
81
82 if (!info->dwarf_section) {
83 info->dwarf_section_length = 0;
84 }
85
86 if (!info->compact_unwind_section) {
87 info->compact_unwind_section_length = 0;
88 }
89
90 return true;
91 }
92 #endif
93
94#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
95
96// When statically linked on bare-metal, the symbols for the EH table are looked
97// up without going through the dynamic loader.
98
99// The following linker script may be used to produce the necessary sections and symbols.
100// Unless the --eh-frame-hdr linker option is provided, the section is not generated
101// and does not take space in the output file.
102//
103// .eh_frame :
104// {
105// __eh_frame_start = .;
106// KEEP(*(.eh_frame))
107// __eh_frame_end = .;
108// }
109//
110// .eh_frame_hdr :
111// {
112// KEEP(*(.eh_frame_hdr))
113// }
114//
115// __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
116// __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
117
118extern char __eh_frame_start;
119extern char __eh_frame_end;
120
121#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
122extern char __eh_frame_hdr_start;
123extern char __eh_frame_hdr_end;
124#endif
125
126#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
127
128// When statically linked on bare-metal, the symbols for the EH table are looked
129// up without going through the dynamic loader.
130extern char __exidx_start;
131extern char __exidx_end;
132
133#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
134
135// ELF-based systems may use dl_iterate_phdr() to access sections
136// containing unwinding information. The ElfW() macro for pointer-size
137// independent ELF header traversal is not provided by <link.h> on some
138// systems (e.g., FreeBSD). On these systems the data structures are
139// just called Elf_XXX. Define ElfW() locally.
140#ifndef _WIN32
141#include <link.h>
142#else
143#include <windows.h>
144#include <psapi.h>
145#endif
146#if !defined(ElfW)
147#define ElfW(type) Elf_##type
148#endif
149
150#endif
151
152namespace libunwind {
153
154/// Used by findUnwindSections() to return info about needed sections.
155struct UnwindInfoSections {
156#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \
157 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
158 // No dso_base for SEH or ARM EHABI.
159 uintptr_t dso_base;
160#endif
161#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
162 uintptr_t dwarf_section;
163 uintptr_t dwarf_section_length;
164#endif
165#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
166 uintptr_t dwarf_index_section;
167 uintptr_t dwarf_index_section_length;
168#endif
169#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
170 uintptr_t compact_unwind_section;
171 uintptr_t compact_unwind_section_length;
172#endif
173#if defined(_LIBUNWIND_ARM_EHABI)
174 uintptr_t arm_section;
175 uintptr_t arm_section_length;
176#endif
177};
178
179
180/// LocalAddressSpace is used as a template parameter to UnwindCursor when
181/// unwinding a thread in the same process. The wrappers compile away,
182/// making local unwinds fast.
183class _LIBUNWIND_HIDDEN LocalAddressSpace {
184public:
185 typedef uintptr_t pint_t;
186 typedef intptr_t sint_t;
187 uint8_t get8(pint_t addr) {
188 uint8_t val;
189 memcpy(&val, (void *)addr, sizeof(val));
190 return val;
191 }
192 uint16_t get16(pint_t addr) {
193 uint16_t val;
194 memcpy(&val, (void *)addr, sizeof(val));
195 return val;
196 }
197 uint32_t get32(pint_t addr) {
198 uint32_t val;
199 memcpy(&val, (void *)addr, sizeof(val));
200 return val;
201 }
202 uint64_t get64(pint_t addr) {
203 uint64_t val;
204 memcpy(&val, (void *)addr, sizeof(val));
205 return val;
206 }
207 double getDouble(pint_t addr) {
208 double val;
209 memcpy(&val, (void *)addr, sizeof(val));
210 return val;
211 }
212 v128 getVector(pint_t addr) {
213 v128 val;
214 memcpy(&val, (void *)addr, sizeof(val));
215 return val;
216 }
217 uintptr_t getP(pint_t addr);
218 uint64_t getRegister(pint_t addr);
219 static uint64_t getULEB128(pint_t &addr, pint_t end);
220 static int64_t getSLEB128(pint_t &addr, pint_t end);
221
222 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
223 pint_t datarelBase = 0);
224 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
225 unw_word_t *offset);
226 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
227 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
228
229 static LocalAddressSpace sThisAddressSpace;
230};
231
232inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
233#if __SIZEOF_POINTER__ == 8
234 return get64(addr);
235#else
236 return get32(addr);
237#endif
238}
239
240inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
241#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
242 return get64(addr);
243#else
244 return get32(addr);
245#endif
246}
247
248/// Read a ULEB128 into a 64-bit word.
249inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
250 const uint8_t *p = (uint8_t *)addr;
251 const uint8_t *pend = (uint8_t *)end;
252 uint64_t result = 0;
253 int bit = 0;
254 do {
255 uint64_t b;
256
257 if (p == pend)
258 _LIBUNWIND_ABORT("truncated uleb128 expression");
259
260 b = *p & 0x7f;
261
262 if (bit >= 64 || b << bit >> bit != b) {
263 _LIBUNWIND_ABORT("malformed uleb128 expression");
264 } else {
265 result |= b << bit;
266 bit += 7;
267 }
268 } while (*p++ >= 0x80);
269 addr = (pint_t) p;
270 return result;
271}
272
273/// Read a SLEB128 into a 64-bit word.
274inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
275 const uint8_t *p = (uint8_t *)addr;
276 const uint8_t *pend = (uint8_t *)end;
277 int64_t result = 0;
278 int bit = 0;
279 uint8_t byte;
280 do {
281 if (p == pend)
282 _LIBUNWIND_ABORT("truncated sleb128 expression");
283 byte = *p++;
284 result |= ((byte & 0x7f) << bit);
285 bit += 7;
286 } while (byte & 0x80);
287 // sign extend negative numbers
288 if ((byte & 0x40) != 0)
289 result |= (-1ULL) << bit;
290 addr = (pint_t) p;
291 return result;
292}
293
294inline LocalAddressSpace::pint_t
295LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
296 pint_t datarelBase) {
297 pint_t startAddr = addr;
298 const uint8_t *p = (uint8_t *)addr;
299 pint_t result;
300
301 // first get value
302 switch (encoding & 0x0F) {
303 case DW_EH_PE_ptr:
304 result = getP(addr);
305 p += sizeof(pint_t);
306 addr = (pint_t) p;
307 break;
308 case DW_EH_PE_uleb128:
309 result = (pint_t)getULEB128(addr, end);
310 break;
311 case DW_EH_PE_udata2:
312 result = get16(addr);
313 p += 2;
314 addr = (pint_t) p;
315 break;
316 case DW_EH_PE_udata4:
317 result = get32(addr);
318 p += 4;
319 addr = (pint_t) p;
320 break;
321 case DW_EH_PE_udata8:
322 result = (pint_t)get64(addr);
323 p += 8;
324 addr = (pint_t) p;
325 break;
326 case DW_EH_PE_sleb128:
327 result = (pint_t)getSLEB128(addr, end);
328 break;
329 case DW_EH_PE_sdata2:
330 // Sign extend from signed 16-bit value.
331 result = (pint_t)(int16_t)get16(addr);
332 p += 2;
333 addr = (pint_t) p;
334 break;
335 case DW_EH_PE_sdata4:
336 // Sign extend from signed 32-bit value.
337 result = (pint_t)(int32_t)get32(addr);
338 p += 4;
339 addr = (pint_t) p;
340 break;
341 case DW_EH_PE_sdata8:
342 result = (pint_t)get64(addr);
343 p += 8;
344 addr = (pint_t) p;
345 break;
346 default:
347 _LIBUNWIND_ABORT("unknown pointer encoding");
348 }
349
350 // then add relative offset
351 switch (encoding & 0x70) {
352 case DW_EH_PE_absptr:
353 // do nothing
354 break;
355 case DW_EH_PE_pcrel:
356 result += startAddr;
357 break;
358 case DW_EH_PE_textrel:
359 _LIBUNWIND_ABORT("DW_EH_PE_textrel pointer encoding not supported");
360 break;
361 case DW_EH_PE_datarel:
362 // DW_EH_PE_datarel is only valid in a few places, so the parameter has a
363 // default value of 0, and we abort in the event that someone calls this
364 // function with a datarelBase of 0 and DW_EH_PE_datarel encoding.
365 if (datarelBase == 0)
366 _LIBUNWIND_ABORT("DW_EH_PE_datarel is invalid with a datarelBase of 0");
367 result += datarelBase;
368 break;
369 case DW_EH_PE_funcrel:
370 _LIBUNWIND_ABORT("DW_EH_PE_funcrel pointer encoding not supported");
371 break;
372 case DW_EH_PE_aligned:
373 _LIBUNWIND_ABORT("DW_EH_PE_aligned pointer encoding not supported");
374 break;
375 default:
376 _LIBUNWIND_ABORT("unknown pointer encoding");
377 break;
378 }
379
380 if (encoding & DW_EH_PE_indirect)
381 result = getP(result);
382
383 return result;
384}
385
386inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
387 UnwindInfoSections &info) {
388#ifdef __APPLE__
389 dyld_unwind_sections dyldInfo;
390 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
391 info.dso_base = (uintptr_t)dyldInfo.mh;
392 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
393 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section;
394 info.dwarf_section_length = dyldInfo.dwarf_section_length;
395 #endif
396 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section;
397 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
398 return true;
399 }
400#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
401 // Bare metal is statically linked, so no need to ask the dynamic loader
402 info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start);
403 info.dwarf_section = (uintptr_t)(&__eh_frame_start);
404 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
405 (void *)info.dwarf_section, (void *)info.dwarf_section_length);
406#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
407 info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start);
408 info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start);
409 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p",
410 (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length);
411#endif
412 if (info.dwarf_section_length)
413 return true;
414#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL)
415 // Bare metal is statically linked, so no need to ask the dynamic loader
416 info.arm_section = (uintptr_t)(&__exidx_start);
417 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start);
418 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p",
419 (void *)info.arm_section, (void *)info.arm_section_length);
420 if (info.arm_section && info.arm_section_length)
421 return true;
422#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
423 HMODULE mods[1024];
424 HANDLE process = GetCurrentProcess();
425 DWORD needed;
426
427 if (!EnumProcessModules(process, mods, sizeof(mods), &needed))
428 return false;
429
430 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) {
431 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i];
432 PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE *)pidh + pidh->e_lfanew);
433 PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
434 PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh);
435 bool found_obj = false;
436 bool found_hdr = false;
437
438 info.dso_base = (uintptr_t)mods[i];
439 for (unsigned j = 0; j < pifh->NumberOfSections; j++, pish++) {
440 uintptr_t begin = pish->VirtualAddress + (uintptr_t)mods[i];
441 uintptr_t end = begin + pish->Misc.VirtualSize;
442 if (!strncmp((const char *)pish->Name, ".text",
443 IMAGE_SIZEOF_SHORT_NAME)) {
444 if (targetAddr >= begin && targetAddr < end)
445 found_obj = true;
446 } else if (!strncmp((const char *)pish->Name, ".eh_frame",
447 IMAGE_SIZEOF_SHORT_NAME)) {
448 info.dwarf_section = begin;
449 info.dwarf_section_length = pish->Misc.VirtualSize;
450 found_hdr = true;
451 }
452 if (found_obj && found_hdr)
453 return true;
454 }
455 }
456 return false;
457#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
458 // Don't even bother, since Windows has functions that do all this stuff
459 // for us.
460 return true;
461#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \
462 (__ANDROID_API__ < 21)
463 int length = 0;
464 info.arm_section =
465 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length);
466 info.arm_section_length = (uintptr_t)length;
467 if (info.arm_section && info.arm_section_length)
468 return true;
469#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
470 struct dl_iterate_cb_data {
471 LocalAddressSpace *addressSpace;
472 UnwindInfoSections *sects;
473 uintptr_t targetAddr;
474 };
475
476 dl_iterate_cb_data cb_data = {this, &info, targetAddr};
477 int found = dl_iterate_phdr(
478 [](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
479 auto cbdata = static_cast<dl_iterate_cb_data *>(data);
480 bool found_obj = false;
481 bool found_hdr = false;
482
483 assert(cbdata);
484 assert(cbdata->sects);
485
486 if (cbdata->targetAddr < pinfo->dlpi_addr) {
487 return false;
488 }
489
490#if !defined(Elf_Half)
491 typedef ElfW(Half) Elf_Half;
492#endif
493#if !defined(Elf_Phdr)
494 typedef ElfW(Phdr) Elf_Phdr;
495#endif
496#if !defined(Elf_Addr) && defined(__ANDROID__)
497 typedef ElfW(Addr) Elf_Addr;
498#endif
499
500 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
501 #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
502 #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
503 #endif
504 size_t object_length;
505#if defined(__ANDROID__)
506 Elf_Addr image_base =
507 pinfo->dlpi_phnum
508 ? reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
509 reinterpret_cast<const Elf_Phdr *>(pinfo->dlpi_phdr)
510 ->p_offset
511 : 0;
512#endif
513
514 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
515 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
516 if (phdr->p_type == PT_LOAD) {
517 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
518#if defined(__ANDROID__)
519 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
520 begin = begin + image_base;
521#endif
522 uintptr_t end = begin + phdr->p_memsz;
523 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) {
524 cbdata->sects->dso_base = begin;
525 object_length = phdr->p_memsz;
526 found_obj = true;
527 }
528 } else if (phdr->p_type == PT_GNU_EH_FRAME) {
529 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
530 uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr;
531#if defined(__ANDROID__)
532 if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base)
533 eh_frame_hdr_start = eh_frame_hdr_start + image_base;
534#endif
535 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
536 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
537 found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
538 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
539 hdrInfo);
540 if (found_hdr)
541 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
542 }
543 }
544
545 if (found_obj && found_hdr) {
546 cbdata->sects->dwarf_section_length = object_length;
547 return true;
548 } else {
549 return false;
550 }
551 #else // defined(_LIBUNWIND_ARM_EHABI)
552 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
553 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
554 if (phdr->p_type == PT_LOAD) {
555 uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr;
556 uintptr_t end = begin + phdr->p_memsz;
557 if (cbdata->targetAddr >= begin && cbdata->targetAddr < end)
558 found_obj = true;
559 } else if (phdr->p_type == PT_ARM_EXIDX) {
560 uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr;
561 cbdata->sects->arm_section = exidx_start;
562 cbdata->sects->arm_section_length = phdr->p_memsz;
563 found_hdr = true;
564 }
565 }
566 return found_obj && found_hdr;
567 #endif
568 },
569 &cb_data);
570 return static_cast<bool>(found);
571#endif
572
573 return false;
574}
575
576
577inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
578#ifdef __APPLE__
579 return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde));
580#else
581 // TO DO: if OS has way to dynamically register FDEs, check that.
582 (void)targetAddr;
583 (void)fde;
584 return false;
585#endif
586}
587
588inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
589 size_t bufLen,
590 unw_word_t *offset) {
591#if _LIBUNWIND_USE_DLADDR
592 Dl_info dyldInfo;
593 if (dladdr((void *)addr, &dyldInfo)) {
594 if (dyldInfo.dli_sname != NULL) {
595 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname);
596 *offset = (addr - (pint_t) dyldInfo.dli_saddr);
597 return true;
598 }
599 }
600#endif
601 return false;
602}
603
604
605
606#ifdef UNW_REMOTE
607
608/// RemoteAddressSpace is used as a template parameter to UnwindCursor when
609/// unwinding a thread in the another process. The other process can be a
610/// different endianness and a different pointer size which is handled by
611/// the P template parameter.
612template <typename P>
613class RemoteAddressSpace {
614public:
615 RemoteAddressSpace(task_t task) : fTask(task) {}
616
617 typedef typename P::uint_t pint_t;
618
619 uint8_t get8(pint_t addr);
620 uint16_t get16(pint_t addr);
621 uint32_t get32(pint_t addr);
622 uint64_t get64(pint_t addr);
623 pint_t getP(pint_t addr);
624 uint64_t getRegister(pint_t addr);
625 uint64_t getULEB128(pint_t &addr, pint_t end);
626 int64_t getSLEB128(pint_t &addr, pint_t end);
627 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
628 pint_t datarelBase = 0);
629 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
630 unw_word_t *offset);
631 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
632 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
633private:
634 void *localCopy(pint_t addr);
635
636 task_t fTask;
637};
638
639template <typename P> uint8_t RemoteAddressSpace<P>::get8(pint_t addr) {
640 return *((uint8_t *)localCopy(addr));
641}
642
643template <typename P> uint16_t RemoteAddressSpace<P>::get16(pint_t addr) {
644 return P::E::get16(*(uint16_t *)localCopy(addr));
645}
646
647template <typename P> uint32_t RemoteAddressSpace<P>::get32(pint_t addr) {
648 return P::E::get32(*(uint32_t *)localCopy(addr));
649}
650
651template <typename P> uint64_t RemoteAddressSpace<P>::get64(pint_t addr) {
652 return P::E::get64(*(uint64_t *)localCopy(addr));
653}
654
655template <typename P>
656typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
657 return P::getP(*(uint64_t *)localCopy(addr));
658}
659
660template <typename P>
661typename P::uint_t OtherAddressSpace<P>::getRegister(pint_t addr) {
662 return P::getRegister(*(uint64_t *)localCopy(addr));
663}
664
665template <typename P>
666uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
667 uintptr_t size = (end - addr);
668 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
669 LocalAddressSpace::pint_t sladdr = laddr;
670 uint64_t result = LocalAddressSpace::getULEB128(laddr, laddr + size);
671 addr += (laddr - sladdr);
672 return result;
673}
674
675template <typename P>
676int64_t RemoteAddressSpace<P>::getSLEB128(pint_t &addr, pint_t end) {
677 uintptr_t size = (end - addr);
678 LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
679 LocalAddressSpace::pint_t sladdr = laddr;
680 uint64_t result = LocalAddressSpace::getSLEB128(laddr, laddr + size);
681 addr += (laddr - sladdr);
682 return result;
683}
684
685template <typename P> void *RemoteAddressSpace<P>::localCopy(pint_t addr) {
686 // FIX ME
687}
688
689template <typename P>
690bool RemoteAddressSpace<P>::findFunctionName(pint_t addr, char *buf,
691 size_t bufLen,
692 unw_word_t *offset) {
693 // FIX ME
694}
695
696/// unw_addr_space is the base class that abstract unw_addr_space_t type in
697/// libunwind.h points to.
698struct unw_addr_space {
699 cpu_type_t cpuType;
700 task_t taskPort;
701};
702
703/// unw_addr_space_i386 is the concrete instance that a unw_addr_space_t points
704/// to when examining
705/// a 32-bit intel process.
706struct unw_addr_space_i386 : public unw_addr_space {
707 unw_addr_space_i386(task_t task) : oas(task) {}
708 RemoteAddressSpace<Pointer32<LittleEndian>> oas;
709};
710
711/// unw_addr_space_x86_64 is the concrete instance that a unw_addr_space_t
712/// points to when examining
713/// a 64-bit intel process.
714struct unw_addr_space_x86_64 : public unw_addr_space {
715 unw_addr_space_x86_64(task_t task) : oas(task) {}
716 RemoteAddressSpace<Pointer64<LittleEndian>> oas;
717};
718
719/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
720/// to when examining
721/// a 32-bit PowerPC process.
722struct unw_addr_space_ppc : public unw_addr_space {
723 unw_addr_space_ppc(task_t task) : oas(task) {}
724 RemoteAddressSpace<Pointer32<BigEndian>> oas;
725};
726
727/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
728/// to when examining a 64-bit PowerPC process.
729struct unw_addr_space_ppc64 : public unw_addr_space {
730 unw_addr_space_ppc64(task_t task) : oas(task) {}
731 RemoteAddressSpace<Pointer64<LittleEndian>> oas;
732};
733
734#endif // UNW_REMOTE
735
736} // namespace libunwind
737
738#endif // __ADDRESSSPACE_HPP__
libunwind/src/CompactUnwinder.hpp created+698
...@@ -0,0 +1,698 @@
1//===-------------------------- CompactUnwinder.hpp -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Does runtime stack unwinding using compact unwind encodings.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef __COMPACT_UNWINDER_HPP__
14#define __COMPACT_UNWINDER_HPP__
15
16#include <stdint.h>
17#include <stdlib.h>
18
19#include <libunwind.h>
20#include <mach-o/compact_unwind_encoding.h>
21
22#include "Registers.hpp"
23
24#define EXTRACT_BITS(value, mask) \
25 ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1))
26
27namespace libunwind {
28
29#if defined(_LIBUNWIND_TARGET_I386)
30/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka
31/// unwind) by modifying a Registers_x86 register set
32template <typename A>
33class CompactUnwinder_x86 {
34public:
35
36 static int stepWithCompactEncoding(compact_unwind_encoding_t info,
37 uint32_t functionStart, A &addressSpace,
38 Registers_x86 &registers);
39
40private:
41 typename A::pint_t pint_t;
42
43 static void frameUnwind(A &addressSpace, Registers_x86 &registers);
44 static void framelessUnwind(A &addressSpace,
45 typename A::pint_t returnAddressLocation,
46 Registers_x86 &registers);
47 static int
48 stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding,
49 uint32_t functionStart, A &addressSpace,
50 Registers_x86 &registers);
51 static int stepWithCompactEncodingFrameless(
52 compact_unwind_encoding_t compactEncoding, uint32_t functionStart,
53 A &addressSpace, Registers_x86 &registers, bool indirectStackSize);
54};
55
56template <typename A>
57int CompactUnwinder_x86<A>::stepWithCompactEncoding(
58 compact_unwind_encoding_t compactEncoding, uint32_t functionStart,
59 A &addressSpace, Registers_x86 &registers) {
60 switch (compactEncoding & UNWIND_X86_MODE_MASK) {
61 case UNWIND_X86_MODE_EBP_FRAME:
62 return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart,
63 addressSpace, registers);
64 case UNWIND_X86_MODE_STACK_IMMD:
65 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
66 addressSpace, registers, false);
67 case UNWIND_X86_MODE_STACK_IND:
68 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
69 addressSpace, registers, true);
70 }
71 _LIBUNWIND_ABORT("invalid compact unwind encoding");
72}
73
74template <typename A>
75int CompactUnwinder_x86<A>::stepWithCompactEncodingEBPFrame(
76 compact_unwind_encoding_t compactEncoding, uint32_t functionStart,
77 A &addressSpace, Registers_x86 &registers) {
78 uint32_t savedRegistersOffset =
79 EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET);
80 uint32_t savedRegistersLocations =
81 EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_REGISTERS);
82
83 uint32_t savedRegisters = registers.getEBP() - 4 * savedRegistersOffset;
84 for (int i = 0; i < 5; ++i) {
85 switch (savedRegistersLocations & 0x7) {
86 case UNWIND_X86_REG_NONE:
87 // no register saved in this slot
88 break;
89 case UNWIND_X86_REG_EBX:
90 registers.setEBX(addressSpace.get32(savedRegisters));
91 break;
92 case UNWIND_X86_REG_ECX:
93 registers.setECX(addressSpace.get32(savedRegisters));
94 break;
95 case UNWIND_X86_REG_EDX:
96 registers.setEDX(addressSpace.get32(savedRegisters));
97 break;
98 case UNWIND_X86_REG_EDI:
99 registers.setEDI(addressSpace.get32(savedRegisters));
100 break;
101 case UNWIND_X86_REG_ESI:
102 registers.setESI(addressSpace.get32(savedRegisters));
103 break;
104 default:
105 (void)functionStart;
106 _LIBUNWIND_DEBUG_LOG("bad register for EBP frame, encoding=%08X for "
107 "function starting at 0x%X",
108 compactEncoding, functionStart);
109 _LIBUNWIND_ABORT("invalid compact unwind encoding");
110 }
111 savedRegisters += 4;
112 savedRegistersLocations = (savedRegistersLocations >> 3);
113 }
114 frameUnwind(addressSpace, registers);
115 return UNW_STEP_SUCCESS;
116}
117
118template <typename A>
119int CompactUnwinder_x86<A>::stepWithCompactEncodingFrameless(
120 compact_unwind_encoding_t encoding, uint32_t functionStart,
121 A &addressSpace, Registers_x86 &registers, bool indirectStackSize) {
122 uint32_t stackSizeEncoded =
123 EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
124 uint32_t stackAdjust =
125 EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST);
126 uint32_t regCount =
127 EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT);
128 uint32_t permutation =
129 EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION);
130 uint32_t stackSize = stackSizeEncoded * 4;
131 if (indirectStackSize) {
132 // stack size is encoded in subl $xxx,%esp instruction
133 uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded);
134 stackSize = subl + 4 * stackAdjust;
135 }
136 // decompress permutation
137 uint32_t permunreg[6];
138 switch (regCount) {
139 case 6:
140 permunreg[0] = permutation / 120;
141 permutation -= (permunreg[0] * 120);
142 permunreg[1] = permutation / 24;
143 permutation -= (permunreg[1] * 24);
144 permunreg[2] = permutation / 6;
145 permutation -= (permunreg[2] * 6);
146 permunreg[3] = permutation / 2;
147 permutation -= (permunreg[3] * 2);
148 permunreg[4] = permutation;
149 permunreg[5] = 0;
150 break;
151 case 5:
152 permunreg[0] = permutation / 120;
153 permutation -= (permunreg[0] * 120);
154 permunreg[1] = permutation / 24;
155 permutation -= (permunreg[1] * 24);
156 permunreg[2] = permutation / 6;
157 permutation -= (permunreg[2] * 6);
158 permunreg[3] = permutation / 2;
159 permutation -= (permunreg[3] * 2);
160 permunreg[4] = permutation;
161 break;
162 case 4:
163 permunreg[0] = permutation / 60;
164 permutation -= (permunreg[0] * 60);
165 permunreg[1] = permutation / 12;
166 permutation -= (permunreg[1] * 12);
167 permunreg[2] = permutation / 3;
168 permutation -= (permunreg[2] * 3);
169 permunreg[3] = permutation;
170 break;
171 case 3:
172 permunreg[0] = permutation / 20;
173 permutation -= (permunreg[0] * 20);
174 permunreg[1] = permutation / 4;
175 permutation -= (permunreg[1] * 4);
176 permunreg[2] = permutation;
177 break;
178 case 2:
179 permunreg[0] = permutation / 5;
180 permutation -= (permunreg[0] * 5);
181 permunreg[1] = permutation;
182 break;
183 case 1:
184 permunreg[0] = permutation;
185 break;
186 }
187 // re-number registers back to standard numbers
188 int registersSaved[6];
189 bool used[7] = { false, false, false, false, false, false, false };
190 for (uint32_t i = 0; i < regCount; ++i) {
191 uint32_t renum = 0;
192 for (int u = 1; u < 7; ++u) {
193 if (!used[u]) {
194 if (renum == permunreg[i]) {
195 registersSaved[i] = u;
196 used[u] = true;
197 break;
198 }
199 ++renum;
200 }
201 }
202 }
203 uint32_t savedRegisters = registers.getSP() + stackSize - 4 - 4 * regCount;
204 for (uint32_t i = 0; i < regCount; ++i) {
205 switch (registersSaved[i]) {
206 case UNWIND_X86_REG_EBX:
207 registers.setEBX(addressSpace.get32(savedRegisters));
208 break;
209 case UNWIND_X86_REG_ECX:
210 registers.setECX(addressSpace.get32(savedRegisters));
211 break;
212 case UNWIND_X86_REG_EDX:
213 registers.setEDX(addressSpace.get32(savedRegisters));
214 break;
215 case UNWIND_X86_REG_EDI:
216 registers.setEDI(addressSpace.get32(savedRegisters));
217 break;
218 case UNWIND_X86_REG_ESI:
219 registers.setESI(addressSpace.get32(savedRegisters));
220 break;
221 case UNWIND_X86_REG_EBP:
222 registers.setEBP(addressSpace.get32(savedRegisters));
223 break;
224 default:
225 _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "
226 "function starting at 0x%X",
227 encoding, functionStart);
228 _LIBUNWIND_ABORT("invalid compact unwind encoding");
229 }
230 savedRegisters += 4;
231 }
232 framelessUnwind(addressSpace, savedRegisters, registers);
233 return UNW_STEP_SUCCESS;
234}
235
236
237template <typename A>
238void CompactUnwinder_x86<A>::frameUnwind(A &addressSpace,
239 Registers_x86 &registers) {
240 typename A::pint_t bp = registers.getEBP();
241 // ebp points to old ebp
242 registers.setEBP(addressSpace.get32(bp));
243 // old esp is ebp less saved ebp and return address
244 registers.setSP((uint32_t)bp + 8);
245 // pop return address into eip
246 registers.setIP(addressSpace.get32(bp + 4));
247}
248
249template <typename A>
250void CompactUnwinder_x86<A>::framelessUnwind(
251 A &addressSpace, typename A::pint_t returnAddressLocation,
252 Registers_x86 &registers) {
253 // return address is on stack after last saved register
254 registers.setIP(addressSpace.get32(returnAddressLocation));
255 // old esp is before return address
256 registers.setSP((uint32_t)returnAddressLocation + 4);
257}
258#endif // _LIBUNWIND_TARGET_I386
259
260
261#if defined(_LIBUNWIND_TARGET_X86_64)
262/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka
263/// unwind) by modifying a Registers_x86_64 register set
264template <typename A>
265class CompactUnwinder_x86_64 {
266public:
267
268 static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding,
269 uint64_t functionStart, A &addressSpace,
270 Registers_x86_64 &registers);
271
272private:
273 typename A::pint_t pint_t;
274
275 static void frameUnwind(A &addressSpace, Registers_x86_64 &registers);
276 static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation,
277 Registers_x86_64 &registers);
278 static int
279 stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding,
280 uint64_t functionStart, A &addressSpace,
281 Registers_x86_64 &registers);
282 static int stepWithCompactEncodingFrameless(
283 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
284 A &addressSpace, Registers_x86_64 &registers, bool indirectStackSize);
285};
286
287template <typename A>
288int CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
289 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
290 A &addressSpace, Registers_x86_64 &registers) {
291 switch (compactEncoding & UNWIND_X86_64_MODE_MASK) {
292 case UNWIND_X86_64_MODE_RBP_FRAME:
293 return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart,
294 addressSpace, registers);
295 case UNWIND_X86_64_MODE_STACK_IMMD:
296 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
297 addressSpace, registers, false);
298 case UNWIND_X86_64_MODE_STACK_IND:
299 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
300 addressSpace, registers, true);
301 }
302 _LIBUNWIND_ABORT("invalid compact unwind encoding");
303}
304
305template <typename A>
306int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(
307 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
308 A &addressSpace, Registers_x86_64 &registers) {
309 uint32_t savedRegistersOffset =
310 EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET);
311 uint32_t savedRegistersLocations =
312 EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);
313
314 uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset;
315 for (int i = 0; i < 5; ++i) {
316 switch (savedRegistersLocations & 0x7) {
317 case UNWIND_X86_64_REG_NONE:
318 // no register saved in this slot
319 break;
320 case UNWIND_X86_64_REG_RBX:
321 registers.setRBX(addressSpace.get64(savedRegisters));
322 break;
323 case UNWIND_X86_64_REG_R12:
324 registers.setR12(addressSpace.get64(savedRegisters));
325 break;
326 case UNWIND_X86_64_REG_R13:
327 registers.setR13(addressSpace.get64(savedRegisters));
328 break;
329 case UNWIND_X86_64_REG_R14:
330 registers.setR14(addressSpace.get64(savedRegisters));
331 break;
332 case UNWIND_X86_64_REG_R15:
333 registers.setR15(addressSpace.get64(savedRegisters));
334 break;
335 default:
336 (void)functionStart;
337 _LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for "
338 "function starting at 0x%llX",
339 compactEncoding, functionStart);
340 _LIBUNWIND_ABORT("invalid compact unwind encoding");
341 }
342 savedRegisters += 8;
343 savedRegistersLocations = (savedRegistersLocations >> 3);
344 }
345 frameUnwind(addressSpace, registers);
346 return UNW_STEP_SUCCESS;
347}
348
349template <typename A>
350int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(
351 compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace,
352 Registers_x86_64 &registers, bool indirectStackSize) {
353 uint32_t stackSizeEncoded =
354 EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
355 uint32_t stackAdjust =
356 EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
357 uint32_t regCount =
358 EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
359 uint32_t permutation =
360 EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
361 uint32_t stackSize = stackSizeEncoded * 8;
362 if (indirectStackSize) {
363 // stack size is encoded in subl $xxx,%esp instruction
364 uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded);
365 stackSize = subl + 8 * stackAdjust;
366 }
367 // decompress permutation
368 uint32_t permunreg[6];
369 switch (regCount) {
370 case 6:
371 permunreg[0] = permutation / 120;
372 permutation -= (permunreg[0] * 120);
373 permunreg[1] = permutation / 24;
374 permutation -= (permunreg[1] * 24);
375 permunreg[2] = permutation / 6;
376 permutation -= (permunreg[2] * 6);
377 permunreg[3] = permutation / 2;
378 permutation -= (permunreg[3] * 2);
379 permunreg[4] = permutation;
380 permunreg[5] = 0;
381 break;
382 case 5:
383 permunreg[0] = permutation / 120;
384 permutation -= (permunreg[0] * 120);
385 permunreg[1] = permutation / 24;
386 permutation -= (permunreg[1] * 24);
387 permunreg[2] = permutation / 6;
388 permutation -= (permunreg[2] * 6);
389 permunreg[3] = permutation / 2;
390 permutation -= (permunreg[3] * 2);
391 permunreg[4] = permutation;
392 break;
393 case 4:
394 permunreg[0] = permutation / 60;
395 permutation -= (permunreg[0] * 60);
396 permunreg[1] = permutation / 12;
397 permutation -= (permunreg[1] * 12);
398 permunreg[2] = permutation / 3;
399 permutation -= (permunreg[2] * 3);
400 permunreg[3] = permutation;
401 break;
402 case 3:
403 permunreg[0] = permutation / 20;
404 permutation -= (permunreg[0] * 20);
405 permunreg[1] = permutation / 4;
406 permutation -= (permunreg[1] * 4);
407 permunreg[2] = permutation;
408 break;
409 case 2:
410 permunreg[0] = permutation / 5;
411 permutation -= (permunreg[0] * 5);
412 permunreg[1] = permutation;
413 break;
414 case 1:
415 permunreg[0] = permutation;
416 break;
417 }
418 // re-number registers back to standard numbers
419 int registersSaved[6];
420 bool used[7] = { false, false, false, false, false, false, false };
421 for (uint32_t i = 0; i < regCount; ++i) {
422 uint32_t renum = 0;
423 for (int u = 1; u < 7; ++u) {
424 if (!used[u]) {
425 if (renum == permunreg[i]) {
426 registersSaved[i] = u;
427 used[u] = true;
428 break;
429 }
430 ++renum;
431 }
432 }
433 }
434 uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount;
435 for (uint32_t i = 0; i < regCount; ++i) {
436 switch (registersSaved[i]) {
437 case UNWIND_X86_64_REG_RBX:
438 registers.setRBX(addressSpace.get64(savedRegisters));
439 break;
440 case UNWIND_X86_64_REG_R12:
441 registers.setR12(addressSpace.get64(savedRegisters));
442 break;
443 case UNWIND_X86_64_REG_R13:
444 registers.setR13(addressSpace.get64(savedRegisters));
445 break;
446 case UNWIND_X86_64_REG_R14:
447 registers.setR14(addressSpace.get64(savedRegisters));
448 break;
449 case UNWIND_X86_64_REG_R15:
450 registers.setR15(addressSpace.get64(savedRegisters));
451 break;
452 case UNWIND_X86_64_REG_RBP:
453 registers.setRBP(addressSpace.get64(savedRegisters));
454 break;
455 default:
456 _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "
457 "function starting at 0x%llX",
458 encoding, functionStart);
459 _LIBUNWIND_ABORT("invalid compact unwind encoding");
460 }
461 savedRegisters += 8;
462 }
463 framelessUnwind(addressSpace, savedRegisters, registers);
464 return UNW_STEP_SUCCESS;
465}
466
467
468template <typename A>
469void CompactUnwinder_x86_64<A>::frameUnwind(A &addressSpace,
470 Registers_x86_64 &registers) {
471 uint64_t rbp = registers.getRBP();
472 // ebp points to old ebp
473 registers.setRBP(addressSpace.get64(rbp));
474 // old esp is ebp less saved ebp and return address
475 registers.setSP(rbp + 16);
476 // pop return address into eip
477 registers.setIP(addressSpace.get64(rbp + 8));
478}
479
480template <typename A>
481void CompactUnwinder_x86_64<A>::framelessUnwind(A &addressSpace,
482 uint64_t returnAddressLocation,
483 Registers_x86_64 &registers) {
484 // return address is on stack after last saved register
485 registers.setIP(addressSpace.get64(returnAddressLocation));
486 // old esp is before return address
487 registers.setSP(returnAddressLocation + 8);
488}
489#endif // _LIBUNWIND_TARGET_X86_64
490
491
492
493#if defined(_LIBUNWIND_TARGET_AARCH64)
494/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka
495/// unwind) by modifying a Registers_arm64 register set
496template <typename A>
497class CompactUnwinder_arm64 {
498public:
499
500 static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding,
501 uint64_t functionStart, A &addressSpace,
502 Registers_arm64 &registers);
503
504private:
505 typename A::pint_t pint_t;
506
507 static int
508 stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding,
509 uint64_t functionStart, A &addressSpace,
510 Registers_arm64 &registers);
511 static int stepWithCompactEncodingFrameless(
512 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
513 A &addressSpace, Registers_arm64 &registers);
514};
515
516template <typename A>
517int CompactUnwinder_arm64<A>::stepWithCompactEncoding(
518 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,
519 A &addressSpace, Registers_arm64 &registers) {
520 switch (compactEncoding & UNWIND_ARM64_MODE_MASK) {
521 case UNWIND_ARM64_MODE_FRAME:
522 return stepWithCompactEncodingFrame(compactEncoding, functionStart,
523 addressSpace, registers);
524 case UNWIND_ARM64_MODE_FRAMELESS:
525 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,
526 addressSpace, registers);
527 }
528 _LIBUNWIND_ABORT("invalid compact unwind encoding");
529}
530
531template <typename A>
532int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless(
533 compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,
534 Registers_arm64 &registers) {
535 uint32_t stackSize =
536 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK);
537
538 uint64_t savedRegisterLoc = registers.getSP() + stackSize;
539
540 if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
541 registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc));
542 savedRegisterLoc -= 8;
543 registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc));
544 savedRegisterLoc -= 8;
545 }
546 if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
547 registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc));
548 savedRegisterLoc -= 8;
549 registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc));
550 savedRegisterLoc -= 8;
551 }
552 if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
553 registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc));
554 savedRegisterLoc -= 8;
555 registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc));
556 savedRegisterLoc -= 8;
557 }
558 if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
559 registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc));
560 savedRegisterLoc -= 8;
561 registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc));
562 savedRegisterLoc -= 8;
563 }
564 if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
565 registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc));
566 savedRegisterLoc -= 8;
567 registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc));
568 savedRegisterLoc -= 8;
569 }
570
571 if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
572 registers.setFloatRegister(UNW_ARM64_D8,
573 addressSpace.getDouble(savedRegisterLoc));
574 savedRegisterLoc -= 8;
575 registers.setFloatRegister(UNW_ARM64_D9,
576 addressSpace.getDouble(savedRegisterLoc));
577 savedRegisterLoc -= 8;
578 }
579 if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
580 registers.setFloatRegister(UNW_ARM64_D10,
581 addressSpace.getDouble(savedRegisterLoc));
582 savedRegisterLoc -= 8;
583 registers.setFloatRegister(UNW_ARM64_D11,
584 addressSpace.getDouble(savedRegisterLoc));
585 savedRegisterLoc -= 8;
586 }
587 if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
588 registers.setFloatRegister(UNW_ARM64_D12,
589 addressSpace.getDouble(savedRegisterLoc));
590 savedRegisterLoc -= 8;
591 registers.setFloatRegister(UNW_ARM64_D13,
592 addressSpace.getDouble(savedRegisterLoc));
593 savedRegisterLoc -= 8;
594 }
595 if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
596 registers.setFloatRegister(UNW_ARM64_D14,
597 addressSpace.getDouble(savedRegisterLoc));
598 savedRegisterLoc -= 8;
599 registers.setFloatRegister(UNW_ARM64_D15,
600 addressSpace.getDouble(savedRegisterLoc));
601 savedRegisterLoc -= 8;
602 }
603
604 // subtract stack size off of sp
605 registers.setSP(savedRegisterLoc);
606
607 // set pc to be value in lr
608 registers.setIP(registers.getRegister(UNW_ARM64_LR));
609
610 return UNW_STEP_SUCCESS;
611}
612
613template <typename A>
614int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(
615 compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,
616 Registers_arm64 &registers) {
617 uint64_t savedRegisterLoc = registers.getFP() - 8;
618
619 if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
620 registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc));
621 savedRegisterLoc -= 8;
622 registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc));
623 savedRegisterLoc -= 8;
624 }
625 if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
626 registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc));
627 savedRegisterLoc -= 8;
628 registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc));
629 savedRegisterLoc -= 8;
630 }
631 if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
632 registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc));
633 savedRegisterLoc -= 8;
634 registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc));
635 savedRegisterLoc -= 8;
636 }
637 if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
638 registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc));
639 savedRegisterLoc -= 8;
640 registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc));
641 savedRegisterLoc -= 8;
642 }
643 if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
644 registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc));
645 savedRegisterLoc -= 8;
646 registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc));
647 savedRegisterLoc -= 8;
648 }
649
650 if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
651 registers.setFloatRegister(UNW_ARM64_D8,
652 addressSpace.getDouble(savedRegisterLoc));
653 savedRegisterLoc -= 8;
654 registers.setFloatRegister(UNW_ARM64_D9,
655 addressSpace.getDouble(savedRegisterLoc));
656 savedRegisterLoc -= 8;
657 }
658 if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
659 registers.setFloatRegister(UNW_ARM64_D10,
660 addressSpace.getDouble(savedRegisterLoc));
661 savedRegisterLoc -= 8;
662 registers.setFloatRegister(UNW_ARM64_D11,
663 addressSpace.getDouble(savedRegisterLoc));
664 savedRegisterLoc -= 8;
665 }
666 if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
667 registers.setFloatRegister(UNW_ARM64_D12,
668 addressSpace.getDouble(savedRegisterLoc));
669 savedRegisterLoc -= 8;
670 registers.setFloatRegister(UNW_ARM64_D13,
671 addressSpace.getDouble(savedRegisterLoc));
672 savedRegisterLoc -= 8;
673 }
674 if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
675 registers.setFloatRegister(UNW_ARM64_D14,
676 addressSpace.getDouble(savedRegisterLoc));
677 savedRegisterLoc -= 8;
678 registers.setFloatRegister(UNW_ARM64_D15,
679 addressSpace.getDouble(savedRegisterLoc));
680 savedRegisterLoc -= 8;
681 }
682
683 uint64_t fp = registers.getFP();
684 // fp points to old fp
685 registers.setFP(addressSpace.get64(fp));
686 // old sp is fp less saved fp and lr
687 registers.setSP(fp + 16);
688 // pop return address into pc
689 registers.setIP(addressSpace.get64(fp + 8));
690
691 return UNW_STEP_SUCCESS;
692}
693#endif // _LIBUNWIND_TARGET_AARCH64
694
695
696} // namespace libunwind
697
698#endif // __COMPACT_UNWINDER_HPP__
libunwind/src/DwarfInstructions.hpp created+795
...@@ -0,0 +1,795 @@
1//===-------------------------- DwarfInstructions.hpp ---------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Processor specific interpretation of DWARF unwind info.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef __DWARF_INSTRUCTIONS_HPP__
14#define __DWARF_INSTRUCTIONS_HPP__
15
16#include <stdint.h>
17#include <stdio.h>
18#include <stdlib.h>
19
20#include "dwarf2.h"
21#include "Registers.hpp"
22#include "DwarfParser.hpp"
23#include "config.h"
24
25
26namespace libunwind {
27
28
29/// DwarfInstructions maps abtract DWARF unwind instructions to a particular
30/// architecture
31template <typename A, typename R>
32class DwarfInstructions {
33public:
34 typedef typename A::pint_t pint_t;
35 typedef typename A::sint_t sint_t;
36
37 static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
38 R &registers);
39
40private:
41
42 enum {
43 DW_X86_64_RET_ADDR = 16
44 };
45
46 enum {
47 DW_X86_RET_ADDR = 8
48 };
49
50 typedef typename CFI_Parser<A>::RegisterLocation RegisterLocation;
51 typedef typename CFI_Parser<A>::PrologInfo PrologInfo;
52 typedef typename CFI_Parser<A>::FDE_Info FDE_Info;
53 typedef typename CFI_Parser<A>::CIE_Info CIE_Info;
54
55 static pint_t evaluateExpression(pint_t expression, A &addressSpace,
56 const R &registers,
57 pint_t initialStackValue);
58 static pint_t getSavedRegister(A &addressSpace, const R &registers,
59 pint_t cfa, const RegisterLocation &savedReg);
60 static double getSavedFloatRegister(A &addressSpace, const R &registers,
61 pint_t cfa, const RegisterLocation &savedReg);
62 static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
63 pint_t cfa, const RegisterLocation &savedReg);
64
65 static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
66 const R &registers) {
67 if (prolog.cfaRegister != 0)
68 return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
69 prolog.cfaRegisterOffset);
70 if (prolog.cfaExpression != 0)
71 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
72 registers, 0);
73 assert(0 && "getCFA(): unknown location");
74 __builtin_unreachable();
75 }
76};
77
78
79template <typename A, typename R>
80typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
81 A &addressSpace, const R &registers, pint_t cfa,
82 const RegisterLocation &savedReg) {
83 switch (savedReg.location) {
84 case CFI_Parser<A>::kRegisterInCFA:
85 return addressSpace.getRegister(cfa + (pint_t)savedReg.value);
86
87 case CFI_Parser<A>::kRegisterAtExpression:
88 return addressSpace.getRegister(
89 evaluateExpression((pint_t)savedReg.value, addressSpace,
90 registers, cfa));
91
92 case CFI_Parser<A>::kRegisterIsExpression:
93 return evaluateExpression((pint_t)savedReg.value, addressSpace,
94 registers, cfa);
95
96 case CFI_Parser<A>::kRegisterInRegister:
97 return registers.getRegister((int)savedReg.value);
98
99 case CFI_Parser<A>::kRegisterUnused:
100 case CFI_Parser<A>::kRegisterOffsetFromCFA:
101 // FIX ME
102 break;
103 }
104 _LIBUNWIND_ABORT("unsupported restore location for register");
105}
106
107template <typename A, typename R>
108double DwarfInstructions<A, R>::getSavedFloatRegister(
109 A &addressSpace, const R &registers, pint_t cfa,
110 const RegisterLocation &savedReg) {
111 switch (savedReg.location) {
112 case CFI_Parser<A>::kRegisterInCFA:
113 return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
114
115 case CFI_Parser<A>::kRegisterAtExpression:
116 return addressSpace.getDouble(
117 evaluateExpression((pint_t)savedReg.value, addressSpace,
118 registers, cfa));
119
120 case CFI_Parser<A>::kRegisterIsExpression:
121 case CFI_Parser<A>::kRegisterUnused:
122 case CFI_Parser<A>::kRegisterOffsetFromCFA:
123 case CFI_Parser<A>::kRegisterInRegister:
124 // FIX ME
125 break;
126 }
127 _LIBUNWIND_ABORT("unsupported restore location for float register");
128}
129
130template <typename A, typename R>
131v128 DwarfInstructions<A, R>::getSavedVectorRegister(
132 A &addressSpace, const R &registers, pint_t cfa,
133 const RegisterLocation &savedReg) {
134 switch (savedReg.location) {
135 case CFI_Parser<A>::kRegisterInCFA:
136 return addressSpace.getVector(cfa + (pint_t)savedReg.value);
137
138 case CFI_Parser<A>::kRegisterAtExpression:
139 return addressSpace.getVector(
140 evaluateExpression((pint_t)savedReg.value, addressSpace,
141 registers, cfa));
142
143 case CFI_Parser<A>::kRegisterIsExpression:
144 case CFI_Parser<A>::kRegisterUnused:
145 case CFI_Parser<A>::kRegisterOffsetFromCFA:
146 case CFI_Parser<A>::kRegisterInRegister:
147 // FIX ME
148 break;
149 }
150 _LIBUNWIND_ABORT("unsupported restore location for vector register");
151}
152
153template <typename A, typename R>
154int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
155 pint_t fdeStart, R &registers) {
156 FDE_Info fdeInfo;
157 CIE_Info cieInfo;
158 if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
159 &cieInfo) == NULL) {
160 PrologInfo prolog;
161 if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
162 R::getArch(), &prolog)) {
163 // get pointer to cfa (architecture specific)
164 pint_t cfa = getCFA(addressSpace, prolog, registers);
165
166 // restore registers that DWARF says were saved
167 R newRegisters = registers;
168 pint_t returnAddress = 0;
169 const int lastReg = R::lastDwarfRegNum();
170 assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
171 "register range too large");
172 assert(lastReg >= (int)cieInfo.returnAddressRegister &&
173 "register range does not contain return address register");
174 for (int i = 0; i <= lastReg; ++i) {
175 if (prolog.savedRegisters[i].location !=
176 CFI_Parser<A>::kRegisterUnused) {
177 if (registers.validFloatRegister(i))
178 newRegisters.setFloatRegister(
179 i, getSavedFloatRegister(addressSpace, registers, cfa,
180 prolog.savedRegisters[i]));
181 else if (registers.validVectorRegister(i))
182 newRegisters.setVectorRegister(
183 i, getSavedVectorRegister(addressSpace, registers, cfa,
184 prolog.savedRegisters[i]));
185 else if (i == (int)cieInfo.returnAddressRegister)
186 returnAddress = getSavedRegister(addressSpace, registers, cfa,
187 prolog.savedRegisters[i]);
188 else if (registers.validRegister(i))
189 newRegisters.setRegister(
190 i, getSavedRegister(addressSpace, registers, cfa,
191 prolog.savedRegisters[i]));
192 else
193 return UNW_EBADREG;
194 }
195 }
196
197 // By definition, the CFA is the stack pointer at the call site, so
198 // restoring SP means setting it to CFA.
199 newRegisters.setSP(cfa);
200
201#if defined(_LIBUNWIND_TARGET_AARCH64)
202 // If the target is aarch64 then the return address may have been signed
203 // using the v8.3 pointer authentication extensions. The original
204 // return address needs to be authenticated before the return address is
205 // restored. autia1716 is used instead of autia as autia1716 assembles
206 // to a NOP on pre-v8.3a architectures.
207 if ((R::getArch() == REGISTERS_ARM64) &&
208 prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) {
209#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
210 return UNW_ECROSSRASIGNING;
211#else
212 register unsigned long long x17 __asm("x17") = returnAddress;
213 register unsigned long long x16 __asm("x16") = cfa;
214
215 // These are the autia1716/autib1716 instructions. The hint instructions
216 // are used here as gcc does not assemble autia1716/autib1716 for pre
217 // armv8.3a targets.
218 if (cieInfo.addressesSignedWithBKey)
219 asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
220 else
221 asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
222 returnAddress = x17;
223#endif
224 }
225#endif
226
227#if defined(_LIBUNWIND_TARGET_SPARC)
228 if (R::getArch() == REGISTERS_SPARC) {
229 // Skip call site instruction and delay slot
230 returnAddress += 8;
231 // Skip unimp instruction if function returns a struct
232 if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
233 returnAddress += 4;
234 }
235#endif
236
237 // Return address is address after call site instruction, so setting IP to
238 // that does simualates a return.
239 newRegisters.setIP(returnAddress);
240
241 // Simulate the step by replacing the register set with the new ones.
242 registers = newRegisters;
243
244 return UNW_STEP_SUCCESS;
245 }
246 }
247 return UNW_EBADFRAME;
248}
249
250template <typename A, typename R>
251typename A::pint_t
252DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
253 const R &registers,
254 pint_t initialStackValue) {
255 const bool log = false;
256 pint_t p = expression;
257 pint_t expressionEnd = expression + 20; // temp, until len read
258 pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
259 expressionEnd = p + length;
260 if (log)
261 fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
262 (uint64_t)length);
263 pint_t stack[100];
264 pint_t *sp = stack;
265 *(++sp) = initialStackValue;
266
267 while (p < expressionEnd) {
268 if (log) {
269 for (pint_t *t = sp; t > stack; --t) {
270 fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
271 }
272 }
273 uint8_t opcode = addressSpace.get8(p++);
274 sint_t svalue, svalue2;
275 pint_t value;
276 uint32_t reg;
277 switch (opcode) {
278 case DW_OP_addr:
279 // push immediate address sized value
280 value = addressSpace.getP(p);
281 p += sizeof(pint_t);
282 *(++sp) = value;
283 if (log)
284 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
285 break;
286
287 case DW_OP_deref:
288 // pop stack, dereference, push result
289 value = *sp--;
290 *(++sp) = addressSpace.getP(value);
291 if (log)
292 fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
293 break;
294
295 case DW_OP_const1u:
296 // push immediate 1 byte value
297 value = addressSpace.get8(p);
298 p += 1;
299 *(++sp) = value;
300 if (log)
301 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
302 break;
303
304 case DW_OP_const1s:
305 // push immediate 1 byte signed value
306 svalue = (int8_t) addressSpace.get8(p);
307 p += 1;
308 *(++sp) = (pint_t)svalue;
309 if (log)
310 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
311 break;
312
313 case DW_OP_const2u:
314 // push immediate 2 byte value
315 value = addressSpace.get16(p);
316 p += 2;
317 *(++sp) = value;
318 if (log)
319 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
320 break;
321
322 case DW_OP_const2s:
323 // push immediate 2 byte signed value
324 svalue = (int16_t) addressSpace.get16(p);
325 p += 2;
326 *(++sp) = (pint_t)svalue;
327 if (log)
328 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
329 break;
330
331 case DW_OP_const4u:
332 // push immediate 4 byte value
333 value = addressSpace.get32(p);
334 p += 4;
335 *(++sp) = value;
336 if (log)
337 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
338 break;
339
340 case DW_OP_const4s:
341 // push immediate 4 byte signed value
342 svalue = (int32_t)addressSpace.get32(p);
343 p += 4;
344 *(++sp) = (pint_t)svalue;
345 if (log)
346 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
347 break;
348
349 case DW_OP_const8u:
350 // push immediate 8 byte value
351 value = (pint_t)addressSpace.get64(p);
352 p += 8;
353 *(++sp) = value;
354 if (log)
355 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
356 break;
357
358 case DW_OP_const8s:
359 // push immediate 8 byte signed value
360 value = (pint_t)addressSpace.get64(p);
361 p += 8;
362 *(++sp) = value;
363 if (log)
364 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
365 break;
366
367 case DW_OP_constu:
368 // push immediate ULEB128 value
369 value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
370 *(++sp) = value;
371 if (log)
372 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
373 break;
374
375 case DW_OP_consts:
376 // push immediate SLEB128 value
377 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
378 *(++sp) = (pint_t)svalue;
379 if (log)
380 fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
381 break;
382
383 case DW_OP_dup:
384 // push top of stack
385 value = *sp;
386 *(++sp) = value;
387 if (log)
388 fprintf(stderr, "duplicate top of stack\n");
389 break;
390
391 case DW_OP_drop:
392 // pop
393 --sp;
394 if (log)
395 fprintf(stderr, "pop top of stack\n");
396 break;
397
398 case DW_OP_over:
399 // dup second
400 value = sp[-1];
401 *(++sp) = value;
402 if (log)
403 fprintf(stderr, "duplicate second in stack\n");
404 break;
405
406 case DW_OP_pick:
407 // pick from
408 reg = addressSpace.get8(p);
409 p += 1;
410 value = sp[-reg];
411 *(++sp) = value;
412 if (log)
413 fprintf(stderr, "duplicate %d in stack\n", reg);
414 break;
415
416 case DW_OP_swap:
417 // swap top two
418 value = sp[0];
419 sp[0] = sp[-1];
420 sp[-1] = value;
421 if (log)
422 fprintf(stderr, "swap top of stack\n");
423 break;
424
425 case DW_OP_rot:
426 // rotate top three
427 value = sp[0];
428 sp[0] = sp[-1];
429 sp[-1] = sp[-2];
430 sp[-2] = value;
431 if (log)
432 fprintf(stderr, "rotate top three of stack\n");
433 break;
434
435 case DW_OP_xderef:
436 // pop stack, dereference, push result
437 value = *sp--;
438 *sp = *((pint_t*)value);
439 if (log)
440 fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
441 break;
442
443 case DW_OP_abs:
444 svalue = (sint_t)*sp;
445 if (svalue < 0)
446 *sp = (pint_t)(-svalue);
447 if (log)
448 fprintf(stderr, "abs\n");
449 break;
450
451 case DW_OP_and:
452 value = *sp--;
453 *sp &= value;
454 if (log)
455 fprintf(stderr, "and\n");
456 break;
457
458 case DW_OP_div:
459 svalue = (sint_t)(*sp--);
460 svalue2 = (sint_t)*sp;
461 *sp = (pint_t)(svalue2 / svalue);
462 if (log)
463 fprintf(stderr, "div\n");
464 break;
465
466 case DW_OP_minus:
467 value = *sp--;
468 *sp = *sp - value;
469 if (log)
470 fprintf(stderr, "minus\n");
471 break;
472
473 case DW_OP_mod:
474 svalue = (sint_t)(*sp--);
475 svalue2 = (sint_t)*sp;
476 *sp = (pint_t)(svalue2 % svalue);
477 if (log)
478 fprintf(stderr, "module\n");
479 break;
480
481 case DW_OP_mul:
482 svalue = (sint_t)(*sp--);
483 svalue2 = (sint_t)*sp;
484 *sp = (pint_t)(svalue2 * svalue);
485 if (log)
486 fprintf(stderr, "mul\n");
487 break;
488
489 case DW_OP_neg:
490 *sp = 0 - *sp;
491 if (log)
492 fprintf(stderr, "neg\n");
493 break;
494
495 case DW_OP_not:
496 svalue = (sint_t)(*sp);
497 *sp = (pint_t)(~svalue);
498 if (log)
499 fprintf(stderr, "not\n");
500 break;
501
502 case DW_OP_or:
503 value = *sp--;
504 *sp |= value;
505 if (log)
506 fprintf(stderr, "or\n");
507 break;
508
509 case DW_OP_plus:
510 value = *sp--;
511 *sp += value;
512 if (log)
513 fprintf(stderr, "plus\n");
514 break;
515
516 case DW_OP_plus_uconst:
517 // pop stack, add uelb128 constant, push result
518 *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
519 if (log)
520 fprintf(stderr, "add constant\n");
521 break;
522
523 case DW_OP_shl:
524 value = *sp--;
525 *sp = *sp << value;
526 if (log)
527 fprintf(stderr, "shift left\n");
528 break;
529
530 case DW_OP_shr:
531 value = *sp--;
532 *sp = *sp >> value;
533 if (log)
534 fprintf(stderr, "shift left\n");
535 break;
536
537 case DW_OP_shra:
538 value = *sp--;
539 svalue = (sint_t)*sp;
540 *sp = (pint_t)(svalue >> value);
541 if (log)
542 fprintf(stderr, "shift left arithmetric\n");
543 break;
544
545 case DW_OP_xor:
546 value = *sp--;
547 *sp ^= value;
548 if (log)
549 fprintf(stderr, "xor\n");
550 break;
551
552 case DW_OP_skip:
553 svalue = (int16_t) addressSpace.get16(p);
554 p += 2;
555 p = (pint_t)((sint_t)p + svalue);
556 if (log)
557 fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
558 break;
559
560 case DW_OP_bra:
561 svalue = (int16_t) addressSpace.get16(p);
562 p += 2;
563 if (*sp--)
564 p = (pint_t)((sint_t)p + svalue);
565 if (log)
566 fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
567 break;
568
569 case DW_OP_eq:
570 value = *sp--;
571 *sp = (*sp == value);
572 if (log)
573 fprintf(stderr, "eq\n");
574 break;
575
576 case DW_OP_ge:
577 value = *sp--;
578 *sp = (*sp >= value);
579 if (log)
580 fprintf(stderr, "ge\n");
581 break;
582
583 case DW_OP_gt:
584 value = *sp--;
585 *sp = (*sp > value);
586 if (log)
587 fprintf(stderr, "gt\n");
588 break;
589
590 case DW_OP_le:
591 value = *sp--;
592 *sp = (*sp <= value);
593 if (log)
594 fprintf(stderr, "le\n");
595 break;
596
597 case DW_OP_lt:
598 value = *sp--;
599 *sp = (*sp < value);
600 if (log)
601 fprintf(stderr, "lt\n");
602 break;
603
604 case DW_OP_ne:
605 value = *sp--;
606 *sp = (*sp != value);
607 if (log)
608 fprintf(stderr, "ne\n");
609 break;
610
611 case DW_OP_lit0:
612 case DW_OP_lit1:
613 case DW_OP_lit2:
614 case DW_OP_lit3:
615 case DW_OP_lit4:
616 case DW_OP_lit5:
617 case DW_OP_lit6:
618 case DW_OP_lit7:
619 case DW_OP_lit8:
620 case DW_OP_lit9:
621 case DW_OP_lit10:
622 case DW_OP_lit11:
623 case DW_OP_lit12:
624 case DW_OP_lit13:
625 case DW_OP_lit14:
626 case DW_OP_lit15:
627 case DW_OP_lit16:
628 case DW_OP_lit17:
629 case DW_OP_lit18:
630 case DW_OP_lit19:
631 case DW_OP_lit20:
632 case DW_OP_lit21:
633 case DW_OP_lit22:
634 case DW_OP_lit23:
635 case DW_OP_lit24:
636 case DW_OP_lit25:
637 case DW_OP_lit26:
638 case DW_OP_lit27:
639 case DW_OP_lit28:
640 case DW_OP_lit29:
641 case DW_OP_lit30:
642 case DW_OP_lit31:
643 value = static_cast<pint_t>(opcode - DW_OP_lit0);
644 *(++sp) = value;
645 if (log)
646 fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
647 break;
648
649 case DW_OP_reg0:
650 case DW_OP_reg1:
651 case DW_OP_reg2:
652 case DW_OP_reg3:
653 case DW_OP_reg4:
654 case DW_OP_reg5:
655 case DW_OP_reg6:
656 case DW_OP_reg7:
657 case DW_OP_reg8:
658 case DW_OP_reg9:
659 case DW_OP_reg10:
660 case DW_OP_reg11:
661 case DW_OP_reg12:
662 case DW_OP_reg13:
663 case DW_OP_reg14:
664 case DW_OP_reg15:
665 case DW_OP_reg16:
666 case DW_OP_reg17:
667 case DW_OP_reg18:
668 case DW_OP_reg19:
669 case DW_OP_reg20:
670 case DW_OP_reg21:
671 case DW_OP_reg22:
672 case DW_OP_reg23:
673 case DW_OP_reg24:
674 case DW_OP_reg25:
675 case DW_OP_reg26:
676 case DW_OP_reg27:
677 case DW_OP_reg28:
678 case DW_OP_reg29:
679 case DW_OP_reg30:
680 case DW_OP_reg31:
681 reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
682 *(++sp) = registers.getRegister((int)reg);
683 if (log)
684 fprintf(stderr, "push reg %d\n", reg);
685 break;
686
687 case DW_OP_regx:
688 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
689 *(++sp) = registers.getRegister((int)reg);
690 if (log)
691 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
692 break;
693
694 case DW_OP_breg0:
695 case DW_OP_breg1:
696 case DW_OP_breg2:
697 case DW_OP_breg3:
698 case DW_OP_breg4:
699 case DW_OP_breg5:
700 case DW_OP_breg6:
701 case DW_OP_breg7:
702 case DW_OP_breg8:
703 case DW_OP_breg9:
704 case DW_OP_breg10:
705 case DW_OP_breg11:
706 case DW_OP_breg12:
707 case DW_OP_breg13:
708 case DW_OP_breg14:
709 case DW_OP_breg15:
710 case DW_OP_breg16:
711 case DW_OP_breg17:
712 case DW_OP_breg18:
713 case DW_OP_breg19:
714 case DW_OP_breg20:
715 case DW_OP_breg21:
716 case DW_OP_breg22:
717 case DW_OP_breg23:
718 case DW_OP_breg24:
719 case DW_OP_breg25:
720 case DW_OP_breg26:
721 case DW_OP_breg27:
722 case DW_OP_breg28:
723 case DW_OP_breg29:
724 case DW_OP_breg30:
725 case DW_OP_breg31:
726 reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
727 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
728 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
729 *(++sp) = (pint_t)(svalue);
730 if (log)
731 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
732 break;
733
734 case DW_OP_bregx:
735 reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
736 svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
737 svalue += static_cast<sint_t>(registers.getRegister((int)reg));
738 *(++sp) = (pint_t)(svalue);
739 if (log)
740 fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
741 break;
742
743 case DW_OP_fbreg:
744 _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
745 break;
746
747 case DW_OP_piece:
748 _LIBUNWIND_ABORT("DW_OP_piece not implemented");
749 break;
750
751 case DW_OP_deref_size:
752 // pop stack, dereference, push result
753 value = *sp--;
754 switch (addressSpace.get8(p++)) {
755 case 1:
756 value = addressSpace.get8(value);
757 break;
758 case 2:
759 value = addressSpace.get16(value);
760 break;
761 case 4:
762 value = addressSpace.get32(value);
763 break;
764 case 8:
765 value = (pint_t)addressSpace.get64(value);
766 break;
767 default:
768 _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
769 }
770 *(++sp) = value;
771 if (log)
772 fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
773 break;
774
775 case DW_OP_xderef_size:
776 case DW_OP_nop:
777 case DW_OP_push_object_addres:
778 case DW_OP_call2:
779 case DW_OP_call4:
780 case DW_OP_call_ref:
781 default:
782 _LIBUNWIND_ABORT("DWARF opcode not implemented");
783 }
784
785 }
786 if (log)
787 fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
788 return *sp;
789}
790
791
792
793} // namespace libunwind
794
795#endif // __DWARF_INSTRUCTIONS_HPP__
libunwind/src/DwarfParser.hpp created+766
...@@ -0,0 +1,766 @@
1//===--------------------------- DwarfParser.hpp --------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Parses DWARF CFIs (FDEs and CIEs).
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef __DWARF_PARSER_HPP__
14#define __DWARF_PARSER_HPP__
15
16#include <inttypes.h>
17#include <stdint.h>
18#include <stdio.h>
19#include <stdlib.h>
20
21#include "libunwind.h"
22#include "dwarf2.h"
23#include "Registers.hpp"
24
25#include "config.h"
26
27namespace libunwind {
28
29/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
30/// See DWARF Spec for details:
31/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
32///
33template <typename A>
34class CFI_Parser {
35public:
36 typedef typename A::pint_t pint_t;
37
38 /// Information encoded in a CIE (Common Information Entry)
39 struct CIE_Info {
40 pint_t cieStart;
41 pint_t cieLength;
42 pint_t cieInstructions;
43 uint8_t pointerEncoding;
44 uint8_t lsdaEncoding;
45 uint8_t personalityEncoding;
46 uint8_t personalityOffsetInCIE;
47 pint_t personality;
48 uint32_t codeAlignFactor;
49 int dataAlignFactor;
50 bool isSignalFrame;
51 bool fdesHaveAugmentationData;
52 uint8_t returnAddressRegister;
53#if defined(_LIBUNWIND_TARGET_AARCH64)
54 bool addressesSignedWithBKey;
55#endif
56 };
57
58 /// Information about an FDE (Frame Description Entry)
59 struct FDE_Info {
60 pint_t fdeStart;
61 pint_t fdeLength;
62 pint_t fdeInstructions;
63 pint_t pcStart;
64 pint_t pcEnd;
65 pint_t lsda;
66 };
67
68 enum {
69 kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER
70 };
71 enum RegisterSavedWhere {
72 kRegisterUnused,
73 kRegisterInCFA,
74 kRegisterOffsetFromCFA,
75 kRegisterInRegister,
76 kRegisterAtExpression,
77 kRegisterIsExpression
78 };
79 struct RegisterLocation {
80 RegisterSavedWhere location;
81 int64_t value;
82 };
83 /// Information about a frame layout and registers saved determined
84 /// by "running" the DWARF FDE "instructions"
85 struct PrologInfo {
86 uint32_t cfaRegister;
87 int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
88 int64_t cfaExpression; // CFA = expression
89 uint32_t spExtraArgSize;
90 uint32_t codeOffsetAtStackDecrement;
91 bool registersInOtherRegisters;
92 bool sameValueUsed;
93 RegisterLocation savedRegisters[kMaxRegisterNumber + 1];
94 };
95
96 struct PrologInfoStackEntry {
97 PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
98 : next(n), info(i) {}
99 PrologInfoStackEntry *next;
100 PrologInfo info;
101 };
102
103 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
104 uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
105 CIE_Info *cieInfo);
106 static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
107 FDE_Info *fdeInfo, CIE_Info *cieInfo);
108 static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
109 const CIE_Info &cieInfo, pint_t upToPC,
110 int arch, PrologInfo *results);
111
112 static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
113
114private:
115 static bool parseInstructions(A &addressSpace, pint_t instructions,
116 pint_t instructionsEnd, const CIE_Info &cieInfo,
117 pint_t pcoffset,
118 PrologInfoStackEntry *&rememberStack, int arch,
119 PrologInfo *results);
120};
121
122/// Parse a FDE into a CIE_Info and an FDE_Info
123template <typename A>
124const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
125 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
126 pint_t p = fdeStart;
127 pint_t cfiLength = (pint_t)addressSpace.get32(p);
128 p += 4;
129 if (cfiLength == 0xffffffff) {
130 // 0xffffffff means length is really next 8 bytes
131 cfiLength = (pint_t)addressSpace.get64(p);
132 p += 8;
133 }
134 if (cfiLength == 0)
135 return "FDE has zero length"; // end marker
136 uint32_t ciePointer = addressSpace.get32(p);
137 if (ciePointer == 0)
138 return "FDE is really a CIE"; // this is a CIE not an FDE
139 pint_t nextCFI = p + cfiLength;
140 pint_t cieStart = p - ciePointer;
141 const char *err = parseCIE(addressSpace, cieStart, cieInfo);
142 if (err != NULL)
143 return err;
144 p += 4;
145 // Parse pc begin and range.
146 pint_t pcStart =
147 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
148 pint_t pcRange =
149 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
150 // Parse rest of info.
151 fdeInfo->lsda = 0;
152 // Check for augmentation length.
153 if (cieInfo->fdesHaveAugmentationData) {
154 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
155 pint_t endOfAug = p + augLen;
156 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
157 // Peek at value (without indirection). Zero means no LSDA.
158 pint_t lsdaStart = p;
159 if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
160 0) {
161 // Reset pointer and re-parse LSDA address.
162 p = lsdaStart;
163 fdeInfo->lsda =
164 addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
165 }
166 }
167 p = endOfAug;
168 }
169 fdeInfo->fdeStart = fdeStart;
170 fdeInfo->fdeLength = nextCFI - fdeStart;
171 fdeInfo->fdeInstructions = p;
172 fdeInfo->pcStart = pcStart;
173 fdeInfo->pcEnd = pcStart + pcRange;
174 return NULL; // success
175}
176
177/// Scan an eh_frame section to find an FDE for a pc
178template <typename A>
179bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
180 uint32_t sectionLength, pint_t fdeHint,
181 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
182 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
183 pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
184 const pint_t ehSectionEnd = p + sectionLength;
185 while (p < ehSectionEnd) {
186 pint_t currentCFI = p;
187 //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
188 pint_t cfiLength = addressSpace.get32(p);
189 p += 4;
190 if (cfiLength == 0xffffffff) {
191 // 0xffffffff means length is really next 8 bytes
192 cfiLength = (pint_t)addressSpace.get64(p);
193 p += 8;
194 }
195 if (cfiLength == 0)
196 return false; // end marker
197 uint32_t id = addressSpace.get32(p);
198 if (id == 0) {
199 // Skip over CIEs.
200 p += cfiLength;
201 } else {
202 // Process FDE to see if it covers pc.
203 pint_t nextCFI = p + cfiLength;
204 uint32_t ciePointer = addressSpace.get32(p);
205 pint_t cieStart = p - ciePointer;
206 // Validate pointer to CIE is within section.
207 if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
208 if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
209 p += 4;
210 // Parse pc begin and range.
211 pint_t pcStart =
212 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
213 pint_t pcRange = addressSpace.getEncodedP(
214 p, nextCFI, cieInfo->pointerEncoding & 0x0F);
215 // Test if pc is within the function this FDE covers.
216 if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
217 // parse rest of info
218 fdeInfo->lsda = 0;
219 // check for augmentation length
220 if (cieInfo->fdesHaveAugmentationData) {
221 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
222 pint_t endOfAug = p + augLen;
223 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
224 // Peek at value (without indirection). Zero means no LSDA.
225 pint_t lsdaStart = p;
226 if (addressSpace.getEncodedP(
227 p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
228 // Reset pointer and re-parse LSDA address.
229 p = lsdaStart;
230 fdeInfo->lsda = addressSpace
231 .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
232 }
233 }
234 p = endOfAug;
235 }
236 fdeInfo->fdeStart = currentCFI;
237 fdeInfo->fdeLength = nextCFI - currentCFI;
238 fdeInfo->fdeInstructions = p;
239 fdeInfo->pcStart = pcStart;
240 fdeInfo->pcEnd = pcStart + pcRange;
241 return true;
242 } else {
243 // pc is not in begin/range, skip this FDE
244 }
245 } else {
246 // Malformed CIE, now augmentation describing pc range encoding.
247 }
248 } else {
249 // malformed FDE. CIE is bad
250 }
251 p = nextCFI;
252 }
253 }
254 return false;
255}
256
257/// Extract info from a CIE
258template <typename A>
259const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
260 CIE_Info *cieInfo) {
261 cieInfo->pointerEncoding = 0;
262 cieInfo->lsdaEncoding = DW_EH_PE_omit;
263 cieInfo->personalityEncoding = 0;
264 cieInfo->personalityOffsetInCIE = 0;
265 cieInfo->personality = 0;
266 cieInfo->codeAlignFactor = 0;
267 cieInfo->dataAlignFactor = 0;
268 cieInfo->isSignalFrame = false;
269 cieInfo->fdesHaveAugmentationData = false;
270#if defined(_LIBUNWIND_TARGET_AARCH64)
271 cieInfo->addressesSignedWithBKey = false;
272#endif
273 cieInfo->cieStart = cie;
274 pint_t p = cie;
275 pint_t cieLength = (pint_t)addressSpace.get32(p);
276 p += 4;
277 pint_t cieContentEnd = p + cieLength;
278 if (cieLength == 0xffffffff) {
279 // 0xffffffff means length is really next 8 bytes
280 cieLength = (pint_t)addressSpace.get64(p);
281 p += 8;
282 cieContentEnd = p + cieLength;
283 }
284 if (cieLength == 0)
285 return NULL;
286 // CIE ID is always 0
287 if (addressSpace.get32(p) != 0)
288 return "CIE ID is not zero";
289 p += 4;
290 // Version is always 1 or 3
291 uint8_t version = addressSpace.get8(p);
292 if ((version != 1) && (version != 3))
293 return "CIE version is not 1 or 3";
294 ++p;
295 // save start of augmentation string and find end
296 pint_t strStart = p;
297 while (addressSpace.get8(p) != 0)
298 ++p;
299 ++p;
300 // parse code aligment factor
301 cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
302 // parse data alignment factor
303 cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
304 // parse return address register
305 uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd);
306 assert(raReg < 255 && "return address register too large");
307 cieInfo->returnAddressRegister = (uint8_t)raReg;
308 // parse augmentation data based on augmentation string
309 const char *result = NULL;
310 if (addressSpace.get8(strStart) == 'z') {
311 // parse augmentation data length
312 addressSpace.getULEB128(p, cieContentEnd);
313 for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
314 switch (addressSpace.get8(s)) {
315 case 'z':
316 cieInfo->fdesHaveAugmentationData = true;
317 break;
318 case 'P':
319 cieInfo->personalityEncoding = addressSpace.get8(p);
320 ++p;
321 cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
322 cieInfo->personality = addressSpace
323 .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
324 break;
325 case 'L':
326 cieInfo->lsdaEncoding = addressSpace.get8(p);
327 ++p;
328 break;
329 case 'R':
330 cieInfo->pointerEncoding = addressSpace.get8(p);
331 ++p;
332 break;
333 case 'S':
334 cieInfo->isSignalFrame = true;
335 break;
336#if defined(_LIBUNWIND_TARGET_AARCH64)
337 case 'B':
338 cieInfo->addressesSignedWithBKey = true;
339 break;
340#endif
341 default:
342 // ignore unknown letters
343 break;
344 }
345 }
346 }
347 cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
348 cieInfo->cieInstructions = p;
349 return result;
350}
351
352
353/// "run" the DWARF instructions and create the abstact PrologInfo for an FDE
354template <typename A>
355bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
356 const FDE_Info &fdeInfo,
357 const CIE_Info &cieInfo, pint_t upToPC,
358 int arch, PrologInfo *results) {
359 // clear results
360 memset(results, '\0', sizeof(PrologInfo));
361 PrologInfoStackEntry *rememberStack = NULL;
362
363 // parse CIE then FDE instructions
364 return parseInstructions(addressSpace, cieInfo.cieInstructions,
365 cieInfo.cieStart + cieInfo.cieLength, cieInfo,
366 (pint_t)(-1), rememberStack, arch, results) &&
367 parseInstructions(addressSpace, fdeInfo.fdeInstructions,
368 fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
369 upToPC - fdeInfo.pcStart, rememberStack, arch,
370 results);
371}
372
373/// "run" the DWARF instructions
374template <typename A>
375bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
376 pint_t instructionsEnd,
377 const CIE_Info &cieInfo, pint_t pcoffset,
378 PrologInfoStackEntry *&rememberStack,
379 int arch, PrologInfo *results) {
380 pint_t p = instructions;
381 pint_t codeOffset = 0;
382 PrologInfo initialState = *results;
383
384 _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n",
385 static_cast<uint64_t>(instructionsEnd));
386
387 // see DWARF Spec, section 6.4.2 for details on unwind opcodes
388 while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
389 uint64_t reg;
390 uint64_t reg2;
391 int64_t offset;
392 uint64_t length;
393 uint8_t opcode = addressSpace.get8(p);
394 uint8_t operand;
395#if !defined(_LIBUNWIND_NO_HEAP)
396 PrologInfoStackEntry *entry;
397#endif
398 ++p;
399 switch (opcode) {
400 case DW_CFA_nop:
401 _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n");
402 break;
403 case DW_CFA_set_loc:
404 codeOffset =
405 addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
406 _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n");
407 break;
408 case DW_CFA_advance_loc1:
409 codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
410 p += 1;
411 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n",
412 static_cast<uint64_t>(codeOffset));
413 break;
414 case DW_CFA_advance_loc2:
415 codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
416 p += 2;
417 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n",
418 static_cast<uint64_t>(codeOffset));
419 break;
420 case DW_CFA_advance_loc4:
421 codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
422 p += 4;
423 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n",
424 static_cast<uint64_t>(codeOffset));
425 break;
426 case DW_CFA_offset_extended:
427 reg = addressSpace.getULEB128(p, instructionsEnd);
428 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
429 * cieInfo.dataAlignFactor;
430 if (reg > kMaxRegisterNumber) {
431 _LIBUNWIND_LOG0(
432 "malformed DW_CFA_offset_extended DWARF unwind, reg too big");
433 return false;
434 }
435 results->savedRegisters[reg].location = kRegisterInCFA;
436 results->savedRegisters[reg].value = offset;
437 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", "
438 "offset=%" PRId64 ")\n",
439 reg, offset);
440 break;
441 case DW_CFA_restore_extended:
442 reg = addressSpace.getULEB128(p, instructionsEnd);
443 if (reg > kMaxRegisterNumber) {
444 _LIBUNWIND_LOG0(
445 "malformed DW_CFA_restore_extended DWARF unwind, reg too big");
446 return false;
447 }
448 results->savedRegisters[reg] = initialState.savedRegisters[reg];
449 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg);
450 break;
451 case DW_CFA_undefined:
452 reg = addressSpace.getULEB128(p, instructionsEnd);
453 if (reg > kMaxRegisterNumber) {
454 _LIBUNWIND_LOG0(
455 "malformed DW_CFA_undefined DWARF unwind, reg too big");
456 return false;
457 }
458 results->savedRegisters[reg].location = kRegisterUnused;
459 _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg);
460 break;
461 case DW_CFA_same_value:
462 reg = addressSpace.getULEB128(p, instructionsEnd);
463 if (reg > kMaxRegisterNumber) {
464 _LIBUNWIND_LOG0(
465 "malformed DW_CFA_same_value DWARF unwind, reg too big");
466 return false;
467 }
468 // <rdar://problem/8456377> DW_CFA_same_value unsupported
469 // "same value" means register was stored in frame, but its current
470 // value has not changed, so no need to restore from frame.
471 // We model this as if the register was never saved.
472 results->savedRegisters[reg].location = kRegisterUnused;
473 // set flag to disable conversion to compact unwind
474 results->sameValueUsed = true;
475 _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg);
476 break;
477 case DW_CFA_register:
478 reg = addressSpace.getULEB128(p, instructionsEnd);
479 reg2 = addressSpace.getULEB128(p, instructionsEnd);
480 if (reg > kMaxRegisterNumber) {
481 _LIBUNWIND_LOG0(
482 "malformed DW_CFA_register DWARF unwind, reg too big");
483 return false;
484 }
485 if (reg2 > kMaxRegisterNumber) {
486 _LIBUNWIND_LOG0(
487 "malformed DW_CFA_register DWARF unwind, reg2 too big");
488 return false;
489 }
490 results->savedRegisters[reg].location = kRegisterInRegister;
491 results->savedRegisters[reg].value = (int64_t)reg2;
492 // set flag to disable conversion to compact unwind
493 results->registersInOtherRegisters = true;
494 _LIBUNWIND_TRACE_DWARF(
495 "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2);
496 break;
497#if !defined(_LIBUNWIND_NO_HEAP)
498 case DW_CFA_remember_state:
499 // avoid operator new, because that would be an upward dependency
500 entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
501 if (entry != NULL) {
502 entry->next = rememberStack;
503 entry->info = *results;
504 rememberStack = entry;
505 } else {
506 return false;
507 }
508 _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n");
509 break;
510 case DW_CFA_restore_state:
511 if (rememberStack != NULL) {
512 PrologInfoStackEntry *top = rememberStack;
513 *results = top->info;
514 rememberStack = top->next;
515 free((char *)top);
516 } else {
517 return false;
518 }
519 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n");
520 break;
521#endif
522 case DW_CFA_def_cfa:
523 reg = addressSpace.getULEB128(p, instructionsEnd);
524 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
525 if (reg > kMaxRegisterNumber) {
526 _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big");
527 return false;
528 }
529 results->cfaRegister = (uint32_t)reg;
530 results->cfaRegisterOffset = (int32_t)offset;
531 _LIBUNWIND_TRACE_DWARF(
532 "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset);
533 break;
534 case DW_CFA_def_cfa_register:
535 reg = addressSpace.getULEB128(p, instructionsEnd);
536 if (reg > kMaxRegisterNumber) {
537 _LIBUNWIND_LOG0(
538 "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big");
539 return false;
540 }
541 results->cfaRegister = (uint32_t)reg;
542 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg);
543 break;
544 case DW_CFA_def_cfa_offset:
545 results->cfaRegisterOffset = (int32_t)
546 addressSpace.getULEB128(p, instructionsEnd);
547 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
548 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n",
549 results->cfaRegisterOffset);
550 break;
551 case DW_CFA_def_cfa_expression:
552 results->cfaRegister = 0;
553 results->cfaExpression = (int64_t)p;
554 length = addressSpace.getULEB128(p, instructionsEnd);
555 assert(length < static_cast<pint_t>(~0) && "pointer overflow");
556 p += static_cast<pint_t>(length);
557 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64
558 ", length=%" PRIu64 ")\n",
559 results->cfaExpression, length);
560 break;
561 case DW_CFA_expression:
562 reg = addressSpace.getULEB128(p, instructionsEnd);
563 if (reg > kMaxRegisterNumber) {
564 _LIBUNWIND_LOG0(
565 "malformed DW_CFA_expression DWARF unwind, reg too big");
566 return false;
567 }
568 results->savedRegisters[reg].location = kRegisterAtExpression;
569 results->savedRegisters[reg].value = (int64_t)p;
570 length = addressSpace.getULEB128(p, instructionsEnd);
571 assert(length < static_cast<pint_t>(~0) && "pointer overflow");
572 p += static_cast<pint_t>(length);
573 _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", "
574 "expression=0x%" PRIx64 ", "
575 "length=%" PRIu64 ")\n",
576 reg, results->savedRegisters[reg].value, length);
577 break;
578 case DW_CFA_offset_extended_sf:
579 reg = addressSpace.getULEB128(p, instructionsEnd);
580 if (reg > kMaxRegisterNumber) {
581 _LIBUNWIND_LOG0(
582 "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big");
583 return false;
584 }
585 offset =
586 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
587 results->savedRegisters[reg].location = kRegisterInCFA;
588 results->savedRegisters[reg].value = offset;
589 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", "
590 "offset=%" PRId64 ")\n",
591 reg, offset);
592 break;
593 case DW_CFA_def_cfa_sf:
594 reg = addressSpace.getULEB128(p, instructionsEnd);
595 offset =
596 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
597 if (reg > kMaxRegisterNumber) {
598 _LIBUNWIND_LOG0(
599 "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big");
600 return false;
601 }
602 results->cfaRegister = (uint32_t)reg;
603 results->cfaRegisterOffset = (int32_t)offset;
604 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", "
605 "offset=%" PRId64 ")\n",
606 reg, offset);
607 break;
608 case DW_CFA_def_cfa_offset_sf:
609 results->cfaRegisterOffset = (int32_t)
610 (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
611 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
612 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n",
613 results->cfaRegisterOffset);
614 break;
615 case DW_CFA_val_offset:
616 reg = addressSpace.getULEB128(p, instructionsEnd);
617 if (reg > kMaxRegisterNumber) {
618 _LIBUNWIND_LOG(
619 "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64
620 ") out of range\n",
621 reg);
622 return false;
623 }
624 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
625 * cieInfo.dataAlignFactor;
626 results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
627 results->savedRegisters[reg].value = offset;
628 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", "
629 "offset=%" PRId64 "\n",
630 reg, offset);
631 break;
632 case DW_CFA_val_offset_sf:
633 reg = addressSpace.getULEB128(p, instructionsEnd);
634 if (reg > kMaxRegisterNumber) {
635 _LIBUNWIND_LOG0(
636 "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big");
637 return false;
638 }
639 offset =
640 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
641 results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
642 results->savedRegisters[reg].value = offset;
643 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", "
644 "offset=%" PRId64 "\n",
645 reg, offset);
646 break;
647 case DW_CFA_val_expression:
648 reg = addressSpace.getULEB128(p, instructionsEnd);
649 if (reg > kMaxRegisterNumber) {
650 _LIBUNWIND_LOG0(
651 "malformed DW_CFA_val_expression DWARF unwind, reg too big");
652 return false;
653 }
654 results->savedRegisters[reg].location = kRegisterIsExpression;
655 results->savedRegisters[reg].value = (int64_t)p;
656 length = addressSpace.getULEB128(p, instructionsEnd);
657 assert(length < static_cast<pint_t>(~0) && "pointer overflow");
658 p += static_cast<pint_t>(length);
659 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", "
660 "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n",
661 reg, results->savedRegisters[reg].value, length);
662 break;
663 case DW_CFA_GNU_args_size:
664 length = addressSpace.getULEB128(p, instructionsEnd);
665 results->spExtraArgSize = (uint32_t)length;
666 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length);
667 break;
668 case DW_CFA_GNU_negative_offset_extended:
669 reg = addressSpace.getULEB128(p, instructionsEnd);
670 if (reg > kMaxRegisterNumber) {
671 _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF "
672 "unwind, reg too big");
673 return false;
674 }
675 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
676 * cieInfo.dataAlignFactor;
677 results->savedRegisters[reg].location = kRegisterInCFA;
678 results->savedRegisters[reg].value = -offset;
679 _LIBUNWIND_TRACE_DWARF(
680 "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset);
681 break;
682
683#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC)
684 // The same constant is used to represent different instructions on
685 // AArch64 (negate_ra_state) and SPARC (window_save).
686 static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save,
687 "uses the same constant");
688 case DW_CFA_AARCH64_negate_ra_state:
689 switch (arch) {
690#if defined(_LIBUNWIND_TARGET_AARCH64)
691 case REGISTERS_ARM64:
692 results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1;
693 _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n");
694 break;
695#endif
696#if defined(_LIBUNWIND_TARGET_SPARC)
697 // case DW_CFA_GNU_window_save:
698 case REGISTERS_SPARC:
699 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n");
700 for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) {
701 results->savedRegisters[reg].location = kRegisterInRegister;
702 results->savedRegisters[reg].value =
703 ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0;
704 }
705
706 for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
707 results->savedRegisters[reg].location = kRegisterInCFA;
708 results->savedRegisters[reg].value =
709 ((int64_t)reg - UNW_SPARC_L0) * 4;
710 }
711 break;
712#endif
713 }
714 break;
715#else
716 (void)arch;
717#endif
718
719 default:
720 operand = opcode & 0x3F;
721 switch (opcode & 0xC0) {
722 case DW_CFA_offset:
723 reg = operand;
724 if (reg > kMaxRegisterNumber) {
725 _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64
726 ") out of range",
727 reg);
728 return false;
729 }
730 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
731 * cieInfo.dataAlignFactor;
732 results->savedRegisters[reg].location = kRegisterInCFA;
733 results->savedRegisters[reg].value = offset;
734 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n",
735 operand, offset);
736 break;
737 case DW_CFA_advance_loc:
738 codeOffset += operand * cieInfo.codeAlignFactor;
739 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n",
740 static_cast<uint64_t>(codeOffset));
741 break;
742 case DW_CFA_restore:
743 reg = operand;
744 if (reg > kMaxRegisterNumber) {
745 _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64
746 ") out of range",
747 reg);
748 return false;
749 }
750 results->savedRegisters[reg] = initialState.savedRegisters[reg];
751 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n",
752 static_cast<uint64_t>(operand));
753 break;
754 default:
755 _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode);
756 return false;
757 }
758 }
759 }
760
761 return true;
762}
763
764} // namespace libunwind
765
766#endif // __DWARF_PARSER_HPP__
libunwind/src/EHHeaderParser.hpp created+168
...@@ -0,0 +1,168 @@
1//===------------------------- EHHeaderParser.hpp -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Parses ELF .eh_frame_hdr sections.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef __EHHEADERPARSER_HPP__
14#define __EHHEADERPARSER_HPP__
15
16#include "libunwind.h"
17
18#include "DwarfParser.hpp"
19
20namespace libunwind {
21
22/// \brief EHHeaderParser does basic parsing of an ELF .eh_frame_hdr section.
23///
24/// See DWARF spec for details:
25/// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
26///
27template <typename A> class EHHeaderParser {
28public:
29 typedef typename A::pint_t pint_t;
30
31 /// Information encoded in the EH frame header.
32 struct EHHeaderInfo {
33 pint_t eh_frame_ptr;
34 size_t fde_count;
35 pint_t table;
36 uint8_t table_enc;
37 };
38
39 static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
40 EHHeaderInfo &ehHdrInfo);
41 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
42 uint32_t sectionLength,
43 typename CFI_Parser<A>::FDE_Info *fdeInfo,
44 typename CFI_Parser<A>::CIE_Info *cieInfo);
45
46private:
47 static bool decodeTableEntry(A &addressSpace, pint_t &tableEntry,
48 pint_t ehHdrStart, pint_t ehHdrEnd,
49 uint8_t tableEnc,
50 typename CFI_Parser<A>::FDE_Info *fdeInfo,
51 typename CFI_Parser<A>::CIE_Info *cieInfo);
52 static size_t getTableEntrySize(uint8_t tableEnc);
53};
54
55template <typename A>
56bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
57 pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
58 pint_t p = ehHdrStart;
59 uint8_t version = addressSpace.get8(p++);
60 if (version != 1) {
61 _LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version");
62 return false;
63 }
64
65 uint8_t eh_frame_ptr_enc = addressSpace.get8(p++);
66 uint8_t fde_count_enc = addressSpace.get8(p++);
67 ehHdrInfo.table_enc = addressSpace.get8(p++);
68
69 ehHdrInfo.eh_frame_ptr =
70 addressSpace.getEncodedP(p, ehHdrEnd, eh_frame_ptr_enc, ehHdrStart);
71 ehHdrInfo.fde_count =
72 fde_count_enc == DW_EH_PE_omit
73 ? 0
74 : addressSpace.getEncodedP(p, ehHdrEnd, fde_count_enc, ehHdrStart);
75 ehHdrInfo.table = p;
76
77 return true;
78}
79
80template <typename A>
81bool EHHeaderParser<A>::decodeTableEntry(
82 A &addressSpace, pint_t &tableEntry, pint_t ehHdrStart, pint_t ehHdrEnd,
83 uint8_t tableEnc, typename CFI_Parser<A>::FDE_Info *fdeInfo,
84 typename CFI_Parser<A>::CIE_Info *cieInfo) {
85 // Have to decode the whole FDE for the PC range anyway, so just throw away
86 // the PC start.
87 addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart);
88 pint_t fde =
89 addressSpace.getEncodedP(tableEntry, ehHdrEnd, tableEnc, ehHdrStart);
90 const char *message =
91 CFI_Parser<A>::decodeFDE(addressSpace, fde, fdeInfo, cieInfo);
92 if (message != NULL) {
93 _LIBUNWIND_DEBUG_LOG("EHHeaderParser::decodeTableEntry: bad fde: %s",
94 message);
95 return false;
96 }
97
98 return true;
99}
100
101template <typename A>
102bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
103 uint32_t sectionLength,
104 typename CFI_Parser<A>::FDE_Info *fdeInfo,
105 typename CFI_Parser<A>::CIE_Info *cieInfo) {
106 pint_t ehHdrEnd = ehHdrStart + sectionLength;
107
108 EHHeaderParser<A>::EHHeaderInfo hdrInfo;
109 if (!EHHeaderParser<A>::decodeEHHdr(addressSpace, ehHdrStart, ehHdrEnd,
110 hdrInfo))
111 return false;
112
113 size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc);
114 pint_t tableEntry;
115
116 size_t low = 0;
117 for (size_t len = hdrInfo.fde_count; len > 1;) {
118 size_t mid = low + (len / 2);
119 tableEntry = hdrInfo.table + mid * tableEntrySize;
120 pint_t start = addressSpace.getEncodedP(tableEntry, ehHdrEnd,
121 hdrInfo.table_enc, ehHdrStart);
122
123 if (start == pc) {
124 low = mid;
125 break;
126 } else if (start < pc) {
127 low = mid;
128 len -= (len / 2);
129 } else {
130 len /= 2;
131 }
132 }
133
134 tableEntry = hdrInfo.table + low * tableEntrySize;
135 if (decodeTableEntry(addressSpace, tableEntry, ehHdrStart, ehHdrEnd,
136 hdrInfo.table_enc, fdeInfo, cieInfo)) {
137 if (pc >= fdeInfo->pcStart && pc < fdeInfo->pcEnd)
138 return true;
139 }
140
141 return false;
142}
143
144template <typename A>
145size_t EHHeaderParser<A>::getTableEntrySize(uint8_t tableEnc) {
146 switch (tableEnc & 0x0f) {
147 case DW_EH_PE_sdata2:
148 case DW_EH_PE_udata2:
149 return 4;
150 case DW_EH_PE_sdata4:
151 case DW_EH_PE_udata4:
152 return 8;
153 case DW_EH_PE_sdata8:
154 case DW_EH_PE_udata8:
155 return 16;
156 case DW_EH_PE_sleb128:
157 case DW_EH_PE_uleb128:
158 _LIBUNWIND_ABORT("Can't binary search on variable length encoded data.");
159 case DW_EH_PE_omit:
160 return 0;
161 default:
162 _LIBUNWIND_ABORT("Unknown DWARF encoding for search table.");
163 }
164}
165
166}
167
168#endif
libunwind/src/RWMutex.hpp created+77
...@@ -0,0 +1,77 @@
1//===----------------------------- Registers.hpp --------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Abstract interface to shared reader/writer log, hiding platform and
10// configuration differences.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef __RWMUTEX_HPP__
15#define __RWMUTEX_HPP__
16
17#if defined(_WIN32)
18#include <windows.h>
19#elif !defined(_LIBUNWIND_HAS_NO_THREADS)
20#include <pthread.h>
21#endif
22
23namespace libunwind {
24
25#if defined(_LIBUNWIND_HAS_NO_THREADS)
26
27class _LIBUNWIND_HIDDEN RWMutex {
28public:
29 bool lock_shared() { return true; }
30 bool unlock_shared() { return true; }
31 bool lock() { return true; }
32 bool unlock() { return true; }
33};
34
35#elif defined(_WIN32)
36
37class _LIBUNWIND_HIDDEN RWMutex {
38public:
39 bool lock_shared() {
40 AcquireSRWLockShared(&_lock);
41 return true;
42 }
43 bool unlock_shared() {
44 ReleaseSRWLockShared(&_lock);
45 return true;
46 }
47 bool lock() {
48 AcquireSRWLockExclusive(&_lock);
49 return true;
50 }
51 bool unlock() {
52 ReleaseSRWLockExclusive(&_lock);
53 return true;
54 }
55
56private:
57 SRWLOCK _lock = SRWLOCK_INIT;
58};
59
60#else
61
62class _LIBUNWIND_HIDDEN RWMutex {
63public:
64 bool lock_shared() { return pthread_rwlock_rdlock(&_lock) == 0; }
65 bool unlock_shared() { return pthread_rwlock_unlock(&_lock) == 0; }
66 bool lock() { return pthread_rwlock_wrlock(&_lock) == 0; }
67 bool unlock() { return pthread_rwlock_unlock(&_lock) == 0; }
68
69private:
70 pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER;
71};
72
73#endif
74
75} // namespace libunwind
76
77#endif // __RWMUTEX_HPP__
libunwind/src/Registers.hpp created+3523
...@@ -0,0 +1,3523 @@
1//===----------------------------- Registers.hpp --------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Models register sets for supported processors.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef __REGISTERS_HPP__
14#define __REGISTERS_HPP__
15
16#include <stdint.h>
17#include <string.h>
18
19#include "libunwind.h"
20#include "config.h"
21
22namespace libunwind {
23
24// For emulating 128-bit registers
25struct v128 { uint32_t vec[4]; };
26
27enum {
28 REGISTERS_X86,
29 REGISTERS_X86_64,
30 REGISTERS_PPC,
31 REGISTERS_PPC64,
32 REGISTERS_ARM64,
33 REGISTERS_ARM,
34 REGISTERS_OR1K,
35 REGISTERS_MIPS_O32,
36 REGISTERS_MIPS_NEWABI,
37 REGISTERS_SPARC,
38};
39
40#if defined(_LIBUNWIND_TARGET_I386)
41/// Registers_x86 holds the register state of a thread in a 32-bit intel
42/// process.
43class _LIBUNWIND_HIDDEN Registers_x86 {
44public:
45 Registers_x86();
46 Registers_x86(const void *registers);
47
48 bool validRegister(int num) const;
49 uint32_t getRegister(int num) const;
50 void setRegister(int num, uint32_t value);
51 bool validFloatRegister(int) const { return false; }
52 double getFloatRegister(int num) const;
53 void setFloatRegister(int num, double value);
54 bool validVectorRegister(int) const { return false; }
55 v128 getVectorRegister(int num) const;
56 void setVectorRegister(int num, v128 value);
57 static const char *getRegisterName(int num);
58 void jumpto();
59 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }
60 static int getArch() { return REGISTERS_X86; }
61
62 uint32_t getSP() const { return _registers.__esp; }
63 void setSP(uint32_t value) { _registers.__esp = value; }
64 uint32_t getIP() const { return _registers.__eip; }
65 void setIP(uint32_t value) { _registers.__eip = value; }
66 uint32_t getEBP() const { return _registers.__ebp; }
67 void setEBP(uint32_t value) { _registers.__ebp = value; }
68 uint32_t getEBX() const { return _registers.__ebx; }
69 void setEBX(uint32_t value) { _registers.__ebx = value; }
70 uint32_t getECX() const { return _registers.__ecx; }
71 void setECX(uint32_t value) { _registers.__ecx = value; }
72 uint32_t getEDX() const { return _registers.__edx; }
73 void setEDX(uint32_t value) { _registers.__edx = value; }
74 uint32_t getESI() const { return _registers.__esi; }
75 void setESI(uint32_t value) { _registers.__esi = value; }
76 uint32_t getEDI() const { return _registers.__edi; }
77 void setEDI(uint32_t value) { _registers.__edi = value; }
78
79private:
80 struct GPRs {
81 unsigned int __eax;
82 unsigned int __ebx;
83 unsigned int __ecx;
84 unsigned int __edx;
85 unsigned int __edi;
86 unsigned int __esi;
87 unsigned int __ebp;
88 unsigned int __esp;
89 unsigned int __ss;
90 unsigned int __eflags;
91 unsigned int __eip;
92 unsigned int __cs;
93 unsigned int __ds;
94 unsigned int __es;
95 unsigned int __fs;
96 unsigned int __gs;
97 };
98
99 GPRs _registers;
100};
101
102inline Registers_x86::Registers_x86(const void *registers) {
103 static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),
104 "x86 registers do not fit into unw_context_t");
105 memcpy(&_registers, registers, sizeof(_registers));
106}
107
108inline Registers_x86::Registers_x86() {
109 memset(&_registers, 0, sizeof(_registers));
110}
111
112inline bool Registers_x86::validRegister(int regNum) const {
113 if (regNum == UNW_REG_IP)
114 return true;
115 if (regNum == UNW_REG_SP)
116 return true;
117 if (regNum < 0)
118 return false;
119 if (regNum > 7)
120 return false;
121 return true;
122}
123
124inline uint32_t Registers_x86::getRegister(int regNum) const {
125 switch (regNum) {
126 case UNW_REG_IP:
127 return _registers.__eip;
128 case UNW_REG_SP:
129 return _registers.__esp;
130 case UNW_X86_EAX:
131 return _registers.__eax;
132 case UNW_X86_ECX:
133 return _registers.__ecx;
134 case UNW_X86_EDX:
135 return _registers.__edx;
136 case UNW_X86_EBX:
137 return _registers.__ebx;
138#if !defined(__APPLE__)
139 case UNW_X86_ESP:
140#else
141 case UNW_X86_EBP:
142#endif
143 return _registers.__ebp;
144#if !defined(__APPLE__)
145 case UNW_X86_EBP:
146#else
147 case UNW_X86_ESP:
148#endif
149 return _registers.__esp;
150 case UNW_X86_ESI:
151 return _registers.__esi;
152 case UNW_X86_EDI:
153 return _registers.__edi;
154 }
155 _LIBUNWIND_ABORT("unsupported x86 register");
156}
157
158inline void Registers_x86::setRegister(int regNum, uint32_t value) {
159 switch (regNum) {
160 case UNW_REG_IP:
161 _registers.__eip = value;
162 return;
163 case UNW_REG_SP:
164 _registers.__esp = value;
165 return;
166 case UNW_X86_EAX:
167 _registers.__eax = value;
168 return;
169 case UNW_X86_ECX:
170 _registers.__ecx = value;
171 return;
172 case UNW_X86_EDX:
173 _registers.__edx = value;
174 return;
175 case UNW_X86_EBX:
176 _registers.__ebx = value;
177 return;
178#if !defined(__APPLE__)
179 case UNW_X86_ESP:
180#else
181 case UNW_X86_EBP:
182#endif
183 _registers.__ebp = value;
184 return;
185#if !defined(__APPLE__)
186 case UNW_X86_EBP:
187#else
188 case UNW_X86_ESP:
189#endif
190 _registers.__esp = value;
191 return;
192 case UNW_X86_ESI:
193 _registers.__esi = value;
194 return;
195 case UNW_X86_EDI:
196 _registers.__edi = value;
197 return;
198 }
199 _LIBUNWIND_ABORT("unsupported x86 register");
200}
201
202inline const char *Registers_x86::getRegisterName(int regNum) {
203 switch (regNum) {
204 case UNW_REG_IP:
205 return "ip";
206 case UNW_REG_SP:
207 return "esp";
208 case UNW_X86_EAX:
209 return "eax";
210 case UNW_X86_ECX:
211 return "ecx";
212 case UNW_X86_EDX:
213 return "edx";
214 case UNW_X86_EBX:
215 return "ebx";
216 case UNW_X86_EBP:
217 return "ebp";
218 case UNW_X86_ESP:
219 return "esp";
220 case UNW_X86_ESI:
221 return "esi";
222 case UNW_X86_EDI:
223 return "edi";
224 default:
225 return "unknown register";
226 }
227}
228
229inline double Registers_x86::getFloatRegister(int) const {
230 _LIBUNWIND_ABORT("no x86 float registers");
231}
232
233inline void Registers_x86::setFloatRegister(int, double) {
234 _LIBUNWIND_ABORT("no x86 float registers");
235}
236
237inline v128 Registers_x86::getVectorRegister(int) const {
238 _LIBUNWIND_ABORT("no x86 vector registers");
239}
240
241inline void Registers_x86::setVectorRegister(int, v128) {
242 _LIBUNWIND_ABORT("no x86 vector registers");
243}
244#endif // _LIBUNWIND_TARGET_I386
245
246
247#if defined(_LIBUNWIND_TARGET_X86_64)
248/// Registers_x86_64 holds the register state of a thread in a 64-bit intel
249/// process.
250class _LIBUNWIND_HIDDEN Registers_x86_64 {
251public:
252 Registers_x86_64();
253 Registers_x86_64(const void *registers);
254
255 bool validRegister(int num) const;
256 uint64_t getRegister(int num) const;
257 void setRegister(int num, uint64_t value);
258 bool validFloatRegister(int) const { return false; }
259 double getFloatRegister(int num) const;
260 void setFloatRegister(int num, double value);
261 bool validVectorRegister(int) const;
262 v128 getVectorRegister(int num) const;
263 void setVectorRegister(int num, v128 value);
264 static const char *getRegisterName(int num);
265 void jumpto();
266 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }
267 static int getArch() { return REGISTERS_X86_64; }
268
269 uint64_t getSP() const { return _registers.__rsp; }
270 void setSP(uint64_t value) { _registers.__rsp = value; }
271 uint64_t getIP() const { return _registers.__rip; }
272 void setIP(uint64_t value) { _registers.__rip = value; }
273 uint64_t getRBP() const { return _registers.__rbp; }
274 void setRBP(uint64_t value) { _registers.__rbp = value; }
275 uint64_t getRBX() const { return _registers.__rbx; }
276 void setRBX(uint64_t value) { _registers.__rbx = value; }
277 uint64_t getR12() const { return _registers.__r12; }
278 void setR12(uint64_t value) { _registers.__r12 = value; }
279 uint64_t getR13() const { return _registers.__r13; }
280 void setR13(uint64_t value) { _registers.__r13 = value; }
281 uint64_t getR14() const { return _registers.__r14; }
282 void setR14(uint64_t value) { _registers.__r14 = value; }
283 uint64_t getR15() const { return _registers.__r15; }
284 void setR15(uint64_t value) { _registers.__r15 = value; }
285
286private:
287 struct GPRs {
288 uint64_t __rax;
289 uint64_t __rbx;
290 uint64_t __rcx;
291 uint64_t __rdx;
292 uint64_t __rdi;
293 uint64_t __rsi;
294 uint64_t __rbp;
295 uint64_t __rsp;
296 uint64_t __r8;
297 uint64_t __r9;
298 uint64_t __r10;
299 uint64_t __r11;
300 uint64_t __r12;
301 uint64_t __r13;
302 uint64_t __r14;
303 uint64_t __r15;
304 uint64_t __rip;
305 uint64_t __rflags;
306 uint64_t __cs;
307 uint64_t __fs;
308 uint64_t __gs;
309#if defined(_WIN64)
310 uint64_t __padding; // 16-byte align
311#endif
312 };
313 GPRs _registers;
314#if defined(_WIN64)
315 v128 _xmm[16];
316#endif
317};
318
319inline Registers_x86_64::Registers_x86_64(const void *registers) {
320 static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),
321 "x86_64 registers do not fit into unw_context_t");
322 memcpy(&_registers, registers, sizeof(_registers));
323}
324
325inline Registers_x86_64::Registers_x86_64() {
326 memset(&_registers, 0, sizeof(_registers));
327}
328
329inline bool Registers_x86_64::validRegister(int regNum) const {
330 if (regNum == UNW_REG_IP)
331 return true;
332 if (regNum == UNW_REG_SP)
333 return true;
334 if (regNum < 0)
335 return false;
336 if (regNum > 15)
337 return false;
338 return true;
339}
340
341inline uint64_t Registers_x86_64::getRegister(int regNum) const {
342 switch (regNum) {
343 case UNW_REG_IP:
344 return _registers.__rip;
345 case UNW_REG_SP:
346 return _registers.__rsp;
347 case UNW_X86_64_RAX:
348 return _registers.__rax;
349 case UNW_X86_64_RDX:
350 return _registers.__rdx;
351 case UNW_X86_64_RCX:
352 return _registers.__rcx;
353 case UNW_X86_64_RBX:
354 return _registers.__rbx;
355 case UNW_X86_64_RSI:
356 return _registers.__rsi;
357 case UNW_X86_64_RDI:
358 return _registers.__rdi;
359 case UNW_X86_64_RBP:
360 return _registers.__rbp;
361 case UNW_X86_64_RSP:
362 return _registers.__rsp;
363 case UNW_X86_64_R8:
364 return _registers.__r8;
365 case UNW_X86_64_R9:
366 return _registers.__r9;
367 case UNW_X86_64_R10:
368 return _registers.__r10;
369 case UNW_X86_64_R11:
370 return _registers.__r11;
371 case UNW_X86_64_R12:
372 return _registers.__r12;
373 case UNW_X86_64_R13:
374 return _registers.__r13;
375 case UNW_X86_64_R14:
376 return _registers.__r14;
377 case UNW_X86_64_R15:
378 return _registers.__r15;
379 }
380 _LIBUNWIND_ABORT("unsupported x86_64 register");
381}
382
383inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
384 switch (regNum) {
385 case UNW_REG_IP:
386 _registers.__rip = value;
387 return;
388 case UNW_REG_SP:
389 _registers.__rsp = value;
390 return;
391 case UNW_X86_64_RAX:
392 _registers.__rax = value;
393 return;
394 case UNW_X86_64_RDX:
395 _registers.__rdx = value;
396 return;
397 case UNW_X86_64_RCX:
398 _registers.__rcx = value;
399 return;
400 case UNW_X86_64_RBX:
401 _registers.__rbx = value;
402 return;
403 case UNW_X86_64_RSI:
404 _registers.__rsi = value;
405 return;
406 case UNW_X86_64_RDI:
407 _registers.__rdi = value;
408 return;
409 case UNW_X86_64_RBP:
410 _registers.__rbp = value;
411 return;
412 case UNW_X86_64_RSP:
413 _registers.__rsp = value;
414 return;
415 case UNW_X86_64_R8:
416 _registers.__r8 = value;
417 return;
418 case UNW_X86_64_R9:
419 _registers.__r9 = value;
420 return;
421 case UNW_X86_64_R10:
422 _registers.__r10 = value;
423 return;
424 case UNW_X86_64_R11:
425 _registers.__r11 = value;
426 return;
427 case UNW_X86_64_R12:
428 _registers.__r12 = value;
429 return;
430 case UNW_X86_64_R13:
431 _registers.__r13 = value;
432 return;
433 case UNW_X86_64_R14:
434 _registers.__r14 = value;
435 return;
436 case UNW_X86_64_R15:
437 _registers.__r15 = value;
438 return;
439 }
440 _LIBUNWIND_ABORT("unsupported x86_64 register");
441}
442
443inline const char *Registers_x86_64::getRegisterName(int regNum) {
444 switch (regNum) {
445 case UNW_REG_IP:
446 return "rip";
447 case UNW_REG_SP:
448 return "rsp";
449 case UNW_X86_64_RAX:
450 return "rax";
451 case UNW_X86_64_RDX:
452 return "rdx";
453 case UNW_X86_64_RCX:
454 return "rcx";
455 case UNW_X86_64_RBX:
456 return "rbx";
457 case UNW_X86_64_RSI:
458 return "rsi";
459 case UNW_X86_64_RDI:
460 return "rdi";
461 case UNW_X86_64_RBP:
462 return "rbp";
463 case UNW_X86_64_RSP:
464 return "rsp";
465 case UNW_X86_64_R8:
466 return "r8";
467 case UNW_X86_64_R9:
468 return "r9";
469 case UNW_X86_64_R10:
470 return "r10";
471 case UNW_X86_64_R11:
472 return "r11";
473 case UNW_X86_64_R12:
474 return "r12";
475 case UNW_X86_64_R13:
476 return "r13";
477 case UNW_X86_64_R14:
478 return "r14";
479 case UNW_X86_64_R15:
480 return "r15";
481 case UNW_X86_64_XMM0:
482 return "xmm0";
483 case UNW_X86_64_XMM1:
484 return "xmm1";
485 case UNW_X86_64_XMM2:
486 return "xmm2";
487 case UNW_X86_64_XMM3:
488 return "xmm3";
489 case UNW_X86_64_XMM4:
490 return "xmm4";
491 case UNW_X86_64_XMM5:
492 return "xmm5";
493 case UNW_X86_64_XMM6:
494 return "xmm6";
495 case UNW_X86_64_XMM7:
496 return "xmm7";
497 case UNW_X86_64_XMM8:
498 return "xmm8";
499 case UNW_X86_64_XMM9:
500 return "xmm9";
501 case UNW_X86_64_XMM10:
502 return "xmm10";
503 case UNW_X86_64_XMM11:
504 return "xmm11";
505 case UNW_X86_64_XMM12:
506 return "xmm12";
507 case UNW_X86_64_XMM13:
508 return "xmm13";
509 case UNW_X86_64_XMM14:
510 return "xmm14";
511 case UNW_X86_64_XMM15:
512 return "xmm15";
513 default:
514 return "unknown register";
515 }
516}
517
518inline double Registers_x86_64::getFloatRegister(int) const {
519 _LIBUNWIND_ABORT("no x86_64 float registers");
520}
521
522inline void Registers_x86_64::setFloatRegister(int, double) {
523 _LIBUNWIND_ABORT("no x86_64 float registers");
524}
525
526inline bool Registers_x86_64::validVectorRegister(int regNum) const {
527#if defined(_WIN64)
528 if (regNum < UNW_X86_64_XMM0)
529 return false;
530 if (regNum > UNW_X86_64_XMM15)
531 return false;
532 return true;
533#else
534 (void)regNum; // suppress unused parameter warning
535 return false;
536#endif
537}
538
539inline v128 Registers_x86_64::getVectorRegister(int regNum) const {
540#if defined(_WIN64)
541 assert(validVectorRegister(regNum));
542 return _xmm[regNum - UNW_X86_64_XMM0];
543#else
544 (void)regNum; // suppress unused parameter warning
545 _LIBUNWIND_ABORT("no x86_64 vector registers");
546#endif
547}
548
549inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {
550#if defined(_WIN64)
551 assert(validVectorRegister(regNum));
552 _xmm[regNum - UNW_X86_64_XMM0] = value;
553#else
554 (void)regNum; (void)value; // suppress unused parameter warnings
555 _LIBUNWIND_ABORT("no x86_64 vector registers");
556#endif
557}
558#endif // _LIBUNWIND_TARGET_X86_64
559
560
561#if defined(_LIBUNWIND_TARGET_PPC)
562/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
563/// process.
564class _LIBUNWIND_HIDDEN Registers_ppc {
565public:
566 Registers_ppc();
567 Registers_ppc(const void *registers);
568
569 bool validRegister(int num) const;
570 uint32_t getRegister(int num) const;
571 void setRegister(int num, uint32_t value);
572 bool validFloatRegister(int num) const;
573 double getFloatRegister(int num) const;
574 void setFloatRegister(int num, double value);
575 bool validVectorRegister(int num) const;
576 v128 getVectorRegister(int num) const;
577 void setVectorRegister(int num, v128 value);
578 static const char *getRegisterName(int num);
579 void jumpto();
580 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; }
581 static int getArch() { return REGISTERS_PPC; }
582
583 uint64_t getSP() const { return _registers.__r1; }
584 void setSP(uint32_t value) { _registers.__r1 = value; }
585 uint64_t getIP() const { return _registers.__srr0; }
586 void setIP(uint32_t value) { _registers.__srr0 = value; }
587
588private:
589 struct ppc_thread_state_t {
590 unsigned int __srr0; /* Instruction address register (PC) */
591 unsigned int __srr1; /* Machine state register (supervisor) */
592 unsigned int __r0;
593 unsigned int __r1;
594 unsigned int __r2;
595 unsigned int __r3;
596 unsigned int __r4;
597 unsigned int __r5;
598 unsigned int __r6;
599 unsigned int __r7;
600 unsigned int __r8;
601 unsigned int __r9;
602 unsigned int __r10;
603 unsigned int __r11;
604 unsigned int __r12;
605 unsigned int __r13;
606 unsigned int __r14;
607 unsigned int __r15;
608 unsigned int __r16;
609 unsigned int __r17;
610 unsigned int __r18;
611 unsigned int __r19;
612 unsigned int __r20;
613 unsigned int __r21;
614 unsigned int __r22;
615 unsigned int __r23;
616 unsigned int __r24;
617 unsigned int __r25;
618 unsigned int __r26;
619 unsigned int __r27;
620 unsigned int __r28;
621 unsigned int __r29;
622 unsigned int __r30;
623 unsigned int __r31;
624 unsigned int __cr; /* Condition register */
625 unsigned int __xer; /* User's integer exception register */
626 unsigned int __lr; /* Link register */
627 unsigned int __ctr; /* Count register */
628 unsigned int __mq; /* MQ register (601 only) */
629 unsigned int __vrsave; /* Vector Save Register */
630 };
631
632 struct ppc_float_state_t {
633 double __fpregs[32];
634
635 unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
636 unsigned int __fpscr; /* floating point status register */
637 };
638
639 ppc_thread_state_t _registers;
640 ppc_float_state_t _floatRegisters;
641 v128 _vectorRegisters[32]; // offset 424
642};
643
644inline Registers_ppc::Registers_ppc(const void *registers) {
645 static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),
646 "ppc registers do not fit into unw_context_t");
647 memcpy(&_registers, static_cast<const uint8_t *>(registers),
648 sizeof(_registers));
649 static_assert(sizeof(ppc_thread_state_t) == 160,
650 "expected float register offset to be 160");
651 memcpy(&_floatRegisters,
652 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),
653 sizeof(_floatRegisters));
654 static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,
655 "expected vector register offset to be 424 bytes");
656 memcpy(_vectorRegisters,
657 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +
658 sizeof(ppc_float_state_t),
659 sizeof(_vectorRegisters));
660}
661
662inline Registers_ppc::Registers_ppc() {
663 memset(&_registers, 0, sizeof(_registers));
664 memset(&_floatRegisters, 0, sizeof(_floatRegisters));
665 memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
666}
667
668inline bool Registers_ppc::validRegister(int regNum) const {
669 if (regNum == UNW_REG_IP)
670 return true;
671 if (regNum == UNW_REG_SP)
672 return true;
673 if (regNum == UNW_PPC_VRSAVE)
674 return true;
675 if (regNum < 0)
676 return false;
677 if (regNum <= UNW_PPC_R31)
678 return true;
679 if (regNum == UNW_PPC_MQ)
680 return true;
681 if (regNum == UNW_PPC_LR)
682 return true;
683 if (regNum == UNW_PPC_CTR)
684 return true;
685 if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
686 return true;
687 return false;
688}
689
690inline uint32_t Registers_ppc::getRegister(int regNum) const {
691 switch (regNum) {
692 case UNW_REG_IP:
693 return _registers.__srr0;
694 case UNW_REG_SP:
695 return _registers.__r1;
696 case UNW_PPC_R0:
697 return _registers.__r0;
698 case UNW_PPC_R1:
699 return _registers.__r1;
700 case UNW_PPC_R2:
701 return _registers.__r2;
702 case UNW_PPC_R3:
703 return _registers.__r3;
704 case UNW_PPC_R4:
705 return _registers.__r4;
706 case UNW_PPC_R5:
707 return _registers.__r5;
708 case UNW_PPC_R6:
709 return _registers.__r6;
710 case UNW_PPC_R7:
711 return _registers.__r7;
712 case UNW_PPC_R8:
713 return _registers.__r8;
714 case UNW_PPC_R9:
715 return _registers.__r9;
716 case UNW_PPC_R10:
717 return _registers.__r10;
718 case UNW_PPC_R11:
719 return _registers.__r11;
720 case UNW_PPC_R12:
721 return _registers.__r12;
722 case UNW_PPC_R13:
723 return _registers.__r13;
724 case UNW_PPC_R14:
725 return _registers.__r14;
726 case UNW_PPC_R15:
727 return _registers.__r15;
728 case UNW_PPC_R16:
729 return _registers.__r16;
730 case UNW_PPC_R17:
731 return _registers.__r17;
732 case UNW_PPC_R18:
733 return _registers.__r18;
734 case UNW_PPC_R19:
735 return _registers.__r19;
736 case UNW_PPC_R20:
737 return _registers.__r20;
738 case UNW_PPC_R21:
739 return _registers.__r21;
740 case UNW_PPC_R22:
741 return _registers.__r22;
742 case UNW_PPC_R23:
743 return _registers.__r23;
744 case UNW_PPC_R24:
745 return _registers.__r24;
746 case UNW_PPC_R25:
747 return _registers.__r25;
748 case UNW_PPC_R26:
749 return _registers.__r26;
750 case UNW_PPC_R27:
751 return _registers.__r27;
752 case UNW_PPC_R28:
753 return _registers.__r28;
754 case UNW_PPC_R29:
755 return _registers.__r29;
756 case UNW_PPC_R30:
757 return _registers.__r30;
758 case UNW_PPC_R31:
759 return _registers.__r31;
760 case UNW_PPC_LR:
761 return _registers.__lr;
762 case UNW_PPC_CR0:
763 return (_registers.__cr & 0xF0000000);
764 case UNW_PPC_CR1:
765 return (_registers.__cr & 0x0F000000);
766 case UNW_PPC_CR2:
767 return (_registers.__cr & 0x00F00000);
768 case UNW_PPC_CR3:
769 return (_registers.__cr & 0x000F0000);
770 case UNW_PPC_CR4:
771 return (_registers.__cr & 0x0000F000);
772 case UNW_PPC_CR5:
773 return (_registers.__cr & 0x00000F00);
774 case UNW_PPC_CR6:
775 return (_registers.__cr & 0x000000F0);
776 case UNW_PPC_CR7:
777 return (_registers.__cr & 0x0000000F);
778 case UNW_PPC_VRSAVE:
779 return _registers.__vrsave;
780 }
781 _LIBUNWIND_ABORT("unsupported ppc register");
782}
783
784inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
785 //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
786 switch (regNum) {
787 case UNW_REG_IP:
788 _registers.__srr0 = value;
789 return;
790 case UNW_REG_SP:
791 _registers.__r1 = value;
792 return;
793 case UNW_PPC_R0:
794 _registers.__r0 = value;
795 return;
796 case UNW_PPC_R1:
797 _registers.__r1 = value;
798 return;
799 case UNW_PPC_R2:
800 _registers.__r2 = value;
801 return;
802 case UNW_PPC_R3:
803 _registers.__r3 = value;
804 return;
805 case UNW_PPC_R4:
806 _registers.__r4 = value;
807 return;
808 case UNW_PPC_R5:
809 _registers.__r5 = value;
810 return;
811 case UNW_PPC_R6:
812 _registers.__r6 = value;
813 return;
814 case UNW_PPC_R7:
815 _registers.__r7 = value;
816 return;
817 case UNW_PPC_R8:
818 _registers.__r8 = value;
819 return;
820 case UNW_PPC_R9:
821 _registers.__r9 = value;
822 return;
823 case UNW_PPC_R10:
824 _registers.__r10 = value;
825 return;
826 case UNW_PPC_R11:
827 _registers.__r11 = value;
828 return;
829 case UNW_PPC_R12:
830 _registers.__r12 = value;
831 return;
832 case UNW_PPC_R13:
833 _registers.__r13 = value;
834 return;
835 case UNW_PPC_R14:
836 _registers.__r14 = value;
837 return;
838 case UNW_PPC_R15:
839 _registers.__r15 = value;
840 return;
841 case UNW_PPC_R16:
842 _registers.__r16 = value;
843 return;
844 case UNW_PPC_R17:
845 _registers.__r17 = value;
846 return;
847 case UNW_PPC_R18:
848 _registers.__r18 = value;
849 return;
850 case UNW_PPC_R19:
851 _registers.__r19 = value;
852 return;
853 case UNW_PPC_R20:
854 _registers.__r20 = value;
855 return;
856 case UNW_PPC_R21:
857 _registers.__r21 = value;
858 return;
859 case UNW_PPC_R22:
860 _registers.__r22 = value;
861 return;
862 case UNW_PPC_R23:
863 _registers.__r23 = value;
864 return;
865 case UNW_PPC_R24:
866 _registers.__r24 = value;
867 return;
868 case UNW_PPC_R25:
869 _registers.__r25 = value;
870 return;
871 case UNW_PPC_R26:
872 _registers.__r26 = value;
873 return;
874 case UNW_PPC_R27:
875 _registers.__r27 = value;
876 return;
877 case UNW_PPC_R28:
878 _registers.__r28 = value;
879 return;
880 case UNW_PPC_R29:
881 _registers.__r29 = value;
882 return;
883 case UNW_PPC_R30:
884 _registers.__r30 = value;
885 return;
886 case UNW_PPC_R31:
887 _registers.__r31 = value;
888 return;
889 case UNW_PPC_MQ:
890 _registers.__mq = value;
891 return;
892 case UNW_PPC_LR:
893 _registers.__lr = value;
894 return;
895 case UNW_PPC_CTR:
896 _registers.__ctr = value;
897 return;
898 case UNW_PPC_CR0:
899 _registers.__cr &= 0x0FFFFFFF;
900 _registers.__cr |= (value & 0xF0000000);
901 return;
902 case UNW_PPC_CR1:
903 _registers.__cr &= 0xF0FFFFFF;
904 _registers.__cr |= (value & 0x0F000000);
905 return;
906 case UNW_PPC_CR2:
907 _registers.__cr &= 0xFF0FFFFF;
908 _registers.__cr |= (value & 0x00F00000);
909 return;
910 case UNW_PPC_CR3:
911 _registers.__cr &= 0xFFF0FFFF;
912 _registers.__cr |= (value & 0x000F0000);
913 return;
914 case UNW_PPC_CR4:
915 _registers.__cr &= 0xFFFF0FFF;
916 _registers.__cr |= (value & 0x0000F000);
917 return;
918 case UNW_PPC_CR5:
919 _registers.__cr &= 0xFFFFF0FF;
920 _registers.__cr |= (value & 0x00000F00);
921 return;
922 case UNW_PPC_CR6:
923 _registers.__cr &= 0xFFFFFF0F;
924 _registers.__cr |= (value & 0x000000F0);
925 return;
926 case UNW_PPC_CR7:
927 _registers.__cr &= 0xFFFFFFF0;
928 _registers.__cr |= (value & 0x0000000F);
929 return;
930 case UNW_PPC_VRSAVE:
931 _registers.__vrsave = value;
932 return;
933 // not saved
934 return;
935 case UNW_PPC_XER:
936 _registers.__xer = value;
937 return;
938 case UNW_PPC_AP:
939 case UNW_PPC_VSCR:
940 case UNW_PPC_SPEFSCR:
941 // not saved
942 return;
943 }
944 _LIBUNWIND_ABORT("unsupported ppc register");
945}
946
947inline bool Registers_ppc::validFloatRegister(int regNum) const {
948 if (regNum < UNW_PPC_F0)
949 return false;
950 if (regNum > UNW_PPC_F31)
951 return false;
952 return true;
953}
954
955inline double Registers_ppc::getFloatRegister(int regNum) const {
956 assert(validFloatRegister(regNum));
957 return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
958}
959
960inline void Registers_ppc::setFloatRegister(int regNum, double value) {
961 assert(validFloatRegister(regNum));
962 _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
963}
964
965inline bool Registers_ppc::validVectorRegister(int regNum) const {
966 if (regNum < UNW_PPC_V0)
967 return false;
968 if (regNum > UNW_PPC_V31)
969 return false;
970 return true;
971}
972
973inline v128 Registers_ppc::getVectorRegister(int regNum) const {
974 assert(validVectorRegister(regNum));
975 v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
976 return result;
977}
978
979inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
980 assert(validVectorRegister(regNum));
981 _vectorRegisters[regNum - UNW_PPC_V0] = value;
982}
983
984inline const char *Registers_ppc::getRegisterName(int regNum) {
985 switch (regNum) {
986 case UNW_REG_IP:
987 return "ip";
988 case UNW_REG_SP:
989 return "sp";
990 case UNW_PPC_R0:
991 return "r0";
992 case UNW_PPC_R1:
993 return "r1";
994 case UNW_PPC_R2:
995 return "r2";
996 case UNW_PPC_R3:
997 return "r3";
998 case UNW_PPC_R4:
999 return "r4";
1000 case UNW_PPC_R5:
1001 return "r5";
1002 case UNW_PPC_R6:
1003 return "r6";
1004 case UNW_PPC_R7:
1005 return "r7";
1006 case UNW_PPC_R8:
1007 return "r8";
1008 case UNW_PPC_R9:
1009 return "r9";
1010 case UNW_PPC_R10:
1011 return "r10";
1012 case UNW_PPC_R11:
1013 return "r11";
1014 case UNW_PPC_R12:
1015 return "r12";
1016 case UNW_PPC_R13:
1017 return "r13";
1018 case UNW_PPC_R14:
1019 return "r14";
1020 case UNW_PPC_R15:
1021 return "r15";
1022 case UNW_PPC_R16:
1023 return "r16";
1024 case UNW_PPC_R17:
1025 return "r17";
1026 case UNW_PPC_R18:
1027 return "r18";
1028 case UNW_PPC_R19:
1029 return "r19";
1030 case UNW_PPC_R20:
1031 return "r20";
1032 case UNW_PPC_R21:
1033 return "r21";
1034 case UNW_PPC_R22:
1035 return "r22";
1036 case UNW_PPC_R23:
1037 return "r23";
1038 case UNW_PPC_R24:
1039 return "r24";
1040 case UNW_PPC_R25:
1041 return "r25";
1042 case UNW_PPC_R26:
1043 return "r26";
1044 case UNW_PPC_R27:
1045 return "r27";
1046 case UNW_PPC_R28:
1047 return "r28";
1048 case UNW_PPC_R29:
1049 return "r29";
1050 case UNW_PPC_R30:
1051 return "r30";
1052 case UNW_PPC_R31:
1053 return "r31";
1054 case UNW_PPC_F0:
1055 return "fp0";
1056 case UNW_PPC_F1:
1057 return "fp1";
1058 case UNW_PPC_F2:
1059 return "fp2";
1060 case UNW_PPC_F3:
1061 return "fp3";
1062 case UNW_PPC_F4:
1063 return "fp4";
1064 case UNW_PPC_F5:
1065 return "fp5";
1066 case UNW_PPC_F6:
1067 return "fp6";
1068 case UNW_PPC_F7:
1069 return "fp7";
1070 case UNW_PPC_F8:
1071 return "fp8";
1072 case UNW_PPC_F9:
1073 return "fp9";
1074 case UNW_PPC_F10:
1075 return "fp10";
1076 case UNW_PPC_F11:
1077 return "fp11";
1078 case UNW_PPC_F12:
1079 return "fp12";
1080 case UNW_PPC_F13:
1081 return "fp13";
1082 case UNW_PPC_F14:
1083 return "fp14";
1084 case UNW_PPC_F15:
1085 return "fp15";
1086 case UNW_PPC_F16:
1087 return "fp16";
1088 case UNW_PPC_F17:
1089 return "fp17";
1090 case UNW_PPC_F18:
1091 return "fp18";
1092 case UNW_PPC_F19:
1093 return "fp19";
1094 case UNW_PPC_F20:
1095 return "fp20";
1096 case UNW_PPC_F21:
1097 return "fp21";
1098 case UNW_PPC_F22:
1099 return "fp22";
1100 case UNW_PPC_F23:
1101 return "fp23";
1102 case UNW_PPC_F24:
1103 return "fp24";
1104 case UNW_PPC_F25:
1105 return "fp25";
1106 case UNW_PPC_F26:
1107 return "fp26";
1108 case UNW_PPC_F27:
1109 return "fp27";
1110 case UNW_PPC_F28:
1111 return "fp28";
1112 case UNW_PPC_F29:
1113 return "fp29";
1114 case UNW_PPC_F30:
1115 return "fp30";
1116 case UNW_PPC_F31:
1117 return "fp31";
1118 case UNW_PPC_LR:
1119 return "lr";
1120 default:
1121 return "unknown register";
1122 }
1123
1124}
1125#endif // _LIBUNWIND_TARGET_PPC
1126
1127#if defined(_LIBUNWIND_TARGET_PPC64)
1128/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
1129/// process.
1130class _LIBUNWIND_HIDDEN Registers_ppc64 {
1131public:
1132 Registers_ppc64();
1133 Registers_ppc64(const void *registers);
1134
1135 bool validRegister(int num) const;
1136 uint64_t getRegister(int num) const;
1137 void setRegister(int num, uint64_t value);
1138 bool validFloatRegister(int num) const;
1139 double getFloatRegister(int num) const;
1140 void setFloatRegister(int num, double value);
1141 bool validVectorRegister(int num) const;
1142 v128 getVectorRegister(int num) const;
1143 void setVectorRegister(int num, v128 value);
1144 static const char *getRegisterName(int num);
1145 void jumpto();
1146 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; }
1147 static int getArch() { return REGISTERS_PPC64; }
1148
1149 uint64_t getSP() const { return _registers.__r1; }
1150 void setSP(uint64_t value) { _registers.__r1 = value; }
1151 uint64_t getIP() const { return _registers.__srr0; }
1152 void setIP(uint64_t value) { _registers.__srr0 = value; }
1153
1154private:
1155 struct ppc64_thread_state_t {
1156 uint64_t __srr0; // Instruction address register (PC)
1157 uint64_t __srr1; // Machine state register (supervisor)
1158 uint64_t __r0;
1159 uint64_t __r1;
1160 uint64_t __r2;
1161 uint64_t __r3;
1162 uint64_t __r4;
1163 uint64_t __r5;
1164 uint64_t __r6;
1165 uint64_t __r7;
1166 uint64_t __r8;
1167 uint64_t __r9;
1168 uint64_t __r10;
1169 uint64_t __r11;
1170 uint64_t __r12;
1171 uint64_t __r13;
1172 uint64_t __r14;
1173 uint64_t __r15;
1174 uint64_t __r16;
1175 uint64_t __r17;
1176 uint64_t __r18;
1177 uint64_t __r19;
1178 uint64_t __r20;
1179 uint64_t __r21;
1180 uint64_t __r22;
1181 uint64_t __r23;
1182 uint64_t __r24;
1183 uint64_t __r25;
1184 uint64_t __r26;
1185 uint64_t __r27;
1186 uint64_t __r28;
1187 uint64_t __r29;
1188 uint64_t __r30;
1189 uint64_t __r31;
1190 uint64_t __cr; // Condition register
1191 uint64_t __xer; // User's integer exception register
1192 uint64_t __lr; // Link register
1193 uint64_t __ctr; // Count register
1194 uint64_t __vrsave; // Vector Save Register
1195 };
1196
1197 union ppc64_vsr_t {
1198 struct asfloat_s {
1199 double f;
1200 uint64_t v2;
1201 } asfloat;
1202 v128 v;
1203 };
1204
1205 ppc64_thread_state_t _registers;
1206 ppc64_vsr_t _vectorScalarRegisters[64];
1207
1208 static int getVectorRegNum(int num);
1209};
1210
1211inline Registers_ppc64::Registers_ppc64(const void *registers) {
1212 static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),
1213 "ppc64 registers do not fit into unw_context_t");
1214 memcpy(&_registers, static_cast<const uint8_t *>(registers),
1215 sizeof(_registers));
1216 static_assert(sizeof(_registers) == 312,
1217 "expected vector scalar register offset to be 312");
1218 memcpy(&_vectorScalarRegisters,
1219 static_cast<const uint8_t *>(registers) + sizeof(_registers),
1220 sizeof(_vectorScalarRegisters));
1221 static_assert(sizeof(_registers) +
1222 sizeof(_vectorScalarRegisters) == 1336,
1223 "expected vector register offset to be 1336 bytes");
1224}
1225
1226inline Registers_ppc64::Registers_ppc64() {
1227 memset(&_registers, 0, sizeof(_registers));
1228 memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
1229}
1230
1231inline bool Registers_ppc64::validRegister(int regNum) const {
1232 switch (regNum) {
1233 case UNW_REG_IP:
1234 case UNW_REG_SP:
1235 case UNW_PPC64_XER:
1236 case UNW_PPC64_LR:
1237 case UNW_PPC64_CTR:
1238 case UNW_PPC64_VRSAVE:
1239 return true;
1240 }
1241
1242 if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
1243 return true;
1244 if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
1245 return true;
1246
1247 return false;
1248}
1249
1250inline uint64_t Registers_ppc64::getRegister(int regNum) const {
1251 switch (regNum) {
1252 case UNW_REG_IP:
1253 return _registers.__srr0;
1254 case UNW_PPC64_R0:
1255 return _registers.__r0;
1256 case UNW_PPC64_R1:
1257 case UNW_REG_SP:
1258 return _registers.__r1;
1259 case UNW_PPC64_R2:
1260 return _registers.__r2;
1261 case UNW_PPC64_R3:
1262 return _registers.__r3;
1263 case UNW_PPC64_R4:
1264 return _registers.__r4;
1265 case UNW_PPC64_R5:
1266 return _registers.__r5;
1267 case UNW_PPC64_R6:
1268 return _registers.__r6;
1269 case UNW_PPC64_R7:
1270 return _registers.__r7;
1271 case UNW_PPC64_R8:
1272 return _registers.__r8;
1273 case UNW_PPC64_R9:
1274 return _registers.__r9;
1275 case UNW_PPC64_R10:
1276 return _registers.__r10;
1277 case UNW_PPC64_R11:
1278 return _registers.__r11;
1279 case UNW_PPC64_R12:
1280 return _registers.__r12;
1281 case UNW_PPC64_R13:
1282 return _registers.__r13;
1283 case UNW_PPC64_R14:
1284 return _registers.__r14;
1285 case UNW_PPC64_R15:
1286 return _registers.__r15;
1287 case UNW_PPC64_R16:
1288 return _registers.__r16;
1289 case UNW_PPC64_R17:
1290 return _registers.__r17;
1291 case UNW_PPC64_R18:
1292 return _registers.__r18;
1293 case UNW_PPC64_R19:
1294 return _registers.__r19;
1295 case UNW_PPC64_R20:
1296 return _registers.__r20;
1297 case UNW_PPC64_R21:
1298 return _registers.__r21;
1299 case UNW_PPC64_R22:
1300 return _registers.__r22;
1301 case UNW_PPC64_R23:
1302 return _registers.__r23;
1303 case UNW_PPC64_R24:
1304 return _registers.__r24;
1305 case UNW_PPC64_R25:
1306 return _registers.__r25;
1307 case UNW_PPC64_R26:
1308 return _registers.__r26;
1309 case UNW_PPC64_R27:
1310 return _registers.__r27;
1311 case UNW_PPC64_R28:
1312 return _registers.__r28;
1313 case UNW_PPC64_R29:
1314 return _registers.__r29;
1315 case UNW_PPC64_R30:
1316 return _registers.__r30;
1317 case UNW_PPC64_R31:
1318 return _registers.__r31;
1319 case UNW_PPC64_CR0:
1320 return (_registers.__cr & 0xF0000000);
1321 case UNW_PPC64_CR1:
1322 return (_registers.__cr & 0x0F000000);
1323 case UNW_PPC64_CR2:
1324 return (_registers.__cr & 0x00F00000);
1325 case UNW_PPC64_CR3:
1326 return (_registers.__cr & 0x000F0000);
1327 case UNW_PPC64_CR4:
1328 return (_registers.__cr & 0x0000F000);
1329 case UNW_PPC64_CR5:
1330 return (_registers.__cr & 0x00000F00);
1331 case UNW_PPC64_CR6:
1332 return (_registers.__cr & 0x000000F0);
1333 case UNW_PPC64_CR7:
1334 return (_registers.__cr & 0x0000000F);
1335 case UNW_PPC64_XER:
1336 return _registers.__xer;
1337 case UNW_PPC64_LR:
1338 return _registers.__lr;
1339 case UNW_PPC64_CTR:
1340 return _registers.__ctr;
1341 case UNW_PPC64_VRSAVE:
1342 return _registers.__vrsave;
1343 }
1344 _LIBUNWIND_ABORT("unsupported ppc64 register");
1345}
1346
1347inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
1348 switch (regNum) {
1349 case UNW_REG_IP:
1350 _registers.__srr0 = value;
1351 return;
1352 case UNW_PPC64_R0:
1353 _registers.__r0 = value;
1354 return;
1355 case UNW_PPC64_R1:
1356 case UNW_REG_SP:
1357 _registers.__r1 = value;
1358 return;
1359 case UNW_PPC64_R2:
1360 _registers.__r2 = value;
1361 return;
1362 case UNW_PPC64_R3:
1363 _registers.__r3 = value;
1364 return;
1365 case UNW_PPC64_R4:
1366 _registers.__r4 = value;
1367 return;
1368 case UNW_PPC64_R5:
1369 _registers.__r5 = value;
1370 return;
1371 case UNW_PPC64_R6:
1372 _registers.__r6 = value;
1373 return;
1374 case UNW_PPC64_R7:
1375 _registers.__r7 = value;
1376 return;
1377 case UNW_PPC64_R8:
1378 _registers.__r8 = value;
1379 return;
1380 case UNW_PPC64_R9:
1381 _registers.__r9 = value;
1382 return;
1383 case UNW_PPC64_R10:
1384 _registers.__r10 = value;
1385 return;
1386 case UNW_PPC64_R11:
1387 _registers.__r11 = value;
1388 return;
1389 case UNW_PPC64_R12:
1390 _registers.__r12 = value;
1391 return;
1392 case UNW_PPC64_R13:
1393 _registers.__r13 = value;
1394 return;
1395 case UNW_PPC64_R14:
1396 _registers.__r14 = value;
1397 return;
1398 case UNW_PPC64_R15:
1399 _registers.__r15 = value;
1400 return;
1401 case UNW_PPC64_R16:
1402 _registers.__r16 = value;
1403 return;
1404 case UNW_PPC64_R17:
1405 _registers.__r17 = value;
1406 return;
1407 case UNW_PPC64_R18:
1408 _registers.__r18 = value;
1409 return;
1410 case UNW_PPC64_R19:
1411 _registers.__r19 = value;
1412 return;
1413 case UNW_PPC64_R20:
1414 _registers.__r20 = value;
1415 return;
1416 case UNW_PPC64_R21:
1417 _registers.__r21 = value;
1418 return;
1419 case UNW_PPC64_R22:
1420 _registers.__r22 = value;
1421 return;
1422 case UNW_PPC64_R23:
1423 _registers.__r23 = value;
1424 return;
1425 case UNW_PPC64_R24:
1426 _registers.__r24 = value;
1427 return;
1428 case UNW_PPC64_R25:
1429 _registers.__r25 = value;
1430 return;
1431 case UNW_PPC64_R26:
1432 _registers.__r26 = value;
1433 return;
1434 case UNW_PPC64_R27:
1435 _registers.__r27 = value;
1436 return;
1437 case UNW_PPC64_R28:
1438 _registers.__r28 = value;
1439 return;
1440 case UNW_PPC64_R29:
1441 _registers.__r29 = value;
1442 return;
1443 case UNW_PPC64_R30:
1444 _registers.__r30 = value;
1445 return;
1446 case UNW_PPC64_R31:
1447 _registers.__r31 = value;
1448 return;
1449 case UNW_PPC64_CR0:
1450 _registers.__cr &= 0x0FFFFFFF;
1451 _registers.__cr |= (value & 0xF0000000);
1452 return;
1453 case UNW_PPC64_CR1:
1454 _registers.__cr &= 0xF0FFFFFF;
1455 _registers.__cr |= (value & 0x0F000000);
1456 return;
1457 case UNW_PPC64_CR2:
1458 _registers.__cr &= 0xFF0FFFFF;
1459 _registers.__cr |= (value & 0x00F00000);
1460 return;
1461 case UNW_PPC64_CR3:
1462 _registers.__cr &= 0xFFF0FFFF;
1463 _registers.__cr |= (value & 0x000F0000);
1464 return;
1465 case UNW_PPC64_CR4:
1466 _registers.__cr &= 0xFFFF0FFF;
1467 _registers.__cr |= (value & 0x0000F000);
1468 return;
1469 case UNW_PPC64_CR5:
1470 _registers.__cr &= 0xFFFFF0FF;
1471 _registers.__cr |= (value & 0x00000F00);
1472 return;
1473 case UNW_PPC64_CR6:
1474 _registers.__cr &= 0xFFFFFF0F;
1475 _registers.__cr |= (value & 0x000000F0);
1476 return;
1477 case UNW_PPC64_CR7:
1478 _registers.__cr &= 0xFFFFFFF0;
1479 _registers.__cr |= (value & 0x0000000F);
1480 return;
1481 case UNW_PPC64_XER:
1482 _registers.__xer = value;
1483 return;
1484 case UNW_PPC64_LR:
1485 _registers.__lr = value;
1486 return;
1487 case UNW_PPC64_CTR:
1488 _registers.__ctr = value;
1489 return;
1490 case UNW_PPC64_VRSAVE:
1491 _registers.__vrsave = value;
1492 return;
1493 }
1494 _LIBUNWIND_ABORT("unsupported ppc64 register");
1495}
1496
1497inline bool Registers_ppc64::validFloatRegister(int regNum) const {
1498 return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
1499}
1500
1501inline double Registers_ppc64::getFloatRegister(int regNum) const {
1502 assert(validFloatRegister(regNum));
1503 return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
1504}
1505
1506inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
1507 assert(validFloatRegister(regNum));
1508 _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
1509}
1510
1511inline bool Registers_ppc64::validVectorRegister(int regNum) const {
1512#ifdef PPC64_HAS_VMX
1513 if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
1514 return true;
1515 if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
1516 return true;
1517#else
1518 if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
1519 return true;
1520#endif
1521 return false;
1522}
1523
1524inline int Registers_ppc64::getVectorRegNum(int num)
1525{
1526 if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
1527 return num - UNW_PPC64_VS0;
1528 else
1529 return num - UNW_PPC64_VS32 + 32;
1530}
1531
1532inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
1533 assert(validVectorRegister(regNum));
1534 return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
1535}
1536
1537inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
1538 assert(validVectorRegister(regNum));
1539 _vectorScalarRegisters[getVectorRegNum(regNum)].v = value;
1540}
1541
1542inline const char *Registers_ppc64::getRegisterName(int regNum) {
1543 switch (regNum) {
1544 case UNW_REG_IP:
1545 return "ip";
1546 case UNW_REG_SP:
1547 return "sp";
1548 case UNW_PPC64_R0:
1549 return "r0";
1550 case UNW_PPC64_R1:
1551 return "r1";
1552 case UNW_PPC64_R2:
1553 return "r2";
1554 case UNW_PPC64_R3:
1555 return "r3";
1556 case UNW_PPC64_R4:
1557 return "r4";
1558 case UNW_PPC64_R5:
1559 return "r5";
1560 case UNW_PPC64_R6:
1561 return "r6";
1562 case UNW_PPC64_R7:
1563 return "r7";
1564 case UNW_PPC64_R8:
1565 return "r8";
1566 case UNW_PPC64_R9:
1567 return "r9";
1568 case UNW_PPC64_R10:
1569 return "r10";
1570 case UNW_PPC64_R11:
1571 return "r11";
1572 case UNW_PPC64_R12:
1573 return "r12";
1574 case UNW_PPC64_R13:
1575 return "r13";
1576 case UNW_PPC64_R14:
1577 return "r14";
1578 case UNW_PPC64_R15:
1579 return "r15";
1580 case UNW_PPC64_R16:
1581 return "r16";
1582 case UNW_PPC64_R17:
1583 return "r17";
1584 case UNW_PPC64_R18:
1585 return "r18";
1586 case UNW_PPC64_R19:
1587 return "r19";
1588 case UNW_PPC64_R20:
1589 return "r20";
1590 case UNW_PPC64_R21:
1591 return "r21";
1592 case UNW_PPC64_R22:
1593 return "r22";
1594 case UNW_PPC64_R23:
1595 return "r23";
1596 case UNW_PPC64_R24:
1597 return "r24";
1598 case UNW_PPC64_R25:
1599 return "r25";
1600 case UNW_PPC64_R26:
1601 return "r26";
1602 case UNW_PPC64_R27:
1603 return "r27";
1604 case UNW_PPC64_R28:
1605 return "r28";
1606 case UNW_PPC64_R29:
1607 return "r29";
1608 case UNW_PPC64_R30:
1609 return "r30";
1610 case UNW_PPC64_R31:
1611 return "r31";
1612 case UNW_PPC64_CR0:
1613 return "cr0";
1614 case UNW_PPC64_CR1:
1615 return "cr1";
1616 case UNW_PPC64_CR2:
1617 return "cr2";
1618 case UNW_PPC64_CR3:
1619 return "cr3";
1620 case UNW_PPC64_CR4:
1621 return "cr4";
1622 case UNW_PPC64_CR5:
1623 return "cr5";
1624 case UNW_PPC64_CR6:
1625 return "cr6";
1626 case UNW_PPC64_CR7:
1627 return "cr7";
1628 case UNW_PPC64_XER:
1629 return "xer";
1630 case UNW_PPC64_LR:
1631 return "lr";
1632 case UNW_PPC64_CTR:
1633 return "ctr";
1634 case UNW_PPC64_VRSAVE:
1635 return "vrsave";
1636 case UNW_PPC64_F0:
1637 return "fp0";
1638 case UNW_PPC64_F1:
1639 return "fp1";
1640 case UNW_PPC64_F2:
1641 return "fp2";
1642 case UNW_PPC64_F3:
1643 return "fp3";
1644 case UNW_PPC64_F4:
1645 return "fp4";
1646 case UNW_PPC64_F5:
1647 return "fp5";
1648 case UNW_PPC64_F6:
1649 return "fp6";
1650 case UNW_PPC64_F7:
1651 return "fp7";
1652 case UNW_PPC64_F8:
1653 return "fp8";
1654 case UNW_PPC64_F9:
1655 return "fp9";
1656 case UNW_PPC64_F10:
1657 return "fp10";
1658 case UNW_PPC64_F11:
1659 return "fp11";
1660 case UNW_PPC64_F12:
1661 return "fp12";
1662 case UNW_PPC64_F13:
1663 return "fp13";
1664 case UNW_PPC64_F14:
1665 return "fp14";
1666 case UNW_PPC64_F15:
1667 return "fp15";
1668 case UNW_PPC64_F16:
1669 return "fp16";
1670 case UNW_PPC64_F17:
1671 return "fp17";
1672 case UNW_PPC64_F18:
1673 return "fp18";
1674 case UNW_PPC64_F19:
1675 return "fp19";
1676 case UNW_PPC64_F20:
1677 return "fp20";
1678 case UNW_PPC64_F21:
1679 return "fp21";
1680 case UNW_PPC64_F22:
1681 return "fp22";
1682 case UNW_PPC64_F23:
1683 return "fp23";
1684 case UNW_PPC64_F24:
1685 return "fp24";
1686 case UNW_PPC64_F25:
1687 return "fp25";
1688 case UNW_PPC64_F26:
1689 return "fp26";
1690 case UNW_PPC64_F27:
1691 return "fp27";
1692 case UNW_PPC64_F28:
1693 return "fp28";
1694 case UNW_PPC64_F29:
1695 return "fp29";
1696 case UNW_PPC64_F30:
1697 return "fp30";
1698 case UNW_PPC64_F31:
1699 return "fp31";
1700 case UNW_PPC64_V0:
1701 return "v0";
1702 case UNW_PPC64_V1:
1703 return "v1";
1704 case UNW_PPC64_V2:
1705 return "v2";
1706 case UNW_PPC64_V3:
1707 return "v3";
1708 case UNW_PPC64_V4:
1709 return "v4";
1710 case UNW_PPC64_V5:
1711 return "v5";
1712 case UNW_PPC64_V6:
1713 return "v6";
1714 case UNW_PPC64_V7:
1715 return "v7";
1716 case UNW_PPC64_V8:
1717 return "v8";
1718 case UNW_PPC64_V9:
1719 return "v9";
1720 case UNW_PPC64_V10:
1721 return "v10";
1722 case UNW_PPC64_V11:
1723 return "v11";
1724 case UNW_PPC64_V12:
1725 return "v12";
1726 case UNW_PPC64_V13:
1727 return "v13";
1728 case UNW_PPC64_V14:
1729 return "v14";
1730 case UNW_PPC64_V15:
1731 return "v15";
1732 case UNW_PPC64_V16:
1733 return "v16";
1734 case UNW_PPC64_V17:
1735 return "v17";
1736 case UNW_PPC64_V18:
1737 return "v18";
1738 case UNW_PPC64_V19:
1739 return "v19";
1740 case UNW_PPC64_V20:
1741 return "v20";
1742 case UNW_PPC64_V21:
1743 return "v21";
1744 case UNW_PPC64_V22:
1745 return "v22";
1746 case UNW_PPC64_V23:
1747 return "v23";
1748 case UNW_PPC64_V24:
1749 return "v24";
1750 case UNW_PPC64_V25:
1751 return "v25";
1752 case UNW_PPC64_V26:
1753 return "v26";
1754 case UNW_PPC64_V27:
1755 return "v27";
1756 case UNW_PPC64_V28:
1757 return "v28";
1758 case UNW_PPC64_V29:
1759 return "v29";
1760 case UNW_PPC64_V30:
1761 return "v30";
1762 case UNW_PPC64_V31:
1763 return "v31";
1764 }
1765 return "unknown register";
1766}
1767#endif // _LIBUNWIND_TARGET_PPC64
1768
1769
1770#if defined(_LIBUNWIND_TARGET_AARCH64)
1771/// Registers_arm64 holds the register state of a thread in a 64-bit arm
1772/// process.
1773class _LIBUNWIND_HIDDEN Registers_arm64 {
1774public:
1775 Registers_arm64();
1776 Registers_arm64(const void *registers);
1777
1778 bool validRegister(int num) const;
1779 uint64_t getRegister(int num) const;
1780 void setRegister(int num, uint64_t value);
1781 bool validFloatRegister(int num) const;
1782 double getFloatRegister(int num) const;
1783 void setFloatRegister(int num, double value);
1784 bool validVectorRegister(int num) const;
1785 v128 getVectorRegister(int num) const;
1786 void setVectorRegister(int num, v128 value);
1787 static const char *getRegisterName(int num);
1788 void jumpto();
1789 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }
1790 static int getArch() { return REGISTERS_ARM64; }
1791
1792 uint64_t getSP() const { return _registers.__sp; }
1793 void setSP(uint64_t value) { _registers.__sp = value; }
1794 uint64_t getIP() const { return _registers.__pc; }
1795 void setIP(uint64_t value) { _registers.__pc = value; }
1796 uint64_t getFP() const { return _registers.__fp; }
1797 void setFP(uint64_t value) { _registers.__fp = value; }
1798
1799private:
1800 struct GPRs {
1801 uint64_t __x[29]; // x0-x28
1802 uint64_t __fp; // Frame pointer x29
1803 uint64_t __lr; // Link register x30
1804 uint64_t __sp; // Stack pointer x31
1805 uint64_t __pc; // Program counter
1806 uint64_t __ra_sign_state; // RA sign state register
1807 };
1808
1809 GPRs _registers;
1810 double _vectorHalfRegisters[32];
1811 // Currently only the lower double in 128-bit vectore registers
1812 // is perserved during unwinding. We could define new register
1813 // numbers (> 96) which mean whole vector registers, then this
1814 // struct would need to change to contain whole vector registers.
1815};
1816
1817inline Registers_arm64::Registers_arm64(const void *registers) {
1818 static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),
1819 "arm64 registers do not fit into unw_context_t");
1820 memcpy(&_registers, registers, sizeof(_registers));
1821 static_assert(sizeof(GPRs) == 0x110,
1822 "expected VFP registers to be at offset 272");
1823 memcpy(_vectorHalfRegisters,
1824 static_cast<const uint8_t *>(registers) + sizeof(GPRs),
1825 sizeof(_vectorHalfRegisters));
1826}
1827
1828inline Registers_arm64::Registers_arm64() {
1829 memset(&_registers, 0, sizeof(_registers));
1830 memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
1831}
1832
1833inline bool Registers_arm64::validRegister(int regNum) const {
1834 if (regNum == UNW_REG_IP)
1835 return true;
1836 if (regNum == UNW_REG_SP)
1837 return true;
1838 if (regNum < 0)
1839 return false;
1840 if (regNum > 95)
1841 return false;
1842 if (regNum == UNW_ARM64_RA_SIGN_STATE)
1843 return true;
1844 if ((regNum > 31) && (regNum < 64))
1845 return false;
1846 return true;
1847}
1848
1849inline uint64_t Registers_arm64::getRegister(int regNum) const {
1850 if (regNum == UNW_REG_IP)
1851 return _registers.__pc;
1852 if (regNum == UNW_REG_SP)
1853 return _registers.__sp;
1854 if (regNum == UNW_ARM64_RA_SIGN_STATE)
1855 return _registers.__ra_sign_state;
1856 if ((regNum >= 0) && (regNum < 32))
1857 return _registers.__x[regNum];
1858 _LIBUNWIND_ABORT("unsupported arm64 register");
1859}
1860
1861inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1862 if (regNum == UNW_REG_IP)
1863 _registers.__pc = value;
1864 else if (regNum == UNW_REG_SP)
1865 _registers.__sp = value;
1866 else if (regNum == UNW_ARM64_RA_SIGN_STATE)
1867 _registers.__ra_sign_state = value;
1868 else if ((regNum >= 0) && (regNum < 32))
1869 _registers.__x[regNum] = value;
1870 else
1871 _LIBUNWIND_ABORT("unsupported arm64 register");
1872}
1873
1874inline const char *Registers_arm64::getRegisterName(int regNum) {
1875 switch (regNum) {
1876 case UNW_REG_IP:
1877 return "pc";
1878 case UNW_REG_SP:
1879 return "sp";
1880 case UNW_ARM64_X0:
1881 return "x0";
1882 case UNW_ARM64_X1:
1883 return "x1";
1884 case UNW_ARM64_X2:
1885 return "x2";
1886 case UNW_ARM64_X3:
1887 return "x3";
1888 case UNW_ARM64_X4:
1889 return "x4";
1890 case UNW_ARM64_X5:
1891 return "x5";
1892 case UNW_ARM64_X6:
1893 return "x6";
1894 case UNW_ARM64_X7:
1895 return "x7";
1896 case UNW_ARM64_X8:
1897 return "x8";
1898 case UNW_ARM64_X9:
1899 return "x9";
1900 case UNW_ARM64_X10:
1901 return "x10";
1902 case UNW_ARM64_X11:
1903 return "x11";
1904 case UNW_ARM64_X12:
1905 return "x12";
1906 case UNW_ARM64_X13:
1907 return "x13";
1908 case UNW_ARM64_X14:
1909 return "x14";
1910 case UNW_ARM64_X15:
1911 return "x15";
1912 case UNW_ARM64_X16:
1913 return "x16";
1914 case UNW_ARM64_X17:
1915 return "x17";
1916 case UNW_ARM64_X18:
1917 return "x18";
1918 case UNW_ARM64_X19:
1919 return "x19";
1920 case UNW_ARM64_X20:
1921 return "x20";
1922 case UNW_ARM64_X21:
1923 return "x21";
1924 case UNW_ARM64_X22:
1925 return "x22";
1926 case UNW_ARM64_X23:
1927 return "x23";
1928 case UNW_ARM64_X24:
1929 return "x24";
1930 case UNW_ARM64_X25:
1931 return "x25";
1932 case UNW_ARM64_X26:
1933 return "x26";
1934 case UNW_ARM64_X27:
1935 return "x27";
1936 case UNW_ARM64_X28:
1937 return "x28";
1938 case UNW_ARM64_X29:
1939 return "fp";
1940 case UNW_ARM64_X30:
1941 return "lr";
1942 case UNW_ARM64_X31:
1943 return "sp";
1944 case UNW_ARM64_D0:
1945 return "d0";
1946 case UNW_ARM64_D1:
1947 return "d1";
1948 case UNW_ARM64_D2:
1949 return "d2";
1950 case UNW_ARM64_D3:
1951 return "d3";
1952 case UNW_ARM64_D4:
1953 return "d4";
1954 case UNW_ARM64_D5:
1955 return "d5";
1956 case UNW_ARM64_D6:
1957 return "d6";
1958 case UNW_ARM64_D7:
1959 return "d7";
1960 case UNW_ARM64_D8:
1961 return "d8";
1962 case UNW_ARM64_D9:
1963 return "d9";
1964 case UNW_ARM64_D10:
1965 return "d10";
1966 case UNW_ARM64_D11:
1967 return "d11";
1968 case UNW_ARM64_D12:
1969 return "d12";
1970 case UNW_ARM64_D13:
1971 return "d13";
1972 case UNW_ARM64_D14:
1973 return "d14";
1974 case UNW_ARM64_D15:
1975 return "d15";
1976 case UNW_ARM64_D16:
1977 return "d16";
1978 case UNW_ARM64_D17:
1979 return "d17";
1980 case UNW_ARM64_D18:
1981 return "d18";
1982 case UNW_ARM64_D19:
1983 return "d19";
1984 case UNW_ARM64_D20:
1985 return "d20";
1986 case UNW_ARM64_D21:
1987 return "d21";
1988 case UNW_ARM64_D22:
1989 return "d22";
1990 case UNW_ARM64_D23:
1991 return "d23";
1992 case UNW_ARM64_D24:
1993 return "d24";
1994 case UNW_ARM64_D25:
1995 return "d25";
1996 case UNW_ARM64_D26:
1997 return "d26";
1998 case UNW_ARM64_D27:
1999 return "d27";
2000 case UNW_ARM64_D28:
2001 return "d28";
2002 case UNW_ARM64_D29:
2003 return "d29";
2004 case UNW_ARM64_D30:
2005 return "d30";
2006 case UNW_ARM64_D31:
2007 return "d31";
2008 default:
2009 return "unknown register";
2010 }
2011}
2012
2013inline bool Registers_arm64::validFloatRegister(int regNum) const {
2014 if (regNum < UNW_ARM64_D0)
2015 return false;
2016 if (regNum > UNW_ARM64_D31)
2017 return false;
2018 return true;
2019}
2020
2021inline double Registers_arm64::getFloatRegister(int regNum) const {
2022 assert(validFloatRegister(regNum));
2023 return _vectorHalfRegisters[regNum - UNW_ARM64_D0];
2024}
2025
2026inline void Registers_arm64::setFloatRegister(int regNum, double value) {
2027 assert(validFloatRegister(regNum));
2028 _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value;
2029}
2030
2031inline bool Registers_arm64::validVectorRegister(int) const {
2032 return false;
2033}
2034
2035inline v128 Registers_arm64::getVectorRegister(int) const {
2036 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2037}
2038
2039inline void Registers_arm64::setVectorRegister(int, v128) {
2040 _LIBUNWIND_ABORT("no arm64 vector register support yet");
2041}
2042#endif // _LIBUNWIND_TARGET_AARCH64
2043
2044#if defined(_LIBUNWIND_TARGET_ARM)
2045/// Registers_arm holds the register state of a thread in a 32-bit arm
2046/// process.
2047///
2048/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,
2049/// this uses more memory than required.
2050class _LIBUNWIND_HIDDEN Registers_arm {
2051public:
2052 Registers_arm();
2053 Registers_arm(const void *registers);
2054
2055 bool validRegister(int num) const;
2056 uint32_t getRegister(int num) const;
2057 void setRegister(int num, uint32_t value);
2058 bool validFloatRegister(int num) const;
2059 unw_fpreg_t getFloatRegister(int num);
2060 void setFloatRegister(int num, unw_fpreg_t value);
2061 bool validVectorRegister(int num) const;
2062 v128 getVectorRegister(int num) const;
2063 void setVectorRegister(int num, v128 value);
2064 static const char *getRegisterName(int num);
2065 void jumpto() {
2066 restoreSavedFloatRegisters();
2067 restoreCoreAndJumpTo();
2068 }
2069 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; }
2070 static int getArch() { return REGISTERS_ARM; }
2071
2072 uint32_t getSP() const { return _registers.__sp; }
2073 void setSP(uint32_t value) { _registers.__sp = value; }
2074 uint32_t getIP() const { return _registers.__pc; }
2075 void setIP(uint32_t value) { _registers.__pc = value; }
2076
2077 void saveVFPAsX() {
2078 assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);
2079 _use_X_for_vfp_save = true;
2080 }
2081
2082 void restoreSavedFloatRegisters() {
2083 if (_saved_vfp_d0_d15) {
2084 if (_use_X_for_vfp_save)
2085 restoreVFPWithFLDMX(_vfp_d0_d15_pad);
2086 else
2087 restoreVFPWithFLDMD(_vfp_d0_d15_pad);
2088 }
2089 if (_saved_vfp_d16_d31)
2090 restoreVFPv3(_vfp_d16_d31);
2091#if defined(__ARM_WMMX)
2092 if (_saved_iwmmx)
2093 restoreiWMMX(_iwmmx);
2094 if (_saved_iwmmx_control)
2095 restoreiWMMXControl(_iwmmx_control);
2096#endif
2097 }
2098
2099private:
2100 struct GPRs {
2101 uint32_t __r[13]; // r0-r12
2102 uint32_t __sp; // Stack pointer r13
2103 uint32_t __lr; // Link register r14
2104 uint32_t __pc; // Program counter r15
2105 };
2106
2107 static void saveVFPWithFSTMD(unw_fpreg_t*);
2108 static void saveVFPWithFSTMX(unw_fpreg_t*);
2109 static void saveVFPv3(unw_fpreg_t*);
2110 static void restoreVFPWithFLDMD(unw_fpreg_t*);
2111 static void restoreVFPWithFLDMX(unw_fpreg_t*);
2112 static void restoreVFPv3(unw_fpreg_t*);
2113#if defined(__ARM_WMMX)
2114 static void saveiWMMX(unw_fpreg_t*);
2115 static void saveiWMMXControl(uint32_t*);
2116 static void restoreiWMMX(unw_fpreg_t*);
2117 static void restoreiWMMXControl(uint32_t*);
2118#endif
2119 void restoreCoreAndJumpTo();
2120
2121 // ARM registers
2122 GPRs _registers;
2123
2124 // We save floating point registers lazily because we can't know ahead of
2125 // time which ones are used. See EHABI #4.7.
2126
2127 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.
2128 //
2129 // See EHABI #7.5 that explains how matching instruction sequences for load
2130 // and store need to be used to correctly restore the exact register bits.
2131 bool _use_X_for_vfp_save;
2132 // Whether VFP D0-D15 are saved.
2133 bool _saved_vfp_d0_d15;
2134 // Whether VFPv3 D16-D31 are saved.
2135 bool _saved_vfp_d16_d31;
2136 // VFP registers D0-D15, + padding if saved using FSTMX
2137 unw_fpreg_t _vfp_d0_d15_pad[17];
2138 // VFPv3 registers D16-D31, always saved using FSTMD
2139 unw_fpreg_t _vfp_d16_d31[16];
2140#if defined(__ARM_WMMX)
2141 // Whether iWMMX data registers are saved.
2142 bool _saved_iwmmx;
2143 // Whether iWMMX control registers are saved.
2144 mutable bool _saved_iwmmx_control;
2145 // iWMMX registers
2146 unw_fpreg_t _iwmmx[16];
2147 // iWMMX control registers
2148 mutable uint32_t _iwmmx_control[4];
2149#endif
2150};
2151
2152inline Registers_arm::Registers_arm(const void *registers)
2153 : _use_X_for_vfp_save(false),
2154 _saved_vfp_d0_d15(false),
2155 _saved_vfp_d16_d31(false) {
2156 static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),
2157 "arm registers do not fit into unw_context_t");
2158 // See unw_getcontext() note about data.
2159 memcpy(&_registers, registers, sizeof(_registers));
2160 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2161 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2162#if defined(__ARM_WMMX)
2163 _saved_iwmmx = false;
2164 _saved_iwmmx_control = false;
2165 memset(&_iwmmx, 0, sizeof(_iwmmx));
2166 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2167#endif
2168}
2169
2170inline Registers_arm::Registers_arm()
2171 : _use_X_for_vfp_save(false),
2172 _saved_vfp_d0_d15(false),
2173 _saved_vfp_d16_d31(false) {
2174 memset(&_registers, 0, sizeof(_registers));
2175 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));
2176 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));
2177#if defined(__ARM_WMMX)
2178 _saved_iwmmx = false;
2179 _saved_iwmmx_control = false;
2180 memset(&_iwmmx, 0, sizeof(_iwmmx));
2181 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));
2182#endif
2183}
2184
2185inline bool Registers_arm::validRegister(int regNum) const {
2186 // Returns true for all non-VFP registers supported by the EHABI
2187 // virtual register set (VRS).
2188 if (regNum == UNW_REG_IP)
2189 return true;
2190
2191 if (regNum == UNW_REG_SP)
2192 return true;
2193
2194 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)
2195 return true;
2196
2197#if defined(__ARM_WMMX)
2198 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)
2199 return true;
2200#endif
2201
2202 return false;
2203}
2204
2205inline uint32_t Registers_arm::getRegister(int regNum) const {
2206 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
2207 return _registers.__sp;
2208
2209 if (regNum == UNW_ARM_LR)
2210 return _registers.__lr;
2211
2212 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
2213 return _registers.__pc;
2214
2215 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)
2216 return _registers.__r[regNum];
2217
2218#if defined(__ARM_WMMX)
2219 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2220 if (!_saved_iwmmx_control) {
2221 _saved_iwmmx_control = true;
2222 saveiWMMXControl(_iwmmx_control);
2223 }
2224 return _iwmmx_control[regNum - UNW_ARM_WC0];
2225 }
2226#endif
2227
2228 _LIBUNWIND_ABORT("unsupported arm register");
2229}
2230
2231inline void Registers_arm::setRegister(int regNum, uint32_t value) {
2232 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {
2233 _registers.__sp = value;
2234 return;
2235 }
2236
2237 if (regNum == UNW_ARM_LR) {
2238 _registers.__lr = value;
2239 return;
2240 }
2241
2242 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {
2243 _registers.__pc = value;
2244 return;
2245 }
2246
2247 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {
2248 _registers.__r[regNum] = value;
2249 return;
2250 }
2251
2252#if defined(__ARM_WMMX)
2253 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {
2254 if (!_saved_iwmmx_control) {
2255 _saved_iwmmx_control = true;
2256 saveiWMMXControl(_iwmmx_control);
2257 }
2258 _iwmmx_control[regNum - UNW_ARM_WC0] = value;
2259 return;
2260 }
2261#endif
2262
2263 _LIBUNWIND_ABORT("unsupported arm register");
2264}
2265
2266inline const char *Registers_arm::getRegisterName(int regNum) {
2267 switch (regNum) {
2268 case UNW_REG_IP:
2269 case UNW_ARM_IP: // UNW_ARM_R15 is alias
2270 return "pc";
2271 case UNW_ARM_LR: // UNW_ARM_R14 is alias
2272 return "lr";
2273 case UNW_REG_SP:
2274 case UNW_ARM_SP: // UNW_ARM_R13 is alias
2275 return "sp";
2276 case UNW_ARM_R0:
2277 return "r0";
2278 case UNW_ARM_R1:
2279 return "r1";
2280 case UNW_ARM_R2:
2281 return "r2";
2282 case UNW_ARM_R3:
2283 return "r3";
2284 case UNW_ARM_R4:
2285 return "r4";
2286 case UNW_ARM_R5:
2287 return "r5";
2288 case UNW_ARM_R6:
2289 return "r6";
2290 case UNW_ARM_R7:
2291 return "r7";
2292 case UNW_ARM_R8:
2293 return "r8";
2294 case UNW_ARM_R9:
2295 return "r9";
2296 case UNW_ARM_R10:
2297 return "r10";
2298 case UNW_ARM_R11:
2299 return "r11";
2300 case UNW_ARM_R12:
2301 return "r12";
2302 case UNW_ARM_S0:
2303 return "s0";
2304 case UNW_ARM_S1:
2305 return "s1";
2306 case UNW_ARM_S2:
2307 return "s2";
2308 case UNW_ARM_S3:
2309 return "s3";
2310 case UNW_ARM_S4:
2311 return "s4";
2312 case UNW_ARM_S5:
2313 return "s5";
2314 case UNW_ARM_S6:
2315 return "s6";
2316 case UNW_ARM_S7:
2317 return "s7";
2318 case UNW_ARM_S8:
2319 return "s8";
2320 case UNW_ARM_S9:
2321 return "s9";
2322 case UNW_ARM_S10:
2323 return "s10";
2324 case UNW_ARM_S11:
2325 return "s11";
2326 case UNW_ARM_S12:
2327 return "s12";
2328 case UNW_ARM_S13:
2329 return "s13";
2330 case UNW_ARM_S14:
2331 return "s14";
2332 case UNW_ARM_S15:
2333 return "s15";
2334 case UNW_ARM_S16:
2335 return "s16";
2336 case UNW_ARM_S17:
2337 return "s17";
2338 case UNW_ARM_S18:
2339 return "s18";
2340 case UNW_ARM_S19:
2341 return "s19";
2342 case UNW_ARM_S20:
2343 return "s20";
2344 case UNW_ARM_S21:
2345 return "s21";
2346 case UNW_ARM_S22:
2347 return "s22";
2348 case UNW_ARM_S23:
2349 return "s23";
2350 case UNW_ARM_S24:
2351 return "s24";
2352 case UNW_ARM_S25:
2353 return "s25";
2354 case UNW_ARM_S26:
2355 return "s26";
2356 case UNW_ARM_S27:
2357 return "s27";
2358 case UNW_ARM_S28:
2359 return "s28";
2360 case UNW_ARM_S29:
2361 return "s29";
2362 case UNW_ARM_S30:
2363 return "s30";
2364 case UNW_ARM_S31:
2365 return "s31";
2366 case UNW_ARM_D0:
2367 return "d0";
2368 case UNW_ARM_D1:
2369 return "d1";
2370 case UNW_ARM_D2:
2371 return "d2";
2372 case UNW_ARM_D3:
2373 return "d3";
2374 case UNW_ARM_D4:
2375 return "d4";
2376 case UNW_ARM_D5:
2377 return "d5";
2378 case UNW_ARM_D6:
2379 return "d6";
2380 case UNW_ARM_D7:
2381 return "d7";
2382 case UNW_ARM_D8:
2383 return "d8";
2384 case UNW_ARM_D9:
2385 return "d9";
2386 case UNW_ARM_D10:
2387 return "d10";
2388 case UNW_ARM_D11:
2389 return "d11";
2390 case UNW_ARM_D12:
2391 return "d12";
2392 case UNW_ARM_D13:
2393 return "d13";
2394 case UNW_ARM_D14:
2395 return "d14";
2396 case UNW_ARM_D15:
2397 return "d15";
2398 case UNW_ARM_D16:
2399 return "d16";
2400 case UNW_ARM_D17:
2401 return "d17";
2402 case UNW_ARM_D18:
2403 return "d18";
2404 case UNW_ARM_D19:
2405 return "d19";
2406 case UNW_ARM_D20:
2407 return "d20";
2408 case UNW_ARM_D21:
2409 return "d21";
2410 case UNW_ARM_D22:
2411 return "d22";
2412 case UNW_ARM_D23:
2413 return "d23";
2414 case UNW_ARM_D24:
2415 return "d24";
2416 case UNW_ARM_D25:
2417 return "d25";
2418 case UNW_ARM_D26:
2419 return "d26";
2420 case UNW_ARM_D27:
2421 return "d27";
2422 case UNW_ARM_D28:
2423 return "d28";
2424 case UNW_ARM_D29:
2425 return "d29";
2426 case UNW_ARM_D30:
2427 return "d30";
2428 case UNW_ARM_D31:
2429 return "d31";
2430 default:
2431 return "unknown register";
2432 }
2433}
2434
2435inline bool Registers_arm::validFloatRegister(int regNum) const {
2436 // NOTE: Consider the intel MMX registers floating points so the
2437 // unw_get_fpreg can be used to transmit the 64-bit data back.
2438 return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))
2439#if defined(__ARM_WMMX)
2440 || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))
2441#endif
2442 ;
2443}
2444
2445inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {
2446 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2447 if (!_saved_vfp_d0_d15) {
2448 _saved_vfp_d0_d15 = true;
2449 if (_use_X_for_vfp_save)
2450 saveVFPWithFSTMX(_vfp_d0_d15_pad);
2451 else
2452 saveVFPWithFSTMD(_vfp_d0_d15_pad);
2453 }
2454 return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];
2455 }
2456
2457 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2458 if (!_saved_vfp_d16_d31) {
2459 _saved_vfp_d16_d31 = true;
2460 saveVFPv3(_vfp_d16_d31);
2461 }
2462 return _vfp_d16_d31[regNum - UNW_ARM_D16];
2463 }
2464
2465#if defined(__ARM_WMMX)
2466 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2467 if (!_saved_iwmmx) {
2468 _saved_iwmmx = true;
2469 saveiWMMX(_iwmmx);
2470 }
2471 return _iwmmx[regNum - UNW_ARM_WR0];
2472 }
2473#endif
2474
2475 _LIBUNWIND_ABORT("Unknown ARM float register");
2476}
2477
2478inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {
2479 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {
2480 if (!_saved_vfp_d0_d15) {
2481 _saved_vfp_d0_d15 = true;
2482 if (_use_X_for_vfp_save)
2483 saveVFPWithFSTMX(_vfp_d0_d15_pad);
2484 else
2485 saveVFPWithFSTMD(_vfp_d0_d15_pad);
2486 }
2487 _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;
2488 return;
2489 }
2490
2491 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {
2492 if (!_saved_vfp_d16_d31) {
2493 _saved_vfp_d16_d31 = true;
2494 saveVFPv3(_vfp_d16_d31);
2495 }
2496 _vfp_d16_d31[regNum - UNW_ARM_D16] = value;
2497 return;
2498 }
2499
2500#if defined(__ARM_WMMX)
2501 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {
2502 if (!_saved_iwmmx) {
2503 _saved_iwmmx = true;
2504 saveiWMMX(_iwmmx);
2505 }
2506 _iwmmx[regNum - UNW_ARM_WR0] = value;
2507 return;
2508 }
2509#endif
2510
2511 _LIBUNWIND_ABORT("Unknown ARM float register");
2512}
2513
2514inline bool Registers_arm::validVectorRegister(int) const {
2515 return false;
2516}
2517
2518inline v128 Registers_arm::getVectorRegister(int) const {
2519 _LIBUNWIND_ABORT("ARM vector support not implemented");
2520}
2521
2522inline void Registers_arm::setVectorRegister(int, v128) {
2523 _LIBUNWIND_ABORT("ARM vector support not implemented");
2524}
2525#endif // _LIBUNWIND_TARGET_ARM
2526
2527
2528#if defined(_LIBUNWIND_TARGET_OR1K)
2529/// Registers_or1k holds the register state of a thread in an OpenRISC1000
2530/// process.
2531class _LIBUNWIND_HIDDEN Registers_or1k {
2532public:
2533 Registers_or1k();
2534 Registers_or1k(const void *registers);
2535
2536 bool validRegister(int num) const;
2537 uint32_t getRegister(int num) const;
2538 void setRegister(int num, uint32_t value);
2539 bool validFloatRegister(int num) const;
2540 double getFloatRegister(int num) const;
2541 void setFloatRegister(int num, double value);
2542 bool validVectorRegister(int num) const;
2543 v128 getVectorRegister(int num) const;
2544 void setVectorRegister(int num, v128 value);
2545 static const char *getRegisterName(int num);
2546 void jumpto();
2547 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; }
2548 static int getArch() { return REGISTERS_OR1K; }
2549
2550 uint64_t getSP() const { return _registers.__r[1]; }
2551 void setSP(uint32_t value) { _registers.__r[1] = value; }
2552 uint64_t getIP() const { return _registers.__pc; }
2553 void setIP(uint32_t value) { _registers.__pc = value; }
2554
2555private:
2556 struct or1k_thread_state_t {
2557 unsigned int __r[32]; // r0-r31
2558 unsigned int __pc; // Program counter
2559 unsigned int __epcr; // Program counter at exception
2560 };
2561
2562 or1k_thread_state_t _registers;
2563};
2564
2565inline Registers_or1k::Registers_or1k(const void *registers) {
2566 static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),
2567 "or1k registers do not fit into unw_context_t");
2568 memcpy(&_registers, static_cast<const uint8_t *>(registers),
2569 sizeof(_registers));
2570}
2571
2572inline Registers_or1k::Registers_or1k() {
2573 memset(&_registers, 0, sizeof(_registers));
2574}
2575
2576inline bool Registers_or1k::validRegister(int regNum) const {
2577 if (regNum == UNW_REG_IP)
2578 return true;
2579 if (regNum == UNW_REG_SP)
2580 return true;
2581 if (regNum < 0)
2582 return false;
2583 if (regNum <= UNW_OR1K_R31)
2584 return true;
2585 if (regNum == UNW_OR1K_EPCR)
2586 return true;
2587 return false;
2588}
2589
2590inline uint32_t Registers_or1k::getRegister(int regNum) const {
2591 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
2592 return _registers.__r[regNum - UNW_OR1K_R0];
2593
2594 switch (regNum) {
2595 case UNW_REG_IP:
2596 return _registers.__pc;
2597 case UNW_REG_SP:
2598 return _registers.__r[1];
2599 case UNW_OR1K_EPCR:
2600 return _registers.__epcr;
2601 }
2602 _LIBUNWIND_ABORT("unsupported or1k register");
2603}
2604
2605inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
2606 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
2607 _registers.__r[regNum - UNW_OR1K_R0] = value;
2608 return;
2609 }
2610
2611 switch (regNum) {
2612 case UNW_REG_IP:
2613 _registers.__pc = value;
2614 return;
2615 case UNW_REG_SP:
2616 _registers.__r[1] = value;
2617 return;
2618 case UNW_OR1K_EPCR:
2619 _registers.__epcr = value;
2620 return;
2621 }
2622 _LIBUNWIND_ABORT("unsupported or1k register");
2623}
2624
2625inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {
2626 return false;
2627}
2628
2629inline double Registers_or1k::getFloatRegister(int /* regNum */) const {
2630 _LIBUNWIND_ABORT("or1k float support not implemented");
2631}
2632
2633inline void Registers_or1k::setFloatRegister(int /* regNum */,
2634 double /* value */) {
2635 _LIBUNWIND_ABORT("or1k float support not implemented");
2636}
2637
2638inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {
2639 return false;
2640}
2641
2642inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {
2643 _LIBUNWIND_ABORT("or1k vector support not implemented");
2644}
2645
2646inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {
2647 _LIBUNWIND_ABORT("or1k vector support not implemented");
2648}
2649
2650inline const char *Registers_or1k::getRegisterName(int regNum) {
2651 switch (regNum) {
2652 case UNW_OR1K_R0:
2653 return "r0";
2654 case UNW_OR1K_R1:
2655 return "r1";
2656 case UNW_OR1K_R2:
2657 return "r2";
2658 case UNW_OR1K_R3:
2659 return "r3";
2660 case UNW_OR1K_R4:
2661 return "r4";
2662 case UNW_OR1K_R5:
2663 return "r5";
2664 case UNW_OR1K_R6:
2665 return "r6";
2666 case UNW_OR1K_R7:
2667 return "r7";
2668 case UNW_OR1K_R8:
2669 return "r8";
2670 case UNW_OR1K_R9:
2671 return "r9";
2672 case UNW_OR1K_R10:
2673 return "r10";
2674 case UNW_OR1K_R11:
2675 return "r11";
2676 case UNW_OR1K_R12:
2677 return "r12";
2678 case UNW_OR1K_R13:
2679 return "r13";
2680 case UNW_OR1K_R14:
2681 return "r14";
2682 case UNW_OR1K_R15:
2683 return "r15";
2684 case UNW_OR1K_R16:
2685 return "r16";
2686 case UNW_OR1K_R17:
2687 return "r17";
2688 case UNW_OR1K_R18:
2689 return "r18";
2690 case UNW_OR1K_R19:
2691 return "r19";
2692 case UNW_OR1K_R20:
2693 return "r20";
2694 case UNW_OR1K_R21:
2695 return "r21";
2696 case UNW_OR1K_R22:
2697 return "r22";
2698 case UNW_OR1K_R23:
2699 return "r23";
2700 case UNW_OR1K_R24:
2701 return "r24";
2702 case UNW_OR1K_R25:
2703 return "r25";
2704 case UNW_OR1K_R26:
2705 return "r26";
2706 case UNW_OR1K_R27:
2707 return "r27";
2708 case UNW_OR1K_R28:
2709 return "r28";
2710 case UNW_OR1K_R29:
2711 return "r29";
2712 case UNW_OR1K_R30:
2713 return "r30";
2714 case UNW_OR1K_R31:
2715 return "r31";
2716 case UNW_OR1K_EPCR:
2717 return "EPCR";
2718 default:
2719 return "unknown register";
2720 }
2721
2722}
2723#endif // _LIBUNWIND_TARGET_OR1K
2724
2725#if defined(_LIBUNWIND_TARGET_MIPS_O32)
2726/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
2727/// process.
2728class _LIBUNWIND_HIDDEN Registers_mips_o32 {
2729public:
2730 Registers_mips_o32();
2731 Registers_mips_o32(const void *registers);
2732
2733 bool validRegister(int num) const;
2734 uint32_t getRegister(int num) const;
2735 void setRegister(int num, uint32_t value);
2736 bool validFloatRegister(int num) const;
2737 double getFloatRegister(int num) const;
2738 void setFloatRegister(int num, double value);
2739 bool validVectorRegister(int num) const;
2740 v128 getVectorRegister(int num) const;
2741 void setVectorRegister(int num, v128 value);
2742 static const char *getRegisterName(int num);
2743 void jumpto();
2744 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
2745 static int getArch() { return REGISTERS_MIPS_O32; }
2746
2747 uint32_t getSP() const { return _registers.__r[29]; }
2748 void setSP(uint32_t value) { _registers.__r[29] = value; }
2749 uint32_t getIP() const { return _registers.__pc; }
2750 void setIP(uint32_t value) { _registers.__pc = value; }
2751
2752private:
2753 struct mips_o32_thread_state_t {
2754 uint32_t __r[32];
2755 uint32_t __pc;
2756 uint32_t __hi;
2757 uint32_t __lo;
2758 };
2759
2760 mips_o32_thread_state_t _registers;
2761#ifdef __mips_hard_float
2762 /// O32 with 32-bit floating point registers only uses half of this
2763 /// space. However, using the same layout for 32-bit vs 64-bit
2764 /// floating point registers results in a single context size for
2765 /// O32 with hard float.
2766 uint32_t _padding;
2767 double _floats[32];
2768#endif
2769};
2770
2771inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
2772 static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
2773 "mips_o32 registers do not fit into unw_context_t");
2774 memcpy(&_registers, static_cast<const uint8_t *>(registers),
2775 sizeof(_registers));
2776}
2777
2778inline Registers_mips_o32::Registers_mips_o32() {
2779 memset(&_registers, 0, sizeof(_registers));
2780}
2781
2782inline bool Registers_mips_o32::validRegister(int regNum) const {
2783 if (regNum == UNW_REG_IP)
2784 return true;
2785 if (regNum == UNW_REG_SP)
2786 return true;
2787 if (regNum < 0)
2788 return false;
2789 if (regNum <= UNW_MIPS_R31)
2790 return true;
2791#if __mips_isa_rev != 6
2792 if (regNum == UNW_MIPS_HI)
2793 return true;
2794 if (regNum == UNW_MIPS_LO)
2795 return true;
2796#endif
2797#if defined(__mips_hard_float) && __mips_fpr == 32
2798 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2799 return true;
2800#endif
2801 // FIXME: DSP accumulator registers, MSA registers
2802 return false;
2803}
2804
2805inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
2806 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
2807 return _registers.__r[regNum - UNW_MIPS_R0];
2808#if defined(__mips_hard_float) && __mips_fpr == 32
2809 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2810 uint32_t *p;
2811
2812 if (regNum % 2 == 0)
2813 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2814 else
2815 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2816 return *p;
2817 }
2818#endif
2819
2820 switch (regNum) {
2821 case UNW_REG_IP:
2822 return _registers.__pc;
2823 case UNW_REG_SP:
2824 return _registers.__r[29];
2825 case UNW_MIPS_HI:
2826 return _registers.__hi;
2827 case UNW_MIPS_LO:
2828 return _registers.__lo;
2829 }
2830 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2831}
2832
2833inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
2834 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
2835 _registers.__r[regNum - UNW_MIPS_R0] = value;
2836 return;
2837 }
2838#if defined(__mips_hard_float) && __mips_fpr == 32
2839 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
2840 uint32_t *p;
2841
2842 if (regNum % 2 == 0)
2843 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
2844 else
2845 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
2846 *p = value;
2847 return;
2848 }
2849#endif
2850
2851 switch (regNum) {
2852 case UNW_REG_IP:
2853 _registers.__pc = value;
2854 return;
2855 case UNW_REG_SP:
2856 _registers.__r[29] = value;
2857 return;
2858 case UNW_MIPS_HI:
2859 _registers.__hi = value;
2860 return;
2861 case UNW_MIPS_LO:
2862 _registers.__lo = value;
2863 return;
2864 }
2865 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2866}
2867
2868inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
2869#if defined(__mips_hard_float) && __mips_fpr == 64
2870 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
2871 return true;
2872#endif
2873 return false;
2874}
2875
2876inline double Registers_mips_o32::getFloatRegister(int regNum) const {
2877#if defined(__mips_hard_float) && __mips_fpr == 64
2878 assert(validFloatRegister(regNum));
2879 return _floats[regNum - UNW_MIPS_F0];
2880#else
2881 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2882#endif
2883}
2884
2885inline void Registers_mips_o32::setFloatRegister(int regNum,
2886 double value) {
2887#if defined(__mips_hard_float) && __mips_fpr == 64
2888 assert(validFloatRegister(regNum));
2889 _floats[regNum - UNW_MIPS_F0] = value;
2890#else
2891 _LIBUNWIND_ABORT("mips_o32 float support not implemented");
2892#endif
2893}
2894
2895inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
2896 return false;
2897}
2898
2899inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
2900 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2901}
2902
2903inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
2904 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
2905}
2906
2907inline const char *Registers_mips_o32::getRegisterName(int regNum) {
2908 switch (regNum) {
2909 case UNW_MIPS_R0:
2910 return "$0";
2911 case UNW_MIPS_R1:
2912 return "$1";
2913 case UNW_MIPS_R2:
2914 return "$2";
2915 case UNW_MIPS_R3:
2916 return "$3";
2917 case UNW_MIPS_R4:
2918 return "$4";
2919 case UNW_MIPS_R5:
2920 return "$5";
2921 case UNW_MIPS_R6:
2922 return "$6";
2923 case UNW_MIPS_R7:
2924 return "$7";
2925 case UNW_MIPS_R8:
2926 return "$8";
2927 case UNW_MIPS_R9:
2928 return "$9";
2929 case UNW_MIPS_R10:
2930 return "$10";
2931 case UNW_MIPS_R11:
2932 return "$11";
2933 case UNW_MIPS_R12:
2934 return "$12";
2935 case UNW_MIPS_R13:
2936 return "$13";
2937 case UNW_MIPS_R14:
2938 return "$14";
2939 case UNW_MIPS_R15:
2940 return "$15";
2941 case UNW_MIPS_R16:
2942 return "$16";
2943 case UNW_MIPS_R17:
2944 return "$17";
2945 case UNW_MIPS_R18:
2946 return "$18";
2947 case UNW_MIPS_R19:
2948 return "$19";
2949 case UNW_MIPS_R20:
2950 return "$20";
2951 case UNW_MIPS_R21:
2952 return "$21";
2953 case UNW_MIPS_R22:
2954 return "$22";
2955 case UNW_MIPS_R23:
2956 return "$23";
2957 case UNW_MIPS_R24:
2958 return "$24";
2959 case UNW_MIPS_R25:
2960 return "$25";
2961 case UNW_MIPS_R26:
2962 return "$26";
2963 case UNW_MIPS_R27:
2964 return "$27";
2965 case UNW_MIPS_R28:
2966 return "$28";
2967 case UNW_MIPS_R29:
2968 return "$29";
2969 case UNW_MIPS_R30:
2970 return "$30";
2971 case UNW_MIPS_R31:
2972 return "$31";
2973 case UNW_MIPS_F0:
2974 return "$f0";
2975 case UNW_MIPS_F1:
2976 return "$f1";
2977 case UNW_MIPS_F2:
2978 return "$f2";
2979 case UNW_MIPS_F3:
2980 return "$f3";
2981 case UNW_MIPS_F4:
2982 return "$f4";
2983 case UNW_MIPS_F5:
2984 return "$f5";
2985 case UNW_MIPS_F6:
2986 return "$f6";
2987 case UNW_MIPS_F7:
2988 return "$f7";
2989 case UNW_MIPS_F8:
2990 return "$f8";
2991 case UNW_MIPS_F9:
2992 return "$f9";
2993 case UNW_MIPS_F10:
2994 return "$f10";
2995 case UNW_MIPS_F11:
2996 return "$f11";
2997 case UNW_MIPS_F12:
2998 return "$f12";
2999 case UNW_MIPS_F13:
3000 return "$f13";
3001 case UNW_MIPS_F14:
3002 return "$f14";
3003 case UNW_MIPS_F15:
3004 return "$f15";
3005 case UNW_MIPS_F16:
3006 return "$f16";
3007 case UNW_MIPS_F17:
3008 return "$f17";
3009 case UNW_MIPS_F18:
3010 return "$f18";
3011 case UNW_MIPS_F19:
3012 return "$f19";
3013 case UNW_MIPS_F20:
3014 return "$f20";
3015 case UNW_MIPS_F21:
3016 return "$f21";
3017 case UNW_MIPS_F22:
3018 return "$f22";
3019 case UNW_MIPS_F23:
3020 return "$f23";
3021 case UNW_MIPS_F24:
3022 return "$f24";
3023 case UNW_MIPS_F25:
3024 return "$f25";
3025 case UNW_MIPS_F26:
3026 return "$f26";
3027 case UNW_MIPS_F27:
3028 return "$f27";
3029 case UNW_MIPS_F28:
3030 return "$f28";
3031 case UNW_MIPS_F29:
3032 return "$f29";
3033 case UNW_MIPS_F30:
3034 return "$f30";
3035 case UNW_MIPS_F31:
3036 return "$f31";
3037 case UNW_MIPS_HI:
3038 return "$hi";
3039 case UNW_MIPS_LO:
3040 return "$lo";
3041 default:
3042 return "unknown register";
3043 }
3044}
3045#endif // _LIBUNWIND_TARGET_MIPS_O32
3046
3047#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
3048/// Registers_mips_newabi holds the register state of a thread in a
3049/// MIPS process using NEWABI (the N32 or N64 ABIs).
3050class _LIBUNWIND_HIDDEN Registers_mips_newabi {
3051public:
3052 Registers_mips_newabi();
3053 Registers_mips_newabi(const void *registers);
3054
3055 bool validRegister(int num) const;
3056 uint64_t getRegister(int num) const;
3057 void setRegister(int num, uint64_t value);
3058 bool validFloatRegister(int num) const;
3059 double getFloatRegister(int num) const;
3060 void setFloatRegister(int num, double value);
3061 bool validVectorRegister(int num) const;
3062 v128 getVectorRegister(int num) const;
3063 void setVectorRegister(int num, v128 value);
3064 static const char *getRegisterName(int num);
3065 void jumpto();
3066 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
3067 static int getArch() { return REGISTERS_MIPS_NEWABI; }
3068
3069 uint64_t getSP() const { return _registers.__r[29]; }
3070 void setSP(uint64_t value) { _registers.__r[29] = value; }
3071 uint64_t getIP() const { return _registers.__pc; }
3072 void setIP(uint64_t value) { _registers.__pc = value; }
3073
3074private:
3075 struct mips_newabi_thread_state_t {
3076 uint64_t __r[32];
3077 uint64_t __pc;
3078 uint64_t __hi;
3079 uint64_t __lo;
3080 };
3081
3082 mips_newabi_thread_state_t _registers;
3083#ifdef __mips_hard_float
3084 double _floats[32];
3085#endif
3086};
3087
3088inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
3089 static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
3090 "mips_newabi registers do not fit into unw_context_t");
3091 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3092 sizeof(_registers));
3093}
3094
3095inline Registers_mips_newabi::Registers_mips_newabi() {
3096 memset(&_registers, 0, sizeof(_registers));
3097}
3098
3099inline bool Registers_mips_newabi::validRegister(int regNum) const {
3100 if (regNum == UNW_REG_IP)
3101 return true;
3102 if (regNum == UNW_REG_SP)
3103 return true;
3104 if (regNum < 0)
3105 return false;
3106 if (regNum <= UNW_MIPS_R31)
3107 return true;
3108#if __mips_isa_rev != 6
3109 if (regNum == UNW_MIPS_HI)
3110 return true;
3111 if (regNum == UNW_MIPS_LO)
3112 return true;
3113#endif
3114 // FIXME: Hard float, DSP accumulator registers, MSA registers
3115 return false;
3116}
3117
3118inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
3119 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
3120 return _registers.__r[regNum - UNW_MIPS_R0];
3121
3122 switch (regNum) {
3123 case UNW_REG_IP:
3124 return _registers.__pc;
3125 case UNW_REG_SP:
3126 return _registers.__r[29];
3127 case UNW_MIPS_HI:
3128 return _registers.__hi;
3129 case UNW_MIPS_LO:
3130 return _registers.__lo;
3131 }
3132 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3133}
3134
3135inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
3136 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
3137 _registers.__r[regNum - UNW_MIPS_R0] = value;
3138 return;
3139 }
3140
3141 switch (regNum) {
3142 case UNW_REG_IP:
3143 _registers.__pc = value;
3144 return;
3145 case UNW_REG_SP:
3146 _registers.__r[29] = value;
3147 return;
3148 case UNW_MIPS_HI:
3149 _registers.__hi = value;
3150 return;
3151 case UNW_MIPS_LO:
3152 _registers.__lo = value;
3153 return;
3154 }
3155 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3156}
3157
3158inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
3159#ifdef __mips_hard_float
3160 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
3161 return true;
3162#endif
3163 return false;
3164}
3165
3166inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
3167#ifdef __mips_hard_float
3168 assert(validFloatRegister(regNum));
3169 return _floats[regNum - UNW_MIPS_F0];
3170#else
3171 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3172#endif
3173}
3174
3175inline void Registers_mips_newabi::setFloatRegister(int regNum,
3176 double value) {
3177#ifdef __mips_hard_float
3178 assert(validFloatRegister(regNum));
3179 _floats[regNum - UNW_MIPS_F0] = value;
3180#else
3181 _LIBUNWIND_ABORT("mips_newabi float support not implemented");
3182#endif
3183}
3184
3185inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
3186 return false;
3187}
3188
3189inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
3190 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3191}
3192
3193inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
3194 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
3195}
3196
3197inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
3198 switch (regNum) {
3199 case UNW_MIPS_R0:
3200 return "$0";
3201 case UNW_MIPS_R1:
3202 return "$1";
3203 case UNW_MIPS_R2:
3204 return "$2";
3205 case UNW_MIPS_R3:
3206 return "$3";
3207 case UNW_MIPS_R4:
3208 return "$4";
3209 case UNW_MIPS_R5:
3210 return "$5";
3211 case UNW_MIPS_R6:
3212 return "$6";
3213 case UNW_MIPS_R7:
3214 return "$7";
3215 case UNW_MIPS_R8:
3216 return "$8";
3217 case UNW_MIPS_R9:
3218 return "$9";
3219 case UNW_MIPS_R10:
3220 return "$10";
3221 case UNW_MIPS_R11:
3222 return "$11";
3223 case UNW_MIPS_R12:
3224 return "$12";
3225 case UNW_MIPS_R13:
3226 return "$13";
3227 case UNW_MIPS_R14:
3228 return "$14";
3229 case UNW_MIPS_R15:
3230 return "$15";
3231 case UNW_MIPS_R16:
3232 return "$16";
3233 case UNW_MIPS_R17:
3234 return "$17";
3235 case UNW_MIPS_R18:
3236 return "$18";
3237 case UNW_MIPS_R19:
3238 return "$19";
3239 case UNW_MIPS_R20:
3240 return "$20";
3241 case UNW_MIPS_R21:
3242 return "$21";
3243 case UNW_MIPS_R22:
3244 return "$22";
3245 case UNW_MIPS_R23:
3246 return "$23";
3247 case UNW_MIPS_R24:
3248 return "$24";
3249 case UNW_MIPS_R25:
3250 return "$25";
3251 case UNW_MIPS_R26:
3252 return "$26";
3253 case UNW_MIPS_R27:
3254 return "$27";
3255 case UNW_MIPS_R28:
3256 return "$28";
3257 case UNW_MIPS_R29:
3258 return "$29";
3259 case UNW_MIPS_R30:
3260 return "$30";
3261 case UNW_MIPS_R31:
3262 return "$31";
3263 case UNW_MIPS_F0:
3264 return "$f0";
3265 case UNW_MIPS_F1:
3266 return "$f1";
3267 case UNW_MIPS_F2:
3268 return "$f2";
3269 case UNW_MIPS_F3:
3270 return "$f3";
3271 case UNW_MIPS_F4:
3272 return "$f4";
3273 case UNW_MIPS_F5:
3274 return "$f5";
3275 case UNW_MIPS_F6:
3276 return "$f6";
3277 case UNW_MIPS_F7:
3278 return "$f7";
3279 case UNW_MIPS_F8:
3280 return "$f8";
3281 case UNW_MIPS_F9:
3282 return "$f9";
3283 case UNW_MIPS_F10:
3284 return "$f10";
3285 case UNW_MIPS_F11:
3286 return "$f11";
3287 case UNW_MIPS_F12:
3288 return "$f12";
3289 case UNW_MIPS_F13:
3290 return "$f13";
3291 case UNW_MIPS_F14:
3292 return "$f14";
3293 case UNW_MIPS_F15:
3294 return "$f15";
3295 case UNW_MIPS_F16:
3296 return "$f16";
3297 case UNW_MIPS_F17:
3298 return "$f17";
3299 case UNW_MIPS_F18:
3300 return "$f18";
3301 case UNW_MIPS_F19:
3302 return "$f19";
3303 case UNW_MIPS_F20:
3304 return "$f20";
3305 case UNW_MIPS_F21:
3306 return "$f21";
3307 case UNW_MIPS_F22:
3308 return "$f22";
3309 case UNW_MIPS_F23:
3310 return "$f23";
3311 case UNW_MIPS_F24:
3312 return "$f24";
3313 case UNW_MIPS_F25:
3314 return "$f25";
3315 case UNW_MIPS_F26:
3316 return "$f26";
3317 case UNW_MIPS_F27:
3318 return "$f27";
3319 case UNW_MIPS_F28:
3320 return "$f28";
3321 case UNW_MIPS_F29:
3322 return "$f29";
3323 case UNW_MIPS_F30:
3324 return "$f30";
3325 case UNW_MIPS_F31:
3326 return "$f31";
3327 case UNW_MIPS_HI:
3328 return "$hi";
3329 case UNW_MIPS_LO:
3330 return "$lo";
3331 default:
3332 return "unknown register";
3333 }
3334}
3335#endif // _LIBUNWIND_TARGET_MIPS_NEWABI
3336
3337#if defined(_LIBUNWIND_TARGET_SPARC)
3338/// Registers_sparc holds the register state of a thread in a 32-bit Sparc
3339/// process.
3340class _LIBUNWIND_HIDDEN Registers_sparc {
3341public:
3342 Registers_sparc();
3343 Registers_sparc(const void *registers);
3344
3345 bool validRegister(int num) const;
3346 uint32_t getRegister(int num) const;
3347 void setRegister(int num, uint32_t value);
3348 bool validFloatRegister(int num) const;
3349 double getFloatRegister(int num) const;
3350 void setFloatRegister(int num, double value);
3351 bool validVectorRegister(int num) const;
3352 v128 getVectorRegister(int num) const;
3353 void setVectorRegister(int num, v128 value);
3354 static const char *getRegisterName(int num);
3355 void jumpto();
3356 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; }
3357 static int getArch() { return REGISTERS_SPARC; }
3358
3359 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
3360 void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }
3361 uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
3362 void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
3363
3364private:
3365 struct sparc_thread_state_t {
3366 unsigned int __regs[32];
3367 };
3368
3369 sparc_thread_state_t _registers;
3370};
3371
3372inline Registers_sparc::Registers_sparc(const void *registers) {
3373 static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),
3374 "sparc registers do not fit into unw_context_t");
3375 memcpy(&_registers, static_cast<const uint8_t *>(registers),
3376 sizeof(_registers));
3377}
3378
3379inline Registers_sparc::Registers_sparc() {
3380 memset(&_registers, 0, sizeof(_registers));
3381}
3382
3383inline bool Registers_sparc::validRegister(int regNum) const {
3384 if (regNum == UNW_REG_IP)
3385 return true;
3386 if (regNum == UNW_REG_SP)
3387 return true;
3388 if (regNum < 0)
3389 return false;
3390 if (regNum <= UNW_SPARC_I7)
3391 return true;
3392 return false;
3393}
3394
3395inline uint32_t Registers_sparc::getRegister(int regNum) const {
3396 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3397 return _registers.__regs[regNum];
3398 }
3399
3400 switch (regNum) {
3401 case UNW_REG_IP:
3402 return _registers.__regs[UNW_SPARC_O7];
3403 case UNW_REG_SP:
3404 return _registers.__regs[UNW_SPARC_O6];
3405 }
3406 _LIBUNWIND_ABORT("unsupported sparc register");
3407}
3408
3409inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
3410 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {
3411 _registers.__regs[regNum] = value;
3412 return;
3413 }
3414
3415 switch (regNum) {
3416 case UNW_REG_IP:
3417 _registers.__regs[UNW_SPARC_O7] = value;
3418 return;
3419 case UNW_REG_SP:
3420 _registers.__regs[UNW_SPARC_O6] = value;
3421 return;
3422 }
3423 _LIBUNWIND_ABORT("unsupported sparc register");
3424}
3425
3426inline bool Registers_sparc::validFloatRegister(int) const { return false; }
3427
3428inline double Registers_sparc::getFloatRegister(int) const {
3429 _LIBUNWIND_ABORT("no Sparc float registers");
3430}
3431
3432inline void Registers_sparc::setFloatRegister(int, double) {
3433 _LIBUNWIND_ABORT("no Sparc float registers");
3434}
3435
3436inline bool Registers_sparc::validVectorRegister(int) const { return false; }
3437
3438inline v128 Registers_sparc::getVectorRegister(int) const {
3439 _LIBUNWIND_ABORT("no Sparc vector registers");
3440}
3441
3442inline void Registers_sparc::setVectorRegister(int, v128) {
3443 _LIBUNWIND_ABORT("no Sparc vector registers");
3444}
3445
3446inline const char *Registers_sparc::getRegisterName(int regNum) {
3447 switch (regNum) {
3448 case UNW_REG_IP:
3449 return "pc";
3450 case UNW_SPARC_G0:
3451 return "g0";
3452 case UNW_SPARC_G1:
3453 return "g1";
3454 case UNW_SPARC_G2:
3455 return "g2";
3456 case UNW_SPARC_G3:
3457 return "g3";
3458 case UNW_SPARC_G4:
3459 return "g4";
3460 case UNW_SPARC_G5:
3461 return "g5";
3462 case UNW_SPARC_G6:
3463 return "g6";
3464 case UNW_SPARC_G7:
3465 return "g7";
3466 case UNW_SPARC_O0:
3467 return "o0";
3468 case UNW_SPARC_O1:
3469 return "o1";
3470 case UNW_SPARC_O2:
3471 return "o2";
3472 case UNW_SPARC_O3:
3473 return "o3";
3474 case UNW_SPARC_O4:
3475 return "o4";
3476 case UNW_SPARC_O5:
3477 return "o5";
3478 case UNW_REG_SP:
3479 case UNW_SPARC_O6:
3480 return "sp";
3481 case UNW_SPARC_O7:
3482 return "o7";
3483 case UNW_SPARC_L0:
3484 return "l0";
3485 case UNW_SPARC_L1:
3486 return "l1";
3487 case UNW_SPARC_L2:
3488 return "l2";
3489 case UNW_SPARC_L3:
3490 return "l3";
3491 case UNW_SPARC_L4:
3492 return "l4";
3493 case UNW_SPARC_L5:
3494 return "l5";
3495 case UNW_SPARC_L6:
3496 return "l6";
3497 case UNW_SPARC_L7:
3498 return "l7";
3499 case UNW_SPARC_I0:
3500 return "i0";
3501 case UNW_SPARC_I1:
3502 return "i1";
3503 case UNW_SPARC_I2:
3504 return "i2";
3505 case UNW_SPARC_I3:
3506 return "i3";
3507 case UNW_SPARC_I4:
3508 return "i4";
3509 case UNW_SPARC_I5:
3510 return "i5";
3511 case UNW_SPARC_I6:
3512 return "fp";
3513 case UNW_SPARC_I7:
3514 return "i7";
3515 default:
3516 return "unknown register";
3517 }
3518}
3519#endif // _LIBUNWIND_TARGET_SPARC
3520
3521} // namespace libunwind
3522
3523#endif // __REGISTERS_HPP__
libunwind/src/Unwind-EHABI.cpp created+991
...@@ -0,0 +1,991 @@
1//===--------------------------- Unwind-EHABI.cpp -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Implements ARM zero-cost C++ exceptions
10//
11//===----------------------------------------------------------------------===//
12
13#include "Unwind-EHABI.h"
14
15#if defined(_LIBUNWIND_ARM_EHABI)
16
17#include <inttypes.h>
18#include <stdbool.h>
19#include <stdint.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <type_traits>
25
26#include "config.h"
27#include "libunwind.h"
28#include "libunwind_ext.h"
29#include "unwind.h"
30
31namespace {
32
33// Strange order: take words in order, but inside word, take from most to least
34// signinficant byte.
35uint8_t getByte(const uint32_t* data, size_t offset) {
36 const uint8_t* byteData = reinterpret_cast<const uint8_t*>(data);
37 return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))];
38}
39
40const char* getNextWord(const char* data, uint32_t* out) {
41 *out = *reinterpret_cast<const uint32_t*>(data);
42 return data + 4;
43}
44
45const char* getNextNibble(const char* data, uint32_t* out) {
46 *out = *reinterpret_cast<const uint16_t*>(data);
47 return data + 2;
48}
49
50struct Descriptor {
51 // See # 9.2
52 typedef enum {
53 SU16 = 0, // Short descriptor, 16-bit entries
54 LU16 = 1, // Long descriptor, 16-bit entries
55 LU32 = 3, // Long descriptor, 32-bit entries
56 RESERVED0 = 4, RESERVED1 = 5, RESERVED2 = 6, RESERVED3 = 7,
57 RESERVED4 = 8, RESERVED5 = 9, RESERVED6 = 10, RESERVED7 = 11,
58 RESERVED8 = 12, RESERVED9 = 13, RESERVED10 = 14, RESERVED11 = 15
59 } Format;
60
61 // See # 9.2
62 typedef enum {
63 CLEANUP = 0x0,
64 FUNC = 0x1,
65 CATCH = 0x2,
66 INVALID = 0x4
67 } Kind;
68};
69
70_Unwind_Reason_Code ProcessDescriptors(
71 _Unwind_State state,
72 _Unwind_Control_Block* ucbp,
73 struct _Unwind_Context* context,
74 Descriptor::Format format,
75 const char* descriptorStart,
76 uint32_t flags) {
77
78 // EHT is inlined in the index using compact form. No descriptors. #5
79 if (flags & 0x1)
80 return _URC_CONTINUE_UNWIND;
81
82 // TODO: We should check the state here, and determine whether we need to
83 // perform phase1 or phase2 unwinding.
84 (void)state;
85
86 const char* descriptor = descriptorStart;
87 uint32_t descriptorWord;
88 getNextWord(descriptor, &descriptorWord);
89 while (descriptorWord) {
90 // Read descriptor based on # 9.2.
91 uint32_t length;
92 uint32_t offset;
93 switch (format) {
94 case Descriptor::LU32:
95 descriptor = getNextWord(descriptor, &length);
96 descriptor = getNextWord(descriptor, &offset);
97 case Descriptor::LU16:
98 descriptor = getNextNibble(descriptor, &length);
99 descriptor = getNextNibble(descriptor, &offset);
100 default:
101 assert(false);
102 return _URC_FAILURE;
103 }
104
105 // See # 9.2 table for decoding the kind of descriptor. It's a 2-bit value.
106 Descriptor::Kind kind =
107 static_cast<Descriptor::Kind>((length & 0x1) | ((offset & 0x1) << 1));
108
109 // Clear off flag from last bit.
110 length &= ~1u;
111 offset &= ~1u;
112 uintptr_t scopeStart = ucbp->pr_cache.fnstart + offset;
113 uintptr_t scopeEnd = scopeStart + length;
114 uintptr_t pc = _Unwind_GetIP(context);
115 bool isInScope = (scopeStart <= pc) && (pc < scopeEnd);
116
117 switch (kind) {
118 case Descriptor::CLEANUP: {
119 // TODO(ajwong): Handle cleanup descriptors.
120 break;
121 }
122 case Descriptor::FUNC: {
123 // TODO(ajwong): Handle function descriptors.
124 break;
125 }
126 case Descriptor::CATCH: {
127 // Catch descriptors require gobbling one more word.
128 uint32_t landing_pad;
129 descriptor = getNextWord(descriptor, &landing_pad);
130
131 if (isInScope) {
132 // TODO(ajwong): This is only phase1 compatible logic. Implement
133 // phase2.
134 landing_pad = signExtendPrel31(landing_pad & ~0x80000000);
135 if (landing_pad == 0xffffffff) {
136 return _URC_HANDLER_FOUND;
137 } else if (landing_pad == 0xfffffffe) {
138 return _URC_FAILURE;
139 } else {
140 /*
141 bool is_reference_type = landing_pad & 0x80000000;
142 void* matched_object;
143 if (__cxxabiv1::__cxa_type_match(
144 ucbp, reinterpret_cast<const std::type_info *>(landing_pad),
145 is_reference_type,
146 &matched_object) != __cxxabiv1::ctm_failed)
147 return _URC_HANDLER_FOUND;
148 */
149 _LIBUNWIND_ABORT("Type matching not implemented");
150 }
151 }
152 break;
153 }
154 default:
155 _LIBUNWIND_ABORT("Invalid descriptor kind found.");
156 }
157
158 getNextWord(descriptor, &descriptorWord);
159 }
160
161 return _URC_CONTINUE_UNWIND;
162}
163
164static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state,
165 _Unwind_Control_Block* ucbp,
166 struct _Unwind_Context* context) {
167 // Read the compact model EHT entry's header # 6.3
168 const uint32_t* unwindingData = ucbp->pr_cache.ehtp;
169 assert((*unwindingData & 0xf0000000) == 0x80000000 && "Must be a compact entry");
170 Descriptor::Format format =
171 static_cast<Descriptor::Format>((*unwindingData & 0x0f000000) >> 24);
172
173 const char *lsda =
174 reinterpret_cast<const char *>(_Unwind_GetLanguageSpecificData(context));
175
176 // Handle descriptors before unwinding so they are processed in the context
177 // of the correct stack frame.
178 _Unwind_Reason_Code result =
179 ProcessDescriptors(state, ucbp, context, format, lsda,
180 ucbp->pr_cache.additional);
181
182 if (result != _URC_CONTINUE_UNWIND)
183 return result;
184
185 if (unw_step(reinterpret_cast<unw_cursor_t*>(context)) != UNW_STEP_SUCCESS)
186 return _URC_FAILURE;
187 return _URC_CONTINUE_UNWIND;
188}
189
190// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE /
191// _UVRSD_UINT32.
192uint32_t RegisterMask(uint8_t start, uint8_t count_minus_one) {
193 return ((1U << (count_minus_one + 1)) - 1) << start;
194}
195
196// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_VFP /
197// _UVRSD_DOUBLE.
198uint32_t RegisterRange(uint8_t start, uint8_t count_minus_one) {
199 return ((uint32_t)start << 16) | ((uint32_t)count_minus_one + 1);
200}
201
202} // end anonymous namespace
203
204/**
205 * Decodes an EHT entry.
206 *
207 * @param data Pointer to EHT.
208 * @param[out] off Offset from return value (in bytes) to begin interpretation.
209 * @param[out] len Number of bytes in unwind code.
210 * @return Pointer to beginning of unwind code.
211 */
212extern "C" const uint32_t*
213decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) {
214 if ((*data & 0x80000000) == 0) {
215 // 6.2: Generic Model
216 //
217 // EHT entry is a prel31 pointing to the PR, followed by data understood
218 // only by the personality routine. Fortunately, all existing assembler
219 // implementations, including GNU assembler, LLVM integrated assembler,
220 // and ARM assembler, assume that the unwind opcodes come after the
221 // personality rountine address.
222 *off = 1; // First byte is size data.
223 *len = (((data[1] >> 24) & 0xff) + 1) * 4;
224 data++; // Skip the first word, which is the prel31 offset.
225 } else {
226 // 6.3: ARM Compact Model
227 //
228 // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded
229 // by format:
230 Descriptor::Format format =
231 static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24);
232 switch (format) {
233 case Descriptor::SU16:
234 *len = 4;
235 *off = 1;
236 break;
237 case Descriptor::LU16:
238 case Descriptor::LU32:
239 *len = 4 + 4 * ((*data & 0x00ff0000) >> 16);
240 *off = 2;
241 break;
242 default:
243 return nullptr;
244 }
245 }
246 return data;
247}
248
249_LIBUNWIND_EXPORT _Unwind_Reason_Code
250_Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,
251 size_t offset, size_t len) {
252 bool wrotePC = false;
253 bool finish = false;
254 while (offset < len && !finish) {
255 uint8_t byte = getByte(data, offset++);
256 if ((byte & 0x80) == 0) {
257 uint32_t sp;
258 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
259 if (byte & 0x40)
260 sp -= (((uint32_t)byte & 0x3f) << 2) + 4;
261 else
262 sp += ((uint32_t)byte << 2) + 4;
263 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
264 } else {
265 switch (byte & 0xf0) {
266 case 0x80: {
267 if (offset >= len)
268 return _URC_FAILURE;
269 uint32_t registers =
270 (((uint32_t)byte & 0x0f) << 12) |
271 (((uint32_t)getByte(data, offset++)) << 4);
272 if (!registers)
273 return _URC_FAILURE;
274 if (registers & (1 << 15))
275 wrotePC = true;
276 _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);
277 break;
278 }
279 case 0x90: {
280 uint8_t reg = byte & 0x0f;
281 if (reg == 13 || reg == 15)
282 return _URC_FAILURE;
283 uint32_t sp;
284 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg,
285 _UVRSD_UINT32, &sp);
286 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
287 &sp);
288 break;
289 }
290 case 0xa0: {
291 uint32_t registers = RegisterMask(4, byte & 0x07);
292 if (byte & 0x08)
293 registers |= 1 << 14;
294 _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);
295 break;
296 }
297 case 0xb0: {
298 switch (byte) {
299 case 0xb0:
300 finish = true;
301 break;
302 case 0xb1: {
303 if (offset >= len)
304 return _URC_FAILURE;
305 uint8_t registers = getByte(data, offset++);
306 if (registers & 0xf0 || !registers)
307 return _URC_FAILURE;
308 _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);
309 break;
310 }
311 case 0xb2: {
312 uint32_t addend = 0;
313 uint32_t shift = 0;
314 // This decodes a uleb128 value.
315 while (true) {
316 if (offset >= len)
317 return _URC_FAILURE;
318 uint32_t v = getByte(data, offset++);
319 addend |= (v & 0x7f) << shift;
320 if ((v & 0x80) == 0)
321 break;
322 shift += 7;
323 }
324 uint32_t sp;
325 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
326 &sp);
327 sp += 0x204 + (addend << 2);
328 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
329 &sp);
330 break;
331 }
332 case 0xb3: {
333 uint8_t v = getByte(data, offset++);
334 _Unwind_VRS_Pop(context, _UVRSC_VFP,
335 RegisterRange(static_cast<uint8_t>(v >> 4),
336 v & 0x0f), _UVRSD_VFPX);
337 break;
338 }
339 case 0xb4:
340 case 0xb5:
341 case 0xb6:
342 case 0xb7:
343 return _URC_FAILURE;
344 default:
345 _Unwind_VRS_Pop(context, _UVRSC_VFP,
346 RegisterRange(8, byte & 0x07), _UVRSD_VFPX);
347 break;
348 }
349 break;
350 }
351 case 0xc0: {
352 switch (byte) {
353#if defined(__ARM_WMMX)
354 case 0xc0:
355 case 0xc1:
356 case 0xc2:
357 case 0xc3:
358 case 0xc4:
359 case 0xc5:
360 _Unwind_VRS_Pop(context, _UVRSC_WMMXD,
361 RegisterRange(10, byte & 0x7), _UVRSD_DOUBLE);
362 break;
363 case 0xc6: {
364 uint8_t v = getByte(data, offset++);
365 uint8_t start = static_cast<uint8_t>(v >> 4);
366 uint8_t count_minus_one = v & 0xf;
367 if (start + count_minus_one >= 16)
368 return _URC_FAILURE;
369 _Unwind_VRS_Pop(context, _UVRSC_WMMXD,
370 RegisterRange(start, count_minus_one),
371 _UVRSD_DOUBLE);
372 break;
373 }
374 case 0xc7: {
375 uint8_t v = getByte(data, offset++);
376 if (!v || v & 0xf0)
377 return _URC_FAILURE;
378 _Unwind_VRS_Pop(context, _UVRSC_WMMXC, v, _UVRSD_DOUBLE);
379 break;
380 }
381#endif
382 case 0xc8:
383 case 0xc9: {
384 uint8_t v = getByte(data, offset++);
385 uint8_t start =
386 static_cast<uint8_t>(((byte == 0xc8) ? 16 : 0) + (v >> 4));
387 uint8_t count_minus_one = v & 0xf;
388 if (start + count_minus_one >= 32)
389 return _URC_FAILURE;
390 _Unwind_VRS_Pop(context, _UVRSC_VFP,
391 RegisterRange(start, count_minus_one),
392 _UVRSD_DOUBLE);
393 break;
394 }
395 default:
396 return _URC_FAILURE;
397 }
398 break;
399 }
400 case 0xd0: {
401 if (byte & 0x08)
402 return _URC_FAILURE;
403 _Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(8, byte & 0x7),
404 _UVRSD_DOUBLE);
405 break;
406 }
407 default:
408 return _URC_FAILURE;
409 }
410 }
411 }
412 if (!wrotePC) {
413 uint32_t lr;
414 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr);
415 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr);
416 }
417 return _URC_CONTINUE_UNWIND;
418}
419
420extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
421__aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *ucbp,
422 _Unwind_Context *context) {
423 return unwindOneFrame(state, ucbp, context);
424}
425
426extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
427__aeabi_unwind_cpp_pr1(_Unwind_State state, _Unwind_Control_Block *ucbp,
428 _Unwind_Context *context) {
429 return unwindOneFrame(state, ucbp, context);
430}
431
432extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
433__aeabi_unwind_cpp_pr2(_Unwind_State state, _Unwind_Control_Block *ucbp,
434 _Unwind_Context *context) {
435 return unwindOneFrame(state, ucbp, context);
436}
437
438static _Unwind_Reason_Code
439unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
440 // EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during
441 // phase 1 and then restoring it to the "primary VRS" for phase 2. The
442 // effect is phase 2 doesn't see any of the VRS manipulations from phase 1.
443 // In this implementation, the phases don't share the VRS backing store.
444 // Instead, they are passed the original |uc| and they create a new VRS
445 // from scratch thus achieving the same effect.
446 unw_init_local(cursor, uc);
447
448 // Walk each frame looking for a place to stop.
449 for (bool handlerNotFound = true; handlerNotFound;) {
450
451 // See if frame has code to run (has personality routine).
452 unw_proc_info_t frameInfo;
453 if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
454 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
455 "failed => _URC_FATAL_PHASE1_ERROR",
456 static_cast<void *>(exception_object));
457 return _URC_FATAL_PHASE1_ERROR;
458 }
459
460 // When tracing, print state information.
461 if (_LIBUNWIND_TRACING_UNWINDING) {
462 char functionBuf[512];
463 const char *functionName = functionBuf;
464 unw_word_t offset;
465 if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
466 &offset) != UNW_ESUCCESS) ||
467 (frameInfo.start_ip + offset > frameInfo.end_ip))
468 functionName = ".anonymous.";
469 unw_word_t pc;
470 unw_get_reg(cursor, UNW_REG_IP, &pc);
471 _LIBUNWIND_TRACE_UNWINDING(
472 "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR ", func=%s, "
473 "lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
474 static_cast<void *>(exception_object), pc,
475 frameInfo.start_ip, functionName,
476 frameInfo.lsda, frameInfo.handler);
477 }
478
479 // If there is a personality routine, ask it if it will want to stop at
480 // this frame.
481 if (frameInfo.handler != 0) {
482 __personality_routine p =
483 (__personality_routine)(long)(frameInfo.handler);
484 _LIBUNWIND_TRACE_UNWINDING(
485 "unwind_phase1(ex_ojb=%p): calling personality function %p",
486 static_cast<void *>(exception_object),
487 reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p)));
488 struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
489 exception_object->pr_cache.fnstart = frameInfo.start_ip;
490 exception_object->pr_cache.ehtp =
491 (_Unwind_EHT_Header *)frameInfo.unwind_info;
492 exception_object->pr_cache.additional = frameInfo.flags;
493 _Unwind_Reason_Code personalityResult =
494 (*p)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context);
495 _LIBUNWIND_TRACE_UNWINDING(
496 "unwind_phase1(ex_ojb=%p): personality result %d start_ip %x ehtp %p "
497 "additional %x",
498 static_cast<void *>(exception_object), personalityResult,
499 exception_object->pr_cache.fnstart,
500 static_cast<void *>(exception_object->pr_cache.ehtp),
501 exception_object->pr_cache.additional);
502 switch (personalityResult) {
503 case _URC_HANDLER_FOUND:
504 // found a catch clause or locals that need destructing in this frame
505 // stop search and remember stack pointer at the frame
506 handlerNotFound = false;
507 // p should have initialized barrier_cache. EHABI #7.3.5
508 _LIBUNWIND_TRACE_UNWINDING(
509 "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND",
510 static_cast<void *>(exception_object));
511 return _URC_NO_REASON;
512
513 case _URC_CONTINUE_UNWIND:
514 _LIBUNWIND_TRACE_UNWINDING(
515 "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND",
516 static_cast<void *>(exception_object));
517 // continue unwinding
518 break;
519
520 // EHABI #7.3.3
521 case _URC_FAILURE:
522 return _URC_FAILURE;
523
524 default:
525 // something went wrong
526 _LIBUNWIND_TRACE_UNWINDING(
527 "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
528 static_cast<void *>(exception_object));
529 return _URC_FATAL_PHASE1_ERROR;
530 }
531 }
532 }
533 return _URC_NO_REASON;
534}
535
536static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
537 _Unwind_Exception *exception_object,
538 bool resume) {
539 // See comment at the start of unwind_phase1 regarding VRS integrity.
540 unw_init_local(cursor, uc);
541
542 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
543 static_cast<void *>(exception_object));
544 int frame_count = 0;
545
546 // Walk each frame until we reach where search phase said to stop.
547 while (true) {
548 // Ask libunwind to get next frame (skip over first which is
549 // _Unwind_RaiseException or _Unwind_Resume).
550 //
551 // Resume only ever makes sense for 1 frame.
552 _Unwind_State state =
553 resume ? _US_UNWIND_FRAME_RESUME : _US_UNWIND_FRAME_STARTING;
554 if (resume && frame_count == 1) {
555 // On a resume, first unwind the _Unwind_Resume() frame. The next frame
556 // is now the landing pad for the cleanup from a previous execution of
557 // phase2. To continue unwindingly correctly, replace VRS[15] with the
558 // IP of the frame that the previous run of phase2 installed the context
559 // for. After this, continue unwinding as if normal.
560 //
561 // See #7.4.6 for details.
562 unw_set_reg(cursor, UNW_REG_IP,
563 exception_object->unwinder_cache.reserved2);
564 resume = false;
565 }
566
567 // Get info about this frame.
568 unw_word_t sp;
569 unw_proc_info_t frameInfo;
570 unw_get_reg(cursor, UNW_REG_SP, &sp);
571 if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
572 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
573 "failed => _URC_FATAL_PHASE2_ERROR",
574 static_cast<void *>(exception_object));
575 return _URC_FATAL_PHASE2_ERROR;
576 }
577
578 // When tracing, print state information.
579 if (_LIBUNWIND_TRACING_UNWINDING) {
580 char functionBuf[512];
581 const char *functionName = functionBuf;
582 unw_word_t offset;
583 if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
584 &offset) != UNW_ESUCCESS) ||
585 (frameInfo.start_ip + offset > frameInfo.end_ip))
586 functionName = ".anonymous.";
587 _LIBUNWIND_TRACE_UNWINDING(
588 "unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR ", func=%s, sp=0x%" PRIxPTR ", "
589 "lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",
590 static_cast<void *>(exception_object), frameInfo.start_ip,
591 functionName, sp, frameInfo.lsda,
592 frameInfo.handler);
593 }
594
595 // If there is a personality routine, tell it we are unwinding.
596 if (frameInfo.handler != 0) {
597 __personality_routine p =
598 (__personality_routine)(long)(frameInfo.handler);
599 struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
600 // EHABI #7.2
601 exception_object->pr_cache.fnstart = frameInfo.start_ip;
602 exception_object->pr_cache.ehtp =
603 (_Unwind_EHT_Header *)frameInfo.unwind_info;
604 exception_object->pr_cache.additional = frameInfo.flags;
605 _Unwind_Reason_Code personalityResult =
606 (*p)(state, exception_object, context);
607 switch (personalityResult) {
608 case _URC_CONTINUE_UNWIND:
609 // Continue unwinding
610 _LIBUNWIND_TRACE_UNWINDING(
611 "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
612 static_cast<void *>(exception_object));
613 // EHABI #7.2
614 if (sp == exception_object->barrier_cache.sp) {
615 // Phase 1 said we would stop at this frame, but we did not...
616 _LIBUNWIND_ABORT("during phase1 personality function said it would "
617 "stop here, but now in phase2 it did not stop here");
618 }
619 break;
620 case _URC_INSTALL_CONTEXT:
621 _LIBUNWIND_TRACE_UNWINDING(
622 "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT",
623 static_cast<void *>(exception_object));
624 // Personality routine says to transfer control to landing pad.
625 // We may get control back if landing pad calls _Unwind_Resume().
626 if (_LIBUNWIND_TRACING_UNWINDING) {
627 unw_word_t pc;
628 unw_get_reg(cursor, UNW_REG_IP, &pc);
629 unw_get_reg(cursor, UNW_REG_SP, &sp);
630 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
631 "user code with ip=0x%" PRIxPTR ", sp=0x%" PRIxPTR,
632 static_cast<void *>(exception_object),
633 pc, sp);
634 }
635
636 {
637 // EHABI #7.4.1 says we need to preserve pc for when _Unwind_Resume
638 // is called back, to find this same frame.
639 unw_word_t pc;
640 unw_get_reg(cursor, UNW_REG_IP, &pc);
641 exception_object->unwinder_cache.reserved2 = (uint32_t)pc;
642 }
643 unw_resume(cursor);
644 // unw_resume() only returns if there was an error.
645 return _URC_FATAL_PHASE2_ERROR;
646
647 // # EHABI #7.4.3
648 case _URC_FAILURE:
649 abort();
650
651 default:
652 // Personality routine returned an unknown result code.
653 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
654 personalityResult);
655 return _URC_FATAL_PHASE2_ERROR;
656 }
657 }
658 frame_count++;
659 }
660
661 // Clean up phase did not resume at the frame that the search phase
662 // said it would...
663 return _URC_FATAL_PHASE2_ERROR;
664}
665
666/// Called by __cxa_throw. Only returns if there is a fatal error.
667_LIBUNWIND_EXPORT _Unwind_Reason_Code
668_Unwind_RaiseException(_Unwind_Exception *exception_object) {
669 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
670 static_cast<void *>(exception_object));
671 unw_context_t uc;
672 unw_cursor_t cursor;
673 unw_getcontext(&uc);
674
675 // This field for is for compatibility with GCC to say this isn't a forced
676 // unwind. EHABI #7.2
677 exception_object->unwinder_cache.reserved1 = 0;
678
679 // phase 1: the search phase
680 _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
681 if (phase1 != _URC_NO_REASON)
682 return phase1;
683
684 // phase 2: the clean up phase
685 return unwind_phase2(&uc, &cursor, exception_object, false);
686}
687
688_LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) {
689 // This is to be called when exception handling completes to give us a chance
690 // to perform any housekeeping. EHABI #7.2. But we have nothing to do here.
691 (void)exception_object;
692}
693
694/// When _Unwind_RaiseException() is in phase2, it hands control
695/// to the personality function at each frame. The personality
696/// may force a jump to a landing pad in that function, the landing
697/// pad code may then call _Unwind_Resume() to continue with the
698/// unwinding. Note: the call to _Unwind_Resume() is from compiler
699/// geneated user code. All other _Unwind_* routines are called
700/// by the C++ runtime __cxa_* routines.
701///
702/// Note: re-throwing an exception (as opposed to continuing the unwind)
703/// is implemented by having the code call __cxa_rethrow() which
704/// in turn calls _Unwind_Resume_or_Rethrow().
705_LIBUNWIND_EXPORT void
706_Unwind_Resume(_Unwind_Exception *exception_object) {
707 _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)",
708 static_cast<void *>(exception_object));
709 unw_context_t uc;
710 unw_cursor_t cursor;
711 unw_getcontext(&uc);
712
713 // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
714 // which is in the same position as private_1 below.
715 // TODO(ajwong): Who wronte the above? Why is it true?
716 unwind_phase2(&uc, &cursor, exception_object, true);
717
718 // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
719 _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
720}
721
722/// Called by personality handler during phase 2 to get LSDA for current frame.
723_LIBUNWIND_EXPORT uintptr_t
724_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
725 unw_cursor_t *cursor = (unw_cursor_t *)context;
726 unw_proc_info_t frameInfo;
727 uintptr_t result = 0;
728 if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
729 result = (uintptr_t)frameInfo.lsda;
730 _LIBUNWIND_TRACE_API(
731 "_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx",
732 static_cast<void *>(context), (long long)result);
733 return result;
734}
735
736static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
737 void* valuep) {
738 uint64_t value = 0;
739 switch (representation) {
740 case _UVRSD_UINT32:
741 case _UVRSD_FLOAT:
742 memcpy(&value, valuep, sizeof(uint32_t));
743 break;
744
745 case _UVRSD_VFPX:
746 case _UVRSD_UINT64:
747 case _UVRSD_DOUBLE:
748 memcpy(&value, valuep, sizeof(uint64_t));
749 break;
750 }
751 return value;
752}
753
754_LIBUNWIND_EXPORT _Unwind_VRS_Result
755_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
756 uint32_t regno, _Unwind_VRS_DataRepresentation representation,
757 void *valuep) {
758 _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, "
759 "rep=%d, value=0x%llX)",
760 static_cast<void *>(context), regclass, regno,
761 representation,
762 ValueAsBitPattern(representation, valuep));
763 unw_cursor_t *cursor = (unw_cursor_t *)context;
764 switch (regclass) {
765 case _UVRSC_CORE:
766 if (representation != _UVRSD_UINT32 || regno > 15)
767 return _UVRSR_FAILED;
768 return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno),
769 *(unw_word_t *)valuep) == UNW_ESUCCESS
770 ? _UVRSR_OK
771 : _UVRSR_FAILED;
772 case _UVRSC_VFP:
773 if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
774 return _UVRSR_FAILED;
775 if (representation == _UVRSD_VFPX) {
776 // Can only touch d0-15 with FSTMFDX.
777 if (regno > 15)
778 return _UVRSR_FAILED;
779 unw_save_vfp_as_X(cursor);
780 } else {
781 if (regno > 31)
782 return _UVRSR_FAILED;
783 }
784 return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno),
785 *(unw_fpreg_t *)valuep) == UNW_ESUCCESS
786 ? _UVRSR_OK
787 : _UVRSR_FAILED;
788#if defined(__ARM_WMMX)
789 case _UVRSC_WMMXC:
790 if (representation != _UVRSD_UINT32 || regno > 3)
791 return _UVRSR_FAILED;
792 return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
793 *(unw_word_t *)valuep) == UNW_ESUCCESS
794 ? _UVRSR_OK
795 : _UVRSR_FAILED;
796 case _UVRSC_WMMXD:
797 if (representation != _UVRSD_DOUBLE || regno > 31)
798 return _UVRSR_FAILED;
799 return unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),
800 *(unw_fpreg_t *)valuep) == UNW_ESUCCESS
801 ? _UVRSR_OK
802 : _UVRSR_FAILED;
803#else
804 case _UVRSC_WMMXC:
805 case _UVRSC_WMMXD:
806 break;
807#endif
808 }
809 _LIBUNWIND_ABORT("unsupported register class");
810}
811
812static _Unwind_VRS_Result
813_Unwind_VRS_Get_Internal(_Unwind_Context *context,
814 _Unwind_VRS_RegClass regclass, uint32_t regno,
815 _Unwind_VRS_DataRepresentation representation,
816 void *valuep) {
817 unw_cursor_t *cursor = (unw_cursor_t *)context;
818 switch (regclass) {
819 case _UVRSC_CORE:
820 if (representation != _UVRSD_UINT32 || regno > 15)
821 return _UVRSR_FAILED;
822 return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno),
823 (unw_word_t *)valuep) == UNW_ESUCCESS
824 ? _UVRSR_OK
825 : _UVRSR_FAILED;
826 case _UVRSC_VFP:
827 if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
828 return _UVRSR_FAILED;
829 if (representation == _UVRSD_VFPX) {
830 // Can only touch d0-15 with FSTMFDX.
831 if (regno > 15)
832 return _UVRSR_FAILED;
833 unw_save_vfp_as_X(cursor);
834 } else {
835 if (regno > 31)
836 return _UVRSR_FAILED;
837 }
838 return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno),
839 (unw_fpreg_t *)valuep) == UNW_ESUCCESS
840 ? _UVRSR_OK
841 : _UVRSR_FAILED;
842#if defined(__ARM_WMMX)
843 case _UVRSC_WMMXC:
844 if (representation != _UVRSD_UINT32 || regno > 3)
845 return _UVRSR_FAILED;
846 return unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
847 (unw_word_t *)valuep) == UNW_ESUCCESS
848 ? _UVRSR_OK
849 : _UVRSR_FAILED;
850 case _UVRSC_WMMXD:
851 if (representation != _UVRSD_DOUBLE || regno > 31)
852 return _UVRSR_FAILED;
853 return unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),
854 (unw_fpreg_t *)valuep) == UNW_ESUCCESS
855 ? _UVRSR_OK
856 : _UVRSR_FAILED;
857#else
858 case _UVRSC_WMMXC:
859 case _UVRSC_WMMXD:
860 break;
861#endif
862 }
863 _LIBUNWIND_ABORT("unsupported register class");
864}
865
866_LIBUNWIND_EXPORT _Unwind_VRS_Result
867_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
868 uint32_t regno, _Unwind_VRS_DataRepresentation representation,
869 void *valuep) {
870 _Unwind_VRS_Result result =
871 _Unwind_VRS_Get_Internal(context, regclass, regno, representation,
872 valuep);
873 _LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, "
874 "rep=%d, value=0x%llX, result = %d)",
875 static_cast<void *>(context), regclass, regno,
876 representation,
877 ValueAsBitPattern(representation, valuep), result);
878 return result;
879}
880
881_Unwind_VRS_Result
882_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
883 uint32_t discriminator,
884 _Unwind_VRS_DataRepresentation representation) {
885 _LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, "
886 "discriminator=%d, representation=%d)",
887 static_cast<void *>(context), regclass, discriminator,
888 representation);
889 switch (regclass) {
890 case _UVRSC_WMMXC:
891#if !defined(__ARM_WMMX)
892 break;
893#endif
894 case _UVRSC_CORE: {
895 if (representation != _UVRSD_UINT32)
896 return _UVRSR_FAILED;
897 // When popping SP from the stack, we don't want to override it from the
898 // computed new stack location. See EHABI #7.5.4 table 3.
899 bool poppedSP = false;
900 uint32_t* sp;
901 if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,
902 _UVRSD_UINT32, &sp) != _UVRSR_OK) {
903 return _UVRSR_FAILED;
904 }
905 for (uint32_t i = 0; i < 16; ++i) {
906 if (!(discriminator & static_cast<uint32_t>(1 << i)))
907 continue;
908 uint32_t value = *sp++;
909 if (regclass == _UVRSC_CORE && i == 13)
910 poppedSP = true;
911 if (_Unwind_VRS_Set(context, regclass, i,
912 _UVRSD_UINT32, &value) != _UVRSR_OK) {
913 return _UVRSR_FAILED;
914 }
915 }
916 if (!poppedSP) {
917 return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP,
918 _UVRSD_UINT32, &sp);
919 }
920 return _UVRSR_OK;
921 }
922 case _UVRSC_WMMXD:
923#if !defined(__ARM_WMMX)
924 break;
925#endif
926 case _UVRSC_VFP: {
927 if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
928 return _UVRSR_FAILED;
929 uint32_t first = discriminator >> 16;
930 uint32_t count = discriminator & 0xffff;
931 uint32_t end = first+count;
932 uint32_t* sp;
933 if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,
934 _UVRSD_UINT32, &sp) != _UVRSR_OK) {
935 return _UVRSR_FAILED;
936 }
937 // For _UVRSD_VFPX, we're assuming the data is stored in FSTMX "standard
938 // format 1", which is equivalent to FSTMD + a padding word.
939 for (uint32_t i = first; i < end; ++i) {
940 // SP is only 32-bit aligned so don't copy 64-bit at a time.
941 uint64_t value = *sp++;
942 value |= ((uint64_t)(*sp++)) << 32;
943 if (_Unwind_VRS_Set(context, regclass, i, representation, &value) !=
944 _UVRSR_OK)
945 return _UVRSR_FAILED;
946 }
947 if (representation == _UVRSD_VFPX)
948 ++sp;
949 return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
950 &sp);
951 }
952 }
953 _LIBUNWIND_ABORT("unsupported register class");
954}
955
956/// Called by personality handler during phase 2 to find the start of the
957/// function.
958_LIBUNWIND_EXPORT uintptr_t
959_Unwind_GetRegionStart(struct _Unwind_Context *context) {
960 unw_cursor_t *cursor = (unw_cursor_t *)context;
961 unw_proc_info_t frameInfo;
962 uintptr_t result = 0;
963 if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
964 result = (uintptr_t)frameInfo.start_ip;
965 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX",
966 static_cast<void *>(context), (long long)result);
967 return result;
968}
969
970
971/// Called by personality handler during phase 2 if a foreign exception
972// is caught.
973_LIBUNWIND_EXPORT void
974_Unwind_DeleteException(_Unwind_Exception *exception_object) {
975 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
976 static_cast<void *>(exception_object));
977 if (exception_object->exception_cleanup != NULL)
978 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
979 exception_object);
980}
981
982extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
983__gnu_unwind_frame(_Unwind_Exception *exception_object,
984 struct _Unwind_Context *context) {
985 unw_cursor_t *cursor = (unw_cursor_t *)context;
986 if (unw_step(cursor) != UNW_STEP_SUCCESS)
987 return _URC_FAILURE;
988 return _URC_OK;
989}
990
991#endif // defined(_LIBUNWIND_ARM_EHABI)
libunwind/src/Unwind-EHABI.h created+51
...@@ -0,0 +1,51 @@
1//===------------------------- Unwind-EHABI.hpp ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef __UNWIND_EHABI_H__
12#define __UNWIND_EHABI_H__
13
14#include <__libunwind_config.h>
15
16#if defined(_LIBUNWIND_ARM_EHABI)
17
18#include <stdint.h>
19#include <unwind.h>
20
21// Unable to unwind in the ARM index table (section 5 EHABI).
22#define UNW_EXIDX_CANTUNWIND 0x1
23
24static inline uint32_t signExtendPrel31(uint32_t data) {
25 return data | ((data & 0x40000000u) << 1);
26}
27
28static inline uint32_t readPrel31(const uint32_t *data) {
29 return (((uint32_t)(uintptr_t)data) + signExtendPrel31(*data));
30}
31
32#if defined(__cplusplus)
33extern "C" {
34#endif
35
36extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0(
37 _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
38
39extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1(
40 _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
41
42extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(
43 _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
44
45#if defined(__cplusplus)
46} // extern "C"
47#endif
48
49#endif // defined(_LIBUNWIND_ARM_EHABI)
50
51#endif // __UNWIND_EHABI_H__
libunwind/src/Unwind-seh.cpp created+491
...@@ -0,0 +1,491 @@
1//===--------------------------- Unwind-seh.cpp ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Implements SEH-based Itanium C++ exceptions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "config.h"
15
16#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
17
18#include <unwind.h>
19
20#include <stdint.h>
21#include <stdbool.h>
22#include <stdlib.h>
23
24#include <windef.h>
25#include <excpt.h>
26#include <winnt.h>
27#include <ntstatus.h>
28
29#include "libunwind_ext.h"
30#include "UnwindCursor.hpp"
31
32using namespace libunwind;
33
34#define STATUS_USER_DEFINED (1u << 29)
35
36#define STATUS_GCC_MAGIC (('G' << 16) | ('C' << 8) | 'C')
37
38#define MAKE_CUSTOM_STATUS(s, c) \
39 ((NTSTATUS)(((s) << 30) | STATUS_USER_DEFINED | (c)))
40#define MAKE_GCC_EXCEPTION(c) \
41 MAKE_CUSTOM_STATUS(STATUS_SEVERITY_SUCCESS, STATUS_GCC_MAGIC | ((c) << 24))
42
43/// SEH exception raised by libunwind when the program calls
44/// \c _Unwind_RaiseException.
45#define STATUS_GCC_THROW MAKE_GCC_EXCEPTION(0) // 0x20474343
46/// SEH exception raised by libunwind to initiate phase 2 of exception
47/// handling.
48#define STATUS_GCC_UNWIND MAKE_GCC_EXCEPTION(1) // 0x21474343
49
50/// Class of foreign exceptions based on unrecognized SEH exceptions.
51static const uint64_t kSEHExceptionClass = 0x434C4E4753454800; // CLNGSEH\0
52
53/// Exception cleanup routine used by \c _GCC_specific_handler to
54/// free foreign exceptions.
55static void seh_exc_cleanup(_Unwind_Reason_Code urc, _Unwind_Exception *exc) {
56 if (exc->exception_class != kSEHExceptionClass)
57 _LIBUNWIND_ABORT("SEH cleanup called on non-SEH exception");
58 free(exc);
59}
60
61static int _unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx);
62static DISPATCHER_CONTEXT *_unw_seh_get_disp_ctx(unw_cursor_t *cursor);
63static void _unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp);
64
65/// Common implementation of SEH-style handler functions used by Itanium-
66/// style frames. Depending on how and why it was called, it may do one of:
67/// a) Delegate to the given Itanium-style personality function; or
68/// b) Initiate a collided unwind to halt unwinding.
69_LIBUNWIND_EXPORT EXCEPTION_DISPOSITION
70_GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
71 DISPATCHER_CONTEXT *disp, __personality_routine pers) {
72 unw_context_t uc;
73 unw_cursor_t cursor;
74 _Unwind_Exception *exc;
75 _Unwind_Action action;
76 struct _Unwind_Context *ctx = nullptr;
77 _Unwind_Reason_Code urc;
78 uintptr_t retval, target;
79 bool ours = false;
80
81 _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler(%#010x(%x), %p)", ms_exc->ExceptionCode, ms_exc->ExceptionFlags, frame);
82 if (ms_exc->ExceptionCode == STATUS_GCC_UNWIND) {
83 if (IS_TARGET_UNWIND(ms_exc->ExceptionFlags)) {
84 // Set up the upper return value (the lower one and the target PC
85 // were set in the call to RtlUnwindEx()) for the landing pad.
86#ifdef __x86_64__
87 disp->ContextRecord->Rdx = ms_exc->ExceptionInformation[3];
88#elif defined(__arm__)
89 disp->ContextRecord->R1 = ms_exc->ExceptionInformation[3];
90#elif defined(__aarch64__)
91 disp->ContextRecord->X1 = ms_exc->ExceptionInformation[3];
92#endif
93 }
94 // This is the collided unwind to the landing pad. Nothing to do.
95 return ExceptionContinueSearch;
96 }
97
98 if (ms_exc->ExceptionCode == STATUS_GCC_THROW) {
99 // This is (probably) a libunwind-controlled exception/unwind. Recover the
100 // parameters which we set below, and pass them to the personality function.
101 ours = true;
102 exc = (_Unwind_Exception *)ms_exc->ExceptionInformation[0];
103 if (!IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) {
104 ctx = (struct _Unwind_Context *)ms_exc->ExceptionInformation[1];
105 action = (_Unwind_Action)ms_exc->ExceptionInformation[2];
106 }
107 } else {
108 // Foreign exception.
109 exc = (_Unwind_Exception *)malloc(sizeof(_Unwind_Exception));
110 exc->exception_class = kSEHExceptionClass;
111 exc->exception_cleanup = seh_exc_cleanup;
112 memset(exc->private_, 0, sizeof(exc->private_));
113 }
114 if (!ctx) {
115 _unw_init_seh(&cursor, disp->ContextRecord);
116 _unw_seh_set_disp_ctx(&cursor, disp);
117 unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc-1);
118 ctx = (struct _Unwind_Context *)&cursor;
119
120 if (!IS_UNWINDING(ms_exc->ExceptionFlags)) {
121 if (ours && ms_exc->NumberParameters > 1)
122 action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_FORCE_UNWIND);
123 else
124 action = _UA_SEARCH_PHASE;
125 } else {
126 if (ours && ms_exc->ExceptionInformation[1] == (ULONG_PTR)frame)
127 action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
128 else
129 action = _UA_CLEANUP_PHASE;
130 }
131 }
132
133 _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() calling personality function %p(1, %d, %llx, %p, %p)", pers, action, exc->exception_class, exc, ctx);
134 urc = pers(1, action, exc->exception_class, exc, ctx);
135 _LIBUNWIND_TRACE_UNWINDING("_GCC_specific_handler() personality returned %d", urc);
136 switch (urc) {
137 case _URC_CONTINUE_UNWIND:
138 // If we're in phase 2, and the personality routine said to continue
139 // at the target frame, we're in real trouble.
140 if (action & _UA_HANDLER_FRAME)
141 _LIBUNWIND_ABORT("Personality continued unwind at the target frame!");
142 return ExceptionContinueSearch;
143 case _URC_HANDLER_FOUND:
144 // If we were called by __libunwind_seh_personality(), indicate that
145 // a handler was found; otherwise, initiate phase 2 by unwinding.
146 if (ours && ms_exc->NumberParameters > 1)
147 return 4 /* ExecptionExecuteHandler in mingw */;
148 // This should never happen in phase 2.
149 if (IS_UNWINDING(ms_exc->ExceptionFlags))
150 _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!");
151 exc->private_[1] = (ULONG_PTR)frame;
152 if (ours) {
153 ms_exc->NumberParameters = 4;
154 ms_exc->ExceptionInformation[1] = (ULONG_PTR)frame;
155 }
156 // FIXME: Indicate target frame in foreign case!
157 // phase 2: the clean up phase
158 RtlUnwindEx(frame, (PVOID)disp->ControlPc, ms_exc, exc, ms_ctx, disp->HistoryTable);
159 _LIBUNWIND_ABORT("RtlUnwindEx() failed");
160 case _URC_INSTALL_CONTEXT: {
161 // If we were called by __libunwind_seh_personality(), indicate that
162 // a handler was found; otherwise, it's time to initiate a collided
163 // unwind to the target.
164 if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1)
165 return 4 /* ExecptionExecuteHandler in mingw */;
166 // This should never happen in phase 1.
167 if (!IS_UNWINDING(ms_exc->ExceptionFlags))
168 _LIBUNWIND_ABORT("Personality installed context during phase 1!");
169#ifdef __x86_64__
170 exc->private_[2] = disp->TargetIp;
171 unw_get_reg(&cursor, UNW_X86_64_RAX, &retval);
172 unw_get_reg(&cursor, UNW_X86_64_RDX, &exc->private_[3]);
173#elif defined(__arm__)
174 exc->private_[2] = disp->TargetPc;
175 unw_get_reg(&cursor, UNW_ARM_R0, &retval);
176 unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]);
177#elif defined(__aarch64__)
178 exc->private_[2] = disp->TargetPc;
179 unw_get_reg(&cursor, UNW_ARM64_X0, &retval);
180 unw_get_reg(&cursor, UNW_ARM64_X1, &exc->private_[3]);
181#endif
182 unw_get_reg(&cursor, UNW_REG_IP, &target);
183 ms_exc->ExceptionCode = STATUS_GCC_UNWIND;
184#ifdef __x86_64__
185 ms_exc->ExceptionInformation[2] = disp->TargetIp;
186#elif defined(__arm__) || defined(__aarch64__)
187 ms_exc->ExceptionInformation[2] = disp->TargetPc;
188#endif
189 ms_exc->ExceptionInformation[3] = exc->private_[3];
190 // Give NTRTL some scratch space to keep track of the collided unwind.
191 // Don't use the one that was passed in; we don't want to overwrite the
192 // context in the DISPATCHER_CONTEXT.
193 CONTEXT new_ctx;
194 RtlUnwindEx(frame, (PVOID)target, ms_exc, (PVOID)retval, &new_ctx, disp->HistoryTable);
195 _LIBUNWIND_ABORT("RtlUnwindEx() failed");
196 }
197 // Anything else indicates a serious problem.
198 default: return ExceptionContinueExecution;
199 }
200}
201
202/// Personality function returned by \c unw_get_proc_info() in SEH contexts.
203/// This is a wrapper that calls the real SEH handler function, which in
204/// turn (at least, for Itanium-style frames) calls the real Itanium
205/// personality function (see \c _GCC_specific_handler()).
206extern "C" _Unwind_Reason_Code
207__libunwind_seh_personality(int version, _Unwind_Action state,
208 uint64_t klass, _Unwind_Exception *exc,
209 struct _Unwind_Context *context) {
210 EXCEPTION_RECORD ms_exc;
211 bool phase2 = (state & (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE)) == _UA_CLEANUP_PHASE;
212 ms_exc.ExceptionCode = STATUS_GCC_THROW;
213 ms_exc.ExceptionFlags = 0;
214 ms_exc.NumberParameters = 3;
215 ms_exc.ExceptionInformation[0] = (ULONG_PTR)exc;
216 ms_exc.ExceptionInformation[1] = (ULONG_PTR)context;
217 ms_exc.ExceptionInformation[2] = state;
218 DISPATCHER_CONTEXT *disp_ctx = _unw_seh_get_disp_ctx((unw_cursor_t *)context);
219 EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,
220 (PVOID)disp_ctx->EstablisherFrame,
221 disp_ctx->ContextRecord,
222 disp_ctx);
223 switch (ms_act) {
224 case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;
225 case 4 /*ExceptionExecuteHandler*/:
226 return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND;
227 default:
228 return phase2 ? _URC_FATAL_PHASE2_ERROR : _URC_FATAL_PHASE1_ERROR;
229 }
230}
231
232static _Unwind_Reason_Code
233unwind_phase2_forced(unw_context_t *uc,
234 _Unwind_Exception *exception_object,
235 _Unwind_Stop_Fn stop, void *stop_parameter) {
236 unw_cursor_t cursor2;
237 unw_init_local(&cursor2, uc);
238
239 // Walk each frame until we reach where search phase said to stop
240 while (unw_step(&cursor2) > 0) {
241
242 // Update info about this frame.
243 unw_proc_info_t frameInfo;
244 if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
245 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
246 "failed => _URC_END_OF_STACK",
247 (void *)exception_object);
248 return _URC_FATAL_PHASE2_ERROR;
249 }
250
251 // When tracing, print state information.
252 if (_LIBUNWIND_TRACING_UNWINDING) {
253 char functionBuf[512];
254 const char *functionName = functionBuf;
255 unw_word_t offset;
256 if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
257 &offset) != UNW_ESUCCESS) ||
258 (frameInfo.start_ip + offset > frameInfo.end_ip))
259 functionName = ".anonymous.";
260 _LIBUNWIND_TRACE_UNWINDING(
261 "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64
262 ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64,
263 (void *)exception_object, frameInfo.start_ip, functionName,
264 frameInfo.lsda, frameInfo.handler);
265 }
266
267 // Call stop function at each frame.
268 _Unwind_Action action =
269 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
270 _Unwind_Reason_Code stopResult =
271 (*stop)(1, action, exception_object->exception_class, exception_object,
272 (struct _Unwind_Context *)(&cursor2), stop_parameter);
273 _LIBUNWIND_TRACE_UNWINDING(
274 "unwind_phase2_forced(ex_ojb=%p): stop function returned %d",
275 (void *)exception_object, stopResult);
276 if (stopResult != _URC_NO_REASON) {
277 _LIBUNWIND_TRACE_UNWINDING(
278 "unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
279 (void *)exception_object);
280 return _URC_FATAL_PHASE2_ERROR;
281 }
282
283 // If there is a personality routine, tell it we are unwinding.
284 if (frameInfo.handler != 0) {
285 __personality_routine p =
286 (__personality_routine)(intptr_t)(frameInfo.handler);
287 _LIBUNWIND_TRACE_UNWINDING(
288 "unwind_phase2_forced(ex_ojb=%p): calling personality function %p",
289 (void *)exception_object, (void *)(uintptr_t)p);
290 _Unwind_Reason_Code personalityResult =
291 (*p)(1, action, exception_object->exception_class, exception_object,
292 (struct _Unwind_Context *)(&cursor2));
293 switch (personalityResult) {
294 case _URC_CONTINUE_UNWIND:
295 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
296 "personality returned "
297 "_URC_CONTINUE_UNWIND",
298 (void *)exception_object);
299 // Destructors called, continue unwinding
300 break;
301 case _URC_INSTALL_CONTEXT:
302 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
303 "personality returned "
304 "_URC_INSTALL_CONTEXT",
305 (void *)exception_object);
306 // We may get control back if landing pad calls _Unwind_Resume().
307 unw_resume(&cursor2);
308 break;
309 default:
310 // Personality routine returned an unknown result code.
311 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
312 "personality returned %d, "
313 "_URC_FATAL_PHASE2_ERROR",
314 (void *)exception_object, personalityResult);
315 return _URC_FATAL_PHASE2_ERROR;
316 }
317 }
318 }
319
320 // Call stop function one last time and tell it we've reached the end
321 // of the stack.
322 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
323 "function with _UA_END_OF_STACK",
324 (void *)exception_object);
325 _Unwind_Action lastAction =
326 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
327 (*stop)(1, lastAction, exception_object->exception_class, exception_object,
328 (struct _Unwind_Context *)(&cursor2), stop_parameter);
329
330 // Clean up phase did not resume at the frame that the search phase said it
331 // would.
332 return _URC_FATAL_PHASE2_ERROR;
333}
334
335/// Called by \c __cxa_throw(). Only returns if there is a fatal error.
336_LIBUNWIND_EXPORT _Unwind_Reason_Code
337_Unwind_RaiseException(_Unwind_Exception *exception_object) {
338 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
339 (void *)exception_object);
340
341 // Mark that this is a non-forced unwind, so _Unwind_Resume()
342 // can do the right thing.
343 memset(exception_object->private_, 0, sizeof(exception_object->private_));
344
345 // phase 1: the search phase
346 // We'll let the system do that for us.
347 RaiseException(STATUS_GCC_THROW, 0, 1, (ULONG_PTR *)&exception_object);
348
349 // If we get here, either something went horribly wrong or we reached the
350 // top of the stack. Either way, let libc++abi call std::terminate().
351 return _URC_END_OF_STACK;
352}
353
354/// When \c _Unwind_RaiseException() is in phase2, it hands control
355/// to the personality function at each frame. The personality
356/// may force a jump to a landing pad in that function; the landing
357/// pad code may then call \c _Unwind_Resume() to continue with the
358/// unwinding. Note: the call to \c _Unwind_Resume() is from compiler
359/// geneated user code. All other \c _Unwind_* routines are called
360/// by the C++ runtime \c __cxa_* routines.
361///
362/// Note: re-throwing an exception (as opposed to continuing the unwind)
363/// is implemented by having the code call \c __cxa_rethrow() which
364/// in turn calls \c _Unwind_Resume_or_Rethrow().
365_LIBUNWIND_EXPORT void
366_Unwind_Resume(_Unwind_Exception *exception_object) {
367 _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);
368
369 if (exception_object->private_[0] != 0) {
370 unw_context_t uc;
371
372 unw_getcontext(&uc);
373 unwind_phase2_forced(&uc, exception_object,
374 (_Unwind_Stop_Fn) exception_object->private_[0],
375 (void *)exception_object->private_[4]);
376 } else {
377 // Recover the parameters for the unwind from the exception object
378 // so we can start unwinding again.
379 EXCEPTION_RECORD ms_exc;
380 CONTEXT ms_ctx;
381 UNWIND_HISTORY_TABLE hist;
382
383 memset(&ms_exc, 0, sizeof(ms_exc));
384 memset(&hist, 0, sizeof(hist));
385 ms_exc.ExceptionCode = STATUS_GCC_THROW;
386 ms_exc.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
387 ms_exc.NumberParameters = 4;
388 ms_exc.ExceptionInformation[0] = (ULONG_PTR)exception_object;
389 ms_exc.ExceptionInformation[1] = exception_object->private_[1];
390 ms_exc.ExceptionInformation[2] = exception_object->private_[2];
391 ms_exc.ExceptionInformation[3] = exception_object->private_[3];
392 RtlUnwindEx((PVOID)exception_object->private_[1],
393 (PVOID)exception_object->private_[2], &ms_exc,
394 exception_object, &ms_ctx, &hist);
395 }
396
397 // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
398 _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
399}
400
401/// Not used by C++.
402/// Unwinds stack, calling "stop" function at each frame.
403/// Could be used to implement \c longjmp().
404_LIBUNWIND_EXPORT _Unwind_Reason_Code
405_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
406 _Unwind_Stop_Fn stop, void *stop_parameter) {
407 _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
408 (void *)exception_object, (void *)(uintptr_t)stop);
409 unw_context_t uc;
410 unw_getcontext(&uc);
411
412 // Mark that this is a forced unwind, so _Unwind_Resume() can do
413 // the right thing.
414 exception_object->private_[0] = (uintptr_t) stop;
415 exception_object->private_[4] = (uintptr_t) stop_parameter;
416
417 // do it
418 return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
419}
420
421/// Called by personality handler during phase 2 to get LSDA for current frame.
422_LIBUNWIND_EXPORT uintptr_t
423_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
424 uintptr_t result = (uintptr_t)_unw_seh_get_disp_ctx((unw_cursor_t *)context)->HandlerData;
425 _LIBUNWIND_TRACE_API(
426 "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
427 (void *)context, result);
428 return result;
429}
430
431/// Called by personality handler during phase 2 to find the start of the
432/// function.
433_LIBUNWIND_EXPORT uintptr_t
434_Unwind_GetRegionStart(struct _Unwind_Context *context) {
435 DISPATCHER_CONTEXT *disp = _unw_seh_get_disp_ctx((unw_cursor_t *)context);
436 uintptr_t result = (uintptr_t)disp->FunctionEntry->BeginAddress + disp->ImageBase;
437 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,
438 (void *)context, result);
439 return result;
440}
441
442static int
443_unw_init_seh(unw_cursor_t *cursor, CONTEXT *context) {
444#ifdef _LIBUNWIND_TARGET_X86_64
445 new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_x86_64>(
446 context, LocalAddressSpace::sThisAddressSpace);
447 auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
448 co->setInfoBasedOnIPRegister();
449 return UNW_ESUCCESS;
450#elif defined(_LIBUNWIND_TARGET_ARM)
451 new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>(
452 context, LocalAddressSpace::sThisAddressSpace);
453 auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
454 co->setInfoBasedOnIPRegister();
455 return UNW_ESUCCESS;
456#elif defined(_LIBUNWIND_TARGET_AARCH64)
457 new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm64>(
458 context, LocalAddressSpace::sThisAddressSpace);
459 auto *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
460 co->setInfoBasedOnIPRegister();
461 return UNW_ESUCCESS;
462#else
463 return UNW_EINVAL;
464#endif
465}
466
467static DISPATCHER_CONTEXT *
468_unw_seh_get_disp_ctx(unw_cursor_t *cursor) {
469#ifdef _LIBUNWIND_TARGET_X86_64
470 return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->getDispatcherContext();
471#elif defined(_LIBUNWIND_TARGET_ARM)
472 return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->getDispatcherContext();
473#elif defined(_LIBUNWIND_TARGET_AARCH64)
474 return reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->getDispatcherContext();
475#else
476 return nullptr;
477#endif
478}
479
480static void
481_unw_seh_set_disp_ctx(unw_cursor_t *cursor, DISPATCHER_CONTEXT *disp) {
482#ifdef _LIBUNWIND_TARGET_X86_64
483 reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_x86_64> *>(cursor)->setDispatcherContext(disp);
484#elif defined(_LIBUNWIND_TARGET_ARM)
485 reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm> *>(cursor)->setDispatcherContext(disp);
486#elif defined(_LIBUNWIND_TARGET_AARCH64)
487 reinterpret_cast<UnwindCursor<LocalAddressSpace, Registers_arm64> *>(cursor)->setDispatcherContext(disp);
488#endif
489}
490
491#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
libunwind/src/Unwind-sjlj.c created+504
...@@ -0,0 +1,504 @@
1//===--------------------------- Unwind-sjlj.c ----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Implements setjump-longjump based C++ exceptions
10//
11//===----------------------------------------------------------------------===//
12
13#include <unwind.h>
14
15#include <stdint.h>
16#include <stdbool.h>
17#include <stdlib.h>
18
19#include "config.h"
20
21/// With SJLJ based exceptions, any function that has a catch clause or needs to
22/// do any clean up when an exception propagates through it, needs to call
23/// \c _Unwind_SjLj_Register at the start of the function and
24/// \c _Unwind_SjLj_Unregister at the end. The register function is called with
25/// the address of a block of memory in the function's stack frame. The runtime
26/// keeps a linked list (stack) of these blocks - one per thread. The calling
27/// function also sets the personality and lsda fields of the block.
28
29#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
30
31struct _Unwind_FunctionContext {
32 // next function in stack of handlers
33 struct _Unwind_FunctionContext *prev;
34
35 // set by calling function before registering to be the landing pad
36 uint32_t resumeLocation;
37
38 // set by personality handler to be parameters passed to landing pad function
39 uint32_t resumeParameters[4];
40
41 // set by calling function before registering
42 __personality_routine personality; // arm offset=24
43 uintptr_t lsda; // arm offset=28
44
45 // variable length array, contains registers to restore
46 // 0 = r7, 1 = pc, 2 = sp
47 void *jbuf[];
48};
49
50#if defined(_LIBUNWIND_HAS_NO_THREADS)
51# define _LIBUNWIND_THREAD_LOCAL
52#else
53# if __STDC_VERSION__ >= 201112L
54# define _LIBUNWIND_THREAD_LOCAL _Thread_local
55# elif defined(_WIN32)
56# define _LIBUNWIND_THREAD_LOCAL __declspec(thread)
57# elif defined(__GNUC__) || defined(__clang__)
58# define _LIBUNWIND_THREAD_LOCAL __thread
59# else
60# error Unable to create thread local storage
61# endif
62#endif
63
64
65#if !defined(FOR_DYLD)
66
67#if defined(__APPLE__)
68#include <System/pthread_machdep.h>
69#else
70static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL;
71#endif
72
73static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {
74#if defined(__APPLE__)
75 return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
76#else
77 return stack;
78#endif
79}
80
81static void
82__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) {
83#if defined(__APPLE__)
84 _pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc);
85#else
86 stack = fc;
87#endif
88}
89
90#endif
91
92
93/// Called at start of each function that catches exceptions
94_LIBUNWIND_EXPORT void
95_Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) {
96 fc->prev = __Unwind_SjLj_GetTopOfFunctionStack();
97 __Unwind_SjLj_SetTopOfFunctionStack(fc);
98}
99
100
101/// Called at end of each function that catches exceptions
102_LIBUNWIND_EXPORT void
103_Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) {
104 __Unwind_SjLj_SetTopOfFunctionStack(fc->prev);
105}
106
107
108static _Unwind_Reason_Code
109unwind_phase1(struct _Unwind_Exception *exception_object) {
110 _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
111 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p", c);
112
113 // walk each frame looking for a place to stop
114 for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {
115
116 // check for no more frames
117 if (c == NULL) {
118 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached "
119 "bottom => _URC_END_OF_STACK",
120 exception_object);
121 return _URC_END_OF_STACK;
122 }
123
124 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", c);
125 // if there is a personality routine, ask it if it will want to stop at this
126 // frame
127 if (c->personality != NULL) {
128 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling "
129 "personality function %p",
130 exception_object, c->personality);
131 _Unwind_Reason_Code personalityResult = (*c->personality)(
132 1, _UA_SEARCH_PHASE, exception_object->exception_class,
133 exception_object, (struct _Unwind_Context *)c);
134 switch (personalityResult) {
135 case _URC_HANDLER_FOUND:
136 // found a catch clause or locals that need destructing in this frame
137 // stop search and remember function context
138 handlerNotFound = false;
139 exception_object->private_2 = (uintptr_t) c;
140 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
141 "_URC_HANDLER_FOUND", exception_object);
142 return _URC_NO_REASON;
143
144 case _URC_CONTINUE_UNWIND:
145 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
146 "_URC_CONTINUE_UNWIND", exception_object);
147 // continue unwinding
148 break;
149
150 default:
151 // something went wrong
152 _LIBUNWIND_TRACE_UNWINDING(
153 "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
154 exception_object);
155 return _URC_FATAL_PHASE1_ERROR;
156 }
157 }
158 }
159 return _URC_NO_REASON;
160}
161
162
163static _Unwind_Reason_Code
164unwind_phase2(struct _Unwind_Exception *exception_object) {
165 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", exception_object);
166
167 // walk each frame until we reach where search phase said to stop
168 _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
169 while (true) {
170 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p",
171 exception_object, c);
172
173 // check for no more frames
174 if (c == NULL) {
175 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
176 "bottom => _URC_END_OF_STACK",
177 exception_object);
178 return _URC_END_OF_STACK;
179 }
180
181 // if there is a personality routine, tell it we are unwinding
182 if (c->personality != NULL) {
183 _Unwind_Action action = _UA_CLEANUP_PHASE;
184 if ((uintptr_t) c == exception_object->private_2)
185 action = (_Unwind_Action)(
186 _UA_CLEANUP_PHASE |
187 _UA_HANDLER_FRAME); // tell personality this was the frame it marked
188 // in phase 1
189 _Unwind_Reason_Code personalityResult =
190 (*c->personality)(1, action, exception_object->exception_class,
191 exception_object, (struct _Unwind_Context *)c);
192 switch (personalityResult) {
193 case _URC_CONTINUE_UNWIND:
194 // continue unwinding
195 _LIBUNWIND_TRACE_UNWINDING(
196 "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
197 exception_object);
198 if ((uintptr_t) c == exception_object->private_2) {
199 // phase 1 said we would stop at this frame, but we did not...
200 _LIBUNWIND_ABORT("during phase1 personality function said it would "
201 "stop here, but now if phase2 it did not stop here");
202 }
203 break;
204 case _URC_INSTALL_CONTEXT:
205 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): "
206 "_URC_INSTALL_CONTEXT, will resume at "
207 "landing pad %p",
208 exception_object, c->jbuf[1]);
209 // personality routine says to transfer control to landing pad
210 // we may get control back if landing pad calls _Unwind_Resume()
211 __Unwind_SjLj_SetTopOfFunctionStack(c);
212 __builtin_longjmp(c->jbuf, 1);
213 // unw_resume() only returns if there was an error
214 return _URC_FATAL_PHASE2_ERROR;
215 default:
216 // something went wrong
217 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
218 personalityResult);
219 return _URC_FATAL_PHASE2_ERROR;
220 }
221 }
222 c = c->prev;
223 }
224
225 // clean up phase did not resume at the frame that the search phase said it
226 // would
227 return _URC_FATAL_PHASE2_ERROR;
228}
229
230
231static _Unwind_Reason_Code
232unwind_phase2_forced(struct _Unwind_Exception *exception_object,
233 _Unwind_Stop_Fn stop, void *stop_parameter) {
234 // walk each frame until we reach where search phase said to stop
235 _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
236 while (true) {
237
238 // get next frame (skip over first which is _Unwind_RaiseException)
239 if (c == NULL) {
240 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
241 "bottom => _URC_END_OF_STACK",
242 exception_object);
243 return _URC_END_OF_STACK;
244 }
245
246 // call stop function at each frame
247 _Unwind_Action action =
248 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
249 _Unwind_Reason_Code stopResult =
250 (*stop)(1, action, exception_object->exception_class, exception_object,
251 (struct _Unwind_Context *)c, stop_parameter);
252 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
253 "stop function returned %d",
254 exception_object, stopResult);
255 if (stopResult != _URC_NO_REASON) {
256 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
257 "stopped by stop function",
258 exception_object);
259 return _URC_FATAL_PHASE2_ERROR;
260 }
261
262 // if there is a personality routine, tell it we are unwinding
263 if (c->personality != NULL) {
264 __personality_routine p = (__personality_routine) c->personality;
265 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
266 "calling personality function %p",
267 exception_object, p);
268 _Unwind_Reason_Code personalityResult =
269 (*p)(1, action, exception_object->exception_class, exception_object,
270 (struct _Unwind_Context *)c);
271 switch (personalityResult) {
272 case _URC_CONTINUE_UNWIND:
273 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
274 "personality returned _URC_CONTINUE_UNWIND",
275 exception_object);
276 // destructors called, continue unwinding
277 break;
278 case _URC_INSTALL_CONTEXT:
279 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
280 "personality returned _URC_INSTALL_CONTEXT",
281 exception_object);
282 // we may get control back if landing pad calls _Unwind_Resume()
283 __Unwind_SjLj_SetTopOfFunctionStack(c);
284 __builtin_longjmp(c->jbuf, 1);
285 break;
286 default:
287 // something went wrong
288 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
289 "personality returned %d, "
290 "_URC_FATAL_PHASE2_ERROR",
291 exception_object, personalityResult);
292 return _URC_FATAL_PHASE2_ERROR;
293 }
294 }
295 c = c->prev;
296 }
297
298 // call stop function one last time and tell it we've reached the end of the
299 // stack
300 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
301 "function with _UA_END_OF_STACK",
302 exception_object);
303 _Unwind_Action lastAction =
304 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
305 (*stop)(1, lastAction, exception_object->exception_class, exception_object,
306 (struct _Unwind_Context *)c, stop_parameter);
307
308 // clean up phase did not resume at the frame that the search phase said it
309 // would
310 return _URC_FATAL_PHASE2_ERROR;
311}
312
313
314/// Called by __cxa_throw. Only returns if there is a fatal error
315_LIBUNWIND_EXPORT _Unwind_Reason_Code
316_Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) {
317 _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)", exception_object);
318
319 // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right
320 // thing
321 exception_object->private_1 = 0;
322 exception_object->private_2 = 0;
323
324 // phase 1: the search phase
325 _Unwind_Reason_Code phase1 = unwind_phase1(exception_object);
326 if (phase1 != _URC_NO_REASON)
327 return phase1;
328
329 // phase 2: the clean up phase
330 return unwind_phase2(exception_object);
331}
332
333
334
335/// When _Unwind_RaiseException() is in phase2, it hands control
336/// to the personality function at each frame. The personality
337/// may force a jump to a landing pad in that function, the landing
338/// pad code may then call _Unwind_Resume() to continue with the
339/// unwinding. Note: the call to _Unwind_Resume() is from compiler
340/// geneated user code. All other _Unwind_* routines are called
341/// by the C++ runtime __cxa_* routines.
342///
343/// Re-throwing an exception is implemented by having the code call
344/// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
345_LIBUNWIND_EXPORT void
346_Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
347 _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)", exception_object);
348
349 if (exception_object->private_1 != 0)
350 unwind_phase2_forced(exception_object,
351 (_Unwind_Stop_Fn) exception_object->private_1,
352 (void *)exception_object->private_2);
353 else
354 unwind_phase2(exception_object);
355
356 // clients assume _Unwind_Resume() does not return, so all we can do is abort.
357 _LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return");
358}
359
360
361/// Called by __cxa_rethrow().
362_LIBUNWIND_EXPORT _Unwind_Reason_Code
363_Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) {
364 _LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), "
365 "private_1=%ld",
366 exception_object, exception_object->private_1);
367 // If this is non-forced and a stopping place was found, then this is a
368 // re-throw.
369 // Call _Unwind_RaiseException() as if this was a new exception.
370 if (exception_object->private_1 == 0) {
371 return _Unwind_SjLj_RaiseException(exception_object);
372 // should return if there is no catch clause, so that __cxa_rethrow can call
373 // std::terminate()
374 }
375
376 // Call through to _Unwind_Resume() which distiguishes between forced and
377 // regular exceptions.
378 _Unwind_SjLj_Resume(exception_object);
379 _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called "
380 "_Unwind_SjLj_Resume() which unexpectedly returned");
381}
382
383
384/// Called by personality handler during phase 2 to get LSDA for current frame.
385_LIBUNWIND_EXPORT uintptr_t
386_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
387 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
388 _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) "
389 "=> 0x%0lX", context, ufc->lsda);
390 return ufc->lsda;
391}
392
393
394/// Called by personality handler during phase 2 to get register values.
395_LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
396 int index) {
397 _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)",
398 context, index);
399 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
400 return ufc->resumeParameters[index];
401}
402
403
404/// Called by personality handler during phase 2 to alter register values.
405_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
406 uintptr_t new_value) {
407 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0lX)"
408 , context, index, new_value);
409 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
410 ufc->resumeParameters[index] = new_value;
411}
412
413
414/// Called by personality handler during phase 2 to get instruction pointer.
415_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
416 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
417 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%lX", context,
418 ufc->resumeLocation + 1);
419 return ufc->resumeLocation + 1;
420}
421
422
423/// Called by personality handler during phase 2 to get instruction pointer.
424/// ipBefore is a boolean that says if IP is already adjusted to be the call
425/// site address. Normally IP is the return address.
426_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
427 int *ipBefore) {
428 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
429 *ipBefore = 0;
430 _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%lX",
431 context, ipBefore, ufc->resumeLocation + 1);
432 return ufc->resumeLocation + 1;
433}
434
435
436/// Called by personality handler during phase 2 to alter instruction pointer.
437_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
438 uintptr_t new_value) {
439 _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0lX)",
440 context, new_value);
441 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
442 ufc->resumeLocation = new_value - 1;
443}
444
445
446/// Called by personality handler during phase 2 to find the start of the
447/// function.
448_LIBUNWIND_EXPORT uintptr_t
449_Unwind_GetRegionStart(struct _Unwind_Context *context) {
450 // Not supported or needed for sjlj based unwinding
451 (void)context;
452 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", context);
453 return 0;
454}
455
456
457/// Called by personality handler during phase 2 if a foreign exception
458/// is caught.
459_LIBUNWIND_EXPORT void
460_Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
461 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
462 exception_object);
463 if (exception_object->exception_cleanup != NULL)
464 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
465 exception_object);
466}
467
468
469
470/// Called by personality handler during phase 2 to get base address for data
471/// relative encodings.
472_LIBUNWIND_EXPORT uintptr_t
473_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
474 // Not supported or needed for sjlj based unwinding
475 (void)context;
476 _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", context);
477 _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
478}
479
480
481/// Called by personality handler during phase 2 to get base address for text
482/// relative encodings.
483_LIBUNWIND_EXPORT uintptr_t
484_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
485 // Not supported or needed for sjlj based unwinding
486 (void)context;
487 _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", context);
488 _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
489}
490
491
492/// Called by personality handler to get "Call Frame Area" for current frame.
493_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
494 _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", context);
495 if (context != NULL) {
496 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
497 // Setjmp/longjmp based exceptions don't have a true CFA.
498 // Instead, the SP in the jmpbuf is the closest approximation.
499 return (uintptr_t) ufc->jbuf[2];
500 }
501 return 0;
502}
503
504#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)
libunwind/src/UnwindCursor.hpp created+1975
...@@ -0,0 +1,1975 @@
1//===------------------------- UnwindCursor.hpp ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// C++ interface to lower levels of libunwind
10//===----------------------------------------------------------------------===//
11
12#ifndef __UNWINDCURSOR_HPP__
13#define __UNWINDCURSOR_HPP__
14
15#include <algorithm>
16#include <stdint.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <unwind.h>
20
21#ifdef _WIN32
22 #include <windows.h>
23 #include <ntverp.h>
24#endif
25#ifdef __APPLE__
26 #include <mach-o/dyld.h>
27#endif
28
29#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
30// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
31// earlier) SDKs.
32// MinGW-w64 has always provided this struct.
33 #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
34 !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
35struct _DISPATCHER_CONTEXT {
36 ULONG64 ControlPc;
37 ULONG64 ImageBase;
38 PRUNTIME_FUNCTION FunctionEntry;
39 ULONG64 EstablisherFrame;
40 ULONG64 TargetIp;
41 PCONTEXT ContextRecord;
42 PEXCEPTION_ROUTINE LanguageHandler;
43 PVOID HandlerData;
44 PUNWIND_HISTORY_TABLE HistoryTable;
45 ULONG ScopeIndex;
46 ULONG Fill0;
47};
48 #endif
49
50struct UNWIND_INFO {
51 uint8_t Version : 3;
52 uint8_t Flags : 5;
53 uint8_t SizeOfProlog;
54 uint8_t CountOfCodes;
55 uint8_t FrameRegister : 4;
56 uint8_t FrameOffset : 4;
57 uint16_t UnwindCodes[2];
58};
59
60extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
61 int, _Unwind_Action, uint64_t, _Unwind_Exception *,
62 struct _Unwind_Context *);
63
64#endif
65
66#include "config.h"
67
68#include "AddressSpace.hpp"
69#include "CompactUnwinder.hpp"
70#include "config.h"
71#include "DwarfInstructions.hpp"
72#include "EHHeaderParser.hpp"
73#include "libunwind.h"
74#include "Registers.hpp"
75#include "RWMutex.hpp"
76#include "Unwind-EHABI.h"
77
78namespace libunwind {
79
80#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
81/// Cache of recently found FDEs.
82template <typename A>
83class _LIBUNWIND_HIDDEN DwarfFDECache {
84 typedef typename A::pint_t pint_t;
85public:
86 static pint_t findFDE(pint_t mh, pint_t pc);
87 static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
88 static void removeAllIn(pint_t mh);
89 static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
90 unw_word_t ip_end,
91 unw_word_t fde, unw_word_t mh));
92
93private:
94
95 struct entry {
96 pint_t mh;
97 pint_t ip_start;
98 pint_t ip_end;
99 pint_t fde;
100 };
101
102 // These fields are all static to avoid needing an initializer.
103 // There is only one instance of this class per process.
104 static RWMutex _lock;
105#ifdef __APPLE__
106 static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);
107 static bool _registeredForDyldUnloads;
108#endif
109 // Can't use std::vector<> here because this code is below libc++.
110 static entry *_buffer;
111 static entry *_bufferUsed;
112 static entry *_bufferEnd;
113 static entry _initialBuffer[64];
114};
115
116template <typename A>
117typename DwarfFDECache<A>::entry *
118DwarfFDECache<A>::_buffer = _initialBuffer;
119
120template <typename A>
121typename DwarfFDECache<A>::entry *
122DwarfFDECache<A>::_bufferUsed = _initialBuffer;
123
124template <typename A>
125typename DwarfFDECache<A>::entry *
126DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64];
127
128template <typename A>
129typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64];
130
131template <typename A>
132RWMutex DwarfFDECache<A>::_lock;
133
134#ifdef __APPLE__
135template <typename A>
136bool DwarfFDECache<A>::_registeredForDyldUnloads = false;
137#endif
138
139template <typename A>
140typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) {
141 pint_t result = 0;
142 _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
143 for (entry *p = _buffer; p < _bufferUsed; ++p) {
144 if ((mh == p->mh) || (mh == 0)) {
145 if ((p->ip_start <= pc) && (pc < p->ip_end)) {
146 result = p->fde;
147 break;
148 }
149 }
150 }
151 _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared());
152 return result;
153}
154
155template <typename A>
156void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
157 pint_t fde) {
158#if !defined(_LIBUNWIND_NO_HEAP)
159 _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
160 if (_bufferUsed >= _bufferEnd) {
161 size_t oldSize = (size_t)(_bufferEnd - _buffer);
162 size_t newSize = oldSize * 4;
163 // Can't use operator new (we are below it).
164 entry *newBuffer = (entry *)malloc(newSize * sizeof(entry));
165 memcpy(newBuffer, _buffer, oldSize * sizeof(entry));
166 if (_buffer != _initialBuffer)
167 free(_buffer);
168 _buffer = newBuffer;
169 _bufferUsed = &newBuffer[oldSize];
170 _bufferEnd = &newBuffer[newSize];
171 }
172 _bufferUsed->mh = mh;
173 _bufferUsed->ip_start = ip_start;
174 _bufferUsed->ip_end = ip_end;
175 _bufferUsed->fde = fde;
176 ++_bufferUsed;
177#ifdef __APPLE__
178 if (!_registeredForDyldUnloads) {
179 _dyld_register_func_for_remove_image(&dyldUnloadHook);
180 _registeredForDyldUnloads = true;
181 }
182#endif
183 _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
184#endif
185}
186
187template <typename A>
188void DwarfFDECache<A>::removeAllIn(pint_t mh) {
189 _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
190 entry *d = _buffer;
191 for (const entry *s = _buffer; s < _bufferUsed; ++s) {
192 if (s->mh != mh) {
193 if (d != s)
194 *d = *s;
195 ++d;
196 }
197 }
198 _bufferUsed = d;
199 _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
200}
201
202#ifdef __APPLE__
203template <typename A>
204void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) {
205 removeAllIn((pint_t) mh);
206}
207#endif
208
209template <typename A>
210void DwarfFDECache<A>::iterateCacheEntries(void (*func)(
211 unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
212 _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
213 for (entry *p = _buffer; p < _bufferUsed; ++p) {
214 (*func)(p->ip_start, p->ip_end, p->fde, p->mh);
215 }
216 _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
217}
218#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
219
220
221#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
222
223#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
224template <typename A> class UnwindSectionHeader {
225public:
226 UnwindSectionHeader(A &addressSpace, typename A::pint_t addr)
227 : _addressSpace(addressSpace), _addr(addr) {}
228
229 uint32_t version() const {
230 return _addressSpace.get32(_addr +
231 offsetof(unwind_info_section_header, version));
232 }
233 uint32_t commonEncodingsArraySectionOffset() const {
234 return _addressSpace.get32(_addr +
235 offsetof(unwind_info_section_header,
236 commonEncodingsArraySectionOffset));
237 }
238 uint32_t commonEncodingsArrayCount() const {
239 return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
240 commonEncodingsArrayCount));
241 }
242 uint32_t personalityArraySectionOffset() const {
243 return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
244 personalityArraySectionOffset));
245 }
246 uint32_t personalityArrayCount() const {
247 return _addressSpace.get32(
248 _addr + offsetof(unwind_info_section_header, personalityArrayCount));
249 }
250 uint32_t indexSectionOffset() const {
251 return _addressSpace.get32(
252 _addr + offsetof(unwind_info_section_header, indexSectionOffset));
253 }
254 uint32_t indexCount() const {
255 return _addressSpace.get32(
256 _addr + offsetof(unwind_info_section_header, indexCount));
257 }
258
259private:
260 A &_addressSpace;
261 typename A::pint_t _addr;
262};
263
264template <typename A> class UnwindSectionIndexArray {
265public:
266 UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr)
267 : _addressSpace(addressSpace), _addr(addr) {}
268
269 uint32_t functionOffset(uint32_t index) const {
270 return _addressSpace.get32(
271 _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
272 functionOffset));
273 }
274 uint32_t secondLevelPagesSectionOffset(uint32_t index) const {
275 return _addressSpace.get32(
276 _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
277 secondLevelPagesSectionOffset));
278 }
279 uint32_t lsdaIndexArraySectionOffset(uint32_t index) const {
280 return _addressSpace.get32(
281 _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
282 lsdaIndexArraySectionOffset));
283 }
284
285private:
286 A &_addressSpace;
287 typename A::pint_t _addr;
288};
289
290template <typename A> class UnwindSectionRegularPageHeader {
291public:
292 UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr)
293 : _addressSpace(addressSpace), _addr(addr) {}
294
295 uint32_t kind() const {
296 return _addressSpace.get32(
297 _addr + offsetof(unwind_info_regular_second_level_page_header, kind));
298 }
299 uint16_t entryPageOffset() const {
300 return _addressSpace.get16(
301 _addr + offsetof(unwind_info_regular_second_level_page_header,
302 entryPageOffset));
303 }
304 uint16_t entryCount() const {
305 return _addressSpace.get16(
306 _addr +
307 offsetof(unwind_info_regular_second_level_page_header, entryCount));
308 }
309
310private:
311 A &_addressSpace;
312 typename A::pint_t _addr;
313};
314
315template <typename A> class UnwindSectionRegularArray {
316public:
317 UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr)
318 : _addressSpace(addressSpace), _addr(addr) {}
319
320 uint32_t functionOffset(uint32_t index) const {
321 return _addressSpace.get32(
322 _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index,
323 functionOffset));
324 }
325 uint32_t encoding(uint32_t index) const {
326 return _addressSpace.get32(
327 _addr +
328 arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding));
329 }
330
331private:
332 A &_addressSpace;
333 typename A::pint_t _addr;
334};
335
336template <typename A> class UnwindSectionCompressedPageHeader {
337public:
338 UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr)
339 : _addressSpace(addressSpace), _addr(addr) {}
340
341 uint32_t kind() const {
342 return _addressSpace.get32(
343 _addr +
344 offsetof(unwind_info_compressed_second_level_page_header, kind));
345 }
346 uint16_t entryPageOffset() const {
347 return _addressSpace.get16(
348 _addr + offsetof(unwind_info_compressed_second_level_page_header,
349 entryPageOffset));
350 }
351 uint16_t entryCount() const {
352 return _addressSpace.get16(
353 _addr +
354 offsetof(unwind_info_compressed_second_level_page_header, entryCount));
355 }
356 uint16_t encodingsPageOffset() const {
357 return _addressSpace.get16(
358 _addr + offsetof(unwind_info_compressed_second_level_page_header,
359 encodingsPageOffset));
360 }
361 uint16_t encodingsCount() const {
362 return _addressSpace.get16(
363 _addr + offsetof(unwind_info_compressed_second_level_page_header,
364 encodingsCount));
365 }
366
367private:
368 A &_addressSpace;
369 typename A::pint_t _addr;
370};
371
372template <typename A> class UnwindSectionCompressedArray {
373public:
374 UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr)
375 : _addressSpace(addressSpace), _addr(addr) {}
376
377 uint32_t functionOffset(uint32_t index) const {
378 return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
379 _addressSpace.get32(_addr + index * sizeof(uint32_t)));
380 }
381 uint16_t encodingIndex(uint32_t index) const {
382 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
383 _addressSpace.get32(_addr + index * sizeof(uint32_t)));
384 }
385
386private:
387 A &_addressSpace;
388 typename A::pint_t _addr;
389};
390
391template <typename A> class UnwindSectionLsdaArray {
392public:
393 UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr)
394 : _addressSpace(addressSpace), _addr(addr) {}
395
396 uint32_t functionOffset(uint32_t index) const {
397 return _addressSpace.get32(
398 _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
399 index, functionOffset));
400 }
401 uint32_t lsdaOffset(uint32_t index) const {
402 return _addressSpace.get32(
403 _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
404 index, lsdaOffset));
405 }
406
407private:
408 A &_addressSpace;
409 typename A::pint_t _addr;
410};
411#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
412
413class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
414public:
415 // NOTE: provide a class specific placement deallocation function (S5.3.4 p20)
416 // This avoids an unnecessary dependency to libc++abi.
417 void operator delete(void *, size_t) {}
418
419 virtual ~AbstractUnwindCursor() {}
420 virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }
421 virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }
422 virtual void setReg(int, unw_word_t) {
423 _LIBUNWIND_ABORT("setReg not implemented");
424 }
425 virtual bool validFloatReg(int) {
426 _LIBUNWIND_ABORT("validFloatReg not implemented");
427 }
428 virtual unw_fpreg_t getFloatReg(int) {
429 _LIBUNWIND_ABORT("getFloatReg not implemented");
430 }
431 virtual void setFloatReg(int, unw_fpreg_t) {
432 _LIBUNWIND_ABORT("setFloatReg not implemented");
433 }
434 virtual int step() { _LIBUNWIND_ABORT("step not implemented"); }
435 virtual void getInfo(unw_proc_info_t *) {
436 _LIBUNWIND_ABORT("getInfo not implemented");
437 }
438 virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
439 virtual bool isSignalFrame() {
440 _LIBUNWIND_ABORT("isSignalFrame not implemented");
441 }
442 virtual bool getFunctionName(char *, size_t, unw_word_t *) {
443 _LIBUNWIND_ABORT("getFunctionName not implemented");
444 }
445 virtual void setInfoBasedOnIPRegister(bool = false) {
446 _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");
447 }
448 virtual const char *getRegisterName(int) {
449 _LIBUNWIND_ABORT("getRegisterName not implemented");
450 }
451#ifdef __arm__
452 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
453#endif
454};
455
456#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
457
458/// \c UnwindCursor contains all state (including all register values) during
459/// an unwind. This is normally stack-allocated inside a unw_cursor_t.
460template <typename A, typename R>
461class UnwindCursor : public AbstractUnwindCursor {
462 typedef typename A::pint_t pint_t;
463public:
464 UnwindCursor(unw_context_t *context, A &as);
465 UnwindCursor(CONTEXT *context, A &as);
466 UnwindCursor(A &as, void *threadArg);
467 virtual ~UnwindCursor() {}
468 virtual bool validReg(int);
469 virtual unw_word_t getReg(int);
470 virtual void setReg(int, unw_word_t);
471 virtual bool validFloatReg(int);
472 virtual unw_fpreg_t getFloatReg(int);
473 virtual void setFloatReg(int, unw_fpreg_t);
474 virtual int step();
475 virtual void getInfo(unw_proc_info_t *);
476 virtual void jumpto();
477 virtual bool isSignalFrame();
478 virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);
479 virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);
480 virtual const char *getRegisterName(int num);
481#ifdef __arm__
482 virtual void saveVFPAsX();
483#endif
484
485 DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
486 void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
487
488private:
489
490 pint_t getLastPC() const { return _dispContext.ControlPc; }
491 void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }
492 RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
493 _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,
494 &_dispContext.ImageBase,
495 _dispContext.HistoryTable);
496 *base = _dispContext.ImageBase;
497 return _dispContext.FunctionEntry;
498 }
499 bool getInfoFromSEH(pint_t pc);
500 int stepWithSEHData() {
501 _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER,
502 _dispContext.ImageBase,
503 _dispContext.ControlPc,
504 _dispContext.FunctionEntry,
505 _dispContext.ContextRecord,
506 &_dispContext.HandlerData,
507 &_dispContext.EstablisherFrame,
508 NULL);
509 // Update some fields of the unwind info now, since we have them.
510 _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
511 if (_dispContext.LanguageHandler) {
512 _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
513 } else
514 _info.handler = 0;
515 return UNW_STEP_SUCCESS;
516 }
517
518 A &_addressSpace;
519 unw_proc_info_t _info;
520 DISPATCHER_CONTEXT _dispContext;
521 CONTEXT _msContext;
522 UNWIND_HISTORY_TABLE _histTable;
523 bool _unwindInfoMissing;
524};
525
526
527template <typename A, typename R>
528UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
529 : _addressSpace(as), _unwindInfoMissing(false) {
530 static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
531 "UnwindCursor<> does not fit in unw_cursor_t");
532 memset(&_info, 0, sizeof(_info));
533 memset(&_histTable, 0, sizeof(_histTable));
534 _dispContext.ContextRecord = &_msContext;
535 _dispContext.HistoryTable = &_histTable;
536 // Initialize MS context from ours.
537 R r(context);
538 _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
539#if defined(_LIBUNWIND_TARGET_X86_64)
540 _msContext.Rax = r.getRegister(UNW_X86_64_RAX);
541 _msContext.Rcx = r.getRegister(UNW_X86_64_RCX);
542 _msContext.Rdx = r.getRegister(UNW_X86_64_RDX);
543 _msContext.Rbx = r.getRegister(UNW_X86_64_RBX);
544 _msContext.Rsp = r.getRegister(UNW_X86_64_RSP);
545 _msContext.Rbp = r.getRegister(UNW_X86_64_RBP);
546 _msContext.Rsi = r.getRegister(UNW_X86_64_RSI);
547 _msContext.Rdi = r.getRegister(UNW_X86_64_RDI);
548 _msContext.R8 = r.getRegister(UNW_X86_64_R8);
549 _msContext.R9 = r.getRegister(UNW_X86_64_R9);
550 _msContext.R10 = r.getRegister(UNW_X86_64_R10);
551 _msContext.R11 = r.getRegister(UNW_X86_64_R11);
552 _msContext.R12 = r.getRegister(UNW_X86_64_R12);
553 _msContext.R13 = r.getRegister(UNW_X86_64_R13);
554 _msContext.R14 = r.getRegister(UNW_X86_64_R14);
555 _msContext.R15 = r.getRegister(UNW_X86_64_R15);
556 _msContext.Rip = r.getRegister(UNW_REG_IP);
557 union {
558 v128 v;
559 M128A m;
560 } t;
561 t.v = r.getVectorRegister(UNW_X86_64_XMM0);
562 _msContext.Xmm0 = t.m;
563 t.v = r.getVectorRegister(UNW_X86_64_XMM1);
564 _msContext.Xmm1 = t.m;
565 t.v = r.getVectorRegister(UNW_X86_64_XMM2);
566 _msContext.Xmm2 = t.m;
567 t.v = r.getVectorRegister(UNW_X86_64_XMM3);
568 _msContext.Xmm3 = t.m;
569 t.v = r.getVectorRegister(UNW_X86_64_XMM4);
570 _msContext.Xmm4 = t.m;
571 t.v = r.getVectorRegister(UNW_X86_64_XMM5);
572 _msContext.Xmm5 = t.m;
573 t.v = r.getVectorRegister(UNW_X86_64_XMM6);
574 _msContext.Xmm6 = t.m;
575 t.v = r.getVectorRegister(UNW_X86_64_XMM7);
576 _msContext.Xmm7 = t.m;
577 t.v = r.getVectorRegister(UNW_X86_64_XMM8);
578 _msContext.Xmm8 = t.m;
579 t.v = r.getVectorRegister(UNW_X86_64_XMM9);
580 _msContext.Xmm9 = t.m;
581 t.v = r.getVectorRegister(UNW_X86_64_XMM10);
582 _msContext.Xmm10 = t.m;
583 t.v = r.getVectorRegister(UNW_X86_64_XMM11);
584 _msContext.Xmm11 = t.m;
585 t.v = r.getVectorRegister(UNW_X86_64_XMM12);
586 _msContext.Xmm12 = t.m;
587 t.v = r.getVectorRegister(UNW_X86_64_XMM13);
588 _msContext.Xmm13 = t.m;
589 t.v = r.getVectorRegister(UNW_X86_64_XMM14);
590 _msContext.Xmm14 = t.m;
591 t.v = r.getVectorRegister(UNW_X86_64_XMM15);
592 _msContext.Xmm15 = t.m;
593#elif defined(_LIBUNWIND_TARGET_ARM)
594 _msContext.R0 = r.getRegister(UNW_ARM_R0);
595 _msContext.R1 = r.getRegister(UNW_ARM_R1);
596 _msContext.R2 = r.getRegister(UNW_ARM_R2);
597 _msContext.R3 = r.getRegister(UNW_ARM_R3);
598 _msContext.R4 = r.getRegister(UNW_ARM_R4);
599 _msContext.R5 = r.getRegister(UNW_ARM_R5);
600 _msContext.R6 = r.getRegister(UNW_ARM_R6);
601 _msContext.R7 = r.getRegister(UNW_ARM_R7);
602 _msContext.R8 = r.getRegister(UNW_ARM_R8);
603 _msContext.R9 = r.getRegister(UNW_ARM_R9);
604 _msContext.R10 = r.getRegister(UNW_ARM_R10);
605 _msContext.R11 = r.getRegister(UNW_ARM_R11);
606 _msContext.R12 = r.getRegister(UNW_ARM_R12);
607 _msContext.Sp = r.getRegister(UNW_ARM_SP);
608 _msContext.Lr = r.getRegister(UNW_ARM_LR);
609 _msContext.Pc = r.getRegister(UNW_ARM_IP);
610 for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) {
611 union {
612 uint64_t w;
613 double d;
614 } d;
615 d.d = r.getFloatRegister(i);
616 _msContext.D[i - UNW_ARM_D0] = d.w;
617 }
618#elif defined(_LIBUNWIND_TARGET_AARCH64)
619 for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i)
620 _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i);
621 _msContext.Sp = r.getRegister(UNW_REG_SP);
622 _msContext.Pc = r.getRegister(UNW_REG_IP);
623 for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i)
624 _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i);
625#endif
626}
627
628template <typename A, typename R>
629UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
630 : _addressSpace(as), _unwindInfoMissing(false) {
631 static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
632 "UnwindCursor<> does not fit in unw_cursor_t");
633 memset(&_info, 0, sizeof(_info));
634 memset(&_histTable, 0, sizeof(_histTable));
635 _dispContext.ContextRecord = &_msContext;
636 _dispContext.HistoryTable = &_histTable;
637 _msContext = *context;
638}
639
640
641template <typename A, typename R>
642bool UnwindCursor<A, R>::validReg(int regNum) {
643 if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;
644#if defined(_LIBUNWIND_TARGET_X86_64)
645 if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true;
646#elif defined(_LIBUNWIND_TARGET_ARM)
647 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true;
648#elif defined(_LIBUNWIND_TARGET_AARCH64)
649 if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true;
650#endif
651 return false;
652}
653
654template <typename A, typename R>
655unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
656 switch (regNum) {
657#if defined(_LIBUNWIND_TARGET_X86_64)
658 case UNW_REG_IP: return _msContext.Rip;
659 case UNW_X86_64_RAX: return _msContext.Rax;
660 case UNW_X86_64_RDX: return _msContext.Rdx;
661 case UNW_X86_64_RCX: return _msContext.Rcx;
662 case UNW_X86_64_RBX: return _msContext.Rbx;
663 case UNW_REG_SP:
664 case UNW_X86_64_RSP: return _msContext.Rsp;
665 case UNW_X86_64_RBP: return _msContext.Rbp;
666 case UNW_X86_64_RSI: return _msContext.Rsi;
667 case UNW_X86_64_RDI: return _msContext.Rdi;
668 case UNW_X86_64_R8: return _msContext.R8;
669 case UNW_X86_64_R9: return _msContext.R9;
670 case UNW_X86_64_R10: return _msContext.R10;
671 case UNW_X86_64_R11: return _msContext.R11;
672 case UNW_X86_64_R12: return _msContext.R12;
673 case UNW_X86_64_R13: return _msContext.R13;
674 case UNW_X86_64_R14: return _msContext.R14;
675 case UNW_X86_64_R15: return _msContext.R15;
676#elif defined(_LIBUNWIND_TARGET_ARM)
677 case UNW_ARM_R0: return _msContext.R0;
678 case UNW_ARM_R1: return _msContext.R1;
679 case UNW_ARM_R2: return _msContext.R2;
680 case UNW_ARM_R3: return _msContext.R3;
681 case UNW_ARM_R4: return _msContext.R4;
682 case UNW_ARM_R5: return _msContext.R5;
683 case UNW_ARM_R6: return _msContext.R6;
684 case UNW_ARM_R7: return _msContext.R7;
685 case UNW_ARM_R8: return _msContext.R8;
686 case UNW_ARM_R9: return _msContext.R9;
687 case UNW_ARM_R10: return _msContext.R10;
688 case UNW_ARM_R11: return _msContext.R11;
689 case UNW_ARM_R12: return _msContext.R12;
690 case UNW_REG_SP:
691 case UNW_ARM_SP: return _msContext.Sp;
692 case UNW_ARM_LR: return _msContext.Lr;
693 case UNW_REG_IP:
694 case UNW_ARM_IP: return _msContext.Pc;
695#elif defined(_LIBUNWIND_TARGET_AARCH64)
696 case UNW_REG_SP: return _msContext.Sp;
697 case UNW_REG_IP: return _msContext.Pc;
698 default: return _msContext.X[regNum - UNW_ARM64_X0];
699#endif
700 }
701 _LIBUNWIND_ABORT("unsupported register");
702}
703
704template <typename A, typename R>
705void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
706 switch (regNum) {
707#if defined(_LIBUNWIND_TARGET_X86_64)
708 case UNW_REG_IP: _msContext.Rip = value; break;
709 case UNW_X86_64_RAX: _msContext.Rax = value; break;
710 case UNW_X86_64_RDX: _msContext.Rdx = value; break;
711 case UNW_X86_64_RCX: _msContext.Rcx = value; break;
712 case UNW_X86_64_RBX: _msContext.Rbx = value; break;
713 case UNW_REG_SP:
714 case UNW_X86_64_RSP: _msContext.Rsp = value; break;
715 case UNW_X86_64_RBP: _msContext.Rbp = value; break;
716 case UNW_X86_64_RSI: _msContext.Rsi = value; break;
717 case UNW_X86_64_RDI: _msContext.Rdi = value; break;
718 case UNW_X86_64_R8: _msContext.R8 = value; break;
719 case UNW_X86_64_R9: _msContext.R9 = value; break;
720 case UNW_X86_64_R10: _msContext.R10 = value; break;
721 case UNW_X86_64_R11: _msContext.R11 = value; break;
722 case UNW_X86_64_R12: _msContext.R12 = value; break;
723 case UNW_X86_64_R13: _msContext.R13 = value; break;
724 case UNW_X86_64_R14: _msContext.R14 = value; break;
725 case UNW_X86_64_R15: _msContext.R15 = value; break;
726#elif defined(_LIBUNWIND_TARGET_ARM)
727 case UNW_ARM_R0: _msContext.R0 = value; break;
728 case UNW_ARM_R1: _msContext.R1 = value; break;
729 case UNW_ARM_R2: _msContext.R2 = value; break;
730 case UNW_ARM_R3: _msContext.R3 = value; break;
731 case UNW_ARM_R4: _msContext.R4 = value; break;
732 case UNW_ARM_R5: _msContext.R5 = value; break;
733 case UNW_ARM_R6: _msContext.R6 = value; break;
734 case UNW_ARM_R7: _msContext.R7 = value; break;
735 case UNW_ARM_R8: _msContext.R8 = value; break;
736 case UNW_ARM_R9: _msContext.R9 = value; break;
737 case UNW_ARM_R10: _msContext.R10 = value; break;
738 case UNW_ARM_R11: _msContext.R11 = value; break;
739 case UNW_ARM_R12: _msContext.R12 = value; break;
740 case UNW_REG_SP:
741 case UNW_ARM_SP: _msContext.Sp = value; break;
742 case UNW_ARM_LR: _msContext.Lr = value; break;
743 case UNW_REG_IP:
744 case UNW_ARM_IP: _msContext.Pc = value; break;
745#elif defined(_LIBUNWIND_TARGET_AARCH64)
746 case UNW_REG_SP: _msContext.Sp = value; break;
747 case UNW_REG_IP: _msContext.Pc = value; break;
748 case UNW_ARM64_X0:
749 case UNW_ARM64_X1:
750 case UNW_ARM64_X2:
751 case UNW_ARM64_X3:
752 case UNW_ARM64_X4:
753 case UNW_ARM64_X5:
754 case UNW_ARM64_X6:
755 case UNW_ARM64_X7:
756 case UNW_ARM64_X8:
757 case UNW_ARM64_X9:
758 case UNW_ARM64_X10:
759 case UNW_ARM64_X11:
760 case UNW_ARM64_X12:
761 case UNW_ARM64_X13:
762 case UNW_ARM64_X14:
763 case UNW_ARM64_X15:
764 case UNW_ARM64_X16:
765 case UNW_ARM64_X17:
766 case UNW_ARM64_X18:
767 case UNW_ARM64_X19:
768 case UNW_ARM64_X20:
769 case UNW_ARM64_X21:
770 case UNW_ARM64_X22:
771 case UNW_ARM64_X23:
772 case UNW_ARM64_X24:
773 case UNW_ARM64_X25:
774 case UNW_ARM64_X26:
775 case UNW_ARM64_X27:
776 case UNW_ARM64_X28:
777 case UNW_ARM64_FP:
778 case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break;
779#endif
780 default:
781 _LIBUNWIND_ABORT("unsupported register");
782 }
783}
784
785template <typename A, typename R>
786bool UnwindCursor<A, R>::validFloatReg(int regNum) {
787#if defined(_LIBUNWIND_TARGET_ARM)
788 if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true;
789 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true;
790#elif defined(_LIBUNWIND_TARGET_AARCH64)
791 if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true;
792#endif
793 return false;
794}
795
796template <typename A, typename R>
797unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
798#if defined(_LIBUNWIND_TARGET_ARM)
799 if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
800 union {
801 uint32_t w;
802 float f;
803 } d;
804 d.w = _msContext.S[regNum - UNW_ARM_S0];
805 return d.f;
806 }
807 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
808 union {
809 uint64_t w;
810 double d;
811 } d;
812 d.w = _msContext.D[regNum - UNW_ARM_D0];
813 return d.d;
814 }
815 _LIBUNWIND_ABORT("unsupported float register");
816#elif defined(_LIBUNWIND_TARGET_AARCH64)
817 return _msContext.V[regNum - UNW_ARM64_D0].D[0];
818#else
819 _LIBUNWIND_ABORT("float registers unimplemented");
820#endif
821}
822
823template <typename A, typename R>
824void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
825#if defined(_LIBUNWIND_TARGET_ARM)
826 if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
827 union {
828 uint32_t w;
829 float f;
830 } d;
831 d.f = value;
832 _msContext.S[regNum - UNW_ARM_S0] = d.w;
833 }
834 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
835 union {
836 uint64_t w;
837 double d;
838 } d;
839 d.d = value;
840 _msContext.D[regNum - UNW_ARM_D0] = d.w;
841 }
842 _LIBUNWIND_ABORT("unsupported float register");
843#elif defined(_LIBUNWIND_TARGET_AARCH64)
844 _msContext.V[regNum - UNW_ARM64_D0].D[0] = value;
845#else
846 _LIBUNWIND_ABORT("float registers unimplemented");
847#endif
848}
849
850template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
851 RtlRestoreContext(&_msContext, nullptr);
852}
853
854#ifdef __arm__
855template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {}
856#endif
857
858template <typename A, typename R>
859const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
860 return R::getRegisterName(regNum);
861}
862
863template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
864 return false;
865}
866
867#else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
868
869/// UnwindCursor contains all state (including all register values) during
870/// an unwind. This is normally stack allocated inside a unw_cursor_t.
871template <typename A, typename R>
872class UnwindCursor : public AbstractUnwindCursor{
873 typedef typename A::pint_t pint_t;
874public:
875 UnwindCursor(unw_context_t *context, A &as);
876 UnwindCursor(A &as, void *threadArg);
877 virtual ~UnwindCursor() {}
878 virtual bool validReg(int);
879 virtual unw_word_t getReg(int);
880 virtual void setReg(int, unw_word_t);
881 virtual bool validFloatReg(int);
882 virtual unw_fpreg_t getFloatReg(int);
883 virtual void setFloatReg(int, unw_fpreg_t);
884 virtual int step();
885 virtual void getInfo(unw_proc_info_t *);
886 virtual void jumpto();
887 virtual bool isSignalFrame();
888 virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);
889 virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);
890 virtual const char *getRegisterName(int num);
891#ifdef __arm__
892 virtual void saveVFPAsX();
893#endif
894
895private:
896
897#if defined(_LIBUNWIND_ARM_EHABI)
898 bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections &sects);
899
900 int stepWithEHABI() {
901 size_t len = 0;
902 size_t off = 0;
903 // FIXME: Calling decode_eht_entry() here is violating the libunwind
904 // abstraction layer.
905 const uint32_t *ehtp =
906 decode_eht_entry(reinterpret_cast<const uint32_t *>(_info.unwind_info),
907 &off, &len);
908 if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) !=
909 _URC_CONTINUE_UNWIND)
910 return UNW_STEP_END;
911 return UNW_STEP_SUCCESS;
912 }
913#endif
914
915#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
916 bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
917 uint32_t fdeSectionOffsetHint=0);
918 int stepWithDwarfFDE() {
919 return DwarfInstructions<A, R>::stepWithDwarf(_addressSpace,
920 (pint_t)this->getReg(UNW_REG_IP),
921 (pint_t)_info.unwind_info,
922 _registers);
923 }
924#endif
925
926#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
927 bool getInfoFromCompactEncodingSection(pint_t pc,
928 const UnwindInfoSections &sects);
929 int stepWithCompactEncoding() {
930 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
931 if ( compactSaysUseDwarf() )
932 return stepWithDwarfFDE();
933 #endif
934 R dummy;
935 return stepWithCompactEncoding(dummy);
936 }
937
938#if defined(_LIBUNWIND_TARGET_X86_64)
939 int stepWithCompactEncoding(Registers_x86_64 &) {
940 return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
941 _info.format, _info.start_ip, _addressSpace, _registers);
942 }
943#endif
944
945#if defined(_LIBUNWIND_TARGET_I386)
946 int stepWithCompactEncoding(Registers_x86 &) {
947 return CompactUnwinder_x86<A>::stepWithCompactEncoding(
948 _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
949 }
950#endif
951
952#if defined(_LIBUNWIND_TARGET_PPC)
953 int stepWithCompactEncoding(Registers_ppc &) {
954 return UNW_EINVAL;
955 }
956#endif
957
958#if defined(_LIBUNWIND_TARGET_PPC64)
959 int stepWithCompactEncoding(Registers_ppc64 &) {
960 return UNW_EINVAL;
961 }
962#endif
963
964
965#if defined(_LIBUNWIND_TARGET_AARCH64)
966 int stepWithCompactEncoding(Registers_arm64 &) {
967 return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
968 _info.format, _info.start_ip, _addressSpace, _registers);
969 }
970#endif
971
972#if defined(_LIBUNWIND_TARGET_MIPS_O32)
973 int stepWithCompactEncoding(Registers_mips_o32 &) {
974 return UNW_EINVAL;
975 }
976#endif
977
978#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
979 int stepWithCompactEncoding(Registers_mips_newabi &) {
980 return UNW_EINVAL;
981 }
982#endif
983
984#if defined(_LIBUNWIND_TARGET_SPARC)
985 int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
986#endif
987
988 bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
989 R dummy;
990 return compactSaysUseDwarf(dummy, offset);
991 }
992
993#if defined(_LIBUNWIND_TARGET_X86_64)
994 bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {
995 if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {
996 if (offset)
997 *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);
998 return true;
999 }
1000 return false;
1001 }
1002#endif
1003
1004#if defined(_LIBUNWIND_TARGET_I386)
1005 bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {
1006 if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {
1007 if (offset)
1008 *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET);
1009 return true;
1010 }
1011 return false;
1012 }
1013#endif
1014
1015#if defined(_LIBUNWIND_TARGET_PPC)
1016 bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {
1017 return true;
1018 }
1019#endif
1020
1021#if defined(_LIBUNWIND_TARGET_PPC64)
1022 bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const {
1023 return true;
1024 }
1025#endif
1026
1027#if defined(_LIBUNWIND_TARGET_AARCH64)
1028 bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
1029 if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
1030 if (offset)
1031 *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET);
1032 return true;
1033 }
1034 return false;
1035 }
1036#endif
1037
1038#if defined(_LIBUNWIND_TARGET_MIPS_O32)
1039 bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const {
1040 return true;
1041 }
1042#endif
1043
1044#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1045 bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {
1046 return true;
1047 }
1048#endif
1049
1050#if defined(_LIBUNWIND_TARGET_SPARC)
1051 bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
1052#endif
1053
1054#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1055
1056#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1057 compact_unwind_encoding_t dwarfEncoding() const {
1058 R dummy;
1059 return dwarfEncoding(dummy);
1060 }
1061
1062#if defined(_LIBUNWIND_TARGET_X86_64)
1063 compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
1064 return UNWIND_X86_64_MODE_DWARF;
1065 }
1066#endif
1067
1068#if defined(_LIBUNWIND_TARGET_I386)
1069 compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
1070 return UNWIND_X86_MODE_DWARF;
1071 }
1072#endif
1073
1074#if defined(_LIBUNWIND_TARGET_PPC)
1075 compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
1076 return 0;
1077 }
1078#endif
1079
1080#if defined(_LIBUNWIND_TARGET_PPC64)
1081 compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const {
1082 return 0;
1083 }
1084#endif
1085
1086#if defined(_LIBUNWIND_TARGET_AARCH64)
1087 compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
1088 return UNWIND_ARM64_MODE_DWARF;
1089 }
1090#endif
1091
1092#if defined(_LIBUNWIND_TARGET_ARM)
1093 compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const {
1094 return 0;
1095 }
1096#endif
1097
1098#if defined (_LIBUNWIND_TARGET_OR1K)
1099 compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {
1100 return 0;
1101 }
1102#endif
1103
1104#if defined (_LIBUNWIND_TARGET_MIPS_O32)
1105 compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const {
1106 return 0;
1107 }
1108#endif
1109
1110#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
1111 compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {
1112 return 0;
1113 }
1114#endif
1115
1116#if defined(_LIBUNWIND_TARGET_SPARC)
1117 compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
1118#endif
1119
1120#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1121
1122#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1123 // For runtime environments using SEH unwind data without Windows runtime
1124 // support.
1125 pint_t getLastPC() const { /* FIXME: Implement */ return 0; }
1126 void setLastPC(pint_t pc) { /* FIXME: Implement */ }
1127 RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
1128 /* FIXME: Implement */
1129 *base = 0;
1130 return nullptr;
1131 }
1132 bool getInfoFromSEH(pint_t pc);
1133 int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1134#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1135
1136
1137 A &_addressSpace;
1138 R _registers;
1139 unw_proc_info_t _info;
1140 bool _unwindInfoMissing;
1141 bool _isSignalFrame;
1142};
1143
1144
1145template <typename A, typename R>
1146UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
1147 : _addressSpace(as), _registers(context), _unwindInfoMissing(false),
1148 _isSignalFrame(false) {
1149 static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
1150 "UnwindCursor<> does not fit in unw_cursor_t");
1151 memset(&_info, 0, sizeof(_info));
1152}
1153
1154template <typename A, typename R>
1155UnwindCursor<A, R>::UnwindCursor(A &as, void *)
1156 : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
1157 memset(&_info, 0, sizeof(_info));
1158 // FIXME
1159 // fill in _registers from thread arg
1160}
1161
1162
1163template <typename A, typename R>
1164bool UnwindCursor<A, R>::validReg(int regNum) {
1165 return _registers.validRegister(regNum);
1166}
1167
1168template <typename A, typename R>
1169unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
1170 return _registers.getRegister(regNum);
1171}
1172
1173template <typename A, typename R>
1174void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
1175 _registers.setRegister(regNum, (typename A::pint_t)value);
1176}
1177
1178template <typename A, typename R>
1179bool UnwindCursor<A, R>::validFloatReg(int regNum) {
1180 return _registers.validFloatRegister(regNum);
1181}
1182
1183template <typename A, typename R>
1184unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
1185 return _registers.getFloatRegister(regNum);
1186}
1187
1188template <typename A, typename R>
1189void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
1190 _registers.setFloatRegister(regNum, value);
1191}
1192
1193template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
1194 _registers.jumpto();
1195}
1196
1197#ifdef __arm__
1198template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
1199 _registers.saveVFPAsX();
1200}
1201#endif
1202
1203template <typename A, typename R>
1204const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
1205 return _registers.getRegisterName(regNum);
1206}
1207
1208template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
1209 return _isSignalFrame;
1210}
1211
1212#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1213
1214#if defined(_LIBUNWIND_ARM_EHABI)
1215struct EHABIIndexEntry {
1216 uint32_t functionOffset;
1217 uint32_t data;
1218};
1219
1220template<typename A>
1221struct EHABISectionIterator {
1222 typedef EHABISectionIterator _Self;
1223
1224 typedef std::random_access_iterator_tag iterator_category;
1225 typedef typename A::pint_t value_type;
1226 typedef typename A::pint_t* pointer;
1227 typedef typename A::pint_t& reference;
1228 typedef size_t size_type;
1229 typedef size_t difference_type;
1230
1231 static _Self begin(A& addressSpace, const UnwindInfoSections& sects) {
1232 return _Self(addressSpace, sects, 0);
1233 }
1234 static _Self end(A& addressSpace, const UnwindInfoSections& sects) {
1235 return _Self(addressSpace, sects,
1236 sects.arm_section_length / sizeof(EHABIIndexEntry));
1237 }
1238
1239 EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i)
1240 : _i(i), _addressSpace(&addressSpace), _sects(&sects) {}
1241
1242 _Self& operator++() { ++_i; return *this; }
1243 _Self& operator+=(size_t a) { _i += a; return *this; }
1244 _Self& operator--() { assert(_i > 0); --_i; return *this; }
1245 _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; }
1246
1247 _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; }
1248 _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; }
1249
1250 size_t operator-(const _Self& other) { return _i - other._i; }
1251
1252 bool operator==(const _Self& other) const {
1253 assert(_addressSpace == other._addressSpace);
1254 assert(_sects == other._sects);
1255 return _i == other._i;
1256 }
1257
1258 typename A::pint_t operator*() const { return functionAddress(); }
1259
1260 typename A::pint_t functionAddress() const {
1261 typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1262 EHABIIndexEntry, _i, functionOffset);
1263 return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr));
1264 }
1265
1266 typename A::pint_t dataAddress() {
1267 typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1268 EHABIIndexEntry, _i, data);
1269 return indexAddr;
1270 }
1271
1272 private:
1273 size_t _i;
1274 A* _addressSpace;
1275 const UnwindInfoSections* _sects;
1276};
1277
1278template <typename A, typename R>
1279bool UnwindCursor<A, R>::getInfoFromEHABISection(
1280 pint_t pc,
1281 const UnwindInfoSections &sects) {
1282 EHABISectionIterator<A> begin =
1283 EHABISectionIterator<A>::begin(_addressSpace, sects);
1284 EHABISectionIterator<A> end =
1285 EHABISectionIterator<A>::end(_addressSpace, sects);
1286 if (begin == end)
1287 return false;
1288
1289 EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc);
1290 if (itNextPC == begin)
1291 return false;
1292 EHABISectionIterator<A> itThisPC = itNextPC - 1;
1293
1294 pint_t thisPC = itThisPC.functionAddress();
1295 // If an exception is thrown from a function, corresponding to the last entry
1296 // in the table, we don't really know the function extent and have to choose a
1297 // value for nextPC. Choosing max() will allow the range check during trace to
1298 // succeed.
1299 pint_t nextPC = (itNextPC == end) ? std::numeric_limits<pint_t>::max()
1300 : itNextPC.functionAddress();
1301 pint_t indexDataAddr = itThisPC.dataAddress();
1302
1303 if (indexDataAddr == 0)
1304 return false;
1305
1306 uint32_t indexData = _addressSpace.get32(indexDataAddr);
1307 if (indexData == UNW_EXIDX_CANTUNWIND)
1308 return false;
1309
1310 // If the high bit is set, the exception handling table entry is inline inside
1311 // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
1312 // the table points at an offset in the exception handling table (section 5 EHABI).
1313 pint_t exceptionTableAddr;
1314 uint32_t exceptionTableData;
1315 bool isSingleWordEHT;
1316 if (indexData & 0x80000000) {
1317 exceptionTableAddr = indexDataAddr;
1318 // TODO(ajwong): Should this data be 0?
1319 exceptionTableData = indexData;
1320 isSingleWordEHT = true;
1321 } else {
1322 exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData);
1323 exceptionTableData = _addressSpace.get32(exceptionTableAddr);
1324 isSingleWordEHT = false;
1325 }
1326
1327 // Now we know the 3 things:
1328 // exceptionTableAddr -- exception handler table entry.
1329 // exceptionTableData -- the data inside the first word of the eht entry.
1330 // isSingleWordEHT -- whether the entry is in the index.
1331 unw_word_t personalityRoutine = 0xbadf00d;
1332 bool scope32 = false;
1333 uintptr_t lsda;
1334
1335 // If the high bit in the exception handling table entry is set, the entry is
1336 // in compact form (section 6.3 EHABI).
1337 if (exceptionTableData & 0x80000000) {
1338 // Grab the index of the personality routine from the compact form.
1339 uint32_t choice = (exceptionTableData & 0x0f000000) >> 24;
1340 uint32_t extraWords = 0;
1341 switch (choice) {
1342 case 0:
1343 personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0;
1344 extraWords = 0;
1345 scope32 = false;
1346 lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4);
1347 break;
1348 case 1:
1349 personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1;
1350 extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1351 scope32 = false;
1352 lsda = exceptionTableAddr + (extraWords + 1) * 4;
1353 break;
1354 case 2:
1355 personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2;
1356 extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1357 scope32 = true;
1358 lsda = exceptionTableAddr + (extraWords + 1) * 4;
1359 break;
1360 default:
1361 _LIBUNWIND_ABORT("unknown personality routine");
1362 return false;
1363 }
1364
1365 if (isSingleWordEHT) {
1366 if (extraWords != 0) {
1367 _LIBUNWIND_ABORT("index inlined table detected but pr function "
1368 "requires extra words");
1369 return false;
1370 }
1371 }
1372 } else {
1373 pint_t personalityAddr =
1374 exceptionTableAddr + signExtendPrel31(exceptionTableData);
1375 personalityRoutine = personalityAddr;
1376
1377 // ARM EHABI # 6.2, # 9.2
1378 //
1379 // +---- ehtp
1380 // v
1381 // +--------------------------------------+
1382 // | +--------+--------+--------+-------+ |
1383 // | |0| prel31 to personalityRoutine | |
1384 // | +--------+--------+--------+-------+ |
1385 // | | N | unwind opcodes | | <-- UnwindData
1386 // | +--------+--------+--------+-------+ |
1387 // | | Word 2 unwind opcodes | |
1388 // | +--------+--------+--------+-------+ |
1389 // | ... |
1390 // | +--------+--------+--------+-------+ |
1391 // | | Word N unwind opcodes | |
1392 // | +--------+--------+--------+-------+ |
1393 // | | LSDA | | <-- lsda
1394 // | | ... | |
1395 // | +--------+--------+--------+-------+ |
1396 // +--------------------------------------+
1397
1398 uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1;
1399 uint32_t FirstDataWord = *UnwindData;
1400 size_t N = ((FirstDataWord >> 24) & 0xff);
1401 size_t NDataWords = N + 1;
1402 lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords);
1403 }
1404
1405 _info.start_ip = thisPC;
1406 _info.end_ip = nextPC;
1407 _info.handler = personalityRoutine;
1408 _info.unwind_info = exceptionTableAddr;
1409 _info.lsda = lsda;
1410 // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
1411 _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0; // Use enum?
1412
1413 return true;
1414}
1415#endif
1416
1417#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1418template <typename A, typename R>
1419bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
1420 const UnwindInfoSections &sects,
1421 uint32_t fdeSectionOffsetHint) {
1422 typename CFI_Parser<A>::FDE_Info fdeInfo;
1423 typename CFI_Parser<A>::CIE_Info cieInfo;
1424 bool foundFDE = false;
1425 bool foundInCache = false;
1426 // If compact encoding table gave offset into dwarf section, go directly there
1427 if (fdeSectionOffsetHint != 0) {
1428 foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1429 (uint32_t)sects.dwarf_section_length,
1430 sects.dwarf_section + fdeSectionOffsetHint,
1431 &fdeInfo, &cieInfo);
1432 }
1433#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1434 if (!foundFDE && (sects.dwarf_index_section != 0)) {
1435 foundFDE = EHHeaderParser<A>::findFDE(
1436 _addressSpace, pc, sects.dwarf_index_section,
1437 (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);
1438 }
1439#endif
1440 if (!foundFDE) {
1441 // otherwise, search cache of previously found FDEs.
1442 pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc);
1443 if (cachedFDE != 0) {
1444 foundFDE =
1445 CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1446 (uint32_t)sects.dwarf_section_length,
1447 cachedFDE, &fdeInfo, &cieInfo);
1448 foundInCache = foundFDE;
1449 }
1450 }
1451 if (!foundFDE) {
1452 // Still not found, do full scan of __eh_frame section.
1453 foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1454 (uint32_t)sects.dwarf_section_length, 0,
1455 &fdeInfo, &cieInfo);
1456 }
1457 if (foundFDE) {
1458 typename CFI_Parser<A>::PrologInfo prolog;
1459 if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
1460 R::getArch(), &prolog)) {
1461 // Save off parsed FDE info
1462 _info.start_ip = fdeInfo.pcStart;
1463 _info.end_ip = fdeInfo.pcEnd;
1464 _info.lsda = fdeInfo.lsda;
1465 _info.handler = cieInfo.personality;
1466 _info.gp = prolog.spExtraArgSize;
1467 _info.flags = 0;
1468 _info.format = dwarfEncoding();
1469 _info.unwind_info = fdeInfo.fdeStart;
1470 _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1471 _info.extra = (unw_word_t) sects.dso_base;
1472
1473 // Add to cache (to make next lookup faster) if we had no hint
1474 // and there was no index.
1475 if (!foundInCache && (fdeSectionOffsetHint == 0)) {
1476 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1477 if (sects.dwarf_index_section == 0)
1478 #endif
1479 DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd,
1480 fdeInfo.fdeStart);
1481 }
1482 return true;
1483 }
1484 }
1485 //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
1486 return false;
1487}
1488#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1489
1490
1491#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1492template <typename A, typename R>
1493bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
1494 const UnwindInfoSections &sects) {
1495 const bool log = false;
1496 if (log)
1497 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
1498 (uint64_t)pc, (uint64_t)sects.dso_base);
1499
1500 const UnwindSectionHeader<A> sectionHeader(_addressSpace,
1501 sects.compact_unwind_section);
1502 if (sectionHeader.version() != UNWIND_SECTION_VERSION)
1503 return false;
1504
1505 // do a binary search of top level index to find page with unwind info
1506 pint_t targetFunctionOffset = pc - sects.dso_base;
1507 const UnwindSectionIndexArray<A> topIndex(_addressSpace,
1508 sects.compact_unwind_section
1509 + sectionHeader.indexSectionOffset());
1510 uint32_t low = 0;
1511 uint32_t high = sectionHeader.indexCount();
1512 uint32_t last = high - 1;
1513 while (low < high) {
1514 uint32_t mid = (low + high) / 2;
1515 //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
1516 //mid, low, high, topIndex.functionOffset(mid));
1517 if (topIndex.functionOffset(mid) <= targetFunctionOffset) {
1518 if ((mid == last) ||
1519 (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) {
1520 low = mid;
1521 break;
1522 } else {
1523 low = mid + 1;
1524 }
1525 } else {
1526 high = mid;
1527 }
1528 }
1529 const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);
1530 const uint32_t firstLevelNextPageFunctionOffset =
1531 topIndex.functionOffset(low + 1);
1532 const pint_t secondLevelAddr =
1533 sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low);
1534 const pint_t lsdaArrayStartAddr =
1535 sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low);
1536 const pint_t lsdaArrayEndAddr =
1537 sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1);
1538 if (log)
1539 fprintf(stderr, "\tfirst level search for result index=%d "
1540 "to secondLevelAddr=0x%llX\n",
1541 low, (uint64_t) secondLevelAddr);
1542 // do a binary search of second level page index
1543 uint32_t encoding = 0;
1544 pint_t funcStart = 0;
1545 pint_t funcEnd = 0;
1546 pint_t lsda = 0;
1547 pint_t personality = 0;
1548 uint32_t pageKind = _addressSpace.get32(secondLevelAddr);
1549 if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) {
1550 // regular page
1551 UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace,
1552 secondLevelAddr);
1553 UnwindSectionRegularArray<A> pageIndex(
1554 _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1555 // binary search looks for entry with e where index[e].offset <= pc <
1556 // index[e+1].offset
1557 if (log)
1558 fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in "
1559 "regular page starting at secondLevelAddr=0x%llX\n",
1560 (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr);
1561 low = 0;
1562 high = pageHeader.entryCount();
1563 while (low < high) {
1564 uint32_t mid = (low + high) / 2;
1565 if (pageIndex.functionOffset(mid) <= targetFunctionOffset) {
1566 if (mid == (uint32_t)(pageHeader.entryCount() - 1)) {
1567 // at end of table
1568 low = mid;
1569 funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1570 break;
1571 } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) {
1572 // next is too big, so we found it
1573 low = mid;
1574 funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base;
1575 break;
1576 } else {
1577 low = mid + 1;
1578 }
1579 } else {
1580 high = mid;
1581 }
1582 }
1583 encoding = pageIndex.encoding(low);
1584 funcStart = pageIndex.functionOffset(low) + sects.dso_base;
1585 if (pc < funcStart) {
1586 if (log)
1587 fprintf(
1588 stderr,
1589 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1590 (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
1591 return false;
1592 }
1593 if (pc > funcEnd) {
1594 if (log)
1595 fprintf(
1596 stderr,
1597 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1598 (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
1599 return false;
1600 }
1601 } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) {
1602 // compressed page
1603 UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace,
1604 secondLevelAddr);
1605 UnwindSectionCompressedArray<A> pageIndex(
1606 _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1607 const uint32_t targetFunctionPageOffset =
1608 (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset);
1609 // binary search looks for entry with e where index[e].offset <= pc <
1610 // index[e+1].offset
1611 if (log)
1612 fprintf(stderr, "\tbinary search of compressed page starting at "
1613 "secondLevelAddr=0x%llX\n",
1614 (uint64_t) secondLevelAddr);
1615 low = 0;
1616 last = pageHeader.entryCount() - 1;
1617 high = pageHeader.entryCount();
1618 while (low < high) {
1619 uint32_t mid = (low + high) / 2;
1620 if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) {
1621 if ((mid == last) ||
1622 (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) {
1623 low = mid;
1624 break;
1625 } else {
1626 low = mid + 1;
1627 }
1628 } else {
1629 high = mid;
1630 }
1631 }
1632 funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset
1633 + sects.dso_base;
1634 if (low < last)
1635 funcEnd =
1636 pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset
1637 + sects.dso_base;
1638 else
1639 funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1640 if (pc < funcStart) {
1641 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second "
1642 "level compressed unwind table. funcStart=0x%llX",
1643 (uint64_t) pc, (uint64_t) funcStart);
1644 return false;
1645 }
1646 if (pc > funcEnd) {
1647 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second "
1648 "level compressed unwind table. funcEnd=0x%llX",
1649 (uint64_t) pc, (uint64_t) funcEnd);
1650 return false;
1651 }
1652 uint16_t encodingIndex = pageIndex.encodingIndex(low);
1653 if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) {
1654 // encoding is in common table in section header
1655 encoding = _addressSpace.get32(
1656 sects.compact_unwind_section +
1657 sectionHeader.commonEncodingsArraySectionOffset() +
1658 encodingIndex * sizeof(uint32_t));
1659 } else {
1660 // encoding is in page specific table
1661 uint16_t pageEncodingIndex =
1662 encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount();
1663 encoding = _addressSpace.get32(secondLevelAddr +
1664 pageHeader.encodingsPageOffset() +
1665 pageEncodingIndex * sizeof(uint32_t));
1666 }
1667 } else {
1668 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second "
1669 "level page",
1670 (uint64_t) sects.compact_unwind_section);
1671 return false;
1672 }
1673
1674 // look up LSDA, if encoding says function has one
1675 if (encoding & UNWIND_HAS_LSDA) {
1676 UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr);
1677 uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base);
1678 low = 0;
1679 high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) /
1680 sizeof(unwind_info_section_header_lsda_index_entry);
1681 // binary search looks for entry with exact match for functionOffset
1682 if (log)
1683 fprintf(stderr,
1684 "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
1685 funcStartOffset);
1686 while (low < high) {
1687 uint32_t mid = (low + high) / 2;
1688 if (lsdaIndex.functionOffset(mid) == funcStartOffset) {
1689 lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base;
1690 break;
1691 } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) {
1692 low = mid + 1;
1693 } else {
1694 high = mid;
1695 }
1696 }
1697 if (lsda == 0) {
1698 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
1699 "pc=0x%0llX, but lsda table has no entry",
1700 encoding, (uint64_t) pc);
1701 return false;
1702 }
1703 }
1704
1705 // extact personality routine, if encoding says function has one
1706 uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >>
1707 (__builtin_ctz(UNWIND_PERSONALITY_MASK));
1708 if (personalityIndex != 0) {
1709 --personalityIndex; // change 1-based to zero-based index
1710 if (personalityIndex > sectionHeader.personalityArrayCount()) {
1711 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
1712 "but personality table has only %d entires",
1713 encoding, personalityIndex,
1714 sectionHeader.personalityArrayCount());
1715 return false;
1716 }
1717 int32_t personalityDelta = (int32_t)_addressSpace.get32(
1718 sects.compact_unwind_section +
1719 sectionHeader.personalityArraySectionOffset() +
1720 personalityIndex * sizeof(uint32_t));
1721 pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;
1722 personality = _addressSpace.getP(personalityPointer);
1723 if (log)
1724 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1725 "personalityDelta=0x%08X, personality=0x%08llX\n",
1726 (uint64_t) pc, personalityDelta, (uint64_t) personality);
1727 }
1728
1729 if (log)
1730 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1731 "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
1732 (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart);
1733 _info.start_ip = funcStart;
1734 _info.end_ip = funcEnd;
1735 _info.lsda = lsda;
1736 _info.handler = personality;
1737 _info.gp = 0;
1738 _info.flags = 0;
1739 _info.format = encoding;
1740 _info.unwind_info = 0;
1741 _info.unwind_info_size = 0;
1742 _info.extra = sects.dso_base;
1743 return true;
1744}
1745#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1746
1747
1748#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1749template <typename A, typename R>
1750bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
1751 pint_t base;
1752 RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base);
1753 if (!unwindEntry) {
1754 _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc);
1755 return false;
1756 }
1757 _info.gp = 0;
1758 _info.flags = 0;
1759 _info.format = 0;
1760 _info.unwind_info_size = sizeof(RUNTIME_FUNCTION);
1761 _info.unwind_info = reinterpret_cast<unw_word_t>(unwindEntry);
1762 _info.extra = base;
1763 _info.start_ip = base + unwindEntry->BeginAddress;
1764#ifdef _LIBUNWIND_TARGET_X86_64
1765 _info.end_ip = base + unwindEntry->EndAddress;
1766 // Only fill in the handler and LSDA if they're stale.
1767 if (pc != getLastPC()) {
1768 UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData);
1769 if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) {
1770 // The personality is given in the UNWIND_INFO itself. The LSDA immediately
1771 // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
1772 // these structures.)
1773 // N.B. UNWIND_INFO structs are DWORD-aligned.
1774 uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;
1775 const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]);
1776 _info.lsda = reinterpret_cast<unw_word_t>(handler+1);
1777 if (*handler) {
1778 _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
1779 } else
1780 _info.handler = 0;
1781 } else {
1782 _info.lsda = 0;
1783 _info.handler = 0;
1784 }
1785 }
1786#elif defined(_LIBUNWIND_TARGET_ARM)
1787 _info.end_ip = _info.start_ip + unwindEntry->FunctionLength;
1788 _info.lsda = 0; // FIXME
1789 _info.handler = 0; // FIXME
1790#endif
1791 setLastPC(pc);
1792 return true;
1793}
1794#endif
1795
1796
1797template <typename A, typename R>
1798void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
1799 pint_t pc = (pint_t)this->getReg(UNW_REG_IP);
1800#if defined(_LIBUNWIND_ARM_EHABI)
1801 // Remove the thumb bit so the IP represents the actual instruction address.
1802 // This matches the behaviour of _Unwind_GetIP on arm.
1803 pc &= (pint_t)~0x1;
1804#endif
1805
1806 // If the last line of a function is a "throw" the compiler sometimes
1807 // emits no instructions after the call to __cxa_throw. This means
1808 // the return address is actually the start of the next function.
1809 // To disambiguate this, back up the pc when we know it is a return
1810 // address.
1811 if (isReturnAddress)
1812 --pc;
1813
1814 // Ask address space object to find unwind sections for this pc.
1815 UnwindInfoSections sects;
1816 if (_addressSpace.findUnwindSections(pc, sects)) {
1817#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1818 // If there is a compact unwind encoding table, look there first.
1819 if (sects.compact_unwind_section != 0) {
1820 if (this->getInfoFromCompactEncodingSection(pc, sects)) {
1821 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1822 // Found info in table, done unless encoding says to use dwarf.
1823 uint32_t dwarfOffset;
1824 if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) {
1825 if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) {
1826 // found info in dwarf, done
1827 return;
1828 }
1829 }
1830 #endif
1831 // If unwind table has entry, but entry says there is no unwind info,
1832 // record that we have no unwind info.
1833 if (_info.format == 0)
1834 _unwindInfoMissing = true;
1835 return;
1836 }
1837 }
1838#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1839
1840#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1841 // If there is SEH unwind info, look there next.
1842 if (this->getInfoFromSEH(pc))
1843 return;
1844#endif
1845
1846#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1847 // If there is dwarf unwind info, look there next.
1848 if (sects.dwarf_section != 0) {
1849 if (this->getInfoFromDwarfSection(pc, sects)) {
1850 // found info in dwarf, done
1851 return;
1852 }
1853 }
1854#endif
1855
1856#if defined(_LIBUNWIND_ARM_EHABI)
1857 // If there is ARM EHABI unwind info, look there next.
1858 if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects))
1859 return;
1860#endif
1861 }
1862
1863#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1864 // There is no static unwind info for this pc. Look to see if an FDE was
1865 // dynamically registered for it.
1866 pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc);
1867 if (cachedFDE != 0) {
1868 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
1869 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
1870 const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace,
1871 cachedFDE, &fdeInfo, &cieInfo);
1872 if (msg == NULL) {
1873 typename CFI_Parser<A>::PrologInfo prolog;
1874 if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
1875 pc, R::getArch(), &prolog)) {
1876 // save off parsed FDE info
1877 _info.start_ip = fdeInfo.pcStart;
1878 _info.end_ip = fdeInfo.pcEnd;
1879 _info.lsda = fdeInfo.lsda;
1880 _info.handler = cieInfo.personality;
1881 _info.gp = prolog.spExtraArgSize;
1882 // Some frameless functions need SP
1883 // altered when resuming in function.
1884 _info.flags = 0;
1885 _info.format = dwarfEncoding();
1886 _info.unwind_info = fdeInfo.fdeStart;
1887 _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1888 _info.extra = 0;
1889 return;
1890 }
1891 }
1892 }
1893
1894 // Lastly, ask AddressSpace object about platform specific ways to locate
1895 // other FDEs.
1896 pint_t fde;
1897 if (_addressSpace.findOtherFDE(pc, fde)) {
1898 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
1899 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
1900 if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
1901 // Double check this FDE is for a function that includes the pc.
1902 if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
1903 typename CFI_Parser<A>::PrologInfo prolog;
1904 if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
1905 pc, R::getArch(), &prolog)) {
1906 // save off parsed FDE info
1907 _info.start_ip = fdeInfo.pcStart;
1908 _info.end_ip = fdeInfo.pcEnd;
1909 _info.lsda = fdeInfo.lsda;
1910 _info.handler = cieInfo.personality;
1911 _info.gp = prolog.spExtraArgSize;
1912 _info.flags = 0;
1913 _info.format = dwarfEncoding();
1914 _info.unwind_info = fdeInfo.fdeStart;
1915 _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1916 _info.extra = 0;
1917 return;
1918 }
1919 }
1920 }
1921 }
1922#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1923
1924 // no unwind info, flag that we can't reliably unwind
1925 _unwindInfoMissing = true;
1926}
1927
1928template <typename A, typename R>
1929int UnwindCursor<A, R>::step() {
1930 // Bottom of stack is defined is when unwind info cannot be found.
1931 if (_unwindInfoMissing)
1932 return UNW_STEP_END;
1933
1934 // Use unwinding info to modify register set as if function returned.
1935 int result;
1936#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1937 result = this->stepWithCompactEncoding();
1938#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1939 result = this->stepWithSEHData();
1940#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1941 result = this->stepWithDwarfFDE();
1942#elif defined(_LIBUNWIND_ARM_EHABI)
1943 result = this->stepWithEHABI();
1944#else
1945 #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
1946 _LIBUNWIND_SUPPORT_SEH_UNWIND or \
1947 _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
1948 _LIBUNWIND_ARM_EHABI
1949#endif
1950
1951 // update info based on new PC
1952 if (result == UNW_STEP_SUCCESS) {
1953 this->setInfoBasedOnIPRegister(true);
1954 if (_unwindInfoMissing)
1955 return UNW_STEP_END;
1956 }
1957
1958 return result;
1959}
1960
1961template <typename A, typename R>
1962void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
1963 *info = _info;
1964}
1965
1966template <typename A, typename R>
1967bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
1968 unw_word_t *offset) {
1969 return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP),
1970 buf, bufLen, offset);
1971}
1972
1973} // namespace libunwind
1974
1975#endif // __UNWINDCURSOR_HPP__
libunwind/src/UnwindLevel1-gcc-ext.c created+320
...@@ -0,0 +1,320 @@
1//===--------------------- UnwindLevel1-gcc-ext.c -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Implements gcc extensions to the C++ ABI Exception Handling Level 1.
10//
11//===----------------------------------------------------------------------===//
12
13#include <inttypes.h>
14#include <stdbool.h>
15#include <stdint.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include "config.h"
21#include "libunwind_ext.h"
22#include "libunwind.h"
23#include "Unwind-EHABI.h"
24#include "unwind.h"
25
26#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
27
28#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
29#define private_1 private_[0]
30#endif
31
32/// Called by __cxa_rethrow().
33_LIBUNWIND_EXPORT _Unwind_Reason_Code
34_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
35#if defined(_LIBUNWIND_ARM_EHABI)
36 _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld",
37 (void *)exception_object,
38 (long)exception_object->unwinder_cache.reserved1);
39#else
40 _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR,
41 (void *)exception_object,
42 (intptr_t)exception_object->private_1);
43#endif
44
45#if defined(_LIBUNWIND_ARM_EHABI)
46 // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
47 // which is in the same position as private_1 below.
48 return _Unwind_RaiseException(exception_object);
49#else
50 // If this is non-forced and a stopping place was found, then this is a
51 // re-throw.
52 // Call _Unwind_RaiseException() as if this was a new exception
53 if (exception_object->private_1 == 0) {
54 return _Unwind_RaiseException(exception_object);
55 // Will return if there is no catch clause, so that __cxa_rethrow can call
56 // std::terminate().
57 }
58
59 // Call through to _Unwind_Resume() which distiguishes between forced and
60 // regular exceptions.
61 _Unwind_Resume(exception_object);
62 _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()"
63 " which unexpectedly returned");
64#endif
65}
66
67
68/// Called by personality handler during phase 2 to get base address for data
69/// relative encodings.
70_LIBUNWIND_EXPORT uintptr_t
71_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
72 (void)context;
73 _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
74 _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
75}
76
77
78/// Called by personality handler during phase 2 to get base address for text
79/// relative encodings.
80_LIBUNWIND_EXPORT uintptr_t
81_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
82 (void)context;
83 _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context);
84 _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
85}
86
87
88/// Scans unwind information to find the function that contains the
89/// specified code address "pc".
90_LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) {
91 _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc);
92 // This is slow, but works.
93 // We create an unwind cursor then alter the IP to be pc
94 unw_cursor_t cursor;
95 unw_context_t uc;
96 unw_proc_info_t info;
97 unw_getcontext(&uc);
98 unw_init_local(&cursor, &uc);
99 unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc);
100 if (unw_get_proc_info(&cursor, &info) == UNW_ESUCCESS)
101 return (void *)(intptr_t) info.start_ip;
102 else
103 return NULL;
104}
105
106/// Walk every frame and call trace function at each one. If trace function
107/// returns anything other than _URC_NO_REASON, then walk is terminated.
108_LIBUNWIND_EXPORT _Unwind_Reason_Code
109_Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
110 unw_cursor_t cursor;
111 unw_context_t uc;
112 unw_getcontext(&uc);
113 unw_init_local(&cursor, &uc);
114
115 _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)",
116 (void *)(uintptr_t)callback);
117
118#if defined(_LIBUNWIND_ARM_EHABI)
119 // Create a mock exception object for force unwinding.
120 _Unwind_Exception ex;
121 memset(&ex, '\0', sizeof(ex));
122 ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0
123#endif
124
125 // walk each frame
126 while (true) {
127 _Unwind_Reason_Code result;
128
129#if !defined(_LIBUNWIND_ARM_EHABI)
130 // ask libunwind to get next frame (skip over first frame which is
131 // _Unwind_Backtrace())
132 if (unw_step(&cursor) <= 0) {
133 _LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached "
134 "bottom of stack, returning %d",
135 _URC_END_OF_STACK);
136 return _URC_END_OF_STACK;
137 }
138#else
139 // Get the information for this frame.
140 unw_proc_info_t frameInfo;
141 if (unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) {
142 return _URC_END_OF_STACK;
143 }
144
145 // Update the pr_cache in the mock exception object.
146 const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info;
147 ex.pr_cache.fnstart = frameInfo.start_ip;
148 ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo;
149 ex.pr_cache.additional= frameInfo.flags;
150
151 struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor;
152 // Get and call the personality function to unwind the frame.
153 __personality_routine handler = (__personality_routine) frameInfo.handler;
154 if (handler == NULL) {
155 return _URC_END_OF_STACK;
156 }
157 if (handler(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, &ex, context) !=
158 _URC_CONTINUE_UNWIND) {
159 return _URC_END_OF_STACK;
160 }
161#endif // defined(_LIBUNWIND_ARM_EHABI)
162
163 // debugging
164 if (_LIBUNWIND_TRACING_UNWINDING) {
165 char functionName[512];
166 unw_proc_info_t frame;
167 unw_word_t offset;
168 unw_get_proc_name(&cursor, functionName, 512, &offset);
169 unw_get_proc_info(&cursor, &frame);
170 _LIBUNWIND_TRACE_UNWINDING(
171 " _backtrace: start_ip=0x%" PRIxPTR ", func=%s, lsda=0x%" PRIxPTR ", context=%p",
172 frame.start_ip, functionName, frame.lsda,
173 (void *)&cursor);
174 }
175
176 // call trace function with this frame
177 result = (*callback)((struct _Unwind_Context *)(&cursor), ref);
178 if (result != _URC_NO_REASON) {
179 _LIBUNWIND_TRACE_UNWINDING(
180 " _backtrace: ended because callback returned %d", result);
181 return result;
182 }
183 }
184}
185
186
187/// Find DWARF unwind info for an address 'pc' in some function.
188_LIBUNWIND_EXPORT const void *_Unwind_Find_FDE(const void *pc,
189 struct dwarf_eh_bases *bases) {
190 // This is slow, but works.
191 // We create an unwind cursor then alter the IP to be pc
192 unw_cursor_t cursor;
193 unw_context_t uc;
194 unw_proc_info_t info;
195 unw_getcontext(&uc);
196 unw_init_local(&cursor, &uc);
197 unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)(intptr_t) pc);
198 unw_get_proc_info(&cursor, &info);
199 bases->tbase = (uintptr_t)info.extra;
200 bases->dbase = 0; // dbase not used on Mac OS X
201 bases->func = (uintptr_t)info.start_ip;
202 _LIBUNWIND_TRACE_API("_Unwind_Find_FDE(pc=%p) => %p", pc,
203 (void *)(intptr_t) info.unwind_info);
204 return (void *)(intptr_t) info.unwind_info;
205}
206
207/// Returns the CFA (call frame area, or stack pointer at start of function)
208/// for the current context.
209_LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
210 unw_cursor_t *cursor = (unw_cursor_t *)context;
211 unw_word_t result;
212 unw_get_reg(cursor, UNW_REG_SP, &result);
213 _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p) => 0x%" PRIxPTR,
214 (void *)context, result);
215 return (uintptr_t)result;
216}
217
218
219/// Called by personality handler during phase 2 to get instruction pointer.
220/// ipBefore is a boolean that says if IP is already adjusted to be the call
221/// site address. Normally IP is the return address.
222_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
223 int *ipBefore) {
224 _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)", (void *)context);
225 *ipBefore = 0;
226 return _Unwind_GetIP(context);
227}
228
229#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
230
231/// Called by programs with dynamic code generators that want
232/// to register a dynamically generated FDE.
233/// This function has existed on Mac OS X since 10.4, but
234/// was broken until 10.6.
235_LIBUNWIND_EXPORT void __register_frame(const void *fde) {
236 _LIBUNWIND_TRACE_API("__register_frame(%p)", fde);
237 _unw_add_dynamic_fde((unw_word_t)(uintptr_t) fde);
238}
239
240
241/// Called by programs with dynamic code generators that want
242/// to unregister a dynamically generated FDE.
243/// This function has existed on Mac OS X since 10.4, but
244/// was broken until 10.6.
245_LIBUNWIND_EXPORT void __deregister_frame(const void *fde) {
246 _LIBUNWIND_TRACE_API("__deregister_frame(%p)", fde);
247 _unw_remove_dynamic_fde((unw_word_t)(uintptr_t) fde);
248}
249
250
251// The following register/deregister functions are gcc extensions.
252// They have existed on Mac OS X, but have never worked because Mac OS X
253// before 10.6 used keymgr to track known FDEs, but these functions
254// never got updated to use keymgr.
255// For now, we implement these as do-nothing functions to keep any existing
256// applications working. We also add the not in 10.6 symbol so that nwe
257// application won't be able to use them.
258
259#if defined(_LIBUNWIND_SUPPORT_FRAME_APIS)
260_LIBUNWIND_EXPORT void __register_frame_info_bases(const void *fde, void *ob,
261 void *tb, void *db) {
262 (void)fde;
263 (void)ob;
264 (void)tb;
265 (void)db;
266 _LIBUNWIND_TRACE_API("__register_frame_info_bases(%p,%p, %p, %p)",
267 fde, ob, tb, db);
268 // do nothing, this function never worked in Mac OS X
269}
270
271_LIBUNWIND_EXPORT void __register_frame_info(const void *fde, void *ob) {
272 (void)fde;
273 (void)ob;
274 _LIBUNWIND_TRACE_API("__register_frame_info(%p, %p)", fde, ob);
275 // do nothing, this function never worked in Mac OS X
276}
277
278_LIBUNWIND_EXPORT void __register_frame_info_table_bases(const void *fde,
279 void *ob, void *tb,
280 void *db) {
281 (void)fde;
282 (void)ob;
283 (void)tb;
284 (void)db;
285 _LIBUNWIND_TRACE_API("__register_frame_info_table_bases"
286 "(%p,%p, %p, %p)", fde, ob, tb, db);
287 // do nothing, this function never worked in Mac OS X
288}
289
290_LIBUNWIND_EXPORT void __register_frame_info_table(const void *fde, void *ob) {
291 (void)fde;
292 (void)ob;
293 _LIBUNWIND_TRACE_API("__register_frame_info_table(%p, %p)", fde, ob);
294 // do nothing, this function never worked in Mac OS X
295}
296
297_LIBUNWIND_EXPORT void __register_frame_table(const void *fde) {
298 (void)fde;
299 _LIBUNWIND_TRACE_API("__register_frame_table(%p)", fde);
300 // do nothing, this function never worked in Mac OS X
301}
302
303_LIBUNWIND_EXPORT void *__deregister_frame_info(const void *fde) {
304 (void)fde;
305 _LIBUNWIND_TRACE_API("__deregister_frame_info(%p)", fde);
306 // do nothing, this function never worked in Mac OS X
307 return NULL;
308}
309
310_LIBUNWIND_EXPORT void *__deregister_frame_info_bases(const void *fde) {
311 (void)fde;
312 _LIBUNWIND_TRACE_API("__deregister_frame_info_bases(%p)", fde);
313 // do nothing, this function never worked in Mac OS X
314 return NULL;
315}
316#endif // defined(_LIBUNWIND_SUPPORT_FRAME_APIS)
317
318#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
319
320#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
libunwind/src/UnwindLevel1.c created+509
...@@ -0,0 +1,509 @@
1//===------------------------- UnwindLevel1.c -----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Implements C++ ABI Exception Handling Level 1 as documented at:
10// http://mentorembedded.github.io/cxx-abi/abi-eh.html
11// using libunwind
12//
13//===----------------------------------------------------------------------===//
14
15// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are
16// defining inline functions to delegate the function calls to
17// _Unwind_VRS_{Get,Set}(). However, some applications might declare the
18// function protetype directly (instead of including <unwind.h>), thus we need
19// to export these functions from libunwind.so as well.
20#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1
21
22#include <inttypes.h>
23#include <stdint.h>
24#include <stdbool.h>
25#include <stdlib.h>
26#include <stdio.h>
27#include <string.h>
28
29#include "libunwind.h"
30#include "unwind.h"
31#include "config.h"
32
33#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)
34
35#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
36
37static _Unwind_Reason_Code
38unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
39 unw_init_local(cursor, uc);
40
41 // Walk each frame looking for a place to stop.
42 bool handlerNotFound = true;
43 while (handlerNotFound) {
44 // Ask libunwind to get next frame (skip over first which is
45 // _Unwind_RaiseException).
46 int stepResult = unw_step(cursor);
47 if (stepResult == 0) {
48 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
49 "bottom => _URC_END_OF_STACK",
50 (void *)exception_object);
51 return _URC_END_OF_STACK;
52 } else if (stepResult < 0) {
53 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => "
54 "_URC_FATAL_PHASE1_ERROR",
55 (void *)exception_object);
56 return _URC_FATAL_PHASE1_ERROR;
57 }
58
59 // See if frame has code to run (has personality routine).
60 unw_proc_info_t frameInfo;
61 unw_word_t sp;
62 if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
63 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
64 "failed => _URC_FATAL_PHASE1_ERROR",
65 (void *)exception_object);
66 return _URC_FATAL_PHASE1_ERROR;
67 }
68
69 // When tracing, print state information.
70 if (_LIBUNWIND_TRACING_UNWINDING) {
71 char functionBuf[512];
72 const char *functionName = functionBuf;
73 unw_word_t offset;
74 if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
75 &offset) != UNW_ESUCCESS) ||
76 (frameInfo.start_ip + offset > frameInfo.end_ip))
77 functionName = ".anonymous.";
78 unw_word_t pc;
79 unw_get_reg(cursor, UNW_REG_IP, &pc);
80 _LIBUNWIND_TRACE_UNWINDING(
81 "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR
82 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",
83 (void *)exception_object, pc, frameInfo.start_ip, functionName,
84 frameInfo.lsda, frameInfo.handler);
85 }
86
87 // If there is a personality routine, ask it if it will want to stop at
88 // this frame.
89 if (frameInfo.handler != 0) {
90 __personality_routine p =
91 (__personality_routine)(uintptr_t)(frameInfo.handler);
92 _LIBUNWIND_TRACE_UNWINDING(
93 "unwind_phase1(ex_ojb=%p): calling personality function %p",
94 (void *)exception_object, (void *)(uintptr_t)p);
95 _Unwind_Reason_Code personalityResult =
96 (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
97 exception_object, (struct _Unwind_Context *)(cursor));
98 switch (personalityResult) {
99 case _URC_HANDLER_FOUND:
100 // found a catch clause or locals that need destructing in this frame
101 // stop search and remember stack pointer at the frame
102 handlerNotFound = false;
103 unw_get_reg(cursor, UNW_REG_SP, &sp);
104 exception_object->private_2 = (uintptr_t)sp;
105 _LIBUNWIND_TRACE_UNWINDING(
106 "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND",
107 (void *)exception_object);
108 return _URC_NO_REASON;
109
110 case _URC_CONTINUE_UNWIND:
111 _LIBUNWIND_TRACE_UNWINDING(
112 "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND",
113 (void *)exception_object);
114 // continue unwinding
115 break;
116
117 default:
118 // something went wrong
119 _LIBUNWIND_TRACE_UNWINDING(
120 "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
121 (void *)exception_object);
122 return _URC_FATAL_PHASE1_ERROR;
123 }
124 }
125 }
126 return _URC_NO_REASON;
127}
128
129
130static _Unwind_Reason_Code
131unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
132 unw_init_local(cursor, uc);
133
134 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
135 (void *)exception_object);
136
137 // Walk each frame until we reach where search phase said to stop.
138 while (true) {
139
140 // Ask libunwind to get next frame (skip over first which is
141 // _Unwind_RaiseException).
142 int stepResult = unw_step(cursor);
143 if (stepResult == 0) {
144 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
145 "bottom => _URC_END_OF_STACK",
146 (void *)exception_object);
147 return _URC_END_OF_STACK;
148 } else if (stepResult < 0) {
149 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
150 "_URC_FATAL_PHASE1_ERROR",
151 (void *)exception_object);
152 return _URC_FATAL_PHASE2_ERROR;
153 }
154
155 // Get info about this frame.
156 unw_word_t sp;
157 unw_proc_info_t frameInfo;
158 unw_get_reg(cursor, UNW_REG_SP, &sp);
159 if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
160 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
161 "failed => _URC_FATAL_PHASE1_ERROR",
162 (void *)exception_object);
163 return _URC_FATAL_PHASE2_ERROR;
164 }
165
166 // When tracing, print state information.
167 if (_LIBUNWIND_TRACING_UNWINDING) {
168 char functionBuf[512];
169 const char *functionName = functionBuf;
170 unw_word_t offset;
171 if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
172 &offset) != UNW_ESUCCESS) ||
173 (frameInfo.start_ip + offset > frameInfo.end_ip))
174 functionName = ".anonymous.";
175 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR
176 ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR
177 ", personality=0x%" PRIxPTR,
178 (void *)exception_object, frameInfo.start_ip,
179 functionName, sp, frameInfo.lsda,
180 frameInfo.handler);
181 }
182
183 // If there is a personality routine, tell it we are unwinding.
184 if (frameInfo.handler != 0) {
185 __personality_routine p =
186 (__personality_routine)(uintptr_t)(frameInfo.handler);
187 _Unwind_Action action = _UA_CLEANUP_PHASE;
188 if (sp == exception_object->private_2) {
189 // Tell personality this was the frame it marked in phase 1.
190 action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
191 }
192 _Unwind_Reason_Code personalityResult =
193 (*p)(1, action, exception_object->exception_class, exception_object,
194 (struct _Unwind_Context *)(cursor));
195 switch (personalityResult) {
196 case _URC_CONTINUE_UNWIND:
197 // Continue unwinding
198 _LIBUNWIND_TRACE_UNWINDING(
199 "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
200 (void *)exception_object);
201 if (sp == exception_object->private_2) {
202 // Phase 1 said we would stop at this frame, but we did not...
203 _LIBUNWIND_ABORT("during phase1 personality function said it would "
204 "stop here, but now in phase2 it did not stop here");
205 }
206 break;
207 case _URC_INSTALL_CONTEXT:
208 _LIBUNWIND_TRACE_UNWINDING(
209 "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT",
210 (void *)exception_object);
211 // Personality routine says to transfer control to landing pad.
212 // We may get control back if landing pad calls _Unwind_Resume().
213 if (_LIBUNWIND_TRACING_UNWINDING) {
214 unw_word_t pc;
215 unw_get_reg(cursor, UNW_REG_IP, &pc);
216 unw_get_reg(cursor, UNW_REG_SP, &sp);
217 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
218 "user code with ip=0x%" PRIxPTR
219 ", sp=0x%" PRIxPTR,
220 (void *)exception_object, pc, sp);
221 }
222 unw_resume(cursor);
223 // unw_resume() only returns if there was an error.
224 return _URC_FATAL_PHASE2_ERROR;
225 default:
226 // Personality routine returned an unknown result code.
227 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
228 personalityResult);
229 return _URC_FATAL_PHASE2_ERROR;
230 }
231 }
232 }
233
234 // Clean up phase did not resume at the frame that the search phase
235 // said it would...
236 return _URC_FATAL_PHASE2_ERROR;
237}
238
239static _Unwind_Reason_Code
240unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
241 _Unwind_Exception *exception_object,
242 _Unwind_Stop_Fn stop, void *stop_parameter) {
243 unw_init_local(cursor, uc);
244
245 // Walk each frame until we reach where search phase said to stop
246 while (unw_step(cursor) > 0) {
247
248 // Update info about this frame.
249 unw_proc_info_t frameInfo;
250 if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
251 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
252 "failed => _URC_END_OF_STACK",
253 (void *)exception_object);
254 return _URC_FATAL_PHASE2_ERROR;
255 }
256
257 // When tracing, print state information.
258 if (_LIBUNWIND_TRACING_UNWINDING) {
259 char functionBuf[512];
260 const char *functionName = functionBuf;
261 unw_word_t offset;
262 if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
263 &offset) != UNW_ESUCCESS) ||
264 (frameInfo.start_ip + offset > frameInfo.end_ip))
265 functionName = ".anonymous.";
266 _LIBUNWIND_TRACE_UNWINDING(
267 "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR
268 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
269 (void *)exception_object, frameInfo.start_ip, functionName,
270 frameInfo.lsda, frameInfo.handler);
271 }
272
273 // Call stop function at each frame.
274 _Unwind_Action action =
275 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
276 _Unwind_Reason_Code stopResult =
277 (*stop)(1, action, exception_object->exception_class, exception_object,
278 (struct _Unwind_Context *)(cursor), stop_parameter);
279 _LIBUNWIND_TRACE_UNWINDING(
280 "unwind_phase2_forced(ex_ojb=%p): stop function returned %d",
281 (void *)exception_object, stopResult);
282 if (stopResult != _URC_NO_REASON) {
283 _LIBUNWIND_TRACE_UNWINDING(
284 "unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
285 (void *)exception_object);
286 return _URC_FATAL_PHASE2_ERROR;
287 }
288
289 // If there is a personality routine, tell it we are unwinding.
290 if (frameInfo.handler != 0) {
291 __personality_routine p =
292 (__personality_routine)(intptr_t)(frameInfo.handler);
293 _LIBUNWIND_TRACE_UNWINDING(
294 "unwind_phase2_forced(ex_ojb=%p): calling personality function %p",
295 (void *)exception_object, (void *)(uintptr_t)p);
296 _Unwind_Reason_Code personalityResult =
297 (*p)(1, action, exception_object->exception_class, exception_object,
298 (struct _Unwind_Context *)(cursor));
299 switch (personalityResult) {
300 case _URC_CONTINUE_UNWIND:
301 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
302 "personality returned "
303 "_URC_CONTINUE_UNWIND",
304 (void *)exception_object);
305 // Destructors called, continue unwinding
306 break;
307 case _URC_INSTALL_CONTEXT:
308 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
309 "personality returned "
310 "_URC_INSTALL_CONTEXT",
311 (void *)exception_object);
312 // We may get control back if landing pad calls _Unwind_Resume().
313 unw_resume(cursor);
314 break;
315 default:
316 // Personality routine returned an unknown result code.
317 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
318 "personality returned %d, "
319 "_URC_FATAL_PHASE2_ERROR",
320 (void *)exception_object, personalityResult);
321 return _URC_FATAL_PHASE2_ERROR;
322 }
323 }
324 }
325
326 // Call stop function one last time and tell it we've reached the end
327 // of the stack.
328 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
329 "function with _UA_END_OF_STACK",
330 (void *)exception_object);
331 _Unwind_Action lastAction =
332 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
333 (*stop)(1, lastAction, exception_object->exception_class, exception_object,
334 (struct _Unwind_Context *)(cursor), stop_parameter);
335
336 // Clean up phase did not resume at the frame that the search phase said it
337 // would.
338 return _URC_FATAL_PHASE2_ERROR;
339}
340
341
342/// Called by __cxa_throw. Only returns if there is a fatal error.
343_LIBUNWIND_EXPORT _Unwind_Reason_Code
344_Unwind_RaiseException(_Unwind_Exception *exception_object) {
345 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
346 (void *)exception_object);
347 unw_context_t uc;
348 unw_cursor_t cursor;
349 unw_getcontext(&uc);
350
351 // Mark that this is a non-forced unwind, so _Unwind_Resume()
352 // can do the right thing.
353 exception_object->private_1 = 0;
354 exception_object->private_2 = 0;
355
356 // phase 1: the search phase
357 _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
358 if (phase1 != _URC_NO_REASON)
359 return phase1;
360
361 // phase 2: the clean up phase
362 return unwind_phase2(&uc, &cursor, exception_object);
363}
364
365
366
367/// When _Unwind_RaiseException() is in phase2, it hands control
368/// to the personality function at each frame. The personality
369/// may force a jump to a landing pad in that function, the landing
370/// pad code may then call _Unwind_Resume() to continue with the
371/// unwinding. Note: the call to _Unwind_Resume() is from compiler
372/// geneated user code. All other _Unwind_* routines are called
373/// by the C++ runtime __cxa_* routines.
374///
375/// Note: re-throwing an exception (as opposed to continuing the unwind)
376/// is implemented by having the code call __cxa_rethrow() which
377/// in turn calls _Unwind_Resume_or_Rethrow().
378_LIBUNWIND_EXPORT void
379_Unwind_Resume(_Unwind_Exception *exception_object) {
380 _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);
381 unw_context_t uc;
382 unw_cursor_t cursor;
383 unw_getcontext(&uc);
384
385 if (exception_object->private_1 != 0)
386 unwind_phase2_forced(&uc, &cursor, exception_object,
387 (_Unwind_Stop_Fn) exception_object->private_1,
388 (void *)exception_object->private_2);
389 else
390 unwind_phase2(&uc, &cursor, exception_object);
391
392 // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
393 _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
394}
395
396
397
398/// Not used by C++.
399/// Unwinds stack, calling "stop" function at each frame.
400/// Could be used to implement longjmp().
401_LIBUNWIND_EXPORT _Unwind_Reason_Code
402_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
403 _Unwind_Stop_Fn stop, void *stop_parameter) {
404 _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
405 (void *)exception_object, (void *)(uintptr_t)stop);
406 unw_context_t uc;
407 unw_cursor_t cursor;
408 unw_getcontext(&uc);
409
410 // Mark that this is a forced unwind, so _Unwind_Resume() can do
411 // the right thing.
412 exception_object->private_1 = (uintptr_t) stop;
413 exception_object->private_2 = (uintptr_t) stop_parameter;
414
415 // do it
416 return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter);
417}
418
419
420/// Called by personality handler during phase 2 to get LSDA for current frame.
421_LIBUNWIND_EXPORT uintptr_t
422_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
423 unw_cursor_t *cursor = (unw_cursor_t *)context;
424 unw_proc_info_t frameInfo;
425 uintptr_t result = 0;
426 if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
427 result = (uintptr_t)frameInfo.lsda;
428 _LIBUNWIND_TRACE_API(
429 "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
430 (void *)context, result);
431 if (result != 0) {
432 if (*((uint8_t *)result) != 0xFF)
433 _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",
434 result);
435 }
436 return result;
437}
438
439
440/// Called by personality handler during phase 2 to find the start of the
441/// function.
442_LIBUNWIND_EXPORT uintptr_t
443_Unwind_GetRegionStart(struct _Unwind_Context *context) {
444 unw_cursor_t *cursor = (unw_cursor_t *)context;
445 unw_proc_info_t frameInfo;
446 uintptr_t result = 0;
447 if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
448 result = (uintptr_t)frameInfo.start_ip;
449 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,
450 (void *)context, result);
451 return result;
452}
453
454#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND
455
456/// Called by personality handler during phase 2 if a foreign exception
457// is caught.
458_LIBUNWIND_EXPORT void
459_Unwind_DeleteException(_Unwind_Exception *exception_object) {
460 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
461 (void *)exception_object);
462 if (exception_object->exception_cleanup != NULL)
463 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
464 exception_object);
465}
466
467/// Called by personality handler during phase 2 to get register values.
468_LIBUNWIND_EXPORT uintptr_t
469_Unwind_GetGR(struct _Unwind_Context *context, int index) {
470 unw_cursor_t *cursor = (unw_cursor_t *)context;
471 unw_word_t result;
472 unw_get_reg(cursor, index, &result);
473 _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIxPTR,
474 (void *)context, index, result);
475 return (uintptr_t)result;
476}
477
478/// Called by personality handler during phase 2 to alter register values.
479_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
480 uintptr_t value) {
481 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIxPTR
482 ")",
483 (void *)context, index, value);
484 unw_cursor_t *cursor = (unw_cursor_t *)context;
485 unw_set_reg(cursor, index, value);
486}
487
488/// Called by personality handler during phase 2 to get instruction pointer.
489_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
490 unw_cursor_t *cursor = (unw_cursor_t *)context;
491 unw_word_t result;
492 unw_get_reg(cursor, UNW_REG_IP, &result);
493 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
494 (void *)context, result);
495 return (uintptr_t)result;
496}
497
498/// Called by personality handler during phase 2 to alter instruction pointer,
499/// such as setting where the landing pad is, so _Unwind_Resume() will
500/// start executing in the landing pad.
501_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
502 uintptr_t value) {
503 _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIxPTR ")",
504 (void *)context, value);
505 unw_cursor_t *cursor = (unw_cursor_t *)context;
506 unw_set_reg(cursor, UNW_REG_IP, value);
507}
508
509#endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)
libunwind/src/UnwindRegistersRestore.S created+1030
...@@ -0,0 +1,1030 @@
1//===-------------------- UnwindRegistersRestore.S ------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "assembly.h"
11
12 .text
13
14#if !defined(__USING_SJLJ_EXCEPTIONS__)
15
16#if defined(__i386__)
17DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv)
18#
19# void libunwind::Registers_x86::jumpto()
20#
21#if defined(_WIN32)
22# On windows, the 'this' pointer is passed in ecx instead of on the stack
23 movl %ecx, %eax
24#else
25# On entry:
26# + +
27# +-----------------------+
28# + thread_state pointer +
29# +-----------------------+
30# + return address +
31# +-----------------------+ <-- SP
32# + +
33 movl 4(%esp), %eax
34#endif
35 # set up eax and ret on new stack location
36 movl 28(%eax), %edx # edx holds new stack pointer
37 subl $8,%edx
38 movl %edx, 28(%eax)
39 movl 0(%eax), %ebx
40 movl %ebx, 0(%edx)
41 movl 40(%eax), %ebx
42 movl %ebx, 4(%edx)
43 # we now have ret and eax pushed onto where new stack will be
44 # restore all registers
45 movl 4(%eax), %ebx
46 movl 8(%eax), %ecx
47 movl 12(%eax), %edx
48 movl 16(%eax), %edi
49 movl 20(%eax), %esi
50 movl 24(%eax), %ebp
51 movl 28(%eax), %esp
52 # skip ss
53 # skip eflags
54 pop %eax # eax was already pushed on new stack
55 ret # eip was already pushed on new stack
56 # skip cs
57 # skip ds
58 # skip es
59 # skip fs
60 # skip gs
61
62#elif defined(__x86_64__)
63
64DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv)
65#
66# void libunwind::Registers_x86_64::jumpto()
67#
68#if defined(_WIN64)
69# On entry, thread_state pointer is in rcx; move it into rdi
70# to share restore code below. Since this routine restores and
71# overwrites all registers, we can use the same registers for
72# pointers and temporaries as on unix even though win64 normally
73# mustn't clobber some of them.
74 movq %rcx, %rdi
75#else
76# On entry, thread_state pointer is in rdi
77#endif
78
79 movq 56(%rdi), %rax # rax holds new stack pointer
80 subq $16, %rax
81 movq %rax, 56(%rdi)
82 movq 32(%rdi), %rbx # store new rdi on new stack
83 movq %rbx, 0(%rax)
84 movq 128(%rdi), %rbx # store new rip on new stack
85 movq %rbx, 8(%rax)
86 # restore all registers
87 movq 0(%rdi), %rax
88 movq 8(%rdi), %rbx
89 movq 16(%rdi), %rcx
90 movq 24(%rdi), %rdx
91 # restore rdi later
92 movq 40(%rdi), %rsi
93 movq 48(%rdi), %rbp
94 # restore rsp later
95 movq 64(%rdi), %r8
96 movq 72(%rdi), %r9
97 movq 80(%rdi), %r10
98 movq 88(%rdi), %r11
99 movq 96(%rdi), %r12
100 movq 104(%rdi), %r13
101 movq 112(%rdi), %r14
102 movq 120(%rdi), %r15
103 # skip rflags
104 # skip cs
105 # skip fs
106 # skip gs
107
108#if defined(_WIN64)
109 movdqu 176(%rdi),%xmm0
110 movdqu 192(%rdi),%xmm1
111 movdqu 208(%rdi),%xmm2
112 movdqu 224(%rdi),%xmm3
113 movdqu 240(%rdi),%xmm4
114 movdqu 256(%rdi),%xmm5
115 movdqu 272(%rdi),%xmm6
116 movdqu 288(%rdi),%xmm7
117 movdqu 304(%rdi),%xmm8
118 movdqu 320(%rdi),%xmm9
119 movdqu 336(%rdi),%xmm10
120 movdqu 352(%rdi),%xmm11
121 movdqu 368(%rdi),%xmm12
122 movdqu 384(%rdi),%xmm13
123 movdqu 400(%rdi),%xmm14
124 movdqu 416(%rdi),%xmm15
125#endif
126 movq 56(%rdi), %rsp # cut back rsp to new location
127 pop %rdi # rdi was saved here earlier
128 ret # rip was saved here
129
130
131#elif defined(__powerpc64__)
132
133DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
134//
135// void libunwind::Registers_ppc64::jumpto()
136//
137// On entry:
138// thread_state pointer is in r3
139//
140
141// load register (GPR)
142#define PPC64_LR(n) \
143 ld %r##n, (8 * (n + 2))(%r3)
144
145 // restore integral registers
146 // skip r0 for now
147 // skip r1 for now
148 PPC64_LR(2)
149 // skip r3 for now
150 // skip r4 for now
151 // skip r5 for now
152 PPC64_LR(6)
153 PPC64_LR(7)
154 PPC64_LR(8)
155 PPC64_LR(9)
156 PPC64_LR(10)
157 PPC64_LR(11)
158 PPC64_LR(12)
159 PPC64_LR(13)
160 PPC64_LR(14)
161 PPC64_LR(15)
162 PPC64_LR(16)
163 PPC64_LR(17)
164 PPC64_LR(18)
165 PPC64_LR(19)
166 PPC64_LR(20)
167 PPC64_LR(21)
168 PPC64_LR(22)
169 PPC64_LR(23)
170 PPC64_LR(24)
171 PPC64_LR(25)
172 PPC64_LR(26)
173 PPC64_LR(27)
174 PPC64_LR(28)
175 PPC64_LR(29)
176 PPC64_LR(30)
177 PPC64_LR(31)
178
179#ifdef PPC64_HAS_VMX
180
181 // restore VS registers
182 // (note that this also restores floating point registers and V registers,
183 // because part of VS is mapped to these registers)
184
185 addi %r4, %r3, PPC64_OFFS_FP
186
187// load VS register
188#define PPC64_LVS(n) \
189 lxvd2x %vs##n, 0, %r4 ;\
190 addi %r4, %r4, 16
191
192 // restore the first 32 VS regs (and also all floating point regs)
193 PPC64_LVS(0)
194 PPC64_LVS(1)
195 PPC64_LVS(2)
196 PPC64_LVS(3)
197 PPC64_LVS(4)
198 PPC64_LVS(5)
199 PPC64_LVS(6)
200 PPC64_LVS(7)
201 PPC64_LVS(8)
202 PPC64_LVS(9)
203 PPC64_LVS(10)
204 PPC64_LVS(11)
205 PPC64_LVS(12)
206 PPC64_LVS(13)
207 PPC64_LVS(14)
208 PPC64_LVS(15)
209 PPC64_LVS(16)
210 PPC64_LVS(17)
211 PPC64_LVS(18)
212 PPC64_LVS(19)
213 PPC64_LVS(20)
214 PPC64_LVS(21)
215 PPC64_LVS(22)
216 PPC64_LVS(23)
217 PPC64_LVS(24)
218 PPC64_LVS(25)
219 PPC64_LVS(26)
220 PPC64_LVS(27)
221 PPC64_LVS(28)
222 PPC64_LVS(29)
223 PPC64_LVS(30)
224 PPC64_LVS(31)
225
226 // use VRSAVE to conditionally restore the remaining VS regs,
227 // that are where the V regs are mapped
228
229 ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave
230 cmpwi %r5, 0
231 beq Lnovec
232
233// conditionally load VS
234#define PPC64_CLVS_BOTTOM(n) \
235 beq Ldone##n ;\
236 addi %r4, %r3, PPC64_OFFS_FP + n * 16 ;\
237 lxvd2x %vs##n, 0, %r4 ;\
238Ldone##n:
239
240#define PPC64_CLVSl(n) \
241 andis. %r0, %r5, (1<<(47-n)) ;\
242PPC64_CLVS_BOTTOM(n)
243
244#define PPC64_CLVSh(n) \
245 andi. %r0, %r5, (1<<(63-n)) ;\
246PPC64_CLVS_BOTTOM(n)
247
248 PPC64_CLVSl(32)
249 PPC64_CLVSl(33)
250 PPC64_CLVSl(34)
251 PPC64_CLVSl(35)
252 PPC64_CLVSl(36)
253 PPC64_CLVSl(37)
254 PPC64_CLVSl(38)
255 PPC64_CLVSl(39)
256 PPC64_CLVSl(40)
257 PPC64_CLVSl(41)
258 PPC64_CLVSl(42)
259 PPC64_CLVSl(43)
260 PPC64_CLVSl(44)
261 PPC64_CLVSl(45)
262 PPC64_CLVSl(46)
263 PPC64_CLVSl(47)
264 PPC64_CLVSh(48)
265 PPC64_CLVSh(49)
266 PPC64_CLVSh(50)
267 PPC64_CLVSh(51)
268 PPC64_CLVSh(52)
269 PPC64_CLVSh(53)
270 PPC64_CLVSh(54)
271 PPC64_CLVSh(55)
272 PPC64_CLVSh(56)
273 PPC64_CLVSh(57)
274 PPC64_CLVSh(58)
275 PPC64_CLVSh(59)
276 PPC64_CLVSh(60)
277 PPC64_CLVSh(61)
278 PPC64_CLVSh(62)
279 PPC64_CLVSh(63)
280
281#else
282
283// load FP register
284#define PPC64_LF(n) \
285 lfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
286
287 // restore float registers
288 PPC64_LF(0)
289 PPC64_LF(1)
290 PPC64_LF(2)
291 PPC64_LF(3)
292 PPC64_LF(4)
293 PPC64_LF(5)
294 PPC64_LF(6)
295 PPC64_LF(7)
296 PPC64_LF(8)
297 PPC64_LF(9)
298 PPC64_LF(10)
299 PPC64_LF(11)
300 PPC64_LF(12)
301 PPC64_LF(13)
302 PPC64_LF(14)
303 PPC64_LF(15)
304 PPC64_LF(16)
305 PPC64_LF(17)
306 PPC64_LF(18)
307 PPC64_LF(19)
308 PPC64_LF(20)
309 PPC64_LF(21)
310 PPC64_LF(22)
311 PPC64_LF(23)
312 PPC64_LF(24)
313 PPC64_LF(25)
314 PPC64_LF(26)
315 PPC64_LF(27)
316 PPC64_LF(28)
317 PPC64_LF(29)
318 PPC64_LF(30)
319 PPC64_LF(31)
320
321 // restore vector registers if any are in use
322 ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave
323 cmpwi %r5, 0
324 beq Lnovec
325
326 subi %r4, %r1, 16
327 // r4 is now a 16-byte aligned pointer into the red zone
328 // the _vectorScalarRegisters may not be 16-byte aligned
329 // so copy via red zone temp buffer
330
331#define PPC64_CLV_UNALIGNED_BOTTOM(n) \
332 beq Ldone##n ;\
333 ld %r0, (PPC64_OFFS_V + n * 16)(%r3) ;\
334 std %r0, 0(%r4) ;\
335 ld %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3) ;\
336 std %r0, 8(%r4) ;\
337 lvx %v##n, 0, %r4 ;\
338Ldone ## n:
339
340#define PPC64_CLV_UNALIGNEDl(n) \
341 andis. %r0, %r5, (1<<(15-n)) ;\
342PPC64_CLV_UNALIGNED_BOTTOM(n)
343
344#define PPC64_CLV_UNALIGNEDh(n) \
345 andi. %r0, %r5, (1<<(31-n)) ;\
346PPC64_CLV_UNALIGNED_BOTTOM(n)
347
348 PPC64_CLV_UNALIGNEDl(0)
349 PPC64_CLV_UNALIGNEDl(1)
350 PPC64_CLV_UNALIGNEDl(2)
351 PPC64_CLV_UNALIGNEDl(3)
352 PPC64_CLV_UNALIGNEDl(4)
353 PPC64_CLV_UNALIGNEDl(5)
354 PPC64_CLV_UNALIGNEDl(6)
355 PPC64_CLV_UNALIGNEDl(7)
356 PPC64_CLV_UNALIGNEDl(8)
357 PPC64_CLV_UNALIGNEDl(9)
358 PPC64_CLV_UNALIGNEDl(10)
359 PPC64_CLV_UNALIGNEDl(11)
360 PPC64_CLV_UNALIGNEDl(12)
361 PPC64_CLV_UNALIGNEDl(13)
362 PPC64_CLV_UNALIGNEDl(14)
363 PPC64_CLV_UNALIGNEDl(15)
364 PPC64_CLV_UNALIGNEDh(16)
365 PPC64_CLV_UNALIGNEDh(17)
366 PPC64_CLV_UNALIGNEDh(18)
367 PPC64_CLV_UNALIGNEDh(19)
368 PPC64_CLV_UNALIGNEDh(20)
369 PPC64_CLV_UNALIGNEDh(21)
370 PPC64_CLV_UNALIGNEDh(22)
371 PPC64_CLV_UNALIGNEDh(23)
372 PPC64_CLV_UNALIGNEDh(24)
373 PPC64_CLV_UNALIGNEDh(25)
374 PPC64_CLV_UNALIGNEDh(26)
375 PPC64_CLV_UNALIGNEDh(27)
376 PPC64_CLV_UNALIGNEDh(28)
377 PPC64_CLV_UNALIGNEDh(29)
378 PPC64_CLV_UNALIGNEDh(30)
379 PPC64_CLV_UNALIGNEDh(31)
380
381#endif
382
383Lnovec:
384 ld %r0, PPC64_OFFS_CR(%r3)
385 mtcr %r0
386 ld %r0, PPC64_OFFS_SRR0(%r3)
387 mtctr %r0
388
389 PPC64_LR(0)
390 PPC64_LR(5)
391 PPC64_LR(4)
392 PPC64_LR(1)
393 PPC64_LR(3)
394 bctr
395
396#elif defined(__ppc__)
397
398DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
399;
400; void libunwind::Registers_ppc::jumpto()
401;
402; On entry:
403; thread_state pointer is in r3
404;
405
406 ; restore integral registerrs
407 ; skip r0 for now
408 ; skip r1 for now
409 lwz r2, 16(r3)
410 ; skip r3 for now
411 ; skip r4 for now
412 ; skip r5 for now
413 lwz r6, 32(r3)
414 lwz r7, 36(r3)
415 lwz r8, 40(r3)
416 lwz r9, 44(r3)
417 lwz r10, 48(r3)
418 lwz r11, 52(r3)
419 lwz r12, 56(r3)
420 lwz r13, 60(r3)
421 lwz r14, 64(r3)
422 lwz r15, 68(r3)
423 lwz r16, 72(r3)
424 lwz r17, 76(r3)
425 lwz r18, 80(r3)
426 lwz r19, 84(r3)
427 lwz r20, 88(r3)
428 lwz r21, 92(r3)
429 lwz r22, 96(r3)
430 lwz r23,100(r3)
431 lwz r24,104(r3)
432 lwz r25,108(r3)
433 lwz r26,112(r3)
434 lwz r27,116(r3)
435 lwz r28,120(r3)
436 lwz r29,124(r3)
437 lwz r30,128(r3)
438 lwz r31,132(r3)
439
440 ; restore float registers
441 lfd f0, 160(r3)
442 lfd f1, 168(r3)
443 lfd f2, 176(r3)
444 lfd f3, 184(r3)
445 lfd f4, 192(r3)
446 lfd f5, 200(r3)
447 lfd f6, 208(r3)
448 lfd f7, 216(r3)
449 lfd f8, 224(r3)
450 lfd f9, 232(r3)
451 lfd f10,240(r3)
452 lfd f11,248(r3)
453 lfd f12,256(r3)
454 lfd f13,264(r3)
455 lfd f14,272(r3)
456 lfd f15,280(r3)
457 lfd f16,288(r3)
458 lfd f17,296(r3)
459 lfd f18,304(r3)
460 lfd f19,312(r3)
461 lfd f20,320(r3)
462 lfd f21,328(r3)
463 lfd f22,336(r3)
464 lfd f23,344(r3)
465 lfd f24,352(r3)
466 lfd f25,360(r3)
467 lfd f26,368(r3)
468 lfd f27,376(r3)
469 lfd f28,384(r3)
470 lfd f29,392(r3)
471 lfd f30,400(r3)
472 lfd f31,408(r3)
473
474 ; restore vector registers if any are in use
475 lwz r5,156(r3) ; test VRsave
476 cmpwi r5,0
477 beq Lnovec
478
479 subi r4,r1,16
480 rlwinm r4,r4,0,0,27 ; mask low 4-bits
481 ; r4 is now a 16-byte aligned pointer into the red zone
482 ; the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer
483
484
485#define LOAD_VECTOR_UNALIGNEDl(_index) \
486 andis. r0,r5,(1<<(15-_index)) @\
487 beq Ldone ## _index @\
488 lwz r0, 424+_index*16(r3) @\
489 stw r0, 0(r4) @\
490 lwz r0, 424+_index*16+4(r3) @\
491 stw r0, 4(r4) @\
492 lwz r0, 424+_index*16+8(r3) @\
493 stw r0, 8(r4) @\
494 lwz r0, 424+_index*16+12(r3)@\
495 stw r0, 12(r4) @\
496 lvx v ## _index,0,r4 @\
497Ldone ## _index:
498
499#define LOAD_VECTOR_UNALIGNEDh(_index) \
500 andi. r0,r5,(1<<(31-_index)) @\
501 beq Ldone ## _index @\
502 lwz r0, 424+_index*16(r3) @\
503 stw r0, 0(r4) @\
504 lwz r0, 424+_index*16+4(r3) @\
505 stw r0, 4(r4) @\
506 lwz r0, 424+_index*16+8(r3) @\
507 stw r0, 8(r4) @\
508 lwz r0, 424+_index*16+12(r3)@\
509 stw r0, 12(r4) @\
510 lvx v ## _index,0,r4 @\
511 Ldone ## _index:
512
513
514 LOAD_VECTOR_UNALIGNEDl(0)
515 LOAD_VECTOR_UNALIGNEDl(1)
516 LOAD_VECTOR_UNALIGNEDl(2)
517 LOAD_VECTOR_UNALIGNEDl(3)
518 LOAD_VECTOR_UNALIGNEDl(4)
519 LOAD_VECTOR_UNALIGNEDl(5)
520 LOAD_VECTOR_UNALIGNEDl(6)
521 LOAD_VECTOR_UNALIGNEDl(7)
522 LOAD_VECTOR_UNALIGNEDl(8)
523 LOAD_VECTOR_UNALIGNEDl(9)
524 LOAD_VECTOR_UNALIGNEDl(10)
525 LOAD_VECTOR_UNALIGNEDl(11)
526 LOAD_VECTOR_UNALIGNEDl(12)
527 LOAD_VECTOR_UNALIGNEDl(13)
528 LOAD_VECTOR_UNALIGNEDl(14)
529 LOAD_VECTOR_UNALIGNEDl(15)
530 LOAD_VECTOR_UNALIGNEDh(16)
531 LOAD_VECTOR_UNALIGNEDh(17)
532 LOAD_VECTOR_UNALIGNEDh(18)
533 LOAD_VECTOR_UNALIGNEDh(19)
534 LOAD_VECTOR_UNALIGNEDh(20)
535 LOAD_VECTOR_UNALIGNEDh(21)
536 LOAD_VECTOR_UNALIGNEDh(22)
537 LOAD_VECTOR_UNALIGNEDh(23)
538 LOAD_VECTOR_UNALIGNEDh(24)
539 LOAD_VECTOR_UNALIGNEDh(25)
540 LOAD_VECTOR_UNALIGNEDh(26)
541 LOAD_VECTOR_UNALIGNEDh(27)
542 LOAD_VECTOR_UNALIGNEDh(28)
543 LOAD_VECTOR_UNALIGNEDh(29)
544 LOAD_VECTOR_UNALIGNEDh(30)
545 LOAD_VECTOR_UNALIGNEDh(31)
546
547Lnovec:
548 lwz r0, 136(r3) ; __cr
549 mtocrf 255,r0
550 lwz r0, 148(r3) ; __ctr
551 mtctr r0
552 lwz r0, 0(r3) ; __ssr0
553 mtctr r0
554 lwz r0, 8(r3) ; do r0 now
555 lwz r5,28(r3) ; do r5 now
556 lwz r4,24(r3) ; do r4 now
557 lwz r1,12(r3) ; do sp now
558 lwz r3,20(r3) ; do r3 last
559 bctr
560
561#elif defined(__arm64__) || defined(__aarch64__)
562
563//
564// void libunwind::Registers_arm64::jumpto()
565//
566// On entry:
567// thread_state pointer is in x0
568//
569 .p2align 2
570DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv)
571 // skip restore of x0,x1 for now
572 ldp x2, x3, [x0, #0x010]
573 ldp x4, x5, [x0, #0x020]
574 ldp x6, x7, [x0, #0x030]
575 ldp x8, x9, [x0, #0x040]
576 ldp x10,x11, [x0, #0x050]
577 ldp x12,x13, [x0, #0x060]
578 ldp x14,x15, [x0, #0x070]
579 ldp x16,x17, [x0, #0x080]
580 ldp x18,x19, [x0, #0x090]
581 ldp x20,x21, [x0, #0x0A0]
582 ldp x22,x23, [x0, #0x0B0]
583 ldp x24,x25, [x0, #0x0C0]
584 ldp x26,x27, [x0, #0x0D0]
585 ldp x28,x29, [x0, #0x0E0]
586 ldr x30, [x0, #0x100] // restore pc into lr
587 ldr x1, [x0, #0x0F8]
588 mov sp,x1 // restore sp
589
590 ldp d0, d1, [x0, #0x110]
591 ldp d2, d3, [x0, #0x120]
592 ldp d4, d5, [x0, #0x130]
593 ldp d6, d7, [x0, #0x140]
594 ldp d8, d9, [x0, #0x150]
595 ldp d10,d11, [x0, #0x160]
596 ldp d12,d13, [x0, #0x170]
597 ldp d14,d15, [x0, #0x180]
598 ldp d16,d17, [x0, #0x190]
599 ldp d18,d19, [x0, #0x1A0]
600 ldp d20,d21, [x0, #0x1B0]
601 ldp d22,d23, [x0, #0x1C0]
602 ldp d24,d25, [x0, #0x1D0]
603 ldp d26,d27, [x0, #0x1E0]
604 ldp d28,d29, [x0, #0x1F0]
605 ldr d30, [x0, #0x200]
606 ldr d31, [x0, #0x208]
607
608 ldp x0, x1, [x0, #0x000] // restore x0,x1
609 ret x30 // jump to pc
610
611#elif defined(__arm__) && !defined(__APPLE__)
612
613#if !defined(__ARM_ARCH_ISA_ARM)
614 .thumb
615#endif
616
617@
618@ void libunwind::Registers_arm::restoreCoreAndJumpTo()
619@
620@ On entry:
621@ thread_state pointer is in r0
622@
623 .p2align 2
624DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv)
625#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
626 @ r8-r11: ldm into r1-r4, then mov to r8-r11
627 adds r0, #0x20
628 ldm r0!, {r1-r4}
629 subs r0, #0x30
630 mov r8, r1
631 mov r9, r2
632 mov r10, r3
633 mov r11, r4
634 @ r12 does not need loading, it it the intra-procedure-call scratch register
635 ldr r2, [r0, #0x34]
636 ldr r3, [r0, #0x3c]
637 mov sp, r2
638 mov lr, r3 @ restore pc into lr
639 ldm r0, {r0-r7}
640#else
641 @ Use lr as base so that r0 can be restored.
642 mov lr, r0
643 @ 32bit thumb-2 restrictions for ldm:
644 @ . the sp (r13) cannot be in the list
645 @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction
646 ldm lr, {r0-r12}
647 ldr sp, [lr, #52]
648 ldr lr, [lr, #60] @ restore pc into lr
649#endif
650 JMP(lr)
651
652@
653@ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values)
654@
655@ On entry:
656@ values pointer is in r0
657@
658 .p2align 2
659#if defined(__ELF__)
660 .fpu vfpv3-d16
661#endif
662DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPy)
663 @ VFP and iwMMX instructions are only available when compiling with the flags
664 @ that enable them. We do not want to do that in the library (because we do not
665 @ want the compiler to generate instructions that access those) but this is
666 @ only accessed if the personality routine needs these registers. Use of
667 @ these registers implies they are, actually, available on the target, so
668 @ it's ok to execute.
669 @ So, generate the instruction using the corresponding coprocessor mnemonic.
670 vldmia r0, {d0-d15}
671 JMP(lr)
672
673@
674@ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values)
675@
676@ On entry:
677@ values pointer is in r0
678@
679 .p2align 2
680#if defined(__ELF__)
681 .fpu vfpv3-d16
682#endif
683DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPy)
684 vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia
685 JMP(lr)
686
687@
688@ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values)
689@
690@ On entry:
691@ values pointer is in r0
692@
693 .p2align 2
694#if defined(__ELF__)
695 .fpu vfpv3
696#endif
697DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPy)
698 vldmia r0, {d16-d31}
699 JMP(lr)
700
701#if defined(__ARM_WMMX)
702
703@
704@ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values)
705@
706@ On entry:
707@ values pointer is in r0
708@
709 .p2align 2
710#if defined(__ELF__)
711 .arch armv5te
712#endif
713DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPy)
714 ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8
715 ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8
716 ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8
717 ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8
718 ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8
719 ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8
720 ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8
721 ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8
722 ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8
723 ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8
724 ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8
725 ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8
726 ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8
727 ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8
728 ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8
729 ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8
730 JMP(lr)
731
732@
733@ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values)
734@
735@ On entry:
736@ values pointer is in r0
737@
738 .p2align 2
739#if defined(__ELF__)
740 .arch armv5te
741#endif
742DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj)
743 ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4
744 ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4
745 ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4
746 ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4
747 JMP(lr)
748
749#endif
750
751#elif defined(__or1k__)
752
753DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
754#
755# void libunwind::Registers_or1k::jumpto()
756#
757# On entry:
758# thread_state pointer is in r3
759#
760
761 # restore integral registers
762 l.lwz r0, 0(r3)
763 l.lwz r1, 4(r3)
764 l.lwz r2, 8(r3)
765 # skip r3 for now
766 l.lwz r4, 16(r3)
767 l.lwz r5, 20(r3)
768 l.lwz r6, 24(r3)
769 l.lwz r7, 28(r3)
770 l.lwz r8, 32(r3)
771 # skip r9
772 l.lwz r10, 40(r3)
773 l.lwz r11, 44(r3)
774 l.lwz r12, 48(r3)
775 l.lwz r13, 52(r3)
776 l.lwz r14, 56(r3)
777 l.lwz r15, 60(r3)
778 l.lwz r16, 64(r3)
779 l.lwz r17, 68(r3)
780 l.lwz r18, 72(r3)
781 l.lwz r19, 76(r3)
782 l.lwz r20, 80(r3)
783 l.lwz r21, 84(r3)
784 l.lwz r22, 88(r3)
785 l.lwz r23, 92(r3)
786 l.lwz r24, 96(r3)
787 l.lwz r25,100(r3)
788 l.lwz r26,104(r3)
789 l.lwz r27,108(r3)
790 l.lwz r28,112(r3)
791 l.lwz r29,116(r3)
792 l.lwz r30,120(r3)
793 l.lwz r31,124(r3)
794
795 # at last, restore r3
796 l.lwz r3, 12(r3)
797
798 # load new pc into ra
799 l.lwz r9, 128(r3)
800 # jump to pc
801 l.jr r9
802 l.nop
803
804#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
805
806//
807// void libunwind::Registers_mips_o32::jumpto()
808//
809// On entry:
810// thread state pointer is in a0 ($4)
811//
812DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
813 .set push
814 .set noat
815 .set noreorder
816 .set nomacro
817#ifdef __mips_hard_float
818#if __mips_fpr != 64
819 ldc1 $f0, (4 * 36 + 8 * 0)($4)
820 ldc1 $f2, (4 * 36 + 8 * 2)($4)
821 ldc1 $f4, (4 * 36 + 8 * 4)($4)
822 ldc1 $f6, (4 * 36 + 8 * 6)($4)
823 ldc1 $f8, (4 * 36 + 8 * 8)($4)
824 ldc1 $f10, (4 * 36 + 8 * 10)($4)
825 ldc1 $f12, (4 * 36 + 8 * 12)($4)
826 ldc1 $f14, (4 * 36 + 8 * 14)($4)
827 ldc1 $f16, (4 * 36 + 8 * 16)($4)
828 ldc1 $f18, (4 * 36 + 8 * 18)($4)
829 ldc1 $f20, (4 * 36 + 8 * 20)($4)
830 ldc1 $f22, (4 * 36 + 8 * 22)($4)
831 ldc1 $f24, (4 * 36 + 8 * 24)($4)
832 ldc1 $f26, (4 * 36 + 8 * 26)($4)
833 ldc1 $f28, (4 * 36 + 8 * 28)($4)
834 ldc1 $f30, (4 * 36 + 8 * 30)($4)
835#else
836 ldc1 $f0, (4 * 36 + 8 * 0)($4)
837 ldc1 $f1, (4 * 36 + 8 * 1)($4)
838 ldc1 $f2, (4 * 36 + 8 * 2)($4)
839 ldc1 $f3, (4 * 36 + 8 * 3)($4)
840 ldc1 $f4, (4 * 36 + 8 * 4)($4)
841 ldc1 $f5, (4 * 36 + 8 * 5)($4)
842 ldc1 $f6, (4 * 36 + 8 * 6)($4)
843 ldc1 $f7, (4 * 36 + 8 * 7)($4)
844 ldc1 $f8, (4 * 36 + 8 * 8)($4)
845 ldc1 $f9, (4 * 36 + 8 * 9)($4)
846 ldc1 $f10, (4 * 36 + 8 * 10)($4)
847 ldc1 $f11, (4 * 36 + 8 * 11)($4)
848 ldc1 $f12, (4 * 36 + 8 * 12)($4)
849 ldc1 $f13, (4 * 36 + 8 * 13)($4)
850 ldc1 $f14, (4 * 36 + 8 * 14)($4)
851 ldc1 $f15, (4 * 36 + 8 * 15)($4)
852 ldc1 $f16, (4 * 36 + 8 * 16)($4)
853 ldc1 $f17, (4 * 36 + 8 * 17)($4)
854 ldc1 $f18, (4 * 36 + 8 * 18)($4)
855 ldc1 $f19, (4 * 36 + 8 * 19)($4)
856 ldc1 $f20, (4 * 36 + 8 * 20)($4)
857 ldc1 $f21, (4 * 36 + 8 * 21)($4)
858 ldc1 $f22, (4 * 36 + 8 * 22)($4)
859 ldc1 $f23, (4 * 36 + 8 * 23)($4)
860 ldc1 $f24, (4 * 36 + 8 * 24)($4)
861 ldc1 $f25, (4 * 36 + 8 * 25)($4)
862 ldc1 $f26, (4 * 36 + 8 * 26)($4)
863 ldc1 $f27, (4 * 36 + 8 * 27)($4)
864 ldc1 $f28, (4 * 36 + 8 * 28)($4)
865 ldc1 $f29, (4 * 36 + 8 * 29)($4)
866 ldc1 $f30, (4 * 36 + 8 * 30)($4)
867 ldc1 $f31, (4 * 36 + 8 * 31)($4)
868#endif
869#endif
870 // restore hi and lo
871 lw $8, (4 * 33)($4)
872 mthi $8
873 lw $8, (4 * 34)($4)
874 mtlo $8
875 // r0 is zero
876 lw $1, (4 * 1)($4)
877 lw $2, (4 * 2)($4)
878 lw $3, (4 * 3)($4)
879 // skip a0 for now
880 lw $5, (4 * 5)($4)
881 lw $6, (4 * 6)($4)
882 lw $7, (4 * 7)($4)
883 lw $8, (4 * 8)($4)
884 lw $9, (4 * 9)($4)
885 lw $10, (4 * 10)($4)
886 lw $11, (4 * 11)($4)
887 lw $12, (4 * 12)($4)
888 lw $13, (4 * 13)($4)
889 lw $14, (4 * 14)($4)
890 lw $15, (4 * 15)($4)
891 lw $16, (4 * 16)($4)
892 lw $17, (4 * 17)($4)
893 lw $18, (4 * 18)($4)
894 lw $19, (4 * 19)($4)
895 lw $20, (4 * 20)($4)
896 lw $21, (4 * 21)($4)
897 lw $22, (4 * 22)($4)
898 lw $23, (4 * 23)($4)
899 lw $24, (4 * 24)($4)
900 lw $25, (4 * 25)($4)
901 lw $26, (4 * 26)($4)
902 lw $27, (4 * 27)($4)
903 lw $28, (4 * 28)($4)
904 lw $29, (4 * 29)($4)
905 lw $30, (4 * 30)($4)
906 // load new pc into ra
907 lw $31, (4 * 32)($4)
908 // jump to ra, load a0 in the delay slot
909 jr $31
910 lw $4, (4 * 4)($4)
911 .set pop
912
913#elif defined(__mips64)
914
915//
916// void libunwind::Registers_mips_newabi::jumpto()
917//
918// On entry:
919// thread state pointer is in a0 ($4)
920//
921DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
922 .set push
923 .set noat
924 .set noreorder
925 .set nomacro
926#ifdef __mips_hard_float
927 ldc1 $f0, (8 * 35)($4)
928 ldc1 $f1, (8 * 36)($4)
929 ldc1 $f2, (8 * 37)($4)
930 ldc1 $f3, (8 * 38)($4)
931 ldc1 $f4, (8 * 39)($4)
932 ldc1 $f5, (8 * 40)($4)
933 ldc1 $f6, (8 * 41)($4)
934 ldc1 $f7, (8 * 42)($4)
935 ldc1 $f8, (8 * 43)($4)
936 ldc1 $f9, (8 * 44)($4)
937 ldc1 $f10, (8 * 45)($4)
938 ldc1 $f11, (8 * 46)($4)
939 ldc1 $f12, (8 * 47)($4)
940 ldc1 $f13, (8 * 48)($4)
941 ldc1 $f14, (8 * 49)($4)
942 ldc1 $f15, (8 * 50)($4)
943 ldc1 $f16, (8 * 51)($4)
944 ldc1 $f17, (8 * 52)($4)
945 ldc1 $f18, (8 * 53)($4)
946 ldc1 $f19, (8 * 54)($4)
947 ldc1 $f20, (8 * 55)($4)
948 ldc1 $f21, (8 * 56)($4)
949 ldc1 $f22, (8 * 57)($4)
950 ldc1 $f23, (8 * 58)($4)
951 ldc1 $f24, (8 * 59)($4)
952 ldc1 $f25, (8 * 60)($4)
953 ldc1 $f26, (8 * 61)($4)
954 ldc1 $f27, (8 * 62)($4)
955 ldc1 $f28, (8 * 63)($4)
956 ldc1 $f29, (8 * 64)($4)
957 ldc1 $f30, (8 * 65)($4)
958 ldc1 $f31, (8 * 66)($4)
959#endif
960 // restore hi and lo
961 ld $8, (8 * 33)($4)
962 mthi $8
963 ld $8, (8 * 34)($4)
964 mtlo $8
965 // r0 is zero
966 ld $1, (8 * 1)($4)
967 ld $2, (8 * 2)($4)
968 ld $3, (8 * 3)($4)
969 // skip a0 for now
970 ld $5, (8 * 5)($4)
971 ld $6, (8 * 6)($4)
972 ld $7, (8 * 7)($4)
973 ld $8, (8 * 8)($4)
974 ld $9, (8 * 9)($4)
975 ld $10, (8 * 10)($4)
976 ld $11, (8 * 11)($4)
977 ld $12, (8 * 12)($4)
978 ld $13, (8 * 13)($4)
979 ld $14, (8 * 14)($4)
980 ld $15, (8 * 15)($4)
981 ld $16, (8 * 16)($4)
982 ld $17, (8 * 17)($4)
983 ld $18, (8 * 18)($4)
984 ld $19, (8 * 19)($4)
985 ld $20, (8 * 20)($4)
986 ld $21, (8 * 21)($4)
987 ld $22, (8 * 22)($4)
988 ld $23, (8 * 23)($4)
989 ld $24, (8 * 24)($4)
990 ld $25, (8 * 25)($4)
991 ld $26, (8 * 26)($4)
992 ld $27, (8 * 27)($4)
993 ld $28, (8 * 28)($4)
994 ld $29, (8 * 29)($4)
995 ld $30, (8 * 30)($4)
996 // load new pc into ra
997 ld $31, (8 * 32)($4)
998 // jump to ra, load a0 in the delay slot
999 jr $31
1000 ld $4, (8 * 4)($4)
1001 .set pop
1002
1003#elif defined(__sparc__)
1004
1005//
1006// void libunwind::Registers_sparc_o32::jumpto()
1007//
1008// On entry:
1009// thread_state pointer is in o0
1010//
1011DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv)
1012 ta 3
1013 ldd [%o0 + 64], %l0
1014 ldd [%o0 + 72], %l2
1015 ldd [%o0 + 80], %l4
1016 ldd [%o0 + 88], %l6
1017 ldd [%o0 + 96], %i0
1018 ldd [%o0 + 104], %i2
1019 ldd [%o0 + 112], %i4
1020 ldd [%o0 + 120], %i6
1021 ld [%o0 + 60], %o7
1022 jmp %o7
1023 nop
1024
1025#endif
1026
1027#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
1028
1029NO_EXEC_STACK_DIRECTIVE
1030
libunwind/src/UnwindRegistersSave.S created+978
...@@ -0,0 +1,978 @@
1//===------------------------ UnwindRegistersSave.S -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "assembly.h"
11
12 .text
13
14#if !defined(__USING_SJLJ_EXCEPTIONS__)
15
16#if defined(__i386__)
17
18#
19# extern int unw_getcontext(unw_context_t* thread_state)
20#
21# On entry:
22# + +
23# +-----------------------+
24# + thread_state pointer +
25# +-----------------------+
26# + return address +
27# +-----------------------+ <-- SP
28# + +
29#
30DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
31 push %eax
32 movl 8(%esp), %eax
33 movl %ebx, 4(%eax)
34 movl %ecx, 8(%eax)
35 movl %edx, 12(%eax)
36 movl %edi, 16(%eax)
37 movl %esi, 20(%eax)
38 movl %ebp, 24(%eax)
39 movl %esp, %edx
40 addl $8, %edx
41 movl %edx, 28(%eax) # store what sp was at call site as esp
42 # skip ss
43 # skip eflags
44 movl 4(%esp), %edx
45 movl %edx, 40(%eax) # store return address as eip
46 # skip cs
47 # skip ds
48 # skip es
49 # skip fs
50 # skip gs
51 movl (%esp), %edx
52 movl %edx, (%eax) # store original eax
53 popl %eax
54 xorl %eax, %eax # return UNW_ESUCCESS
55 ret
56
57#elif defined(__x86_64__)
58
59#
60# extern int unw_getcontext(unw_context_t* thread_state)
61#
62# On entry:
63# thread_state pointer is in rdi
64#
65DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
66#if defined(_WIN64)
67#define PTR %rcx
68#define TMP %rdx
69#else
70#define PTR %rdi
71#define TMP %rsi
72#endif
73
74 movq %rax, (PTR)
75 movq %rbx, 8(PTR)
76 movq %rcx, 16(PTR)
77 movq %rdx, 24(PTR)
78 movq %rdi, 32(PTR)
79 movq %rsi, 40(PTR)
80 movq %rbp, 48(PTR)
81 movq %rsp, 56(PTR)
82 addq $8, 56(PTR)
83 movq %r8, 64(PTR)
84 movq %r9, 72(PTR)
85 movq %r10, 80(PTR)
86 movq %r11, 88(PTR)
87 movq %r12, 96(PTR)
88 movq %r13,104(PTR)
89 movq %r14,112(PTR)
90 movq %r15,120(PTR)
91 movq (%rsp),TMP
92 movq TMP,128(PTR) # store return address as rip
93 # skip rflags
94 # skip cs
95 # skip fs
96 # skip gs
97
98#if defined(_WIN64)
99 movdqu %xmm0,176(PTR)
100 movdqu %xmm1,192(PTR)
101 movdqu %xmm2,208(PTR)
102 movdqu %xmm3,224(PTR)
103 movdqu %xmm4,240(PTR)
104 movdqu %xmm5,256(PTR)
105 movdqu %xmm6,272(PTR)
106 movdqu %xmm7,288(PTR)
107 movdqu %xmm8,304(PTR)
108 movdqu %xmm9,320(PTR)
109 movdqu %xmm10,336(PTR)
110 movdqu %xmm11,352(PTR)
111 movdqu %xmm12,368(PTR)
112 movdqu %xmm13,384(PTR)
113 movdqu %xmm14,400(PTR)
114 movdqu %xmm15,416(PTR)
115#endif
116 xorl %eax, %eax # return UNW_ESUCCESS
117 ret
118
119#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
120
121#
122# extern int unw_getcontext(unw_context_t* thread_state)
123#
124# On entry:
125# thread_state pointer is in a0 ($4)
126#
127DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
128 .set push
129 .set noat
130 .set noreorder
131 .set nomacro
132 sw $1, (4 * 1)($4)
133 sw $2, (4 * 2)($4)
134 sw $3, (4 * 3)($4)
135 sw $4, (4 * 4)($4)
136 sw $5, (4 * 5)($4)
137 sw $6, (4 * 6)($4)
138 sw $7, (4 * 7)($4)
139 sw $8, (4 * 8)($4)
140 sw $9, (4 * 9)($4)
141 sw $10, (4 * 10)($4)
142 sw $11, (4 * 11)($4)
143 sw $12, (4 * 12)($4)
144 sw $13, (4 * 13)($4)
145 sw $14, (4 * 14)($4)
146 sw $15, (4 * 15)($4)
147 sw $16, (4 * 16)($4)
148 sw $17, (4 * 17)($4)
149 sw $18, (4 * 18)($4)
150 sw $19, (4 * 19)($4)
151 sw $20, (4 * 20)($4)
152 sw $21, (4 * 21)($4)
153 sw $22, (4 * 22)($4)
154 sw $23, (4 * 23)($4)
155 sw $24, (4 * 24)($4)
156 sw $25, (4 * 25)($4)
157 sw $26, (4 * 26)($4)
158 sw $27, (4 * 27)($4)
159 sw $28, (4 * 28)($4)
160 sw $29, (4 * 29)($4)
161 sw $30, (4 * 30)($4)
162 sw $31, (4 * 31)($4)
163 # Store return address to pc
164 sw $31, (4 * 32)($4)
165 # hi and lo
166 mfhi $8
167 sw $8, (4 * 33)($4)
168 mflo $8
169 sw $8, (4 * 34)($4)
170#ifdef __mips_hard_float
171#if __mips_fpr != 64
172 sdc1 $f0, (4 * 36 + 8 * 0)($4)
173 sdc1 $f2, (4 * 36 + 8 * 2)($4)
174 sdc1 $f4, (4 * 36 + 8 * 4)($4)
175 sdc1 $f6, (4 * 36 + 8 * 6)($4)
176 sdc1 $f8, (4 * 36 + 8 * 8)($4)
177 sdc1 $f10, (4 * 36 + 8 * 10)($4)
178 sdc1 $f12, (4 * 36 + 8 * 12)($4)
179 sdc1 $f14, (4 * 36 + 8 * 14)($4)
180 sdc1 $f16, (4 * 36 + 8 * 16)($4)
181 sdc1 $f18, (4 * 36 + 8 * 18)($4)
182 sdc1 $f20, (4 * 36 + 8 * 20)($4)
183 sdc1 $f22, (4 * 36 + 8 * 22)($4)
184 sdc1 $f24, (4 * 36 + 8 * 24)($4)
185 sdc1 $f26, (4 * 36 + 8 * 26)($4)
186 sdc1 $f28, (4 * 36 + 8 * 28)($4)
187 sdc1 $f30, (4 * 36 + 8 * 30)($4)
188#else
189 sdc1 $f0, (4 * 36 + 8 * 0)($4)
190 sdc1 $f1, (4 * 36 + 8 * 1)($4)
191 sdc1 $f2, (4 * 36 + 8 * 2)($4)
192 sdc1 $f3, (4 * 36 + 8 * 3)($4)
193 sdc1 $f4, (4 * 36 + 8 * 4)($4)
194 sdc1 $f5, (4 * 36 + 8 * 5)($4)
195 sdc1 $f6, (4 * 36 + 8 * 6)($4)
196 sdc1 $f7, (4 * 36 + 8 * 7)($4)
197 sdc1 $f8, (4 * 36 + 8 * 8)($4)
198 sdc1 $f9, (4 * 36 + 8 * 9)($4)
199 sdc1 $f10, (4 * 36 + 8 * 10)($4)
200 sdc1 $f11, (4 * 36 + 8 * 11)($4)
201 sdc1 $f12, (4 * 36 + 8 * 12)($4)
202 sdc1 $f13, (4 * 36 + 8 * 13)($4)
203 sdc1 $f14, (4 * 36 + 8 * 14)($4)
204 sdc1 $f15, (4 * 36 + 8 * 15)($4)
205 sdc1 $f16, (4 * 36 + 8 * 16)($4)
206 sdc1 $f17, (4 * 36 + 8 * 17)($4)
207 sdc1 $f18, (4 * 36 + 8 * 18)($4)
208 sdc1 $f19, (4 * 36 + 8 * 19)($4)
209 sdc1 $f20, (4 * 36 + 8 * 20)($4)
210 sdc1 $f21, (4 * 36 + 8 * 21)($4)
211 sdc1 $f22, (4 * 36 + 8 * 22)($4)
212 sdc1 $f23, (4 * 36 + 8 * 23)($4)
213 sdc1 $f24, (4 * 36 + 8 * 24)($4)
214 sdc1 $f25, (4 * 36 + 8 * 25)($4)
215 sdc1 $f26, (4 * 36 + 8 * 26)($4)
216 sdc1 $f27, (4 * 36 + 8 * 27)($4)
217 sdc1 $f28, (4 * 36 + 8 * 28)($4)
218 sdc1 $f29, (4 * 36 + 8 * 29)($4)
219 sdc1 $f30, (4 * 36 + 8 * 30)($4)
220 sdc1 $f31, (4 * 36 + 8 * 31)($4)
221#endif
222#endif
223 jr $31
224 # return UNW_ESUCCESS
225 or $2, $0, $0
226 .set pop
227
228#elif defined(__mips64)
229
230#
231# extern int unw_getcontext(unw_context_t* thread_state)
232#
233# On entry:
234# thread_state pointer is in a0 ($4)
235#
236DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
237 .set push
238 .set noat
239 .set noreorder
240 .set nomacro
241 sd $1, (8 * 1)($4)
242 sd $2, (8 * 2)($4)
243 sd $3, (8 * 3)($4)
244 sd $4, (8 * 4)($4)
245 sd $5, (8 * 5)($4)
246 sd $6, (8 * 6)($4)
247 sd $7, (8 * 7)($4)
248 sd $8, (8 * 8)($4)
249 sd $9, (8 * 9)($4)
250 sd $10, (8 * 10)($4)
251 sd $11, (8 * 11)($4)
252 sd $12, (8 * 12)($4)
253 sd $13, (8 * 13)($4)
254 sd $14, (8 * 14)($4)
255 sd $15, (8 * 15)($4)
256 sd $16, (8 * 16)($4)
257 sd $17, (8 * 17)($4)
258 sd $18, (8 * 18)($4)
259 sd $19, (8 * 19)($4)
260 sd $20, (8 * 20)($4)
261 sd $21, (8 * 21)($4)
262 sd $22, (8 * 22)($4)
263 sd $23, (8 * 23)($4)
264 sd $24, (8 * 24)($4)
265 sd $25, (8 * 25)($4)
266 sd $26, (8 * 26)($4)
267 sd $27, (8 * 27)($4)
268 sd $28, (8 * 28)($4)
269 sd $29, (8 * 29)($4)
270 sd $30, (8 * 30)($4)
271 sd $31, (8 * 31)($4)
272 # Store return address to pc
273 sd $31, (8 * 32)($4)
274 # hi and lo
275 mfhi $8
276 sd $8, (8 * 33)($4)
277 mflo $8
278 sd $8, (8 * 34)($4)
279#ifdef __mips_hard_float
280 sdc1 $f0, (8 * 35)($4)
281 sdc1 $f1, (8 * 36)($4)
282 sdc1 $f2, (8 * 37)($4)
283 sdc1 $f3, (8 * 38)($4)
284 sdc1 $f4, (8 * 39)($4)
285 sdc1 $f5, (8 * 40)($4)
286 sdc1 $f6, (8 * 41)($4)
287 sdc1 $f7, (8 * 42)($4)
288 sdc1 $f8, (8 * 43)($4)
289 sdc1 $f9, (8 * 44)($4)
290 sdc1 $f10, (8 * 45)($4)
291 sdc1 $f11, (8 * 46)($4)
292 sdc1 $f12, (8 * 47)($4)
293 sdc1 $f13, (8 * 48)($4)
294 sdc1 $f14, (8 * 49)($4)
295 sdc1 $f15, (8 * 50)($4)
296 sdc1 $f16, (8 * 51)($4)
297 sdc1 $f17, (8 * 52)($4)
298 sdc1 $f18, (8 * 53)($4)
299 sdc1 $f19, (8 * 54)($4)
300 sdc1 $f20, (8 * 55)($4)
301 sdc1 $f21, (8 * 56)($4)
302 sdc1 $f22, (8 * 57)($4)
303 sdc1 $f23, (8 * 58)($4)
304 sdc1 $f24, (8 * 59)($4)
305 sdc1 $f25, (8 * 60)($4)
306 sdc1 $f26, (8 * 61)($4)
307 sdc1 $f27, (8 * 62)($4)
308 sdc1 $f28, (8 * 63)($4)
309 sdc1 $f29, (8 * 64)($4)
310 sdc1 $f30, (8 * 65)($4)
311 sdc1 $f31, (8 * 66)($4)
312#endif
313 jr $31
314 # return UNW_ESUCCESS
315 or $2, $0, $0
316 .set pop
317
318# elif defined(__mips__)
319
320#
321# extern int unw_getcontext(unw_context_t* thread_state)
322#
323# Just trap for the time being.
324DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
325 teq $0, $0
326
327#elif defined(__powerpc64__)
328
329//
330// extern int unw_getcontext(unw_context_t* thread_state)
331//
332// On entry:
333// thread_state pointer is in r3
334//
335DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
336
337// store register (GPR)
338#define PPC64_STR(n) \
339 std %r##n, (8 * (n + 2))(%r3)
340
341 // save GPRs
342 PPC64_STR(0)
343 mflr %r0
344 std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0
345 PPC64_STR(1)
346 PPC64_STR(2)
347 PPC64_STR(3)
348 PPC64_STR(4)
349 PPC64_STR(5)
350 PPC64_STR(6)
351 PPC64_STR(7)
352 PPC64_STR(8)
353 PPC64_STR(9)
354 PPC64_STR(10)
355 PPC64_STR(11)
356 PPC64_STR(12)
357 PPC64_STR(13)
358 PPC64_STR(14)
359 PPC64_STR(15)
360 PPC64_STR(16)
361 PPC64_STR(17)
362 PPC64_STR(18)
363 PPC64_STR(19)
364 PPC64_STR(20)
365 PPC64_STR(21)
366 PPC64_STR(22)
367 PPC64_STR(23)
368 PPC64_STR(24)
369 PPC64_STR(25)
370 PPC64_STR(26)
371 PPC64_STR(27)
372 PPC64_STR(28)
373 PPC64_STR(29)
374 PPC64_STR(30)
375 PPC64_STR(31)
376
377 mfcr %r0
378 std %r0, PPC64_OFFS_CR(%r3)
379 mfxer %r0
380 std %r0, PPC64_OFFS_XER(%r3)
381 mflr %r0
382 std %r0, PPC64_OFFS_LR(%r3)
383 mfctr %r0
384 std %r0, PPC64_OFFS_CTR(%r3)
385 mfvrsave %r0
386 std %r0, PPC64_OFFS_VRSAVE(%r3)
387
388#ifdef PPC64_HAS_VMX
389 // save VS registers
390 // (note that this also saves floating point registers and V registers,
391 // because part of VS is mapped to these registers)
392
393 addi %r4, %r3, PPC64_OFFS_FP
394
395// store VS register
396#define PPC64_STVS(n) \
397 stxvd2x %vs##n, 0, %r4 ;\
398 addi %r4, %r4, 16
399
400 PPC64_STVS(0)
401 PPC64_STVS(1)
402 PPC64_STVS(2)
403 PPC64_STVS(3)
404 PPC64_STVS(4)
405 PPC64_STVS(5)
406 PPC64_STVS(6)
407 PPC64_STVS(7)
408 PPC64_STVS(8)
409 PPC64_STVS(9)
410 PPC64_STVS(10)
411 PPC64_STVS(11)
412 PPC64_STVS(12)
413 PPC64_STVS(13)
414 PPC64_STVS(14)
415 PPC64_STVS(15)
416 PPC64_STVS(16)
417 PPC64_STVS(17)
418 PPC64_STVS(18)
419 PPC64_STVS(19)
420 PPC64_STVS(20)
421 PPC64_STVS(21)
422 PPC64_STVS(22)
423 PPC64_STVS(23)
424 PPC64_STVS(24)
425 PPC64_STVS(25)
426 PPC64_STVS(26)
427 PPC64_STVS(27)
428 PPC64_STVS(28)
429 PPC64_STVS(29)
430 PPC64_STVS(30)
431 PPC64_STVS(31)
432 PPC64_STVS(32)
433 PPC64_STVS(33)
434 PPC64_STVS(34)
435 PPC64_STVS(35)
436 PPC64_STVS(36)
437 PPC64_STVS(37)
438 PPC64_STVS(38)
439 PPC64_STVS(39)
440 PPC64_STVS(40)
441 PPC64_STVS(41)
442 PPC64_STVS(42)
443 PPC64_STVS(43)
444 PPC64_STVS(44)
445 PPC64_STVS(45)
446 PPC64_STVS(46)
447 PPC64_STVS(47)
448 PPC64_STVS(48)
449 PPC64_STVS(49)
450 PPC64_STVS(50)
451 PPC64_STVS(51)
452 PPC64_STVS(52)
453 PPC64_STVS(53)
454 PPC64_STVS(54)
455 PPC64_STVS(55)
456 PPC64_STVS(56)
457 PPC64_STVS(57)
458 PPC64_STVS(58)
459 PPC64_STVS(59)
460 PPC64_STVS(60)
461 PPC64_STVS(61)
462 PPC64_STVS(62)
463 PPC64_STVS(63)
464
465#else
466
467// store FP register
468#define PPC64_STF(n) \
469 stfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
470
471 // save float registers
472 PPC64_STF(0)
473 PPC64_STF(1)
474 PPC64_STF(2)
475 PPC64_STF(3)
476 PPC64_STF(4)
477 PPC64_STF(5)
478 PPC64_STF(6)
479 PPC64_STF(7)
480 PPC64_STF(8)
481 PPC64_STF(9)
482 PPC64_STF(10)
483 PPC64_STF(11)
484 PPC64_STF(12)
485 PPC64_STF(13)
486 PPC64_STF(14)
487 PPC64_STF(15)
488 PPC64_STF(16)
489 PPC64_STF(17)
490 PPC64_STF(18)
491 PPC64_STF(19)
492 PPC64_STF(20)
493 PPC64_STF(21)
494 PPC64_STF(22)
495 PPC64_STF(23)
496 PPC64_STF(24)
497 PPC64_STF(25)
498 PPC64_STF(26)
499 PPC64_STF(27)
500 PPC64_STF(28)
501 PPC64_STF(29)
502 PPC64_STF(30)
503 PPC64_STF(31)
504
505 // save vector registers
506
507 // Use 16-bytes below the stack pointer as an
508 // aligned buffer to save each vector register.
509 // Note that the stack pointer is always 16-byte aligned.
510 subi %r4, %r1, 16
511
512#define PPC64_STV_UNALIGNED(n) \
513 stvx %v##n, 0, %r4 ;\
514 ld %r5, 0(%r4) ;\
515 std %r5, (PPC64_OFFS_V + n * 16)(%r3) ;\
516 ld %r5, 8(%r4) ;\
517 std %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3)
518
519 PPC64_STV_UNALIGNED(0)
520 PPC64_STV_UNALIGNED(1)
521 PPC64_STV_UNALIGNED(2)
522 PPC64_STV_UNALIGNED(3)
523 PPC64_STV_UNALIGNED(4)
524 PPC64_STV_UNALIGNED(5)
525 PPC64_STV_UNALIGNED(6)
526 PPC64_STV_UNALIGNED(7)
527 PPC64_STV_UNALIGNED(8)
528 PPC64_STV_UNALIGNED(9)
529 PPC64_STV_UNALIGNED(10)
530 PPC64_STV_UNALIGNED(11)
531 PPC64_STV_UNALIGNED(12)
532 PPC64_STV_UNALIGNED(13)
533 PPC64_STV_UNALIGNED(14)
534 PPC64_STV_UNALIGNED(15)
535 PPC64_STV_UNALIGNED(16)
536 PPC64_STV_UNALIGNED(17)
537 PPC64_STV_UNALIGNED(18)
538 PPC64_STV_UNALIGNED(19)
539 PPC64_STV_UNALIGNED(20)
540 PPC64_STV_UNALIGNED(21)
541 PPC64_STV_UNALIGNED(22)
542 PPC64_STV_UNALIGNED(23)
543 PPC64_STV_UNALIGNED(24)
544 PPC64_STV_UNALIGNED(25)
545 PPC64_STV_UNALIGNED(26)
546 PPC64_STV_UNALIGNED(27)
547 PPC64_STV_UNALIGNED(28)
548 PPC64_STV_UNALIGNED(29)
549 PPC64_STV_UNALIGNED(30)
550 PPC64_STV_UNALIGNED(31)
551
552#endif
553
554 li %r3, 0 // return UNW_ESUCCESS
555 blr
556
557
558#elif defined(__ppc__)
559
560;
561; extern int unw_getcontext(unw_context_t* thread_state)
562;
563; On entry:
564; thread_state pointer is in r3
565;
566DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
567 stw r0, 8(r3)
568 mflr r0
569 stw r0, 0(r3) ; store lr as ssr0
570 stw r1, 12(r3)
571 stw r2, 16(r3)
572 stw r3, 20(r3)
573 stw r4, 24(r3)
574 stw r5, 28(r3)
575 stw r6, 32(r3)
576 stw r7, 36(r3)
577 stw r8, 40(r3)
578 stw r9, 44(r3)
579 stw r10, 48(r3)
580 stw r11, 52(r3)
581 stw r12, 56(r3)
582 stw r13, 60(r3)
583 stw r14, 64(r3)
584 stw r15, 68(r3)
585 stw r16, 72(r3)
586 stw r17, 76(r3)
587 stw r18, 80(r3)
588 stw r19, 84(r3)
589 stw r20, 88(r3)
590 stw r21, 92(r3)
591 stw r22, 96(r3)
592 stw r23,100(r3)
593 stw r24,104(r3)
594 stw r25,108(r3)
595 stw r26,112(r3)
596 stw r27,116(r3)
597 stw r28,120(r3)
598 stw r29,124(r3)
599 stw r30,128(r3)
600 stw r31,132(r3)
601
602 ; save VRSave register
603 mfspr r0,256
604 stw r0,156(r3)
605 ; save CR registers
606 mfcr r0
607 stw r0,136(r3)
608 ; save CTR register
609 mfctr r0
610 stw r0,148(r3)
611
612 ; save float registers
613 stfd f0, 160(r3)
614 stfd f1, 168(r3)
615 stfd f2, 176(r3)
616 stfd f3, 184(r3)
617 stfd f4, 192(r3)
618 stfd f5, 200(r3)
619 stfd f6, 208(r3)
620 stfd f7, 216(r3)
621 stfd f8, 224(r3)
622 stfd f9, 232(r3)
623 stfd f10,240(r3)
624 stfd f11,248(r3)
625 stfd f12,256(r3)
626 stfd f13,264(r3)
627 stfd f14,272(r3)
628 stfd f15,280(r3)
629 stfd f16,288(r3)
630 stfd f17,296(r3)
631 stfd f18,304(r3)
632 stfd f19,312(r3)
633 stfd f20,320(r3)
634 stfd f21,328(r3)
635 stfd f22,336(r3)
636 stfd f23,344(r3)
637 stfd f24,352(r3)
638 stfd f25,360(r3)
639 stfd f26,368(r3)
640 stfd f27,376(r3)
641 stfd f28,384(r3)
642 stfd f29,392(r3)
643 stfd f30,400(r3)
644 stfd f31,408(r3)
645
646
647 ; save vector registers
648
649 subi r4,r1,16
650 rlwinm r4,r4,0,0,27 ; mask low 4-bits
651 ; r4 is now a 16-byte aligned pointer into the red zone
652
653#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
654 stvx _vec,0,r4 @\
655 lwz r5, 0(r4) @\
656 stw r5, _offset(r3) @\
657 lwz r5, 4(r4) @\
658 stw r5, _offset+4(r3) @\
659 lwz r5, 8(r4) @\
660 stw r5, _offset+8(r3) @\
661 lwz r5, 12(r4) @\
662 stw r5, _offset+12(r3)
663
664 SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
665 SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
666 SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
667 SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
668 SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
669 SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
670 SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
671 SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
672 SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
673 SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
674 SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
675 SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
676 SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
677 SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
678 SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
679 SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
680 SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
681 SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
682 SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
683 SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
684 SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
685 SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
686 SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
687 SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
688 SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
689 SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
690 SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
691 SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
692 SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
693 SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
694 SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
695 SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
696
697 li r3, 0 ; return UNW_ESUCCESS
698 blr
699
700
701#elif defined(__arm64__) || defined(__aarch64__)
702
703//
704// extern int unw_getcontext(unw_context_t* thread_state)
705//
706// On entry:
707// thread_state pointer is in x0
708//
709 .p2align 2
710DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
711 stp x0, x1, [x0, #0x000]
712 stp x2, x3, [x0, #0x010]
713 stp x4, x5, [x0, #0x020]
714 stp x6, x7, [x0, #0x030]
715 stp x8, x9, [x0, #0x040]
716 stp x10,x11, [x0, #0x050]
717 stp x12,x13, [x0, #0x060]
718 stp x14,x15, [x0, #0x070]
719 stp x16,x17, [x0, #0x080]
720 stp x18,x19, [x0, #0x090]
721 stp x20,x21, [x0, #0x0A0]
722 stp x22,x23, [x0, #0x0B0]
723 stp x24,x25, [x0, #0x0C0]
724 stp x26,x27, [x0, #0x0D0]
725 stp x28,x29, [x0, #0x0E0]
726 str x30, [x0, #0x0F0]
727 mov x1,sp
728 str x1, [x0, #0x0F8]
729 str x30, [x0, #0x100] // store return address as pc
730 // skip cpsr
731 stp d0, d1, [x0, #0x110]
732 stp d2, d3, [x0, #0x120]
733 stp d4, d5, [x0, #0x130]
734 stp d6, d7, [x0, #0x140]
735 stp d8, d9, [x0, #0x150]
736 stp d10,d11, [x0, #0x160]
737 stp d12,d13, [x0, #0x170]
738 stp d14,d15, [x0, #0x180]
739 stp d16,d17, [x0, #0x190]
740 stp d18,d19, [x0, #0x1A0]
741 stp d20,d21, [x0, #0x1B0]
742 stp d22,d23, [x0, #0x1C0]
743 stp d24,d25, [x0, #0x1D0]
744 stp d26,d27, [x0, #0x1E0]
745 stp d28,d29, [x0, #0x1F0]
746 str d30, [x0, #0x200]
747 str d31, [x0, #0x208]
748 mov x0, #0 // return UNW_ESUCCESS
749 ret
750
751#elif defined(__arm__) && !defined(__APPLE__)
752
753#if !defined(__ARM_ARCH_ISA_ARM)
754 .thumb
755#endif
756
757@
758@ extern int unw_getcontext(unw_context_t* thread_state)
759@
760@ On entry:
761@ thread_state pointer is in r0
762@
763@ Per EHABI #4.7 this only saves the core integer registers.
764@ EHABI #7.4.5 notes that in general all VRS registers should be restored
765@ however this is very hard to do for VFP registers because it is unknown
766@ to the library how many registers are implemented by the architecture.
767@ Instead, VFP registers are demand saved by logic external to unw_getcontext.
768@
769 .p2align 2
770DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
771#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
772 stm r0!, {r0-r7}
773 mov r1, r8
774 mov r2, r9
775 mov r3, r10
776 stm r0!, {r1-r3}
777 mov r1, r11
778 mov r2, sp
779 mov r3, lr
780 str r1, [r0, #0] @ r11
781 @ r12 does not need storing, it it the intra-procedure-call scratch register
782 str r2, [r0, #8] @ sp
783 str r3, [r0, #12] @ lr
784 str r3, [r0, #16] @ store return address as pc
785 @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
786 @ It is safe to use here though because we are about to return, and cpsr is
787 @ not expected to be preserved.
788 movs r0, #0 @ return UNW_ESUCCESS
789#else
790 @ 32bit thumb-2 restrictions for stm:
791 @ . the sp (r13) cannot be in the list
792 @ . the pc (r15) cannot be in the list in an STM instruction
793 stm r0, {r0-r12}
794 str sp, [r0, #52]
795 str lr, [r0, #56]
796 str lr, [r0, #60] @ store return address as pc
797 mov r0, #0 @ return UNW_ESUCCESS
798#endif
799 JMP(lr)
800
801@
802@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
803@
804@ On entry:
805@ values pointer is in r0
806@
807 .p2align 2
808#if defined(__ELF__)
809 .fpu vfpv3-d16
810#endif
811DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
812 vstmia r0, {d0-d15}
813 JMP(lr)
814
815@
816@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
817@
818@ On entry:
819@ values pointer is in r0
820@
821 .p2align 2
822#if defined(__ELF__)
823 .fpu vfpv3-d16
824#endif
825DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
826 vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
827 JMP(lr)
828
829@
830@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
831@
832@ On entry:
833@ values pointer is in r0
834@
835 .p2align 2
836#if defined(__ELF__)
837 .fpu vfpv3
838#endif
839DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
840 @ VFP and iwMMX instructions are only available when compiling with the flags
841 @ that enable them. We do not want to do that in the library (because we do not
842 @ want the compiler to generate instructions that access those) but this is
843 @ only accessed if the personality routine needs these registers. Use of
844 @ these registers implies they are, actually, available on the target, so
845 @ it's ok to execute.
846 @ So, generate the instructions using the corresponding coprocessor mnemonic.
847 vstmia r0, {d16-d31}
848 JMP(lr)
849
850#if defined(_LIBUNWIND_ARM_WMMX)
851
852@
853@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
854@
855@ On entry:
856@ values pointer is in r0
857@
858 .p2align 2
859#if defined(__ELF__)
860 .arch armv5te
861#endif
862DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
863 stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8
864 stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8
865 stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8
866 stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8
867 stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8
868 stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8
869 stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8
870 stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8
871 stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8
872 stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8
873 stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8
874 stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8
875 stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8
876 stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8
877 stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8
878 stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8
879 JMP(lr)
880
881@
882@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
883@
884@ On entry:
885@ values pointer is in r0
886@
887 .p2align 2
888#if defined(__ELF__)
889 .arch armv5te
890#endif
891DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
892 stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4
893 stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4
894 stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4
895 stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4
896 JMP(lr)
897
898#endif
899
900#elif defined(__or1k__)
901
902#
903# extern int unw_getcontext(unw_context_t* thread_state)
904#
905# On entry:
906# thread_state pointer is in r3
907#
908DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
909 l.sw 0(r3), r0
910 l.sw 4(r3), r1
911 l.sw 8(r3), r2
912 l.sw 12(r3), r3
913 l.sw 16(r3), r4
914 l.sw 20(r3), r5
915 l.sw 24(r3), r6
916 l.sw 28(r3), r7
917 l.sw 32(r3), r8
918 l.sw 36(r3), r9
919 l.sw 40(r3), r10
920 l.sw 44(r3), r11
921 l.sw 48(r3), r12
922 l.sw 52(r3), r13
923 l.sw 56(r3), r14
924 l.sw 60(r3), r15
925 l.sw 64(r3), r16
926 l.sw 68(r3), r17
927 l.sw 72(r3), r18
928 l.sw 76(r3), r19
929 l.sw 80(r3), r20
930 l.sw 84(r3), r21
931 l.sw 88(r3), r22
932 l.sw 92(r3), r23
933 l.sw 96(r3), r24
934 l.sw 100(r3), r25
935 l.sw 104(r3), r26
936 l.sw 108(r3), r27
937 l.sw 112(r3), r28
938 l.sw 116(r3), r29
939 l.sw 120(r3), r30
940 l.sw 124(r3), r31
941 # store ra to pc
942 l.sw 128(r3), r9
943 # zero epcr
944 l.sw 132(r3), r0
945
946#elif defined(__sparc__)
947
948#
949# extern int unw_getcontext(unw_context_t* thread_state)
950#
951# On entry:
952# thread_state pointer is in o0
953#
954DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
955 ta 3
956 add %o7, 8, %o7
957 std %g0, [%o0 + 0]
958 std %g2, [%o0 + 8]
959 std %g4, [%o0 + 16]
960 std %g6, [%o0 + 24]
961 std %o0, [%o0 + 32]
962 std %o2, [%o0 + 40]
963 std %o4, [%o0 + 48]
964 std %o6, [%o0 + 56]
965 std %l0, [%o0 + 64]
966 std %l2, [%o0 + 72]
967 std %l4, [%o0 + 80]
968 std %l6, [%o0 + 88]
969 std %i0, [%o0 + 96]
970 std %i2, [%o0 + 104]
971 std %i4, [%o0 + 112]
972 std %i6, [%o0 + 120]
973 jmp %o7
974 clr %o0 // return UNW_ESUCCESS
975#endif
976#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
977
978NO_EXEC_STACK_DIRECTIVE
libunwind/src/Unwind_AppleExtras.cpp created+184
...@@ -0,0 +1,184 @@
1//===--------------------- Unwind_AppleExtras.cpp -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9//===----------------------------------------------------------------------===//
10
11#include "config.h"
12#include "AddressSpace.hpp"
13#include "DwarfParser.hpp"
14
15
16// private keymgr stuff
17#define KEYMGR_GCC3_DW2_OBJ_LIST 302
18extern "C" {
19 extern void _keymgr_set_and_unlock_processwide_ptr(int key, void *ptr);
20 extern void *_keymgr_get_and_lock_processwide_ptr(int key);
21}
22
23// undocumented libgcc "struct object"
24struct libgcc_object {
25 void *start;
26 void *unused1;
27 void *unused2;
28 void *fde;
29 unsigned long encoding;
30 void *fde_end;
31 libgcc_object *next;
32};
33
34// undocumented libgcc "struct km_object_info" referenced by
35// KEYMGR_GCC3_DW2_OBJ_LIST
36struct libgcc_object_info {
37 libgcc_object *seen_objects;
38 libgcc_object *unseen_objects;
39 unsigned spare[2];
40};
41
42
43// static linker symbols to prevent wrong two level namespace for _Unwind symbols
44#if defined(__arm__)
45 #define NOT_HERE_BEFORE_5_0(sym) \
46 extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \
47 __attribute__((visibility("default"))) const char sym##_tmp30 = 0; \
48 extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); \
49 __attribute__((visibility("default"))) const char sym##_tmp31 = 0; \
50 extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym );\
51 __attribute__((visibility("default"))) const char sym##_tmp32 = 0; \
52 extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); \
53 __attribute__((visibility("default"))) const char sym##_tmp40 = 0; \
54 extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); \
55 __attribute__((visibility("default"))) const char sym##_tmp41 = 0; \
56 extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); \
57 __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \
58 extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \
59 __attribute__((visibility("default"))) const char sym##_tmp43 = 0;
60#elif defined(__arm64__)
61 #define NOT_HERE_BEFORE_10_6(sym)
62 #define NEVER_HERE(sym)
63#else
64 #define NOT_HERE_BEFORE_10_6(sym) \
65 extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
66 __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
67 extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
68 __attribute__((visibility("default"))) const char sym##_tmp5 = 0;
69 #define NEVER_HERE(sym) \
70 extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
71 __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
72 extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
73 __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
74 extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); \
75 __attribute__((visibility("default"))) const char sym##_tmp6 = 0;
76#endif
77
78
79#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
80
81//
82// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in
83// earlier versions
84//
85NOT_HERE_BEFORE_10_6(_Unwind_DeleteException)
86NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE)
87NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind)
88NOT_HERE_BEFORE_10_6(_Unwind_GetGR)
89NOT_HERE_BEFORE_10_6(_Unwind_GetIP)
90NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData)
91NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart)
92NOT_HERE_BEFORE_10_6(_Unwind_RaiseException)
93NOT_HERE_BEFORE_10_6(_Unwind_Resume)
94NOT_HERE_BEFORE_10_6(_Unwind_SetGR)
95NOT_HERE_BEFORE_10_6(_Unwind_SetIP)
96NOT_HERE_BEFORE_10_6(_Unwind_Backtrace)
97NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction)
98NOT_HERE_BEFORE_10_6(_Unwind_GetCFA)
99NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase)
100NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase)
101NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow)
102NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo)
103NOT_HERE_BEFORE_10_6(__register_frame)
104NOT_HERE_BEFORE_10_6(__deregister_frame)
105
106//
107// symbols in libSystem.dylib for compatibility, but we don't want any new code
108// using them
109//
110NEVER_HERE(__register_frame_info_bases)
111NEVER_HERE(__register_frame_info)
112NEVER_HERE(__register_frame_info_table_bases)
113NEVER_HERE(__register_frame_info_table)
114NEVER_HERE(__register_frame_table)
115NEVER_HERE(__deregister_frame_info)
116NEVER_HERE(__deregister_frame_info_bases)
117
118#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
119
120
121
122
123#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
124//
125// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in
126// earlier versions
127//
128NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData)
129NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart)
130NOT_HERE_BEFORE_5_0(_Unwind_GetIP)
131NOT_HERE_BEFORE_5_0(_Unwind_SetGR)
132NOT_HERE_BEFORE_5_0(_Unwind_SetIP)
133NOT_HERE_BEFORE_5_0(_Unwind_DeleteException)
134NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register)
135NOT_HERE_BEFORE_5_0(_Unwind_GetGR)
136NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo)
137NOT_HERE_BEFORE_5_0(_Unwind_GetCFA)
138NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume)
139NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException)
140NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow)
141NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister)
142
143#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)
144
145
146namespace libunwind {
147
148_LIBUNWIND_HIDDEN
149bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) {
150#if __MAC_OS_X_VERSION_MIN_REQUIRED
151 // lastly check for old style keymgr registration of dynamically generated
152 // FDEs acquire exclusive access to libgcc_object_info
153 libgcc_object_info *head = (libgcc_object_info *)
154 _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
155 if (head != NULL) {
156 // look at each FDE in keymgr
157 for (libgcc_object *ob = head->unseen_objects; ob != NULL; ob = ob->next) {
158 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
159 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
160 const char *msg = CFI_Parser<LocalAddressSpace>::decodeFDE(
161 LocalAddressSpace::sThisAddressSpace,
162 (uintptr_t)ob->fde, &fdeInfo, &cieInfo);
163 if (msg == NULL) {
164 // Check if this FDE is for a function that includes the pc
165 if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
166 fde = (void*)fdeInfo.pcStart;
167 _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST,
168 head);
169 return true;
170 }
171 }
172 }
173 }
174 // release libgcc_object_info
175 _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head);
176#else
177 (void)pc;
178 (void)fde;
179#endif
180 return false;
181}
182
183}
184
libunwind/src/assembly.h created+124
...@@ -0,0 +1,124 @@
1/* ===-- assembly.h - libUnwind assembler support macros -------------------===
2 *
3 * The LLVM Compiler Infrastructure
4 *
5 * This file is dual licensed under the MIT and the University of Illinois Open
6 * Source Licenses. See LICENSE.TXT for details.
7 *
8 * ===----------------------------------------------------------------------===
9 *
10 * This file defines macros for use in libUnwind assembler source.
11 * This file is not part of the interface of this library.
12 *
13 * ===----------------------------------------------------------------------===
14 */
15
16#ifndef UNWIND_ASSEMBLY_H
17#define UNWIND_ASSEMBLY_H
18
19#if defined(__powerpc64__)
20#define SEPARATOR ;
21#define PPC64_OFFS_SRR0 0
22#define PPC64_OFFS_CR 272
23#define PPC64_OFFS_XER 280
24#define PPC64_OFFS_LR 288
25#define PPC64_OFFS_CTR 296
26#define PPC64_OFFS_VRSAVE 304
27#define PPC64_OFFS_FP 312
28#define PPC64_OFFS_V 824
29#ifdef _ARCH_PWR8
30#define PPC64_HAS_VMX
31#endif
32#elif defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__)
33#define SEPARATOR @
34#elif defined(__arm64__)
35#define SEPARATOR %%
36#else
37#define SEPARATOR ;
38#endif
39
40#define GLUE2(a, b) a ## b
41#define GLUE(a, b) GLUE2(a, b)
42#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
43
44#if defined(__APPLE__)
45
46#define SYMBOL_IS_FUNC(name)
47#define EXPORT_SYMBOL(name)
48#define HIDDEN_SYMBOL(name) .private_extern name
49#define NO_EXEC_STACK_DIRECTIVE
50
51#elif defined(__ELF__)
52
53#if defined(__arm__)
54#define SYMBOL_IS_FUNC(name) .type name,%function
55#else
56#define SYMBOL_IS_FUNC(name) .type name,@function
57#endif
58#define EXPORT_SYMBOL(name)
59#define HIDDEN_SYMBOL(name) .hidden name
60
61#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
62 defined(__linux__)
63#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
64#else
65#define NO_EXEC_STACK_DIRECTIVE
66#endif
67
68#elif defined(_WIN32)
69
70#define SYMBOL_IS_FUNC(name) \
71 .def name SEPARATOR \
72 .scl 2 SEPARATOR \
73 .type 32 SEPARATOR \
74 .endef
75#define EXPORT_SYMBOL2(name) \
76 .section .drectve,"yn" SEPARATOR \
77 .ascii "-export:", #name, "\0" SEPARATOR \
78 .text
79#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
80#define EXPORT_SYMBOL(name)
81#else
82#define EXPORT_SYMBOL(name) EXPORT_SYMBOL2(name)
83#endif
84#define HIDDEN_SYMBOL(name)
85
86#define NO_EXEC_STACK_DIRECTIVE
87
88#elif defined(__sparc__)
89
90#else
91
92#error Unsupported target
93
94#endif
95
96#define DEFINE_LIBUNWIND_FUNCTION(name) \
97 .globl SYMBOL_NAME(name) SEPARATOR \
98 EXPORT_SYMBOL(name) SEPARATOR \
99 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
100 SYMBOL_NAME(name):
101
102#define DEFINE_LIBUNWIND_PRIVATE_FUNCTION(name) \
103 .globl SYMBOL_NAME(name) SEPARATOR \
104 HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
105 SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
106 SYMBOL_NAME(name):
107
108#if defined(__arm__)
109#if !defined(__ARM_ARCH)
110#define __ARM_ARCH 4
111#endif
112
113#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
114#define ARM_HAS_BX
115#endif
116
117#ifdef ARM_HAS_BX
118#define JMP(r) bx r
119#else
120#define JMP(r) mov pc, r
121#endif
122#endif /* __arm__ */
123
124#endif /* UNWIND_ASSEMBLY_H */
libunwind/src/config.h created+183
...@@ -0,0 +1,183 @@
1//===----------------------------- config.h -------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Defines macros used within libunwind project.
10//
11//===----------------------------------------------------------------------===//
12
13
14#ifndef LIBUNWIND_CONFIG_H
15#define LIBUNWIND_CONFIG_H
16
17#include <assert.h>
18#include <stdio.h>
19#include <stdint.h>
20#include <stdlib.h>
21
22// Define static_assert() unless already defined by compiler.
23#ifndef __has_feature
24 #define __has_feature(__x) 0
25#endif
26#if !(__has_feature(cxx_static_assert)) && !defined(static_assert)
27 #define static_assert(__b, __m) \
28 extern int compile_time_assert_failed[ ( __b ) ? 1 : -1 ] \
29 __attribute__( ( unused ) );
30#endif
31
32// Platform specific configuration defines.
33#ifdef __APPLE__
34 #if defined(FOR_DYLD)
35 #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
36 #else
37 #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND
38 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
39 #endif
40#elif defined(_WIN32)
41 #ifdef __SEH__
42 #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1
43 #else
44 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
45 #endif
46#else
47 #if defined(__ARM_DWARF_EH__) || !defined(__arm__)
48 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
49 #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
50 #endif
51#endif
52
53#if defined(_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS)
54 #define _LIBUNWIND_EXPORT
55 #define _LIBUNWIND_HIDDEN
56#else
57 #if !defined(__ELF__) && !defined(__MACH__)
58 #define _LIBUNWIND_EXPORT __declspec(dllexport)
59 #define _LIBUNWIND_HIDDEN
60 #else
61 #define _LIBUNWIND_EXPORT __attribute__((visibility("default")))
62 #define _LIBUNWIND_HIDDEN __attribute__((visibility("hidden")))
63 #endif
64#endif
65
66#if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__)
67#define _LIBUNWIND_BUILD_SJLJ_APIS
68#endif
69
70#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__)
71#define _LIBUNWIND_SUPPORT_FRAME_APIS
72#endif
73
74#if defined(__i386__) || defined(__x86_64__) || \
75 defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \
76 (!defined(__APPLE__) && defined(__arm__)) || \
77 (defined(__arm64__) || defined(__aarch64__)) || \
78 defined(__mips__)
79#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
80#define _LIBUNWIND_BUILD_ZERO_COST_APIS
81#endif
82#endif
83
84#if defined(__powerpc64__) && defined(_ARCH_PWR8)
85#define PPC64_HAS_VMX
86#endif
87
88#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
89#define _LIBUNWIND_ABORT(msg) \
90 do { \
91 abort(); \
92 } while (0)
93#else
94#define _LIBUNWIND_ABORT(msg) \
95 do { \
96 fprintf(stderr, "libunwind: %s %s:%d - %s\n", __func__, __FILE__, \
97 __LINE__, msg); \
98 fflush(stderr); \
99 abort(); \
100 } while (0)
101#endif
102
103#if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL)
104#define _LIBUNWIND_LOG0(msg)
105#define _LIBUNWIND_LOG(msg, ...)
106#else
107#define _LIBUNWIND_LOG0(msg) \
108 fprintf(stderr, "libunwind: " msg "\n")
109#define _LIBUNWIND_LOG(msg, ...) \
110 fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__)
111#endif
112
113#if defined(NDEBUG)
114 #define _LIBUNWIND_LOG_IF_FALSE(x) x
115#else
116 #define _LIBUNWIND_LOG_IF_FALSE(x) \
117 do { \
118 bool _ret = x; \
119 if (!_ret) \
120 _LIBUNWIND_LOG("" #x " failed in %s", __FUNCTION__); \
121 } while (0)
122#endif
123
124// Macros that define away in non-Debug builds
125#ifdef NDEBUG
126 #define _LIBUNWIND_DEBUG_LOG(msg, ...)
127 #define _LIBUNWIND_TRACE_API(msg, ...)
128 #define _LIBUNWIND_TRACING_UNWINDING (0)
129 #define _LIBUNWIND_TRACING_DWARF (0)
130 #define _LIBUNWIND_TRACE_UNWINDING(msg, ...)
131 #define _LIBUNWIND_TRACE_DWARF(...)
132#else
133 #ifdef __cplusplus
134 extern "C" {
135 #endif
136 extern bool logAPIs();
137 extern bool logUnwinding();
138 extern bool logDWARF();
139 #ifdef __cplusplus
140 }
141 #endif
142 #define _LIBUNWIND_DEBUG_LOG(msg, ...) _LIBUNWIND_LOG(msg, __VA_ARGS__)
143 #define _LIBUNWIND_TRACE_API(msg, ...) \
144 do { \
145 if (logAPIs()) \
146 _LIBUNWIND_LOG(msg, __VA_ARGS__); \
147 } while (0)
148 #define _LIBUNWIND_TRACING_UNWINDING logUnwinding()
149 #define _LIBUNWIND_TRACING_DWARF logDWARF()
150 #define _LIBUNWIND_TRACE_UNWINDING(msg, ...) \
151 do { \
152 if (logUnwinding()) \
153 _LIBUNWIND_LOG(msg, __VA_ARGS__); \
154 } while (0)
155 #define _LIBUNWIND_TRACE_DWARF(...) \
156 do { \
157 if (logDWARF()) \
158 fprintf(stderr, __VA_ARGS__); \
159 } while (0)
160#endif
161
162#ifdef __cplusplus
163// Used to fit UnwindCursor and Registers_xxx types against unw_context_t /
164// unw_cursor_t sized memory blocks.
165#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
166# define COMP_OP ==
167#else
168# define COMP_OP <=
169#endif
170template <typename _Type, typename _Mem>
171struct check_fit {
172 template <typename T>
173 struct blk_count {
174 static const size_t count =
175 (sizeof(T) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
176 };
177 static const bool does_fit =
178 (blk_count<_Type>::count COMP_OP blk_count<_Mem>::count);
179};
180#undef COMP_OP
181#endif // __cplusplus
182
183#endif // LIBUNWIND_CONFIG_H
libunwind/src/dwarf2.h created+240
...@@ -0,0 +1,240 @@
1//===------------------------------- dwarf2.h -----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10
11/*
12 These constants were taken from version 3 of the DWARF standard,
13 which is Copyright (c) 2005 Free Standards Group, and
14 Copyright (c) 1992, 1993 UNIX International, Inc.
15*/
16
17#ifndef __DWARF2__
18#define __DWARF2__
19
20// DWARF unwind instructions
21enum {
22 DW_CFA_nop = 0x0,
23 DW_CFA_set_loc = 0x1,
24 DW_CFA_advance_loc1 = 0x2,
25 DW_CFA_advance_loc2 = 0x3,
26 DW_CFA_advance_loc4 = 0x4,
27 DW_CFA_offset_extended = 0x5,
28 DW_CFA_restore_extended = 0x6,
29 DW_CFA_undefined = 0x7,
30 DW_CFA_same_value = 0x8,
31 DW_CFA_register = 0x9,
32 DW_CFA_remember_state = 0xA,
33 DW_CFA_restore_state = 0xB,
34 DW_CFA_def_cfa = 0xC,
35 DW_CFA_def_cfa_register = 0xD,
36 DW_CFA_def_cfa_offset = 0xE,
37 DW_CFA_def_cfa_expression = 0xF,
38 DW_CFA_expression = 0x10,
39 DW_CFA_offset_extended_sf = 0x11,
40 DW_CFA_def_cfa_sf = 0x12,
41 DW_CFA_def_cfa_offset_sf = 0x13,
42 DW_CFA_val_offset = 0x14,
43 DW_CFA_val_offset_sf = 0x15,
44 DW_CFA_val_expression = 0x16,
45 DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta
46 DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register
47 DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register
48
49 // GNU extensions
50 DW_CFA_GNU_window_save = 0x2D,
51 DW_CFA_GNU_args_size = 0x2E,
52 DW_CFA_GNU_negative_offset_extended = 0x2F,
53
54 // AARCH64 extensions
55 DW_CFA_AARCH64_negate_ra_state = 0x2D
56};
57
58
59// FSF exception handling Pointer-Encoding constants
60// Used in CFI augmentation by GCC
61enum {
62 DW_EH_PE_ptr = 0x00,
63 DW_EH_PE_uleb128 = 0x01,
64 DW_EH_PE_udata2 = 0x02,
65 DW_EH_PE_udata4 = 0x03,
66 DW_EH_PE_udata8 = 0x04,
67 DW_EH_PE_signed = 0x08,
68 DW_EH_PE_sleb128 = 0x09,
69 DW_EH_PE_sdata2 = 0x0A,
70 DW_EH_PE_sdata4 = 0x0B,
71 DW_EH_PE_sdata8 = 0x0C,
72 DW_EH_PE_absptr = 0x00,
73 DW_EH_PE_pcrel = 0x10,
74 DW_EH_PE_textrel = 0x20,
75 DW_EH_PE_datarel = 0x30,
76 DW_EH_PE_funcrel = 0x40,
77 DW_EH_PE_aligned = 0x50,
78 DW_EH_PE_indirect = 0x80,
79 DW_EH_PE_omit = 0xFF
80};
81
82
83// DWARF expressions
84enum {
85 DW_OP_addr = 0x03, // constant address (size target specific)
86 DW_OP_deref = 0x06,
87 DW_OP_const1u = 0x08, // 1-byte constant
88 DW_OP_const1s = 0x09, // 1-byte constant
89 DW_OP_const2u = 0x0A, // 2-byte constant
90 DW_OP_const2s = 0x0B, // 2-byte constant
91 DW_OP_const4u = 0x0C, // 4-byte constant
92 DW_OP_const4s = 0x0D, // 4-byte constant
93 DW_OP_const8u = 0x0E, // 8-byte constant
94 DW_OP_const8s = 0x0F, // 8-byte constant
95 DW_OP_constu = 0x10, // ULEB128 constant
96 DW_OP_consts = 0x11, // SLEB128 constant
97 DW_OP_dup = 0x12,
98 DW_OP_drop = 0x13,
99 DW_OP_over = 0x14,
100 DW_OP_pick = 0x15, // 1-byte stack index
101 DW_OP_swap = 0x16,
102 DW_OP_rot = 0x17,
103 DW_OP_xderef = 0x18,
104 DW_OP_abs = 0x19,
105 DW_OP_and = 0x1A,
106 DW_OP_div = 0x1B,
107 DW_OP_minus = 0x1C,
108 DW_OP_mod = 0x1D,
109 DW_OP_mul = 0x1E,
110 DW_OP_neg = 0x1F,
111 DW_OP_not = 0x20,
112 DW_OP_or = 0x21,
113 DW_OP_plus = 0x22,
114 DW_OP_plus_uconst = 0x23, // ULEB128 addend
115 DW_OP_shl = 0x24,
116 DW_OP_shr = 0x25,
117 DW_OP_shra = 0x26,
118 DW_OP_xor = 0x27,
119 DW_OP_skip = 0x2F, // signed 2-byte constant
120 DW_OP_bra = 0x28, // signed 2-byte constant
121 DW_OP_eq = 0x29,
122 DW_OP_ge = 0x2A,
123 DW_OP_gt = 0x2B,
124 DW_OP_le = 0x2C,
125 DW_OP_lt = 0x2D,
126 DW_OP_ne = 0x2E,
127 DW_OP_lit0 = 0x30, // Literal 0
128 DW_OP_lit1 = 0x31, // Literal 1
129 DW_OP_lit2 = 0x32, // Literal 2
130 DW_OP_lit3 = 0x33, // Literal 3
131 DW_OP_lit4 = 0x34, // Literal 4
132 DW_OP_lit5 = 0x35, // Literal 5
133 DW_OP_lit6 = 0x36, // Literal 6
134 DW_OP_lit7 = 0x37, // Literal 7
135 DW_OP_lit8 = 0x38, // Literal 8
136 DW_OP_lit9 = 0x39, // Literal 9
137 DW_OP_lit10 = 0x3A, // Literal 10
138 DW_OP_lit11 = 0x3B, // Literal 11
139 DW_OP_lit12 = 0x3C, // Literal 12
140 DW_OP_lit13 = 0x3D, // Literal 13
141 DW_OP_lit14 = 0x3E, // Literal 14
142 DW_OP_lit15 = 0x3F, // Literal 15
143 DW_OP_lit16 = 0x40, // Literal 16
144 DW_OP_lit17 = 0x41, // Literal 17
145 DW_OP_lit18 = 0x42, // Literal 18
146 DW_OP_lit19 = 0x43, // Literal 19
147 DW_OP_lit20 = 0x44, // Literal 20
148 DW_OP_lit21 = 0x45, // Literal 21
149 DW_OP_lit22 = 0x46, // Literal 22
150 DW_OP_lit23 = 0x47, // Literal 23
151 DW_OP_lit24 = 0x48, // Literal 24
152 DW_OP_lit25 = 0x49, // Literal 25
153 DW_OP_lit26 = 0x4A, // Literal 26
154 DW_OP_lit27 = 0x4B, // Literal 27
155 DW_OP_lit28 = 0x4C, // Literal 28
156 DW_OP_lit29 = 0x4D, // Literal 29
157 DW_OP_lit30 = 0x4E, // Literal 30
158 DW_OP_lit31 = 0x4F, // Literal 31
159 DW_OP_reg0 = 0x50, // Contents of reg0
160 DW_OP_reg1 = 0x51, // Contents of reg1
161 DW_OP_reg2 = 0x52, // Contents of reg2
162 DW_OP_reg3 = 0x53, // Contents of reg3
163 DW_OP_reg4 = 0x54, // Contents of reg4
164 DW_OP_reg5 = 0x55, // Contents of reg5
165 DW_OP_reg6 = 0x56, // Contents of reg6
166 DW_OP_reg7 = 0x57, // Contents of reg7
167 DW_OP_reg8 = 0x58, // Contents of reg8
168 DW_OP_reg9 = 0x59, // Contents of reg9
169 DW_OP_reg10 = 0x5A, // Contents of reg10
170 DW_OP_reg11 = 0x5B, // Contents of reg11
171 DW_OP_reg12 = 0x5C, // Contents of reg12
172 DW_OP_reg13 = 0x5D, // Contents of reg13
173 DW_OP_reg14 = 0x5E, // Contents of reg14
174 DW_OP_reg15 = 0x5F, // Contents of reg15
175 DW_OP_reg16 = 0x60, // Contents of reg16
176 DW_OP_reg17 = 0x61, // Contents of reg17
177 DW_OP_reg18 = 0x62, // Contents of reg18
178 DW_OP_reg19 = 0x63, // Contents of reg19
179 DW_OP_reg20 = 0x64, // Contents of reg20
180 DW_OP_reg21 = 0x65, // Contents of reg21
181 DW_OP_reg22 = 0x66, // Contents of reg22
182 DW_OP_reg23 = 0x67, // Contents of reg23
183 DW_OP_reg24 = 0x68, // Contents of reg24
184 DW_OP_reg25 = 0x69, // Contents of reg25
185 DW_OP_reg26 = 0x6A, // Contents of reg26
186 DW_OP_reg27 = 0x6B, // Contents of reg27
187 DW_OP_reg28 = 0x6C, // Contents of reg28
188 DW_OP_reg29 = 0x6D, // Contents of reg29
189 DW_OP_reg30 = 0x6E, // Contents of reg30
190 DW_OP_reg31 = 0x6F, // Contents of reg31
191 DW_OP_breg0 = 0x70, // base register 0 + SLEB128 offset
192 DW_OP_breg1 = 0x71, // base register 1 + SLEB128 offset
193 DW_OP_breg2 = 0x72, // base register 2 + SLEB128 offset
194 DW_OP_breg3 = 0x73, // base register 3 + SLEB128 offset
195 DW_OP_breg4 = 0x74, // base register 4 + SLEB128 offset
196 DW_OP_breg5 = 0x75, // base register 5 + SLEB128 offset
197 DW_OP_breg6 = 0x76, // base register 6 + SLEB128 offset
198 DW_OP_breg7 = 0x77, // base register 7 + SLEB128 offset
199 DW_OP_breg8 = 0x78, // base register 8 + SLEB128 offset
200 DW_OP_breg9 = 0x79, // base register 9 + SLEB128 offset
201 DW_OP_breg10 = 0x7A, // base register 10 + SLEB128 offset
202 DW_OP_breg11 = 0x7B, // base register 11 + SLEB128 offset
203 DW_OP_breg12 = 0x7C, // base register 12 + SLEB128 offset
204 DW_OP_breg13 = 0x7D, // base register 13 + SLEB128 offset
205 DW_OP_breg14 = 0x7E, // base register 14 + SLEB128 offset
206 DW_OP_breg15 = 0x7F, // base register 15 + SLEB128 offset
207 DW_OP_breg16 = 0x80, // base register 16 + SLEB128 offset
208 DW_OP_breg17 = 0x81, // base register 17 + SLEB128 offset
209 DW_OP_breg18 = 0x82, // base register 18 + SLEB128 offset
210 DW_OP_breg19 = 0x83, // base register 19 + SLEB128 offset
211 DW_OP_breg20 = 0x84, // base register 20 + SLEB128 offset
212 DW_OP_breg21 = 0x85, // base register 21 + SLEB128 offset
213 DW_OP_breg22 = 0x86, // base register 22 + SLEB128 offset
214 DW_OP_breg23 = 0x87, // base register 23 + SLEB128 offset
215 DW_OP_breg24 = 0x88, // base register 24 + SLEB128 offset
216 DW_OP_breg25 = 0x89, // base register 25 + SLEB128 offset
217 DW_OP_breg26 = 0x8A, // base register 26 + SLEB128 offset
218 DW_OP_breg27 = 0x8B, // base register 27 + SLEB128 offset
219 DW_OP_breg28 = 0x8C, // base register 28 + SLEB128 offset
220 DW_OP_breg29 = 0x8D, // base register 29 + SLEB128 offset
221 DW_OP_breg30 = 0x8E, // base register 30 + SLEB128 offset
222 DW_OP_breg31 = 0x8F, // base register 31 + SLEB128 offset
223 DW_OP_regx = 0x90, // ULEB128 register
224 DW_OP_fbreg = 0x91, // SLEB128 offset
225 DW_OP_bregx = 0x92, // ULEB128 register followed by SLEB128 offset
226 DW_OP_piece = 0x93, // ULEB128 size of piece addressed
227 DW_OP_deref_size = 0x94, // 1-byte size of data retrieved
228 DW_OP_xderef_size = 0x95, // 1-byte size of data retrieved
229 DW_OP_nop = 0x96,
230 DW_OP_push_object_addres = 0x97,
231 DW_OP_call2 = 0x98, // 2-byte offset of DIE
232 DW_OP_call4 = 0x99, // 4-byte offset of DIE
233 DW_OP_call_ref = 0x9A, // 4- or 8-byte offset of DIE
234 DW_OP_lo_user = 0xE0,
235 DW_OP_APPLE_uninit = 0xF0,
236 DW_OP_hi_user = 0xFF
237};
238
239
240#endif
libunwind/src/libunwind.cpp created+410
...@@ -0,0 +1,410 @@
1//===--------------------------- libunwind.cpp ----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Implements unw_* functions from <libunwind.h>
10//
11//===----------------------------------------------------------------------===//
12
13#include <libunwind.h>
14
15#ifndef NDEBUG
16#include <cstdlib> // getenv
17#endif
18#include <new>
19#include <algorithm>
20
21#include "libunwind_ext.h"
22#include "config.h"
23
24#include <stdlib.h>
25
26
27#if !defined(__USING_SJLJ_EXCEPTIONS__)
28#include "AddressSpace.hpp"
29#include "UnwindCursor.hpp"
30
31using namespace libunwind;
32
33/// internal object to represent this processes address space
34LocalAddressSpace LocalAddressSpace::sThisAddressSpace;
35
36_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
37 (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace;
38
39/// record the registers and stack position of the caller
40extern int unw_getcontext(unw_context_t *);
41// note: unw_getcontext() implemented in assembly
42
43/// Create a cursor of a thread in this process given 'context' recorded by
44/// unw_getcontext().
45_LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
46 unw_context_t *context) {
47 _LIBUNWIND_TRACE_API("unw_init_local(cursor=%p, context=%p)",
48 static_cast<void *>(cursor),
49 static_cast<void *>(context));
50#if defined(__i386__)
51# define REGISTER_KIND Registers_x86
52#elif defined(__x86_64__)
53# define REGISTER_KIND Registers_x86_64
54#elif defined(__powerpc64__)
55# define REGISTER_KIND Registers_ppc64
56#elif defined(__ppc__)
57# define REGISTER_KIND Registers_ppc
58#elif defined(__aarch64__)
59# define REGISTER_KIND Registers_arm64
60#elif defined(__arm__)
61# define REGISTER_KIND Registers_arm
62#elif defined(__or1k__)
63# define REGISTER_KIND Registers_or1k
64#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
65# define REGISTER_KIND Registers_mips_o32
66#elif defined(__mips64)
67# define REGISTER_KIND Registers_mips_newabi
68#elif defined(__mips__)
69# warning The MIPS architecture is not supported with this ABI and environment!
70#elif defined(__sparc__)
71# define REGISTER_KIND Registers_sparc
72#else
73# error Architecture not supported
74#endif
75 // Use "placement new" to allocate UnwindCursor in the cursor buffer.
76 new ((void *)cursor) UnwindCursor<LocalAddressSpace, REGISTER_KIND>(
77 context, LocalAddressSpace::sThisAddressSpace);
78#undef REGISTER_KIND
79 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
80 co->setInfoBasedOnIPRegister();
81
82 return UNW_ESUCCESS;
83}
84
85#ifdef UNW_REMOTE
86/// Create a cursor into a thread in another process.
87_LIBUNWIND_EXPORT int unw_init_remote_thread(unw_cursor_t *cursor,
88 unw_addr_space_t as,
89 void *arg) {
90 // special case: unw_init_remote(xx, unw_local_addr_space, xx)
91 if (as == (unw_addr_space_t)&LocalAddressSpace::sThisAddressSpace)
92 return unw_init_local(cursor, NULL); //FIXME
93
94 // use "placement new" to allocate UnwindCursor in the cursor buffer
95 switch (as->cpuType) {
96 case CPU_TYPE_I386:
97 new ((void *)cursor)
98 UnwindCursor<RemoteAddressSpace<Pointer32<LittleEndian>>,
99 Registers_x86>(((unw_addr_space_i386 *)as)->oas, arg);
100 break;
101 case CPU_TYPE_X86_64:
102 new ((void *)cursor)
103 UnwindCursor<RemoteAddressSpace<Pointer64<LittleEndian>>,
104 Registers_x86_64>(((unw_addr_space_x86_64 *)as)->oas, arg);
105 break;
106 case CPU_TYPE_POWERPC:
107 new ((void *)cursor)
108 UnwindCursor<RemoteAddressSpace<Pointer32<BigEndian>>,
109 Registers_ppc>(((unw_addr_space_ppc *)as)->oas, arg);
110 break;
111 default:
112 return UNW_EUNSPEC;
113 }
114 return UNW_ESUCCESS;
115}
116
117
118static bool is64bit(task_t task) {
119 return false; // FIXME
120}
121
122/// Create an address_space object for use in examining another task.
123_LIBUNWIND_EXPORT unw_addr_space_t unw_create_addr_space_for_task(task_t task) {
124#if __i386__
125 if (is64bit(task)) {
126 unw_addr_space_x86_64 *as = new unw_addr_space_x86_64(task);
127 as->taskPort = task;
128 as->cpuType = CPU_TYPE_X86_64;
129 //as->oas
130 } else {
131 unw_addr_space_i386 *as = new unw_addr_space_i386(task);
132 as->taskPort = task;
133 as->cpuType = CPU_TYPE_I386;
134 //as->oas
135 }
136#else
137// FIXME
138#endif
139}
140
141
142/// Delete an address_space object.
143_LIBUNWIND_EXPORT void unw_destroy_addr_space(unw_addr_space_t asp) {
144 switch (asp->cpuType) {
145#if __i386__ || __x86_64__
146 case CPU_TYPE_I386: {
147 unw_addr_space_i386 *as = (unw_addr_space_i386 *)asp;
148 delete as;
149 }
150 break;
151 case CPU_TYPE_X86_64: {
152 unw_addr_space_x86_64 *as = (unw_addr_space_x86_64 *)asp;
153 delete as;
154 }
155 break;
156#endif
157 case CPU_TYPE_POWERPC: {
158 unw_addr_space_ppc *as = (unw_addr_space_ppc *)asp;
159 delete as;
160 }
161 break;
162 }
163}
164#endif // UNW_REMOTE
165
166
167/// Get value of specified register at cursor position in stack frame.
168_LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
169 unw_word_t *value) {
170 _LIBUNWIND_TRACE_API("unw_get_reg(cursor=%p, regNum=%d, &value=%p)",
171 static_cast<void *>(cursor), regNum,
172 static_cast<void *>(value));
173 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
174 if (co->validReg(regNum)) {
175 *value = co->getReg(regNum);
176 return UNW_ESUCCESS;
177 }
178 return UNW_EBADREG;
179}
180
181
182/// Set value of specified register at cursor position in stack frame.
183_LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
184 unw_word_t value) {
185 _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR ")",
186 static_cast<void *>(cursor), regNum, value);
187 typedef LocalAddressSpace::pint_t pint_t;
188 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
189 if (co->validReg(regNum)) {
190 co->setReg(regNum, (pint_t)value);
191 // specical case altering IP to re-find info (being called by personality
192 // function)
193 if (regNum == UNW_REG_IP) {
194 unw_proc_info_t info;
195 // First, get the FDE for the old location and then update it.
196 co->getInfo(&info);
197 co->setInfoBasedOnIPRegister(false);
198 // If the original call expects stack adjustment, perform this now.
199 // Normal frame unwinding would have included the offset already in the
200 // CFA computation.
201 // Note: for PA-RISC and other platforms where the stack grows up,
202 // this should actually be - info.gp. LLVM doesn't currently support
203 // any such platforms and Clang doesn't export a macro for them.
204 if (info.gp)
205 co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp);
206 }
207 return UNW_ESUCCESS;
208 }
209 return UNW_EBADREG;
210}
211
212
213/// Get value of specified float register at cursor position in stack frame.
214_LIBUNWIND_EXPORT int unw_get_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
215 unw_fpreg_t *value) {
216 _LIBUNWIND_TRACE_API("unw_get_fpreg(cursor=%p, regNum=%d, &value=%p)",
217 static_cast<void *>(cursor), regNum,
218 static_cast<void *>(value));
219 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
220 if (co->validFloatReg(regNum)) {
221 *value = co->getFloatReg(regNum);
222 return UNW_ESUCCESS;
223 }
224 return UNW_EBADREG;
225}
226
227
228/// Set value of specified float register at cursor position in stack frame.
229_LIBUNWIND_EXPORT int unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum,
230 unw_fpreg_t value) {
231#if defined(_LIBUNWIND_ARM_EHABI)
232 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)",
233 static_cast<void *>(cursor), regNum, value);
234#else
235 _LIBUNWIND_TRACE_API("unw_set_fpreg(cursor=%p, regNum=%d, value=%g)",
236 static_cast<void *>(cursor), regNum, value);
237#endif
238 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
239 if (co->validFloatReg(regNum)) {
240 co->setFloatReg(regNum, value);
241 return UNW_ESUCCESS;
242 }
243 return UNW_EBADREG;
244}
245
246
247/// Move cursor to next frame.
248_LIBUNWIND_EXPORT int unw_step(unw_cursor_t *cursor) {
249 _LIBUNWIND_TRACE_API("unw_step(cursor=%p)", static_cast<void *>(cursor));
250 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
251 return co->step();
252}
253
254
255/// Get unwind info at cursor position in stack frame.
256_LIBUNWIND_EXPORT int unw_get_proc_info(unw_cursor_t *cursor,
257 unw_proc_info_t *info) {
258 _LIBUNWIND_TRACE_API("unw_get_proc_info(cursor=%p, &info=%p)",
259 static_cast<void *>(cursor), static_cast<void *>(info));
260 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
261 co->getInfo(info);
262 if (info->end_ip == 0)
263 return UNW_ENOINFO;
264 else
265 return UNW_ESUCCESS;
266}
267
268
269/// Resume execution at cursor position (aka longjump).
270_LIBUNWIND_EXPORT int unw_resume(unw_cursor_t *cursor) {
271 _LIBUNWIND_TRACE_API("unw_resume(cursor=%p)", static_cast<void *>(cursor));
272 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
273 co->jumpto();
274 return UNW_EUNSPEC;
275}
276
277
278/// Get name of function at cursor position in stack frame.
279_LIBUNWIND_EXPORT int unw_get_proc_name(unw_cursor_t *cursor, char *buf,
280 size_t bufLen, unw_word_t *offset) {
281 _LIBUNWIND_TRACE_API("unw_get_proc_name(cursor=%p, &buf=%p, bufLen=%lu)",
282 static_cast<void *>(cursor), static_cast<void *>(buf),
283 static_cast<unsigned long>(bufLen));
284 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
285 if (co->getFunctionName(buf, bufLen, offset))
286 return UNW_ESUCCESS;
287 else
288 return UNW_EUNSPEC;
289}
290
291
292/// Checks if a register is a floating-point register.
293_LIBUNWIND_EXPORT int unw_is_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum) {
294 _LIBUNWIND_TRACE_API("unw_is_fpreg(cursor=%p, regNum=%d)",
295 static_cast<void *>(cursor), regNum);
296 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
297 return co->validFloatReg(regNum);
298}
299
300
301/// Checks if a register is a floating-point register.
302_LIBUNWIND_EXPORT const char *unw_regname(unw_cursor_t *cursor,
303 unw_regnum_t regNum) {
304 _LIBUNWIND_TRACE_API("unw_regname(cursor=%p, regNum=%d)",
305 static_cast<void *>(cursor), regNum);
306 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
307 return co->getRegisterName(regNum);
308}
309
310
311/// Checks if current frame is signal trampoline.
312_LIBUNWIND_EXPORT int unw_is_signal_frame(unw_cursor_t *cursor) {
313 _LIBUNWIND_TRACE_API("unw_is_signal_frame(cursor=%p)",
314 static_cast<void *>(cursor));
315 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
316 return co->isSignalFrame();
317}
318
319#ifdef __arm__
320// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
321_LIBUNWIND_EXPORT void unw_save_vfp_as_X(unw_cursor_t *cursor) {
322 _LIBUNWIND_TRACE_API("unw_fpreg_save_vfp_as_X(cursor=%p)",
323 static_cast<void *>(cursor));
324 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
325 return co->saveVFPAsX();
326}
327#endif
328
329
330#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
331/// SPI: walks cached DWARF entries
332_LIBUNWIND_EXPORT void unw_iterate_dwarf_unwind_cache(void (*func)(
333 unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
334 _LIBUNWIND_TRACE_API("unw_iterate_dwarf_unwind_cache(func=%p)",
335 reinterpret_cast<void *>(func));
336 DwarfFDECache<LocalAddressSpace>::iterateCacheEntries(func);
337}
338
339
340/// IPI: for __register_frame()
341void _unw_add_dynamic_fde(unw_word_t fde) {
342 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
343 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
344 const char *message = CFI_Parser<LocalAddressSpace>::decodeFDE(
345 LocalAddressSpace::sThisAddressSpace,
346 (LocalAddressSpace::pint_t) fde, &fdeInfo, &cieInfo);
347 if (message == NULL) {
348 // dynamically registered FDEs don't have a mach_header group they are in.
349 // Use fde as mh_group
350 unw_word_t mh_group = fdeInfo.fdeStart;
351 DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group,
352 fdeInfo.pcStart, fdeInfo.pcEnd,
353 fdeInfo.fdeStart);
354 } else {
355 _LIBUNWIND_DEBUG_LOG("_unw_add_dynamic_fde: bad fde: %s", message);
356 }
357}
358
359/// IPI: for __deregister_frame()
360void _unw_remove_dynamic_fde(unw_word_t fde) {
361 // fde is own mh_group
362 DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde);
363}
364#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
365#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
366
367
368
369// Add logging hooks in Debug builds only
370#ifndef NDEBUG
371#include <stdlib.h>
372
373_LIBUNWIND_HIDDEN
374bool logAPIs() {
375 // do manual lock to avoid use of _cxa_guard_acquire or initializers
376 static bool checked = false;
377 static bool log = false;
378 if (!checked) {
379 log = (getenv("LIBUNWIND_PRINT_APIS") != NULL);
380 checked = true;
381 }
382 return log;
383}
384
385_LIBUNWIND_HIDDEN
386bool logUnwinding() {
387 // do manual lock to avoid use of _cxa_guard_acquire or initializers
388 static bool checked = false;
389 static bool log = false;
390 if (!checked) {
391 log = (getenv("LIBUNWIND_PRINT_UNWINDING") != NULL);
392 checked = true;
393 }
394 return log;
395}
396
397_LIBUNWIND_HIDDEN
398bool logDWARF() {
399 // do manual lock to avoid use of _cxa_guard_acquire or initializers
400 static bool checked = false;
401 static bool log = false;
402 if (!checked) {
403 log = (getenv("LIBUNWIND_PRINT_DWARF") != NULL);
404 checked = true;
405 }
406 return log;
407}
408
409#endif // NDEBUG
410
libunwind/src/libunwind_ext.h created+47
...@@ -0,0 +1,47 @@
1//===------------------------ libunwind_ext.h -----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//
9// Extensions to libunwind API.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef __LIBUNWIND_EXT__
14#define __LIBUNWIND_EXT__
15
16#include "config.h"
17#include <libunwind.h>
18#include <unwind.h>
19
20#define UNW_STEP_SUCCESS 1
21#define UNW_STEP_END 0
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26// SPI
27extern void unw_iterate_dwarf_unwind_cache(void (*func)(unw_word_t ip_start,
28 unw_word_t ip_end,
29 unw_word_t fde,
30 unw_word_t mh));
31
32// IPI
33extern void _unw_add_dynamic_fde(unw_word_t fde);
34extern void _unw_remove_dynamic_fde(unw_word_t fde);
35
36#if defined(_LIBUNWIND_ARM_EHABI)
37extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*);
38extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
39 const uint32_t *data,
40 size_t offset, size_t len);
41#endif
42
43#ifdef __cplusplus
44}
45#endif
46
47#endif // __LIBUNWIND_EXT__