1 //===--------------------------- Unwind-sjlj.c ----------------------------===// 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 setjump-longjump based C++ exceptions 9 // 10 //===----------------------------------------------------------------------===// 11 12 #include <unwind.h> 13 14 #include <inttypes.h> 15 #include <stdint.h> 16 #include <stdbool.h> 17 #include <stdlib.h> 18 19 #include "config.h" 20 21 /// With SJLJ based exceptions, any function that has a catch clause or needs to 22 /// do any clean up when an exception propagates through it, needs to call 23 /// \c _Unwind_SjLj_Register at the start of the function and 24 /// \c _Unwind_SjLj_Unregister at the end. The register function is called with 25 /// the address of a block of memory in the function's stack frame. The runtime 26 /// keeps a linked list (stack) of these blocks - one per thread. The calling 27 /// function also sets the personality and lsda fields of the block. 28 29 #if defined(_LIBUNWIND_BUILD_SJLJ_APIS) 30 31 struct _Unwind_FunctionContext { 32 // next function in stack of handlers 33 struct _Unwind_FunctionContext *prev; 34 35 // set by calling function before registering to be the landing pad 36 uint32_t resumeLocation; 37 38 // set by personality handler to be parameters passed to landing pad function 39 uint32_t resumeParameters[4]; 40 41 // set by calling function before registering 42 __personality_routine personality; // arm offset=24 43 uintptr_t lsda; // arm offset=28 44 45 // variable length array, contains registers to restore 46 // 0 = r7, 1 = pc, 2 = sp 47 void *jbuf[]; 48 }; 49 50 #if defined(_LIBUNWIND_HAS_NO_THREADS) 51 # define _LIBUNWIND_THREAD_LOCAL 52 #else 53 # if __STDC_VERSION__ >= 201112L 54 # define _LIBUNWIND_THREAD_LOCAL _Thread_local 55 # elif defined(_MSC_VER) 56 # define _LIBUNWIND_THREAD_LOCAL __declspec(thread) 57 # elif defined(__GNUC__) || defined(__clang__) 58 # define _LIBUNWIND_THREAD_LOCAL __thread 59 # else 60 # error Unable to create thread local storage 61 # endif 62 #endif 63 64 65 #if !defined(FOR_DYLD) 66 67 #if defined(__APPLE__) 68 #include <System/pthread_machdep.h> 69 #else 70 static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL; 71 #endif 72 73 static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() { 74 #if defined(__APPLE__) 75 return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key); 76 #else 77 return stack; 78 #endif 79 } 80 81 static void 82 __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) { 83 #if defined(__APPLE__) 84 _pthread_setspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key, fc); 85 #else 86 stack = fc; 87 #endif 88 } 89 90 #endif 91 92 93 /// Called at start of each function that catches exceptions 94 _LIBUNWIND_EXPORT void 95 _Unwind_SjLj_Register(struct _Unwind_FunctionContext *fc) { 96 fc->prev = __Unwind_SjLj_GetTopOfFunctionStack(); 97 __Unwind_SjLj_SetTopOfFunctionStack(fc); 98 } 99 100 101 /// Called at end of each function that catches exceptions 102 _LIBUNWIND_EXPORT void 103 _Unwind_SjLj_Unregister(struct _Unwind_FunctionContext *fc) { 104 __Unwind_SjLj_SetTopOfFunctionStack(fc->prev); 105 } 106 107 108 static _Unwind_Reason_Code 109 unwind_phase1(struct _Unwind_Exception *exception_object) { 110 _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); 111 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p", 112 (void *)c); 113 114 // walk each frame looking for a place to stop 115 for (bool handlerNotFound = true; handlerNotFound; c = c->prev) { 116 117 // check for no more frames 118 if (c == NULL) { 119 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): reached " 120 "bottom => _URC_END_OF_STACK", 121 (void *)exception_object); 122 return _URC_END_OF_STACK; 123 } 124 125 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p", (void *)c); 126 // if there is a personality routine, ask it if it will want to stop at this 127 // frame 128 if (c->personality != NULL) { 129 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling " 130 "personality function %p", 131 (void *)exception_object, 132 (void *)c->personality); 133 _Unwind_Reason_Code personalityResult = (*c->personality)( 134 1, _UA_SEARCH_PHASE, exception_object->exception_class, 135 exception_object, (struct _Unwind_Context *)c); 136 switch (personalityResult) { 137 case _URC_HANDLER_FOUND: 138 // found a catch clause or locals that need destructing in this frame 139 // stop search and remember function context 140 handlerNotFound = false; 141 exception_object->private_2 = (uintptr_t) c; 142 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " 143 "_URC_HANDLER_FOUND", 144 (void *)exception_object); 145 return _URC_NO_REASON; 146 147 case _URC_CONTINUE_UNWIND: 148 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " 149 "_URC_CONTINUE_UNWIND", 150 (void *)exception_object); 151 // continue unwinding 152 break; 153 154 default: 155 // something went wrong 156 _LIBUNWIND_TRACE_UNWINDING( 157 "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", 158 (void *)exception_object); 159 return _URC_FATAL_PHASE1_ERROR; 160 } 161 } 162 } 163 return _URC_NO_REASON; 164 } 165 166 167 static _Unwind_Reason_Code 168 unwind_phase2(struct _Unwind_Exception *exception_object) { 169 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", 170 (void *)exception_object); 171 172 // walk each frame until we reach where search phase said to stop 173 _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); 174 while (true) { 175 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p", 176 (void *)exception_object, (void *)c); 177 178 // check for no more frames 179 if (c == NULL) { 180 _LIBUNWIND_TRACE_UNWINDING( 181 "unwind_phase2(ex_ojb=%p): __unw_step() reached " 182 "bottom => _URC_END_OF_STACK", 183 (void *)exception_object); 184 return _URC_END_OF_STACK; 185 } 186 187 // if there is a personality routine, tell it we are unwinding 188 if (c->personality != NULL) { 189 _Unwind_Action action = _UA_CLEANUP_PHASE; 190 if ((uintptr_t) c == exception_object->private_2) 191 action = (_Unwind_Action)( 192 _UA_CLEANUP_PHASE | 193 _UA_HANDLER_FRAME); // tell personality this was the frame it marked 194 // in phase 1 195 _Unwind_Reason_Code personalityResult = 196 (*c->personality)(1, action, exception_object->exception_class, 197 exception_object, (struct _Unwind_Context *)c); 198 switch (personalityResult) { 199 case _URC_CONTINUE_UNWIND: 200 // continue unwinding 201 _LIBUNWIND_TRACE_UNWINDING( 202 "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", 203 (void *)exception_object); 204 if ((uintptr_t) c == exception_object->private_2) { 205 // phase 1 said we would stop at this frame, but we did not... 206 _LIBUNWIND_ABORT("during phase1 personality function said it would " 207 "stop here, but now if phase2 it did not stop here"); 208 } 209 break; 210 case _URC_INSTALL_CONTEXT: 211 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): " 212 "_URC_INSTALL_CONTEXT, will resume at " 213 "landing pad %p", 214 (void *)exception_object, c->jbuf[1]); 215 // personality routine says to transfer control to landing pad 216 // we may get control back if landing pad calls _Unwind_Resume() 217 __Unwind_SjLj_SetTopOfFunctionStack(c); 218 __builtin_longjmp(c->jbuf, 1); 219 // __unw_resume() only returns if there was an error 220 return _URC_FATAL_PHASE2_ERROR; 221 default: 222 // something went wrong 223 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", 224 personalityResult); 225 return _URC_FATAL_PHASE2_ERROR; 226 } 227 } 228 c = c->prev; 229 } 230 231 // clean up phase did not resume at the frame that the search phase said it 232 // would 233 return _URC_FATAL_PHASE2_ERROR; 234 } 235 236 237 static _Unwind_Reason_Code 238 unwind_phase2_forced(struct _Unwind_Exception *exception_object, 239 _Unwind_Stop_Fn stop, void *stop_parameter) { 240 // walk each frame until we reach where search phase said to stop 241 _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack(); 242 while (true) { 243 244 // get next frame (skip over first which is _Unwind_RaiseException) 245 if (c == NULL) { 246 _LIBUNWIND_TRACE_UNWINDING( 247 "unwind_phase2(ex_ojb=%p): __unw_step() reached " 248 "bottom => _URC_END_OF_STACK", 249 (void *)exception_object); 250 return _URC_END_OF_STACK; 251 } 252 253 // call stop function at each frame 254 _Unwind_Action action = 255 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); 256 _Unwind_Reason_Code stopResult = 257 (*stop)(1, action, exception_object->exception_class, exception_object, 258 (struct _Unwind_Context *)c, stop_parameter); 259 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 260 "stop function returned %d", 261 (void *)exception_object, stopResult); 262 if (stopResult != _URC_NO_REASON) { 263 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 264 "stopped by stop function", 265 (void *)exception_object); 266 return _URC_FATAL_PHASE2_ERROR; 267 } 268 269 // if there is a personality routine, tell it we are unwinding 270 if (c->personality != NULL) { 271 __personality_routine p = (__personality_routine) c->personality; 272 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 273 "calling personality function %p", 274 (void *)exception_object, (void *)p); 275 _Unwind_Reason_Code personalityResult = 276 (*p)(1, action, exception_object->exception_class, exception_object, 277 (struct _Unwind_Context *)c); 278 switch (personalityResult) { 279 case _URC_CONTINUE_UNWIND: 280 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 281 "personality returned _URC_CONTINUE_UNWIND", 282 (void *)exception_object); 283 // destructors called, continue unwinding 284 break; 285 case _URC_INSTALL_CONTEXT: 286 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 287 "personality returned _URC_INSTALL_CONTEXT", 288 (void *)exception_object); 289 // we may get control back if landing pad calls _Unwind_Resume() 290 __Unwind_SjLj_SetTopOfFunctionStack(c); 291 __builtin_longjmp(c->jbuf, 1); 292 break; 293 default: 294 // something went wrong 295 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 296 "personality returned %d, " 297 "_URC_FATAL_PHASE2_ERROR", 298 (void *)exception_object, personalityResult); 299 return _URC_FATAL_PHASE2_ERROR; 300 } 301 } 302 c = c->prev; 303 } 304 305 // call stop function one last time and tell it we've reached the end of the 306 // stack 307 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " 308 "function with _UA_END_OF_STACK", 309 (void *)exception_object); 310 _Unwind_Action lastAction = 311 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); 312 (*stop)(1, lastAction, exception_object->exception_class, exception_object, 313 (struct _Unwind_Context *)c, stop_parameter); 314 315 // clean up phase did not resume at the frame that the search phase said it 316 // would 317 return _URC_FATAL_PHASE2_ERROR; 318 } 319 320 321 /// Called by __cxa_throw. Only returns if there is a fatal error 322 _LIBUNWIND_EXPORT _Unwind_Reason_Code 323 _Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) { 324 _LIBUNWIND_TRACE_API("_Unwind_SjLj_RaiseException(ex_obj=%p)", 325 (void *)exception_object); 326 327 // mark that this is a non-forced unwind, so _Unwind_Resume() can do the right 328 // thing 329 exception_object->private_1 = 0; 330 exception_object->private_2 = 0; 331 332 // phase 1: the search phase 333 _Unwind_Reason_Code phase1 = unwind_phase1(exception_object); 334 if (phase1 != _URC_NO_REASON) 335 return phase1; 336 337 // phase 2: the clean up phase 338 return unwind_phase2(exception_object); 339 } 340 341 342 343 /// When _Unwind_RaiseException() is in phase2, it hands control 344 /// to the personality function at each frame. The personality 345 /// may force a jump to a landing pad in that function, the landing 346 /// pad code may then call _Unwind_Resume() to continue with the 347 /// unwinding. Note: the call to _Unwind_Resume() is from compiler 348 /// geneated user code. All other _Unwind_* routines are called 349 /// by the C++ runtime __cxa_* routines. 350 /// 351 /// Re-throwing an exception is implemented by having the code call 352 /// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow() 353 _LIBUNWIND_EXPORT void 354 _Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) { 355 _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)", 356 (void *)exception_object); 357 358 if (exception_object->private_1 != 0) 359 unwind_phase2_forced(exception_object, 360 (_Unwind_Stop_Fn) exception_object->private_1, 361 (void *)exception_object->private_2); 362 else 363 unwind_phase2(exception_object); 364 365 // clients assume _Unwind_Resume() does not return, so all we can do is abort. 366 _LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return"); 367 } 368 369 370 /// Called by __cxa_rethrow(). 371 _LIBUNWIND_EXPORT _Unwind_Reason_Code 372 _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) { 373 _LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), " 374 "private_1=%" PRIuPTR, 375 (void *)exception_object, exception_object->private_1); 376 // If this is non-forced and a stopping place was found, then this is a 377 // re-throw. 378 // Call _Unwind_RaiseException() as if this was a new exception. 379 if (exception_object->private_1 == 0) { 380 return _Unwind_SjLj_RaiseException(exception_object); 381 // should return if there is no catch clause, so that __cxa_rethrow can call 382 // std::terminate() 383 } 384 385 // Call through to _Unwind_Resume() which distiguishes between forced and 386 // regular exceptions. 387 _Unwind_SjLj_Resume(exception_object); 388 _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called " 389 "_Unwind_SjLj_Resume() which unexpectedly returned"); 390 } 391 392 393 /// Called by personality handler during phase 2 to get LSDA for current frame. 394 _LIBUNWIND_EXPORT uintptr_t 395 _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { 396 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; 397 _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) " 398 "=> 0x%" PRIuPTR, 399 (void *)context, ufc->lsda); 400 return ufc->lsda; 401 } 402 403 404 /// Called by personality handler during phase 2 to get register values. 405 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, 406 int index) { 407 _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d)", (void *)context, 408 index); 409 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; 410 return ufc->resumeParameters[index]; 411 } 412 413 414 /// Called by personality handler during phase 2 to alter register values. 415 _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, 416 uintptr_t new_value) { 417 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR 418 ")", 419 (void *)context, index, new_value); 420 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; 421 ufc->resumeParameters[index] = new_value; 422 } 423 424 425 /// Called by personality handler during phase 2 to get instruction pointer. 426 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { 427 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; 428 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32, 429 (void *)context, ufc->resumeLocation + 1); 430 return ufc->resumeLocation + 1; 431 } 432 433 434 /// Called by personality handler during phase 2 to get instruction pointer. 435 /// ipBefore is a boolean that says if IP is already adjusted to be the call 436 /// site address. Normally IP is the return address. 437 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, 438 int *ipBefore) { 439 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; 440 *ipBefore = 0; 441 _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32, 442 (void *)context, (void *)ipBefore, 443 ufc->resumeLocation + 1); 444 return ufc->resumeLocation + 1; 445 } 446 447 448 /// Called by personality handler during phase 2 to alter instruction pointer. 449 _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, 450 uintptr_t new_value) { 451 _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")", 452 (void *)context, new_value); 453 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; 454 ufc->resumeLocation = new_value - 1; 455 } 456 457 458 /// Called by personality handler during phase 2 to find the start of the 459 /// function. 460 _LIBUNWIND_EXPORT uintptr_t 461 _Unwind_GetRegionStart(struct _Unwind_Context *context) { 462 // Not supported or needed for sjlj based unwinding 463 (void)context; 464 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p)", (void *)context); 465 return 0; 466 } 467 468 469 /// Called by personality handler during phase 2 if a foreign exception 470 /// is caught. 471 _LIBUNWIND_EXPORT void 472 _Unwind_DeleteException(struct _Unwind_Exception *exception_object) { 473 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)", 474 (void *)exception_object); 475 if (exception_object->exception_cleanup != NULL) 476 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, 477 exception_object); 478 } 479 480 481 482 /// Called by personality handler during phase 2 to get base address for data 483 /// relative encodings. 484 _LIBUNWIND_EXPORT uintptr_t 485 _Unwind_GetDataRelBase(struct _Unwind_Context *context) { 486 // Not supported or needed for sjlj based unwinding 487 (void)context; 488 _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context); 489 _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented"); 490 } 491 492 493 /// Called by personality handler during phase 2 to get base address for text 494 /// relative encodings. 495 _LIBUNWIND_EXPORT uintptr_t 496 _Unwind_GetTextRelBase(struct _Unwind_Context *context) { 497 // Not supported or needed for sjlj based unwinding 498 (void)context; 499 _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)", (void *)context); 500 _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented"); 501 } 502 503 504 /// Called by personality handler to get "Call Frame Area" for current frame. 505 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { 506 _LIBUNWIND_TRACE_API("_Unwind_GetCFA(context=%p)", (void *)context); 507 if (context != NULL) { 508 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; 509 // Setjmp/longjmp based exceptions don't have a true CFA. 510 // Instead, the SP in the jmpbuf is the closest approximation. 511 return (uintptr_t) ufc->jbuf[2]; 512 } 513 return 0; 514 } 515 516 #endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS) 517