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 "cet_unwind.h" 29 #include "config.h" 30 #include "libunwind.h" 31 #include "libunwind_ext.h" 32 #include "unwind.h" 33 34 #if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) 35 36 #ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND 37 38 // When CET is enabled, each "call" instruction will push return address to 39 // CET shadow stack, each "ret" instruction will pop current CET shadow stack 40 // top and compare it with target address which program will return. 41 // In exception handing, some stack frames will be skipped before jumping to 42 // landing pad and we must adjust CET shadow stack accordingly. 43 // _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we 44 // directly jump to __libunwind_Registerts_x86/x86_64_jumpto instead of using 45 // a regular function call to avoid pushing to CET shadow stack again. 46 #if !defined(_LIBUNWIND_USE_CET) 47 #define __unw_phase2_resume(cursor, fn) __unw_resume((cursor)) 48 #elif defined(_LIBUNWIND_TARGET_I386) 49 #define __unw_phase2_resume(cursor, fn) \ 50 do { \ 51 _LIBUNWIND_POP_CET_SSP((fn)); \ 52 void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ 53 void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ 54 __asm__ volatile("push %%edi\n\t" \ 55 "sub $4, %%esp\n\t" \ 56 "jmp *%%edx\n\t" :: "D"(cetRegContext), \ 57 "d"(cetJumpAddress)); \ 58 } while (0) 59 #elif defined(_LIBUNWIND_TARGET_X86_64) 60 #define __unw_phase2_resume(cursor, fn) \ 61 do { \ 62 _LIBUNWIND_POP_CET_SSP((fn)); \ 63 void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ 64 void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ 65 __asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \ 66 "d"(cetJumpAddress)); \ 67 } while (0) 68 #endif 69 70 static _Unwind_Reason_Code 71 unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { 72 __unw_init_local(cursor, uc); 73 74 // Walk each frame looking for a place to stop. 75 while (true) { 76 // Ask libunwind to get next frame (skip over first which is 77 // _Unwind_RaiseException). 78 int stepResult = __unw_step(cursor); 79 if (stepResult == 0) { 80 _LIBUNWIND_TRACE_UNWINDING( 81 "unwind_phase1(ex_ojb=%p): __unw_step() reached " 82 "bottom => _URC_END_OF_STACK", 83 (void *)exception_object); 84 return _URC_END_OF_STACK; 85 } else if (stepResult < 0) { 86 _LIBUNWIND_TRACE_UNWINDING( 87 "unwind_phase1(ex_ojb=%p): __unw_step failed => " 88 "_URC_FATAL_PHASE1_ERROR", 89 (void *)exception_object); 90 return _URC_FATAL_PHASE1_ERROR; 91 } 92 93 // See if frame has code to run (has personality routine). 94 unw_proc_info_t frameInfo; 95 unw_word_t sp; 96 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { 97 _LIBUNWIND_TRACE_UNWINDING( 98 "unwind_phase1(ex_ojb=%p): __unw_get_proc_info " 99 "failed => _URC_FATAL_PHASE1_ERROR", 100 (void *)exception_object); 101 return _URC_FATAL_PHASE1_ERROR; 102 } 103 104 #ifndef NDEBUG 105 // When tracing, print state information. 106 if (_LIBUNWIND_TRACING_UNWINDING) { 107 char functionBuf[512]; 108 const char *functionName = functionBuf; 109 unw_word_t offset; 110 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), 111 &offset) != UNW_ESUCCESS) || 112 (frameInfo.start_ip + offset > frameInfo.end_ip)) 113 functionName = ".anonymous."; 114 unw_word_t pc; 115 __unw_get_reg(cursor, UNW_REG_IP, &pc); 116 _LIBUNWIND_TRACE_UNWINDING( 117 "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR 118 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "", 119 (void *)exception_object, pc, frameInfo.start_ip, functionName, 120 frameInfo.lsda, frameInfo.handler); 121 } 122 #endif 123 124 // If there is a personality routine, ask it if it will want to stop at 125 // this frame. 126 if (frameInfo.handler != 0) { 127 _Unwind_Personality_Fn p = 128 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); 129 _LIBUNWIND_TRACE_UNWINDING( 130 "unwind_phase1(ex_ojb=%p): calling personality function %p", 131 (void *)exception_object, (void *)(uintptr_t)p); 132 _Unwind_Reason_Code personalityResult = 133 (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class, 134 exception_object, (struct _Unwind_Context *)(cursor)); 135 switch (personalityResult) { 136 case _URC_HANDLER_FOUND: 137 // found a catch clause or locals that need destructing in this frame 138 // stop search and remember stack pointer at the frame 139 __unw_get_reg(cursor, UNW_REG_SP, &sp); 140 exception_object->private_2 = (uintptr_t)sp; 141 _LIBUNWIND_TRACE_UNWINDING( 142 "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND", 143 (void *)exception_object); 144 return _URC_NO_REASON; 145 146 case _URC_CONTINUE_UNWIND: 147 _LIBUNWIND_TRACE_UNWINDING( 148 "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND", 149 (void *)exception_object); 150 // continue unwinding 151 break; 152 153 default: 154 // something went wrong 155 _LIBUNWIND_TRACE_UNWINDING( 156 "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", 157 (void *)exception_object); 158 return _URC_FATAL_PHASE1_ERROR; 159 } 160 } 161 } 162 return _URC_NO_REASON; 163 } 164 165 166 static _Unwind_Reason_Code 167 unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { 168 __unw_init_local(cursor, uc); 169 170 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", 171 (void *)exception_object); 172 173 // uc is initialized by __unw_getcontext in the parent frame. The first stack 174 // frame walked is unwind_phase2. 175 unsigned framesWalked = 1; 176 // Walk each frame until we reach where search phase said to stop. 177 while (true) { 178 179 // Ask libunwind to get next frame (skip over first which is 180 // _Unwind_RaiseException). 181 int stepResult = __unw_step(cursor); 182 if (stepResult == 0) { 183 _LIBUNWIND_TRACE_UNWINDING( 184 "unwind_phase2(ex_ojb=%p): __unw_step() reached " 185 "bottom => _URC_END_OF_STACK", 186 (void *)exception_object); 187 return _URC_END_OF_STACK; 188 } else if (stepResult < 0) { 189 _LIBUNWIND_TRACE_UNWINDING( 190 "unwind_phase2(ex_ojb=%p): __unw_step failed => " 191 "_URC_FATAL_PHASE1_ERROR", 192 (void *)exception_object); 193 return _URC_FATAL_PHASE2_ERROR; 194 } 195 196 // Get info about this frame. 197 unw_word_t sp; 198 unw_proc_info_t frameInfo; 199 __unw_get_reg(cursor, UNW_REG_SP, &sp); 200 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { 201 _LIBUNWIND_TRACE_UNWINDING( 202 "unwind_phase2(ex_ojb=%p): __unw_get_proc_info " 203 "failed => _URC_FATAL_PHASE1_ERROR", 204 (void *)exception_object); 205 return _URC_FATAL_PHASE2_ERROR; 206 } 207 208 #ifndef NDEBUG 209 // When tracing, print state information. 210 if (_LIBUNWIND_TRACING_UNWINDING) { 211 char functionBuf[512]; 212 const char *functionName = functionBuf; 213 unw_word_t offset; 214 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), 215 &offset) != UNW_ESUCCESS) || 216 (frameInfo.start_ip + offset > frameInfo.end_ip)) 217 functionName = ".anonymous."; 218 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR 219 ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR 220 ", personality=0x%" PRIxPTR, 221 (void *)exception_object, frameInfo.start_ip, 222 functionName, sp, frameInfo.lsda, 223 frameInfo.handler); 224 } 225 #endif 226 227 ++framesWalked; 228 // If there is a personality routine, tell it we are unwinding. 229 if (frameInfo.handler != 0) { 230 _Unwind_Personality_Fn p = 231 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); 232 _Unwind_Action action = _UA_CLEANUP_PHASE; 233 if (sp == exception_object->private_2) { 234 // Tell personality this was the frame it marked in phase 1. 235 action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME); 236 } 237 _Unwind_Reason_Code personalityResult = 238 (*p)(1, action, exception_object->exception_class, exception_object, 239 (struct _Unwind_Context *)(cursor)); 240 switch (personalityResult) { 241 case _URC_CONTINUE_UNWIND: 242 // Continue unwinding 243 _LIBUNWIND_TRACE_UNWINDING( 244 "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", 245 (void *)exception_object); 246 if (sp == exception_object->private_2) { 247 // Phase 1 said we would stop at this frame, but we did not... 248 _LIBUNWIND_ABORT("during phase1 personality function said it would " 249 "stop here, but now in phase2 it did not stop here"); 250 } 251 break; 252 case _URC_INSTALL_CONTEXT: 253 _LIBUNWIND_TRACE_UNWINDING( 254 "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT", 255 (void *)exception_object); 256 // Personality routine says to transfer control to landing pad. 257 // We may get control back if landing pad calls _Unwind_Resume(). 258 if (_LIBUNWIND_TRACING_UNWINDING) { 259 unw_word_t pc; 260 __unw_get_reg(cursor, UNW_REG_IP, &pc); 261 __unw_get_reg(cursor, UNW_REG_SP, &sp); 262 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " 263 "user code with ip=0x%" PRIxPTR 264 ", sp=0x%" PRIxPTR, 265 (void *)exception_object, pc, sp); 266 } 267 268 __unw_phase2_resume(cursor, framesWalked); 269 // __unw_phase2_resume() only returns if there was an error. 270 return _URC_FATAL_PHASE2_ERROR; 271 default: 272 // Personality routine returned an unknown result code. 273 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", 274 personalityResult); 275 return _URC_FATAL_PHASE2_ERROR; 276 } 277 } 278 } 279 280 // Clean up phase did not resume at the frame that the search phase 281 // said it would... 282 return _URC_FATAL_PHASE2_ERROR; 283 } 284 285 static _Unwind_Reason_Code 286 unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, 287 _Unwind_Exception *exception_object, 288 _Unwind_Stop_Fn stop, void *stop_parameter) { 289 __unw_init_local(cursor, uc); 290 291 // uc is initialized by __unw_getcontext in the parent frame. The first stack 292 // frame walked is unwind_phase2_forced. 293 unsigned framesWalked = 1; 294 // Walk each frame until we reach where search phase said to stop 295 while (__unw_step(cursor) > 0) { 296 297 // Update info about this frame. 298 unw_proc_info_t frameInfo; 299 if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { 300 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step " 301 "failed => _URC_END_OF_STACK", 302 (void *)exception_object); 303 return _URC_FATAL_PHASE2_ERROR; 304 } 305 306 #ifndef NDEBUG 307 // When tracing, print state information. 308 if (_LIBUNWIND_TRACING_UNWINDING) { 309 char functionBuf[512]; 310 const char *functionName = functionBuf; 311 unw_word_t offset; 312 if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), 313 &offset) != UNW_ESUCCESS) || 314 (frameInfo.start_ip + offset > frameInfo.end_ip)) 315 functionName = ".anonymous."; 316 _LIBUNWIND_TRACE_UNWINDING( 317 "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR 318 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, 319 (void *)exception_object, frameInfo.start_ip, functionName, 320 frameInfo.lsda, frameInfo.handler); 321 } 322 #endif 323 324 // Call stop function at each frame. 325 _Unwind_Action action = 326 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); 327 _Unwind_Reason_Code stopResult = 328 (*stop)(1, action, exception_object->exception_class, exception_object, 329 (struct _Unwind_Context *)(cursor), stop_parameter); 330 _LIBUNWIND_TRACE_UNWINDING( 331 "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", 332 (void *)exception_object, stopResult); 333 if (stopResult != _URC_NO_REASON) { 334 _LIBUNWIND_TRACE_UNWINDING( 335 "unwind_phase2_forced(ex_ojb=%p): stopped by stop function", 336 (void *)exception_object); 337 return _URC_FATAL_PHASE2_ERROR; 338 } 339 340 ++framesWalked; 341 // If there is a personality routine, tell it we are unwinding. 342 if (frameInfo.handler != 0) { 343 _Unwind_Personality_Fn p = 344 (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); 345 _LIBUNWIND_TRACE_UNWINDING( 346 "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", 347 (void *)exception_object, (void *)(uintptr_t)p); 348 _Unwind_Reason_Code personalityResult = 349 (*p)(1, action, exception_object->exception_class, exception_object, 350 (struct _Unwind_Context *)(cursor)); 351 switch (personalityResult) { 352 case _URC_CONTINUE_UNWIND: 353 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 354 "personality returned " 355 "_URC_CONTINUE_UNWIND", 356 (void *)exception_object); 357 // Destructors called, continue unwinding 358 break; 359 case _URC_INSTALL_CONTEXT: 360 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 361 "personality returned " 362 "_URC_INSTALL_CONTEXT", 363 (void *)exception_object); 364 // We may get control back if landing pad calls _Unwind_Resume(). 365 __unw_phase2_resume(cursor, framesWalked); 366 break; 367 default: 368 // Personality routine returned an unknown result code. 369 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 370 "personality returned %d, " 371 "_URC_FATAL_PHASE2_ERROR", 372 (void *)exception_object, personalityResult); 373 return _URC_FATAL_PHASE2_ERROR; 374 } 375 } 376 } 377 378 // Call stop function one last time and tell it we've reached the end 379 // of the stack. 380 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " 381 "function with _UA_END_OF_STACK", 382 (void *)exception_object); 383 _Unwind_Action lastAction = 384 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); 385 (*stop)(1, lastAction, exception_object->exception_class, exception_object, 386 (struct _Unwind_Context *)(cursor), stop_parameter); 387 388 // Clean up phase did not resume at the frame that the search phase said it 389 // would. 390 return _URC_FATAL_PHASE2_ERROR; 391 } 392 393 394 /// Called by __cxa_throw. Only returns if there is a fatal error. 395 _LIBUNWIND_EXPORT _Unwind_Reason_Code 396 _Unwind_RaiseException(_Unwind_Exception *exception_object) { 397 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)", 398 (void *)exception_object); 399 unw_context_t uc; 400 unw_cursor_t cursor; 401 __unw_getcontext(&uc); 402 403 // Mark that this is a non-forced unwind, so _Unwind_Resume() 404 // can do the right thing. 405 exception_object->private_1 = 0; 406 exception_object->private_2 = 0; 407 408 // phase 1: the search phase 409 _Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object); 410 if (phase1 != _URC_NO_REASON) 411 return phase1; 412 413 // phase 2: the clean up phase 414 return unwind_phase2(&uc, &cursor, exception_object); 415 } 416 417 418 419 /// When _Unwind_RaiseException() is in phase2, it hands control 420 /// to the personality function at each frame. The personality 421 /// may force a jump to a landing pad in that function, the landing 422 /// pad code may then call _Unwind_Resume() to continue with the 423 /// unwinding. Note: the call to _Unwind_Resume() is from compiler 424 /// geneated user code. All other _Unwind_* routines are called 425 /// by the C++ runtime __cxa_* routines. 426 /// 427 /// Note: re-throwing an exception (as opposed to continuing the unwind) 428 /// is implemented by having the code call __cxa_rethrow() which 429 /// in turn calls _Unwind_Resume_or_Rethrow(). 430 _LIBUNWIND_EXPORT void 431 _Unwind_Resume(_Unwind_Exception *exception_object) { 432 _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)", (void *)exception_object); 433 unw_context_t uc; 434 unw_cursor_t cursor; 435 __unw_getcontext(&uc); 436 437 if (exception_object->private_1 != 0) 438 unwind_phase2_forced(&uc, &cursor, exception_object, 439 (_Unwind_Stop_Fn) exception_object->private_1, 440 (void *)exception_object->private_2); 441 else 442 unwind_phase2(&uc, &cursor, exception_object); 443 444 // Clients assume _Unwind_Resume() does not return, so all we can do is abort. 445 _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); 446 } 447 448 449 450 /// Not used by C++. 451 /// Unwinds stack, calling "stop" function at each frame. 452 /// Could be used to implement longjmp(). 453 _LIBUNWIND_EXPORT _Unwind_Reason_Code 454 _Unwind_ForcedUnwind(_Unwind_Exception *exception_object, 455 _Unwind_Stop_Fn stop, void *stop_parameter) { 456 _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)", 457 (void *)exception_object, (void *)(uintptr_t)stop); 458 unw_context_t uc; 459 unw_cursor_t cursor; 460 __unw_getcontext(&uc); 461 462 // Mark that this is a forced unwind, so _Unwind_Resume() can do 463 // the right thing. 464 exception_object->private_1 = (uintptr_t) stop; 465 exception_object->private_2 = (uintptr_t) stop_parameter; 466 467 // do it 468 return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter); 469 } 470 471 472 /// Called by personality handler during phase 2 to get LSDA for current frame. 473 _LIBUNWIND_EXPORT uintptr_t 474 _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { 475 unw_cursor_t *cursor = (unw_cursor_t *)context; 476 unw_proc_info_t frameInfo; 477 uintptr_t result = 0; 478 if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) 479 result = (uintptr_t)frameInfo.lsda; 480 _LIBUNWIND_TRACE_API( 481 "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR, 482 (void *)context, result); 483 if (result != 0) { 484 if (*((uint8_t *)result) != 0xFF) 485 _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF", 486 result); 487 } 488 return result; 489 } 490 491 492 /// Called by personality handler during phase 2 to find the start of the 493 /// function. 494 _LIBUNWIND_EXPORT uintptr_t 495 _Unwind_GetRegionStart(struct _Unwind_Context *context) { 496 unw_cursor_t *cursor = (unw_cursor_t *)context; 497 unw_proc_info_t frameInfo; 498 uintptr_t result = 0; 499 if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) 500 result = (uintptr_t)frameInfo.start_ip; 501 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%" PRIxPTR, 502 (void *)context, result); 503 return result; 504 } 505 506 #endif // !_LIBUNWIND_SUPPORT_SEH_UNWIND 507 508 /// Called by personality handler during phase 2 if a foreign exception 509 // is caught. 510 _LIBUNWIND_EXPORT void 511 _Unwind_DeleteException(_Unwind_Exception *exception_object) { 512 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", 513 (void *)exception_object); 514 if (exception_object->exception_cleanup != NULL) 515 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, 516 exception_object); 517 } 518 519 /// Called by personality handler during phase 2 to get register values. 520 _LIBUNWIND_EXPORT uintptr_t 521 _Unwind_GetGR(struct _Unwind_Context *context, int index) { 522 unw_cursor_t *cursor = (unw_cursor_t *)context; 523 unw_word_t result; 524 __unw_get_reg(cursor, index, &result); 525 _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%" PRIxPTR, 526 (void *)context, index, result); 527 return (uintptr_t)result; 528 } 529 530 /// Called by personality handler during phase 2 to alter register values. 531 _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, 532 uintptr_t value) { 533 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%0" PRIxPTR 534 ")", 535 (void *)context, index, value); 536 unw_cursor_t *cursor = (unw_cursor_t *)context; 537 __unw_set_reg(cursor, index, value); 538 } 539 540 /// Called by personality handler during phase 2 to get instruction pointer. 541 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { 542 unw_cursor_t *cursor = (unw_cursor_t *)context; 543 unw_word_t result; 544 __unw_get_reg(cursor, UNW_REG_IP, &result); 545 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR, 546 (void *)context, result); 547 return (uintptr_t)result; 548 } 549 550 /// Called by personality handler during phase 2 to alter instruction pointer, 551 /// such as setting where the landing pad is, so _Unwind_Resume() will 552 /// start executing in the landing pad. 553 _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, 554 uintptr_t value) { 555 _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0" PRIxPTR ")", 556 (void *)context, value); 557 unw_cursor_t *cursor = (unw_cursor_t *)context; 558 __unw_set_reg(cursor, UNW_REG_IP, value); 559 } 560 561 #endif // !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) 562