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, _Unwind_Exception *exception_object) {
195 __unw_init_local(cursor, uc);
196
197 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
198 (void *)exception_object);
199
200 // uc is initialized by __unw_getcontext in the parent frame. The first stack
201 // frame walked is unwind_phase2.
202 unsigned framesWalked = 1;
203#if defined(_LIBUNWIND_USE_CET)
204 unsigned long shadowStackTop = _get_ssp();
205#elif defined(_LIBUNWIND_USE_GCS)
206 unsigned long shadowStackTop = 0;
207 if (__chkfeat(_CHKFEAT_GCS))
208 shadowStackTop = (unsigned long)__gcspr();
209#endif
210 // Walk each frame until we reach where search phase said to stop.
211 while (true) {
212
213 // Ask libunwind to get next frame (skip over first which is
214 // _Unwind_RaiseException).
215 int stepResult = __unw_step_stage2(cursor);
216 if (stepResult == 0) {
217 _LIBUNWIND_TRACE_UNWINDING(
218 "unwind_phase2(ex_obj=%p): __unw_step_stage2() reached "
219 "bottom => _URC_END_OF_STACK",
220 (void *)exception_object);
221 return _URC_END_OF_STACK;
222 } else if (stepResult < 0) {
223 _LIBUNWIND_TRACE_UNWINDING(
224 "unwind_phase2(ex_obj=%p): __unw_step_stage2 failed => "
225 "_URC_FATAL_PHASE1_ERROR",
226 (void *)exception_object);
227 return _URC_FATAL_PHASE2_ERROR;
228 }
229
230 // Get info about this frame.
231 unw_word_t sp;
232 unw_proc_info_t frameInfo;
233 __unw_get_reg(cursor, UNW_REG_SP, &sp);
234 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
235 _LIBUNWIND_TRACE_UNWINDING(
236 "unwind_phase2(ex_obj=%p): __unw_get_proc_info "
237 "failed => _URC_FATAL_PHASE1_ERROR",
238 (void *)exception_object);
239 return _URC_FATAL_PHASE2_ERROR;
240 }
241
242#ifndef NDEBUG
243 // When tracing, print state information.
244 if (_LIBUNWIND_TRACING_UNWINDING) {
245 char functionBuf[512];
246 const char *functionName = functionBuf;
247 unw_word_t offset;
248 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
249 &offset) != UNW_ESUCCESS) ||
250 (frameInfo.start_ip + offset > frameInfo.end_ip))
251 functionName = ".anonymous.";
252 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): start_ip=0x%" PRIxPTR
253 ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR
254 ", personality=0x%" PRIxPTR,
255 (void *)exception_object, frameInfo.start_ip,
256 functionName, sp, frameInfo.lsda,
257 frameInfo.handler);
258 }
259#endif
260
261// In shadow stack enabled environment, we check return address stored in normal
262// stack against return address stored in shadow stack, if the 2 addresses don't
263// match, it means return address in normal stack has been corrupted, we return
264// _URC_FATAL_PHASE2_ERROR.
265#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
266 if (shadowStackTop != 0) {
267 unw_word_t retInNormalStack;
268 __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);
269 unsigned long retInShadowStack =
270 *(unsigned long *)(shadowStackTop + __shstk_step_size * framesWalked);
271 if (retInNormalStack != retInShadowStack)
272 return _URC_FATAL_PHASE2_ERROR;
273 }
274#endif
275 ++framesWalked;
276 // If there is a personality routine, tell it we are unwinding.
277 if (frameInfo.handler != 0) {
278 _Unwind_Personality_Fn p =
279 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
280 _Unwind_Action action = _UA_CLEANUP_PHASE;
281 if (sp == exception_object->private_2) {
282 // Tell personality this was the frame it marked in phase 1.
283 action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
284 }
285 _Unwind_Reason_Code personalityResult =
286 (*p)(1, action, exception_object->exception_class, exception_object,
287 (struct _Unwind_Context *)(cursor));
288 switch (personalityResult) {
289 case _URC_CONTINUE_UNWIND:
290 // Continue unwinding
291 _LIBUNWIND_TRACE_UNWINDING(
292 "unwind_phase2(ex_obj=%p): _URC_CONTINUE_UNWIND",
293 (void *)exception_object);
294 if (sp == exception_object->private_2) {
295 // Phase 1 said we would stop at this frame, but we did not...
296 _LIBUNWIND_ABORT("during phase1 personality function said it would "
297 "stop here, but now in phase2 it did not stop here");
298 }
299 break;
300 case _URC_INSTALL_CONTEXT:
301 _LIBUNWIND_TRACE_UNWINDING(
302 "unwind_phase2(ex_obj=%p): _URC_INSTALL_CONTEXT",
303 (void *)exception_object);
304 // Personality routine says to transfer control to landing pad.
305 // We may get control back if landing pad calls _Unwind_Resume().
306 if (_LIBUNWIND_TRACING_UNWINDING) {
307 unw_word_t pc;
308 __unw_get_reg(cursor, UNW_REG_IP, &pc);
309 __unw_get_reg(cursor, UNW_REG_SP, &sp);
310 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): re-entering "
311 "user code with ip=0x%" PRIxPTR
312 ", sp=0x%" PRIxPTR,
313 (void *)exception_object, pc, sp);
314 }
315
316 __unw_phase2_resume(cursor, framesWalked);
317 // __unw_phase2_resume() only returns if there was an error.
318 return _URC_FATAL_PHASE2_ERROR;
319 default:
320 // Personality routine returned an unknown result code.
321 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
322 personalityResult);
323 return _URC_FATAL_PHASE2_ERROR;
324 }
325 }
326 }
327
328 // Clean up phase did not resume at the frame that the search phase
329 // said it would...
330 return _URC_FATAL_PHASE2_ERROR;
331}
332
333#if defined(_LIBUNWIND_USE_GCS)
334// Enable the GCS target feature to permit gcspop instructions to be used.
335__attribute__((target("gcs")))
336#endif
337static _Unwind_Reason_Code
338unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
339 _Unwind_Exception *exception_object,
340 _Unwind_Stop_Fn stop, void *stop_parameter) {
341 __unw_init_local(cursor, uc);
342
343 // uc is initialized by __unw_getcontext in the parent frame. The first stack
344 // frame walked is unwind_phase2_forced.
345 unsigned framesWalked = 1;
346 // Walk each frame until we reach where search phase said to stop
347 while (__unw_step_stage2(cursor) > 0) {
348
349 // Update info about this frame.
350 unw_proc_info_t frameInfo;
351 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
352 _LIBUNWIND_TRACE_UNWINDING(
353 "unwind_phase2_forced(ex_obj=%p): __unw_get_proc_info "
354 "failed => _URC_END_OF_STACK",
355 (void *)exception_object);
356 return _URC_FATAL_PHASE2_ERROR;
357 }
358
359#ifndef NDEBUG
360 // When tracing, print state information.
361 if (_LIBUNWIND_TRACING_UNWINDING) {
362 char functionBuf[512];
363 const char *functionName = functionBuf;
364 unw_word_t offset;
365 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
366 &offset) != UNW_ESUCCESS) ||
367 (frameInfo.start_ip + offset > frameInfo.end_ip))
368 functionName = ".anonymous.";
369 _LIBUNWIND_TRACE_UNWINDING(
370 "unwind_phase2_forced(ex_obj=%p): start_ip=0x%" PRIxPTR
371 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
372 (void *)exception_object, frameInfo.start_ip, functionName,
373 frameInfo.lsda, frameInfo.handler);
374 }
375#endif
376
377 // Call stop function at each frame.
378 _Unwind_Action action =
379 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
380 _Unwind_Reason_Code stopResult =
381 (*stop)(1, action, exception_object->exception_class, exception_object,
382 (struct _Unwind_Context *)(cursor), stop_parameter);
383 _LIBUNWIND_TRACE_UNWINDING(
384 "unwind_phase2_forced(ex_obj=%p): stop function returned %d",
385 (void *)exception_object, stopResult);
386 if (stopResult != _URC_NO_REASON) {
387 _LIBUNWIND_TRACE_UNWINDING(
388 "unwind_phase2_forced(ex_obj=%p): stopped by stop function",
389 (void *)exception_object);
390 return _URC_FATAL_PHASE2_ERROR;
391 }
392
393 ++framesWalked;
394 // If there is a personality routine, tell it we are unwinding.
395 if (frameInfo.handler != 0) {
396 _Unwind_Personality_Fn p =
397 (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);
398 _LIBUNWIND_TRACE_UNWINDING(
399 "unwind_phase2_forced(ex_obj=%p): calling personality function %p",
400 (void *)exception_object, (void *)(uintptr_t)p);
401 _Unwind_Reason_Code personalityResult =
402 (*p)(1, action, exception_object->exception_class, exception_object,
403 (struct _Unwind_Context *)(cursor));
404 switch (personalityResult) {
405 case _URC_CONTINUE_UNWIND:
406 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
407 "personality returned "
408 "_URC_CONTINUE_UNWIND",
409 (void *)exception_object);
410 // Destructors called, continue unwinding
411 break;
412 case _URC_INSTALL_CONTEXT:
413 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
414 "personality returned "
415 "_URC_INSTALL_CONTEXT",
416 (void *)exception_object);
417 // We may get control back if landing pad calls _Unwind_Resume().
418 __unw_phase2_resume(cursor, framesWalked);
419 break;
420 default:
421 // Personality routine returned an unknown result code.
422 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
423 "personality returned %d, "
424 "_URC_FATAL_PHASE2_ERROR",
425 (void *)exception_object, personalityResult);
426 return _URC_FATAL_PHASE2_ERROR;
427 }
428 }
429 }
430
431 // Call stop function one last time and tell it we've reached the end
432 // of the stack.
433 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): calling stop "
434 "function with _UA_END_OF_STACK",
435 (void *)exception_object);
436 _Unwind_Action lastAction =
437 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
438 (*stop)(1, lastAction, exception_object->exception_class, exception_object,
439 (struct _Unwind_Context *)(cursor), stop_parameter);
440
441 // Clean up phase did not resume at the frame that the search phase said it
442 // would.
443 return _URC_FATAL_PHASE2_ERROR;
444}
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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of libunwind/src/UnwindLevel1.c