1 //===------------------------- UnwindLevel1.c -----------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 // 9 // Implements C++ ABI Exception Handling Level 1 as documented at: 10 // http://mentorembedded.github.io/cxx-abi/abi-eh.html 11 // using libunwind 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include <stdint.h> 16 #include <stdbool.h> 17 #include <stdlib.h> 18 #include <stdio.h> 19 #include <string.h> 20 21 #include "libunwind.h" 22 #include "unwind.h" 23 #include "config.h" 24 25 #if _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI 26 27 static _Unwind_Reason_Code 28 unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) { 29 unw_cursor_t cursor1; 30 unw_init_local(&cursor1, uc); 31 32 // Walk each frame looking for a place to stop. 33 for (bool handlerNotFound = true; handlerNotFound;) { 34 35 // Ask libuwind to get next frame (skip over first which is 36 // _Unwind_RaiseException). 37 int stepResult = unw_step(&cursor1); 38 if (stepResult == 0) { 39 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached " 40 "bottom => _URC_END_OF_STACK\n", 41 exception_object); 42 return _URC_END_OF_STACK; 43 } else if (stepResult < 0) { 44 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step failed => " 45 "_URC_FATAL_PHASE1_ERROR\n", 46 exception_object); 47 return _URC_FATAL_PHASE1_ERROR; 48 } 49 50 // See if frame has code to run (has personality routine). 51 unw_proc_info_t frameInfo; 52 unw_word_t sp; 53 if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) { 54 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info " 55 "failed => _URC_FATAL_PHASE1_ERROR\n", 56 exception_object); 57 return _URC_FATAL_PHASE1_ERROR; 58 } 59 60 // When tracing, print state information. 61 if (_LIBUNWIND_TRACING_UNWINDING) { 62 char functionName[512]; 63 unw_word_t offset; 64 if ((unw_get_proc_name(&cursor1, functionName, 512, &offset) != 65 UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) 66 strcpy(functionName, ".anonymous."); 67 unw_word_t pc; 68 unw_get_reg(&cursor1, UNW_REG_IP, &pc); 69 _LIBUNWIND_TRACE_UNWINDING( 70 "unwind_phase1(ex_ojb=%p): pc=0x%llX, start_ip=0x%llX, func=%s, " 71 "lsda=0x%llX, personality=0x%llX\n", 72 exception_object, pc, frameInfo.start_ip, functionName, 73 frameInfo.lsda, frameInfo.handler); 74 } 75 76 // If there is a personality routine, ask it if it will want to stop at 77 // this frame. 78 if (frameInfo.handler != 0) { 79 __personality_routine p = 80 (__personality_routine)(long)(frameInfo.handler); 81 _LIBUNWIND_TRACE_UNWINDING( 82 "unwind_phase1(ex_ojb=%p): calling personality function %p\n", 83 exception_object, p); 84 _Unwind_Reason_Code personalityResult = 85 (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class, 86 exception_object, (struct _Unwind_Context *)(&cursor1)); 87 switch (personalityResult) { 88 case _URC_HANDLER_FOUND: 89 // found a catch clause or locals that need destructing in this frame 90 // stop search and remember stack pointer at the frame 91 handlerNotFound = false; 92 unw_get_reg(&cursor1, UNW_REG_SP, &sp); 93 exception_object->private_2 = (uintptr_t)sp; 94 _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): " 95 "_URC_HANDLER_FOUND \n", 96 exception_object); 97 return _URC_NO_REASON; 98 99 case _URC_CONTINUE_UNWIND: 100 _LIBUNWIND_TRACE_UNWINDING( 101 "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", 102 exception_object); 103 // continue unwinding 104 break; 105 106 default: 107 // something went wrong 108 _LIBUNWIND_TRACE_UNWINDING( 109 "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n", 110 exception_object); 111 return _URC_FATAL_PHASE1_ERROR; 112 } 113 } 114 } 115 return _URC_NO_REASON; 116 } 117 118 119 static _Unwind_Reason_Code 120 unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) { 121 unw_cursor_t cursor2; 122 unw_init_local(&cursor2, uc); 123 124 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object); 125 126 // Walk each frame until we reach where search phase said to stop. 127 while (true) { 128 129 // Ask libuwind to get next frame (skip over first which is 130 // _Unwind_RaiseException). 131 int stepResult = unw_step(&cursor2); 132 if (stepResult == 0) { 133 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached " 134 "bottom => _URC_END_OF_STACK\n", 135 exception_object); 136 return _URC_END_OF_STACK; 137 } else if (stepResult < 0) { 138 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => " 139 "_URC_FATAL_PHASE1_ERROR\n", 140 exception_object); 141 return _URC_FATAL_PHASE2_ERROR; 142 } 143 144 // Get info about this frame. 145 unw_word_t sp; 146 unw_proc_info_t frameInfo; 147 unw_get_reg(&cursor2, UNW_REG_SP, &sp); 148 if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { 149 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info " 150 "failed => _URC_FATAL_PHASE1_ERROR\n", 151 exception_object); 152 return _URC_FATAL_PHASE2_ERROR; 153 } 154 155 // When tracing, print state information. 156 if (_LIBUNWIND_TRACING_UNWINDING) { 157 char functionName[512]; 158 unw_word_t offset; 159 if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) != 160 UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) 161 strcpy(functionName, ".anonymous."); 162 _LIBUNWIND_TRACE_UNWINDING( 163 "unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, " 164 "lsda=0x%llX, personality=0x%llX\n", 165 exception_object, frameInfo.start_ip, functionName, sp, 166 frameInfo.lsda, frameInfo.handler); 167 } 168 169 // If there is a personality routine, tell it we are unwinding. 170 if (frameInfo.handler != 0) { 171 __personality_routine p = 172 (__personality_routine)(long)(frameInfo.handler); 173 _Unwind_Action action = _UA_CLEANUP_PHASE; 174 if (sp == exception_object->private_2) { 175 // Tell personality this was the frame it marked in phase 1. 176 action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME); 177 } 178 _Unwind_Reason_Code personalityResult = 179 (*p)(1, action, exception_object->exception_class, exception_object, 180 (struct _Unwind_Context *)(&cursor2)); 181 switch (personalityResult) { 182 case _URC_CONTINUE_UNWIND: 183 // Continue unwinding 184 _LIBUNWIND_TRACE_UNWINDING( 185 "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n", 186 exception_object); 187 if (sp == exception_object->private_2) { 188 // Phase 1 said we would stop at this frame, but we did not... 189 _LIBUNWIND_ABORT("during phase1 personality function said it would " 190 "stop here, but now in phase2 it did not stop here"); 191 } 192 break; 193 case _URC_INSTALL_CONTEXT: 194 _LIBUNWIND_TRACE_UNWINDING( 195 "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n", 196 exception_object); 197 // Personality routine says to transfer control to landing pad. 198 // We may get control back if landing pad calls _Unwind_Resume(). 199 if (_LIBUNWIND_TRACING_UNWINDING) { 200 unw_word_t pc; 201 unw_get_reg(&cursor2, UNW_REG_IP, &pc); 202 unw_get_reg(&cursor2, UNW_REG_SP, &sp); 203 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " 204 "user code with ip=0x%llX, sp=0x%llX\n", 205 exception_object, pc, sp); 206 } 207 unw_resume(&cursor2); 208 // unw_resume() only returns if there was an error. 209 return _URC_FATAL_PHASE2_ERROR; 210 default: 211 // Personality routine returned an unknown result code. 212 _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d", 213 personalityResult); 214 return _URC_FATAL_PHASE2_ERROR; 215 } 216 } 217 } 218 219 // Clean up phase did not resume at the frame that the search phase 220 // said it would... 221 return _URC_FATAL_PHASE2_ERROR; 222 } 223 224 static _Unwind_Reason_Code 225 unwind_phase2_forced(unw_context_t *uc, 226 _Unwind_Exception *exception_object, 227 _Unwind_Stop_Fn stop, void *stop_parameter) { 228 unw_cursor_t cursor2; 229 unw_init_local(&cursor2, uc); 230 231 // Walk each frame until we reach where search phase said to stop 232 while (unw_step(&cursor2) > 0) { 233 234 // Update info about this frame. 235 unw_proc_info_t frameInfo; 236 if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) { 237 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step " 238 "failed => _URC_END_OF_STACK\n", 239 exception_object); 240 return _URC_FATAL_PHASE2_ERROR; 241 } 242 243 // When tracing, print state information. 244 if (_LIBUNWIND_TRACING_UNWINDING) { 245 char functionName[512]; 246 unw_word_t offset; 247 if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) != 248 UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) 249 strcpy(functionName, ".anonymous."); 250 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 251 "start_ip=0x%llX, func=%s, lsda=0x%llX, " 252 " personality=0x%llX\n", 253 exception_object, frameInfo.start_ip, 254 functionName, frameInfo.lsda, 255 frameInfo.handler); 256 } 257 258 // Call stop function at each frame. 259 _Unwind_Action action = 260 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); 261 _Unwind_Reason_Code stopResult = 262 (*stop)(1, action, exception_object->exception_class, exception_object, 263 (struct _Unwind_Context *)(&cursor2), stop_parameter); 264 _LIBUNWIND_TRACE_UNWINDING( 265 "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n", 266 exception_object, stopResult); 267 if (stopResult != _URC_NO_REASON) { 268 _LIBUNWIND_TRACE_UNWINDING( 269 "unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n", 270 exception_object); 271 return _URC_FATAL_PHASE2_ERROR; 272 } 273 274 // If there is a personality routine, tell it we are unwinding. 275 if (frameInfo.handler != 0) { 276 __personality_routine p = 277 (__personality_routine)(long)(frameInfo.handler); 278 _LIBUNWIND_TRACE_UNWINDING( 279 "unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n", 280 exception_object, p); 281 _Unwind_Reason_Code personalityResult = 282 (*p)(1, action, exception_object->exception_class, exception_object, 283 (struct _Unwind_Context *)(&cursor2)); 284 switch (personalityResult) { 285 case _URC_CONTINUE_UNWIND: 286 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 287 "personality returned _URC_CONTINUE_UNWIND\n", 288 exception_object); 289 // Destructors called, continue unwinding 290 break; 291 case _URC_INSTALL_CONTEXT: 292 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 293 "personality returned _URC_INSTALL_CONTEXT\n", 294 exception_object); 295 // We may get control back if landing pad calls _Unwind_Resume(). 296 unw_resume(&cursor2); 297 break; 298 default: 299 // Personality routine returned an unknown result code. 300 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " 301 "personality returned %d, " 302 "_URC_FATAL_PHASE2_ERROR\n", 303 exception_object, personalityResult); 304 return _URC_FATAL_PHASE2_ERROR; 305 } 306 } 307 } 308 309 // Call stop function one last time and tell it we've reached the end 310 // of the stack. 311 _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " 312 "function with _UA_END_OF_STACK\n", 313 exception_object); 314 _Unwind_Action lastAction = 315 (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); 316 (*stop)(1, lastAction, exception_object->exception_class, exception_object, 317 (struct _Unwind_Context *)(&cursor2), stop_parameter); 318 319 // Clean up phase did not resume at the frame that the search phase said it 320 // would. 321 return _URC_FATAL_PHASE2_ERROR; 322 } 323 324 325 /// Called by __cxa_throw. Only returns if there is a fatal error. 326 _LIBUNWIND_EXPORT _Unwind_Reason_Code 327 _Unwind_RaiseException(_Unwind_Exception *exception_object) { 328 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n", 329 exception_object); 330 unw_context_t uc; 331 unw_getcontext(&uc); 332 333 // Mark that this is a non-forced unwind, so _Unwind_Resume() 334 // can do the right thing. 335 exception_object->private_1 = 0; 336 exception_object->private_2 = 0; 337 338 // phase 1: the search phase 339 _Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object); 340 if (phase1 != _URC_NO_REASON) 341 return phase1; 342 343 // phase 2: the clean up phase 344 return unwind_phase2(&uc, exception_object); 345 } 346 347 348 349 /// When _Unwind_RaiseException() is in phase2, it hands control 350 /// to the personality function at each frame. The personality 351 /// may force a jump to a landing pad in that function, the landing 352 /// pad code may then call _Unwind_Resume() to continue with the 353 /// unwinding. Note: the call to _Unwind_Resume() is from compiler 354 /// geneated user code. All other _Unwind_* routines are called 355 /// by the C++ runtime __cxa_* routines. 356 /// 357 /// Note: re-throwing an exception (as opposed to continuing the unwind) 358 /// is implemented by having the code call __cxa_rethrow() which 359 /// in turn calls _Unwind_Resume_or_Rethrow(). 360 _LIBUNWIND_EXPORT void 361 _Unwind_Resume(_Unwind_Exception *exception_object) { 362 _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", exception_object); 363 unw_context_t uc; 364 unw_getcontext(&uc); 365 366 if (exception_object->private_1 != 0) 367 unwind_phase2_forced(&uc, exception_object, 368 (_Unwind_Stop_Fn) exception_object->private_1, 369 (void *)exception_object->private_2); 370 else 371 unwind_phase2(&uc, exception_object); 372 373 // Clients assume _Unwind_Resume() does not return, so all we can do is abort. 374 _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); 375 } 376 377 378 379 /// Not used by C++. 380 /// Unwinds stack, calling "stop" function at each frame. 381 /// Could be used to implement longjmp(). 382 _LIBUNWIND_EXPORT _Unwind_Reason_Code 383 _Unwind_ForcedUnwind(_Unwind_Exception *exception_object, 384 _Unwind_Stop_Fn stop, void *stop_parameter) { 385 _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n", 386 exception_object, stop); 387 unw_context_t uc; 388 unw_getcontext(&uc); 389 390 // Mark that this is a forced unwind, so _Unwind_Resume() can do 391 // the right thing. 392 exception_object->private_1 = (uintptr_t) stop; 393 exception_object->private_2 = (uintptr_t) stop_parameter; 394 395 // do it 396 return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter); 397 } 398 399 400 /// Called by personality handler during phase 2 to get LSDA for current frame. 401 _LIBUNWIND_EXPORT uintptr_t 402 _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { 403 unw_cursor_t *cursor = (unw_cursor_t *)context; 404 unw_proc_info_t frameInfo; 405 uintptr_t result = 0; 406 if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) 407 result = (uintptr_t)frameInfo.lsda; 408 _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p)" 409 "=> 0x%lX\n", context, result); 410 if (result != 0) { 411 if (*((uint8_t *)result) != 0xFF) 412 _LIBUNWIND_DEBUG_LOG("lsda at 0x%lX does not start with 0xFF\n", result); 413 } 414 return result; 415 } 416 417 418 419 /// Called by personality handler during phase 2 to get register values. 420 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, 421 int index) { 422 unw_cursor_t *cursor = (unw_cursor_t *)context; 423 unw_word_t result; 424 unw_get_reg(cursor, index, &result); 425 _LIBUNWIND_TRACE_API("_Unwind_GetGR(context=%p, reg=%d) => 0x%llX\n", 426 context, 427 index, (uint64_t) result); 428 return (uintptr_t)result; 429 } 430 431 432 433 /// Called by personality handler during phase 2 to alter register values. 434 _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, 435 uintptr_t new_value) { 436 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, " 437 "value=0x%0llX)\n", context, 438 index, (uint64_t) new_value); 439 unw_cursor_t *cursor = (unw_cursor_t *)context; 440 unw_set_reg(cursor, index, new_value); 441 } 442 443 444 445 /// Called by personality handler during phase 2 to get instruction pointer. 446 _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { 447 unw_cursor_t *cursor = (unw_cursor_t *)context; 448 unw_word_t result; 449 unw_get_reg(cursor, UNW_REG_IP, &result); 450 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%llX\n", context, 451 (uint64_t) result); 452 return (uintptr_t)result; 453 } 454 455 456 457 /// Called by personality handler during phase 2 to alter instruction pointer, 458 /// such as setting where the landing pad is, so _Unwind_Resume() will 459 /// start executing in the landing pad. 460 _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, 461 uintptr_t new_value) { 462 _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%0llX)\n", 463 context, (uint64_t) new_value); 464 unw_cursor_t *cursor = (unw_cursor_t *)context; 465 unw_set_reg(cursor, UNW_REG_IP, new_value); 466 } 467 468 469 /// Called by personality handler during phase 2 to find the start of the 470 /// function. 471 _LIBUNWIND_EXPORT uintptr_t 472 _Unwind_GetRegionStart(struct _Unwind_Context *context) { 473 unw_cursor_t *cursor = (unw_cursor_t *)context; 474 unw_proc_info_t frameInfo; 475 uintptr_t result = 0; 476 if (unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS) 477 result = (uintptr_t)frameInfo.start_ip; 478 _LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%lX\n", 479 context, result); 480 return result; 481 } 482 483 484 /// Called by personality handler during phase 2 if a foreign exception 485 // is caught. 486 _LIBUNWIND_EXPORT void 487 _Unwind_DeleteException(_Unwind_Exception *exception_object) { 488 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)\n", 489 exception_object); 490 if (exception_object->exception_cleanup != NULL) 491 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, 492 exception_object); 493 } 494 495 #endif // _LIBUNWIND_BUILD_ZERO_COST_APIS && !LIBCXXABI_ARM_EHABI 496