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