1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8// Implements C++ ABI Exception Handling Level 1 as documented at:
9// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
10// using libunwind
11//
12//===----------------------------------------------------------------------===//
13
14// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are
15// defining inline functions to delegate the function calls to
16// _Unwind_VRS_{Get,Set}(). However, some applications might declare the
17// function protetype directly (instead of including <unwind.h>), thus we need
18// to export these functions from libunwind.so as well.
19#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1
20
21#include <inttypes.h>
22#include <stdint.h>
23#include <stdbool.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27
28#include "config.h"
29#include "libunwind.h"
30#include "libunwind_ext.h"
31#include "shadow_stack_unwind.h"
32#include "unwind.h"
33
34#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
35 !defined(__wasm__)
36
37#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
38
39// When shadow stack is enabled, a separate stack containing only return
40// addresses would be maintained. On function return, the return address would
41// be compared to the popped address from shadow stack to ensure the return
42// target is not tempered with. When unwinding, we're skipping the normal return
43// procedure for multiple frames and thus need to pop the return addresses of
44// the skipped frames from shadow stack to avoid triggering an exception (using
45// `_LIBUNWIND_POP_SHSTK_SSP()`). Also, some architectures, like the x86-family
46// CET, push the return adddresses onto shadow stack with common call
47// instructions, so for these architectures, normal function calls should be
48// avoided when invoking the `jumpto()` function. To do this, we use inline
49// assemblies to "goto" the `jumpto()` for these architectures.
50#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)
51#define __unw_phase2_resume(cursor, fn) \
52 do { \
53 (void)fn; \
54 __unw_resume((cursor)); \
55 } while (0)
56#elif defined(_LIBUNWIND_TARGET_I386)
57#define __shstk_step_size (4)
58#define __unw_phase2_resume(cursor, fn) \
59 do { \
60 _LIBUNWIND_POP_SHSTK_SSP((fn)); \
61 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
62 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
63 __asm__ volatile("push %%edi\n\t" \
64 "sub $4, %%esp\n\t" \
65 "jmp *%%edx\n\t" ::"D"(shstkRegContext), \
66 "d"(shstkJumpAddress)); \
67 } while (0)
68#elif defined(_LIBUNWIND_TARGET_X86_64)
69#define __shstk_step_size (8)
70#define __unw_phase2_resume(cursor, fn) \
71 do { \
72 _LIBUNWIND_POP_SHSTK_SSP((fn)); \
73 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
74 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
75 __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \
76 "d"(shstkJumpAddress)); \
77 } while (0)
78#elif defined(_LIBUNWIND_TARGET_AARCH64)
79#define __shstk_step_size (8)
80#define __unw_phase2_resume(cursor, fn) \
81 do { \
82 _LIBUNWIND_POP_SHSTK_SSP((fn)); \
83 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
84 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
85 __asm__ volatile("mov x0, %0\n\t" \
86 "br %1\n\t" \
87 : \
88 : "r"(shstkRegContext), "r"(shstkJumpAddress) \
89 : "x0"); \
90 } while (0)
91#endif
92
93static _Unwind_Reason_Code
94unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
95 __unw_init_local(cursor, uc);
96
97 // Walk each frame looking for a place to stop.
98 while (true) {
99 // Ask libunwind to get next frame (skip over first which is
100 // _Unwind_RaiseException).
101 int stepResult = __unw_step(cursor);
102 if (stepResult == 0) {
103 _LIBUNWIND_TRACE_UNWINDING(
104 "unwind_phase1(ex_obj=%p): __unw_step() reached "
105 "bottom => _URC_END_OF_STACK",
106 (void *)exception_object);
107 return _URC_END_OF_STACK;
108 } else if (stepResult < 0) {
109 _LIBUNWIND_TRACE_UNWINDING(
110 "unwind_phase1(ex_obj=%p): __unw_step failed => "
111 "_URC_FATAL_PHASE1_ERROR",
112 (void *)exception_object);
113 return _URC_FATAL_PHASE1_ERROR;
114 }
115
116 // See if frame has code to run (has personality routine).
117 unw_proc_info_t frameInfo;
118 unw_word_t sp;
119 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
120 _LIBUNWIND_TRACE_UNWINDING(
121 "unwind_phase1(ex_obj=%p): __unw_get_proc_info "
122 "failed => _URC_FATAL_PHASE1_ERROR",
123 (void *)exception_object);
124 return _URC_FATAL_PHASE1_ERROR;
125 }
126
127#ifndef NDEBUG
128 // When tracing, print state information.
129 if (_LIBUNWIND_TRACING_UNWINDING) {
130 char functionBuf[512];
131 const char *functionName = functionBuf;
132 unw_word_t offset;
133 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
134 &offset) != UNW_ESUCCESS) ||
135 (frameInfo.start_ip + offset > frameInfo.end_ip))
136 functionName = ".anonymous.";
137 unw_word_t pc;
138 __unw_get_reg(cursor, UNW_REG_IP, &pc);
139 _LIBUNWIND_TRACE_UNWINDING(
140 "unwind_phase1(ex_obj=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR
141 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",
142 (void *)exception_object, pc, frameInfo.start_ip, functionName,
143 frameInfo.lsda, frameInfo.handler);
144 }
145#endif
146
147 // If there is a personality routine, ask it if it will want to stop at
148 // this frame.
149 if (frameInfo.handler != 0) {
150 _Unwind_Personality_Fn p =
151 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
152 _LIBUNWIND_TRACE_UNWINDING(
153 "unwind_phase1(ex_obj=%p): calling personality function %p",
154 (void *)exception_object, (void *)(uintptr_t)p);
155 _Unwind_Reason_Code personalityResult =
156 (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
157 exception_object, (struct _Unwind_Context *)(cursor));
158 switch (personalityResult) {
159 case _URC_HANDLER_FOUND:
160 // found a catch clause or locals that need destructing in this frame
161 // stop search and remember stack pointer at the frame
162 __unw_get_reg(cursor, UNW_REG_SP, &sp);
163 exception_object->private_2 = (uintptr_t)sp;
164 _LIBUNWIND_TRACE_UNWINDING(
165 "unwind_phase1(ex_obj=%p): _URC_HANDLER_FOUND",
166 (void *)exception_object);
167 return _URC_NO_REASON;
168
169 case _URC_CONTINUE_UNWIND:
170 _LIBUNWIND_TRACE_UNWINDING(
171 "unwind_phase1(ex_obj=%p): _URC_CONTINUE_UNWIND",
172 (void *)exception_object);
173 // continue unwinding
174 break;
175
176 default:
177 // something went wrong
178 _LIBUNWIND_TRACE_UNWINDING(
179 "unwind_phase1(ex_obj=%p): _URC_FATAL_PHASE1_ERROR",
180 (void *)exception_object);
181 return _URC_FATAL_PHASE1_ERROR;
182 }
183 }
184 }
185 return _URC_NO_REASON;
186}
187extern int __unw_step_stage2(unw_cursor_t *);
188
189#if defined(_LIBUNWIND_USE_GCS)
190// Enable the GCS target feature to permit gcspop instructions to be used.
191__attribute__((target("+gcs")))
192#endif
193static _Unwind_Reason_Code
194unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
195 _Unwind_Exception *exception_object) {
196 __unw_init_local(cursor, uc);
197
198 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
199 (void *)exception_object);
200
201 // uc is initialized by __unw_getcontext in the parent frame. The first stack
202 // frame walked is unwind_phase2.
203 unsigned framesWalked = 1;
204#if defined(_LIBUNWIND_USE_CET)
205 unsigned long shadowStackTop = _get_ssp();
206#elif defined(_LIBUNWIND_USE_GCS)
207 unsigned long shadowStackTop = 0;
208 if (__chkfeat(_CHKFEAT_GCS))
209 shadowStackTop = (unsigned long)__gcspr();
210#endif
211 // Walk each frame until we reach where search phase said to stop.
212 while (true) {
213
214 // Ask libunwind to get next frame (skip over first which is
215 // _Unwind_RaiseException).
216 int stepResult = __unw_step_stage2(cursor);
217 if (stepResult == 0) {
218 _LIBUNWIND_TRACE_UNWINDING(
219 "unwind_phase2(ex_obj=%p): __unw_step_stage2() reached "
220 "bottom => _URC_END_OF_STACK",
221 (void *)exception_object);
222 return _URC_END_OF_STACK;
223 } else if (stepResult < 0) {
224 _LIBUNWIND_TRACE_UNWINDING(
225 "unwind_phase2(ex_obj=%p): __unw_step_stage2 failed => "
226 "_URC_FATAL_PHASE1_ERROR",
227 (void *)exception_object);
228 return _URC_FATAL_PHASE2_ERROR;
229 }
230
231 // Get info about this frame.
232 unw_word_t sp;
233 unw_proc_info_t frameInfo;
234 __unw_get_reg(cursor, UNW_REG_SP, &sp);
235 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
236 _LIBUNWIND_TRACE_UNWINDING(
237 "unwind_phase2(ex_obj=%p): __unw_get_proc_info "
238 "failed => _URC_FATAL_PHASE1_ERROR",
239 (void *)exception_object);
240 return _URC_FATAL_PHASE2_ERROR;
241 }
242
243#ifndef NDEBUG
244 // When tracing, print state information.
245 if (_LIBUNWIND_TRACING_UNWINDING) {
246 char functionBuf[512];
247 const char *functionName = functionBuf;
248 unw_word_t offset;
249 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
250 &offset) != UNW_ESUCCESS) ||
251 (frameInfo.start_ip + offset > frameInfo.end_ip))
252 functionName = ".anonymous.";
253 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): start_ip=0x%" PRIxPTR
254 ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR
255 ", personality=0x%" PRIxPTR,
256 (void *)exception_object, frameInfo.start_ip,
257 functionName, sp, frameInfo.lsda,
258 frameInfo.handler);
259 }
260#endif
261
262// In shadow stack enabled environment, we check return address stored in normal
263// stack against return address stored in shadow stack, if the 2 addresses don't
264// match, it means return address in normal stack has been corrupted, we return
265// _URC_FATAL_PHASE2_ERROR.
266#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
267 if (shadowStackTop != 0) {
268 unw_word_t retInNormalStack;
269 __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);
270 unsigned long retInShadowStack =
271 *(unsigned long *)(shadowStackTop + __shstk_step_size * framesWalked);
272 if (retInNormalStack != retInShadowStack)
273 return _URC_FATAL_PHASE2_ERROR;
274 }
275#endif
276 ++framesWalked;
277 // If there is a personality routine, tell it we are unwinding.
278 if (frameInfo.handler != 0) {
279 _Unwind_Personality_Fn p =
280 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
281 _Unwind_Action action = _UA_CLEANUP_PHASE;
282 if (sp == exception_object->private_2) {
283 // Tell personality this was the frame it marked in phase 1.
284 action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
285 }
286 _Unwind_Reason_Code personalityResult =
287 (*p)(1, action, exception_object->exception_class, exception_object,
288 (struct _Unwind_Context *)(cursor));
289 switch (personalityResult) {
290 case _URC_CONTINUE_UNWIND:
291 // Continue unwinding
292 _LIBUNWIND_TRACE_UNWINDING(
293 "unwind_phase2(ex_obj=%p): _URC_CONTINUE_UNWIND",
294 (void *)exception_object);
295 if (sp == exception_object->private_2) {
296 // Phase 1 said we would stop at this frame, but we did not...
297 _LIBUNWIND_ABORT("during phase1 personality function said it would "
298 "stop here, but now in phase2 it did not stop here");
299 }
300 break;
301 case _URC_INSTALL_CONTEXT:
302 _LIBUNWIND_TRACE_UNWINDING(
303 "unwind_phase2(ex_obj=%p): _URC_INSTALL_CONTEXT",
304 (void *)exception_object);
305 // Personality routine says to transfer control to landing pad.
306 // We may get control back if landing pad calls _Unwind_Resume().
307 if (_LIBUNWIND_TRACING_UNWINDING) {
308 unw_word_t pc;
309 __unw_get_reg(cursor, UNW_REG_IP, &pc);
310 __unw_get_reg(cursor, UNW_REG_SP, &sp);
311 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): re-entering "
312 "user code with ip=0x%" PRIxPTR
313 ", sp=0x%" PRIxPTR,
314 (void *)exception_object, pc, sp);
315 }
316
317 __unw_phase2_resume(cursor, framesWalked);
318 // __unw_phase2_resume() only returns if there was an error.
319 return _URC_FATAL_PHASE2_ERROR;
320 default:
321 // Personality routine returned an unknown result code.
322 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
323 personalityResult);
324 return _URC_FATAL_PHASE2_ERROR;
325 }
326 }
327 }
328
329 // Clean up phase did not resume at the frame that the search phase
330 // said it would...
331 return _URC_FATAL_PHASE2_ERROR;
332}
333
334#if defined(_LIBUNWIND_USE_GCS)
335// Enable the GCS target feature to permit gcspop instructions to be used.
336__attribute__((target("+gcs")))
337#endif
338static _Unwind_Reason_Code
339unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
340 _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,
341 void *stop_parameter) {
342 __unw_init_local(cursor, uc);
343
344 // uc is initialized by __unw_getcontext in the parent frame. The first stack
345 // frame walked is unwind_phase2_forced.
346 unsigned framesWalked = 1;
347 // Walk each frame until we reach where search phase said to stop
348 while (__unw_step_stage2(cursor) > 0) {
349
350 // Update info about this frame.
351 unw_proc_info_t frameInfo;
352 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
353 _LIBUNWIND_TRACE_UNWINDING(
354 "unwind_phase2_forced(ex_obj=%p): __unw_get_proc_info "
355 "failed => _URC_END_OF_STACK",
356 (void *)exception_object);
357 return _URC_FATAL_PHASE2_ERROR;
358 }
359
360#ifndef NDEBUG
361 // When tracing, print state information.
362 if (_LIBUNWIND_TRACING_UNWINDING) {
363 char functionBuf[512];
364 const char *functionName = functionBuf;
365 unw_word_t offset;
366 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
367 &offset) != UNW_ESUCCESS) ||
368 (frameInfo.start_ip + offset > frameInfo.end_ip))
369 functionName = ".anonymous.";
370 _LIBUNWIND_TRACE_UNWINDING(
371 "unwind_phase2_forced(ex_obj=%p): start_ip=0x%" PRIxPTR
372 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
373 (void *)exception_object, frameInfo.start_ip, functionName,
374 frameInfo.lsda, frameInfo.handler);
375 }
376#endif
377
378 // Call stop function at each frame.
379 _Unwind_Action action =
380 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
381 _Unwind_Reason_Code stopResult =
382 (*stop)(1, action, exception_object->exception_class, exception_object,
383 (struct _Unwind_Context *)(cursor), stop_parameter);
384 _LIBUNWIND_TRACE_UNWINDING(
385 "unwind_phase2_forced(ex_obj=%p): stop function returned %d",
386 (void *)exception_object, stopResult);
387 if (stopResult != _URC_NO_REASON) {
388 _LIBUNWIND_TRACE_UNWINDING(
389 "unwind_phase2_forced(ex_obj=%p): stopped by stop function",
390 (void *)exception_object);
391 return _URC_FATAL_PHASE2_ERROR;
392 }
393
394 ++framesWalked;
395 // If there is a personality routine, tell it we are unwinding.
396 if (frameInfo.handler != 0) {
397 _Unwind_Personality_Fn p =
398 (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);
399 _LIBUNWIND_TRACE_UNWINDING(
400 "unwind_phase2_forced(ex_obj=%p): calling personality function %p",
401 (void *)exception_object, (void *)(uintptr_t)p);
402 _Unwind_Reason_Code personalityResult =
403 (*p)(1, action, exception_object->exception_class, exception_object,
404 (struct _Unwind_Context *)(cursor));
405 switch (personalityResult) {
406 case _URC_CONTINUE_UNWIND:
407 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
408 "personality returned "
409 "_URC_CONTINUE_UNWIND",
410 (void *)exception_object);
411 // Destructors called, continue unwinding
412 break;
413 case _URC_INSTALL_CONTEXT:
414 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
415 "personality returned "
416 "_URC_INSTALL_CONTEXT",
417 (void *)exception_object);
418 // We may get control back if landing pad calls _Unwind_Resume().
419 __unw_phase2_resume(cursor, framesWalked);
420 break;
421 default:
422 // Personality routine returned an unknown result code.
423 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
424 "personality returned %d, "
425 "_URC_FATAL_PHASE2_ERROR",
426 (void *)exception_object, personalityResult);
427 return _URC_FATAL_PHASE2_ERROR;
428 }
429 }
430 }
431
432 // Call stop function one last time and tell it we've reached the end
433 // of the stack.
434 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): calling stop "
435 "function with _UA_END_OF_STACK",
436 (void *)exception_object);
437 _Unwind_Action lastAction =
438 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
439 (*stop)(1, lastAction, exception_object->exception_class, exception_object,
440 (struct _Unwind_Context *)(cursor), stop_parameter);
441
442 // Clean up phase did not resume at the frame that the search phase said it
443 // would.
444 return _URC_FATAL_PHASE2_ERROR;
445}
446
447/// Called by __cxa_throw. Only returns if there is a fatal error.
448_LIBUNWIND_EXPORT _Unwind_Reason_Code
449_Unwind_RaiseException(_Unwind_Exception *exception_object) {
450 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
451 (void *)exception_object);
452 unw_context_t uc;
453 unw_cursor_t cursor;
454 __unw_getcontext(&uc);
455
456 // Mark that this is a non-forced unwind, so _Unwind_Resume()
457 // can do the right thing.
458 exception_object->private_1 = 0;
459 exception_object->private_2 = 0;
460
461 // phase 1: the search phase
462 _Unwind_Reason_Code phase1 = unwind_phase1(uc: &uc, cursor: &cursor, exception_object);
463 if (phase1 != _URC_NO_REASON)
464 return phase1;
465
466 // phase 2: the clean up phase
467 return unwind_phase2(uc: &uc, cursor: &cursor, exception_object);
468}
469
470
471
472/// When _Unwind_RaiseException() is in phase2, it hands control
473/// to the personality function at each frame. The personality
474/// may force a jump to a landing pad in that function, the landing
475/// pad code may then call _Unwind_Resume() to continue with the
476/// unwinding. Note: the call to _Unwind_Resume() is from compiler
477/// generated user code. All other _Unwind_* routines are called
478/// by the C++ runtime __cxa_* routines.
479///
480/// Note: re-throwing an exception (as opposed to continuing the unwind)
481/// is implemented by having the code call __cxa_rethrow() which
482/// in turn calls _Unwind_Resume_or_Rethrow().
483_LIBUNWIND_EXPORT void
484_Unwind_Resume(_Unwind_Exception *exception_object) {
485 _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object);
486 unw_context_t uc;
487 unw_cursor_t cursor;
488 __unw_getcontext(&uc);
489
490 if (exception_object->private_1 != 0)
491 unwind_phase2_forced(uc: &uc, cursor: &cursor, exception_object,
492 stop: (_Unwind_Stop_Fn) exception_object->private_1,
493 stop_parameter: (void *)exception_object->private_2);
494 else
495 unwind_phase2(uc: &uc, cursor: &cursor, exception_object);
496
497 // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
498 _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
499}
500
501
502
503/// Not used by C++.
504/// Unwinds stack, calling "stop" function at each frame.
505/// Could be used to implement longjmp().
506_LIBUNWIND_EXPORT _Unwind_Reason_Code
507_Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
508 _Unwind_Stop_Fn stop, void *stop_parameter) {
509 _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
510 (void *)exception_object, (void *)(uintptr_t)stop);
511 unw_context_t uc;
512 unw_cursor_t cursor;
513 __unw_getcontext(&uc);
514
515 // Mark that this is a forced unwind, so _Unwind_Resume() can do
516 // the right thing.
517 exception_object->private_1 = (uintptr_t) stop;
518 exception_object->private_2 = (uintptr_t) stop_parameter;
519
520 // do it
521 return unwind_phase2_forced(uc: &uc, cursor: &cursor, exception_object, stop, stop_parameter);
522}
523
524
525/// Called by personality handler during phase 2 to get LSDA for current frame.
526_LIBUNWIND_EXPORT uintptr_t
527_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
528 unw_cursor_t *cursor = (unw_cursor_t *)context;
529 unw_proc_info_t frameInfo;
530 uintptr_t result = 0;
531 if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
532 result = (uintptr_t)frameInfo.lsda;
533 _LIBUNWIND_TRACE_API(
534 "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
535 (void *)context, result);
536#if !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
537 if (result != 0) {
538 if (*((uint8_t *)result) != 0xFF)
539 _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",
540 result);
541 }
542#endif
543 return result;
544}
545
546
547/// Called by personality handler during phase 2 to find the start of the
548/// function.
549_LIBUNWIND_EXPORT uintptr_t
550_Unwind_GetRegionStart(struct _Unwind_Context *context) {
551 unw_cursor_t *cursor = (unw_cursor_t *)context;
552 unw_proc_info_t frameInfo;
553 uintptr_t result = 0;
554 if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
555 result = (uintptr_t)frameInfo.start_ip;
556 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR,
557 (void *)context, result);
558 return result;
559}
560
561#endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND
562
563/// Called by personality handler during phase 2 if a foreign exception
564// is caught.
565_LIBUNWIND_EXPORT void
566_Unwind_DeleteException(_Unwind_Exception *exception_object) {
567 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
568 (void *)exception_object);
569 if (exception_object->exception_cleanup != NULL)
570 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
571 exception_object);
572}
573
574/// Called by personality handler during phase 2 to get register values.
575_LIBUNWIND_EXPORT uintptr_t
576_Unwind_GetGR(struct _Unwind_Context *context, int index) {
577 unw_cursor_t *cursor = (unw_cursor_t *)context;
578 unw_word_t result;
579 __unw_get_reg(cursor, index, &result);
580 _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIxPTR,
581 (void *)context, index, result);
582 return (uintptr_t)result;
583}
584
585/// Called by personality handler during phase 2 to alter register values.
586_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
587 uintptr_t value) {
588 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIxPTR
589 ")",
590 (void *)context, index, value);
591 unw_cursor_t *cursor = (unw_cursor_t *)context;
592 __unw_set_reg(cursor, index, value);
593}
594
595/// Called by personality handler during phase 2 to get instruction pointer.
596_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
597 unw_cursor_t *cursor = (unw_cursor_t *)context;
598 unw_word_t result;
599 __unw_get_reg(cursor, UNW_REG_IP, &result);
600 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
601 (void *)context, result);
602 return (uintptr_t)result;
603}
604
605/// Called by personality handler during phase 2 to alter instruction pointer,
606/// such as setting where the landing pad is, so _Unwind_Resume() will
607/// start executing in the landing pad.
608_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
609 uintptr_t value) {
610 _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIxPTR ")",
611 (void *)context, value);
612 unw_cursor_t *cursor = (unw_cursor_t *)context;
613 __unw_set_reg(cursor, UNW_REG_IP, value);
614}
615
616#endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__)
617