1 //===--------------------------- libuwind.cpp -----------------------------===// 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 // 12 //===----------------------------------------------------------------------===// 13 14 #define _UNWIND_GCC_EXTENSIONS 15 16 #include <unwind.h> 17 18 #include "UnwindCursor.hpp" 19 20 using namespace _Unwind; 21 22 typedef CFI_Parser<LocalAddressSpace, NativeUnwindRegisters> MyCFIParser; 23 24 // Internal object representing the address space of this process. 25 static LocalAddressSpace sThisAddressSpace(MyCFIParser::findPCRange); 26 27 typedef UnwindCursor<LocalAddressSpace, NativeUnwindRegisters> ThisUnwindCursor; 28 29 static _Unwind_Reason_Code unwind_phase1(ThisUnwindCursor &cursor, 30 struct _Unwind_Exception *exc) { 31 cursor.setInfoBasedOnIPRegister(); 32 33 // Walk frames looking for a place to stop. 34 for (;;) { 35 // Get next frame. 36 // First frame is _Unwind_RaiseException and skipped. 37 switch (cursor.step()) { 38 case UNW_STEP_END: 39 return _URC_END_OF_STACK; 40 case UNW_STEP_FAILED: 41 return _URC_FATAL_PHASE1_ERROR; 42 case UNW_STEP_SUCCESS: 43 break; 44 } 45 46 // Check if there is a personality routine for this frame. 47 unw_proc_info_t frameInfo; 48 cursor.getInfo(&frameInfo); 49 if (frameInfo.end_ip == 0) 50 return _URC_FATAL_PHASE1_ERROR; 51 52 if (frameInfo.handler == 0) 53 continue; // No personality routine, so try next frame. 54 55 __personality_routine p = (__personality_routine)(frameInfo.handler); 56 _Unwind_Reason_Code result = (*p)(1, _UA_SEARCH_PHASE, exc->exception_class, 57 exc, (struct _Unwind_Context *)(&cursor)); 58 59 switch (result) { 60 case _URC_HANDLER_FOUND: 61 // This is either a catch clause or a local variable 62 // with destructor. 63 // Stop search and remember the frame for phase 2. 64 exc->private_2 = cursor.getSP(); 65 return _URC_NO_REASON; 66 67 case _URC_CONTINUE_UNWIND: 68 // Continue unwinding 69 break; 70 71 default: 72 // Bad personality routine. 73 return _URC_FATAL_PHASE1_ERROR; 74 } 75 } 76 } 77 78 static _Unwind_Reason_Code unwind_phase2(ThisUnwindCursor &cursor, 79 struct _Unwind_Exception *exc) { 80 cursor.setInfoBasedOnIPRegister(); 81 82 // Walk frames until the frame selected in phase 1 is reached. 83 for (;;) { 84 // Get next frame. 85 // First frame is _Unwind_RaiseException and skipped. 86 switch (cursor.step()) { 87 case UNW_STEP_END: 88 return _URC_END_OF_STACK; 89 case UNW_STEP_FAILED: 90 return _URC_FATAL_PHASE2_ERROR; 91 case UNW_STEP_SUCCESS: 92 break; 93 } 94 95 unw_proc_info_t frameInfo; 96 cursor.getInfo(&frameInfo); 97 if (frameInfo.end_ip == 0) 98 return _URC_FATAL_PHASE2_ERROR; 99 100 if (frameInfo.handler == 0) 101 continue; // No personality routine, continue. 102 103 uintptr_t sp = cursor.getSP(); 104 105 _Unwind_Action action = _UA_CLEANUP_PHASE; 106 // If this frame was selected in phase 1, 107 // inform the personality routine. 108 if (sp == exc->private_2) 109 action = (_Unwind_Action)(action | _UA_HANDLER_FRAME); 110 __personality_routine p = (__personality_routine)(frameInfo.handler); 111 _Unwind_Reason_Code result = (*p)(1, action, exc->exception_class, exc, 112 (struct _Unwind_Context *)(&cursor)); 113 switch (result) { 114 case _URC_CONTINUE_UNWIND: 115 // Continue unwinding unless the selected frame passed. 116 if (sp == exc->private_2) 117 return _URC_FATAL_PHASE2_ERROR; 118 break; 119 case _URC_INSTALL_CONTEXT: 120 // Transfer control to landing pad. 121 cursor.jumpto(); 122 __builtin_unreachable(); 123 default: 124 // Bad personality routine. 125 return _URC_FATAL_PHASE2_ERROR; 126 } 127 } 128 } 129 130 static _Unwind_Reason_Code unwind_phase2_forced(ThisUnwindCursor &cursor, 131 struct _Unwind_Exception *exc, 132 _Unwind_Stop_Fn stop, 133 void *stop_arg) { 134 _Unwind_Action action; 135 cursor.setInfoBasedOnIPRegister(); 136 137 // Walk frames until the frame selected in phase 1 is reached. 138 for (;;) { 139 // Get next frame. 140 // First frame is _Unwind_RaiseException and skipped. 141 switch (cursor.step()) { 142 case UNW_STEP_END: 143 case UNW_STEP_FAILED: 144 // End of stack or error condition. 145 // Call the stop function one last time. 146 action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | 147 _UA_END_OF_STACK); 148 (*stop)(1, action, exc->exception_class, exc, 149 (struct _Unwind_Context *)(&cursor), stop_arg); 150 151 // Didn't stop at the expected frame, so return error. 152 return _URC_FATAL_PHASE2_ERROR; 153 154 case UNW_STEP_SUCCESS: 155 break; 156 } 157 158 unw_proc_info_t frameInfo; 159 cursor.getInfo(&frameInfo); 160 if (frameInfo.end_ip == 0) 161 return _URC_FATAL_PHASE2_ERROR; 162 163 // Call stop function for each frame 164 action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); 165 _Unwind_Reason_Code result = 166 (*stop)(1, action, exc->exception_class, exc, 167 (struct _Unwind_Context *)(&cursor), stop_arg); 168 if (result != _URC_NO_REASON) 169 return _URC_FATAL_PHASE2_ERROR; 170 171 if (frameInfo.handler == 0) 172 continue; // No personality routine, continue. 173 174 __personality_routine p = (__personality_routine)(frameInfo.handler); 175 result = (*p)(1, action, exc->exception_class, exc, 176 (struct _Unwind_Context *)(&cursor)); 177 178 switch (result) { 179 case _URC_CONTINUE_UNWIND: 180 // Destructors called, continue. 181 break; 182 case _URC_INSTALL_CONTEXT: 183 // Transfer control to landing pad. 184 cursor.jumpto(); 185 __builtin_unreachable(); 186 default: 187 // Bad personality routine. 188 return _URC_FATAL_PHASE2_ERROR; 189 } 190 } 191 } 192 193 _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) { 194 NativeUnwindRegisters registers; 195 ThisUnwindCursor cursor1(registers, sThisAddressSpace); 196 ThisUnwindCursor cursor2(registers, sThisAddressSpace); 197 198 // Mark this as a non-forced unwind for _Unwind_Resume(). 199 exc->private_1 = 0; 200 exc->private_2 = 0; 201 202 // Phase 1: searching. 203 _Unwind_Reason_Code phase1 = unwind_phase1(cursor1, exc); 204 if (phase1 != _URC_NO_REASON) 205 return phase1; 206 207 // Phase 2: cleaning up. 208 return unwind_phase2(cursor2, exc); 209 } 210 211 _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc, 212 _Unwind_Stop_Fn stop, void *stop_arg) { 213 NativeUnwindRegisters registers; 214 ThisUnwindCursor cursor(registers, sThisAddressSpace); 215 216 // Mark this as forced unwind for _Unwind_Resume(). 217 exc->private_1 = (uintptr_t)stop; 218 exc->private_2 = (uintptr_t)stop_arg; 219 220 return unwind_phase2_forced(cursor, exc, stop, stop_arg); 221 } 222 223 void _Unwind_Resume(struct _Unwind_Exception *exc) { 224 NativeUnwindRegisters registers; 225 ThisUnwindCursor cursor(registers, sThisAddressSpace); 226 227 if (exc->private_1 != 0) 228 unwind_phase2_forced(cursor, exc, (_Unwind_Stop_Fn)exc->private_1, 229 (void *)exc->private_2); 230 else 231 unwind_phase2(cursor, exc); 232 abort(); 233 } 234 235 _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *exc) { 236 // This is a re-throw, if this is a non-forced unwind 237 // and the stopping place was found. 238 // In that case, call _Unwind_RaiseException() as if 239 // it was a new exception. 240 241 if (exc->private_1 != 0) 242 _Unwind_Resume(exc); 243 244 // This can return if there is no catch clause. 245 // In that case, __cxa_rethrow is expected to call std::terminate(). 246 return _Unwind_RaiseException(exc); 247 } 248 249 void _Unwind_DeleteException(struct _Unwind_Exception *exc) { 250 if (exc->exception_cleanup != NULL) 251 (*exc->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exc); 252 } 253 254 uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { 255 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 256 return cursor->getReg(index); 257 } 258 259 void _Unwind_SetGR(struct _Unwind_Context *context, int index, 260 uintptr_t new_value) { 261 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 262 cursor->setReg(index, new_value); 263 } 264 265 uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { 266 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 267 return cursor->getIP(); 268 } 269 270 uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *isSignalFrame) { 271 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 272 *isSignalFrame = cursor->isSignalFrame() ? 1 : 0; 273 return cursor->getIP(); 274 } 275 276 void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) { 277 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 278 cursor->setIP(new_value); 279 unw_proc_info_t info; 280 cursor->getInfo(&info); 281 cursor->setInfoBasedOnIPRegister(false); 282 if (info.extra_args) 283 cursor->setSP(cursor->getSP() + info.extra_args); 284 } 285 286 uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) { 287 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 288 unw_proc_info_t frameInfo; 289 cursor->getInfo(&frameInfo); 290 return frameInfo.end_ip ? frameInfo.start_ip : 0; 291 } 292 293 uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { 294 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 295 unw_proc_info_t frameInfo; 296 cursor->getInfo(&frameInfo); 297 return frameInfo.end_ip ? frameInfo.lsda : 0; 298 } 299 300 _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { 301 NativeUnwindRegisters registers; 302 ThisUnwindCursor cursor(registers, sThisAddressSpace); 303 cursor.setInfoBasedOnIPRegister(); 304 305 // Walk each frame. 306 while (true) { 307 308 // Ask libuwind to get next frame (skip over first frame which is 309 // _Unwind_Backtrace()). 310 if (cursor.step() != UNW_STEP_SUCCESS) 311 return _URC_END_OF_STACK; 312 313 // Call trace function with this frame. 314 _Unwind_Reason_Code result = 315 (*callback)((struct _Unwind_Context *)(&cursor), ref); 316 if (result != _URC_NO_REASON) 317 return result; 318 } 319 } 320 321 uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { 322 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 323 return cursor->getSP(); 324 } 325 326 void *_Unwind_FindEnclosingFunction(void *pc) { 327 NativeUnwindRegisters registers; 328 ThisUnwindCursor cursor(registers, sThisAddressSpace); 329 330 unw_proc_info_t info; 331 cursor.setIP((uintptr_t)pc); 332 cursor.setInfoBasedOnIPRegister(); 333 334 cursor.getInfo(&info); 335 return info.end_ip ? (void *)info.start_ip : NULL; 336 } 337 338 void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases) { 339 NativeUnwindRegisters registers; 340 ThisUnwindCursor cursor(registers, sThisAddressSpace); 341 342 unw_proc_info_t info; 343 cursor.setIP((uintptr_t)pc); 344 cursor.setInfoBasedOnIPRegister(); 345 346 cursor.getInfo(&info); 347 if (info.end_ip == 0) 348 return NULL; 349 bases->tbase = 0; /* Not supported */ 350 bases->dbase = (void *)info.data_base; 351 bases->func = (void *)info.start_ip; 352 return (void *)info.unwind_info; 353 } 354 355 uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) { 356 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 357 unw_proc_info_t frameInfo; 358 cursor->getInfo(&frameInfo); 359 return frameInfo.data_base; 360 } 361 362 uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) { return 0; } 363 364 void __register_frame(const void *fde) { 365 MyCFIParser::pint_t pcStart, pcEnd; 366 367 MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd); 368 if (pcEnd == 0) 369 return; // Bad FDE. 370 371 sThisAddressSpace.addFDE(pcStart, pcEnd, (uintptr_t)fde); 372 } 373 374 void __register_frame_info(const void *ehframe, void *storage) { 375 sThisAddressSpace.setLazyReload(); 376 } 377 378 void __deregister_frame(const void *fde) { 379 MyCFIParser::pint_t pcStart, pcEnd; 380 381 MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd); 382 if (pcEnd == 0) 383 return; // Bad FDE. 384 385 sThisAddressSpace.removeFDE(pcStart, pcEnd, (uintptr_t)fde); 386 } 387 388 void *__deregister_frame_info(const void *ehFrameStart) { 389 sThisAddressSpace.removeDSO((LocalAddressSpace::pint_t)ehFrameStart); 390 return NULL; 391 } 392