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 default: 123 // Bad personality routine. 124 return _URC_FATAL_PHASE2_ERROR; 125 } 126 } 127 } 128 129 static _Unwind_Reason_Code unwind_phase2_forced(ThisUnwindCursor &cursor, 130 struct _Unwind_Exception *exc, 131 _Unwind_Stop_Fn stop, 132 void *stop_arg) { 133 _Unwind_Action action; 134 cursor.setInfoBasedOnIPRegister(); 135 136 // Walk frames until the frame selected in phase 1 is reached. 137 for (;;) { 138 // Get next frame. 139 // First frame is _Unwind_RaiseException and skipped. 140 switch (cursor.step()) { 141 case UNW_STEP_END: 142 case UNW_STEP_FAILED: 143 // End of stack or error condition. 144 // Call the stop function one last time. 145 action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | 146 _UA_END_OF_STACK); 147 (*stop)(1, action, exc->exception_class, exc, 148 (struct _Unwind_Context *)(&cursor), stop_arg); 149 150 // Didn't stop at the expected frame, so return error. 151 return _URC_FATAL_PHASE2_ERROR; 152 153 case UNW_STEP_SUCCESS: 154 break; 155 } 156 157 unw_proc_info_t frameInfo; 158 cursor.getInfo(&frameInfo); 159 if (frameInfo.end_ip == 0) 160 return _URC_FATAL_PHASE2_ERROR; 161 162 // Call stop function for each frame 163 action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); 164 _Unwind_Reason_Code result = 165 (*stop)(1, action, exc->exception_class, exc, 166 (struct _Unwind_Context *)(&cursor), stop_arg); 167 if (result != _URC_NO_REASON) 168 return _URC_FATAL_PHASE2_ERROR; 169 170 if (frameInfo.handler == 0) 171 continue; // No personality routine, continue. 172 173 __personality_routine p = (__personality_routine)(frameInfo.handler); 174 result = (*p)(1, action, exc->exception_class, exc, 175 (struct _Unwind_Context *)(&cursor)); 176 177 switch (result) { 178 case _URC_CONTINUE_UNWIND: 179 // Destructors called, continue. 180 break; 181 case _URC_INSTALL_CONTEXT: 182 // Transfer control to landing pad. 183 cursor.jumpto(); 184 default: 185 // Bad personality routine. 186 return _URC_FATAL_PHASE2_ERROR; 187 } 188 } 189 } 190 191 _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) { 192 NativeUnwindRegisters registers; 193 ThisUnwindCursor cursor1(registers, sThisAddressSpace); 194 ThisUnwindCursor cursor2(registers, sThisAddressSpace); 195 196 // Mark this as a non-forced unwind for _Unwind_Resume(). 197 exc->private_1 = 0; 198 exc->private_2 = 0; 199 200 // Phase 1: searching. 201 _Unwind_Reason_Code phase1 = unwind_phase1(cursor1, exc); 202 if (phase1 != _URC_NO_REASON) 203 return phase1; 204 205 // Phase 2: cleaning up. 206 return unwind_phase2(cursor2, exc); 207 } 208 209 _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc, 210 _Unwind_Stop_Fn stop, void *stop_arg) { 211 NativeUnwindRegisters registers; 212 ThisUnwindCursor cursor(registers, sThisAddressSpace); 213 214 // Mark this as forced unwind for _Unwind_Resume(). 215 exc->private_1 = (uintptr_t)stop; 216 exc->private_2 = (uintptr_t)stop_arg; 217 218 return unwind_phase2_forced(cursor, exc, stop, stop_arg); 219 } 220 221 void _Unwind_Resume(struct _Unwind_Exception *exc) { 222 NativeUnwindRegisters registers; 223 ThisUnwindCursor cursor(registers, sThisAddressSpace); 224 225 if (exc->private_1 != 0) 226 unwind_phase2_forced(cursor, exc, (_Unwind_Stop_Fn)exc->private_1, 227 (void *)exc->private_2); 228 else 229 unwind_phase2(cursor, exc); 230 abort(); 231 } 232 233 _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *exc) { 234 // This is a re-throw, if this is a non-forced unwind 235 // and the stopping place was found. 236 // In that case, call _Unwind_RaiseException() as if 237 // it was a new exception. 238 239 if (exc->private_1 != 0) 240 _Unwind_Resume(exc); 241 242 // This can return if there is no catch clause. 243 // In that case, __cxa_rethrow is expected to call std::terminate(). 244 return _Unwind_RaiseException(exc); 245 } 246 247 void _Unwind_DeleteException(struct _Unwind_Exception *exc) { 248 if (exc->exception_cleanup != NULL) 249 (*exc->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exc); 250 } 251 252 uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { 253 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 254 return cursor->getReg(index); 255 } 256 257 void _Unwind_SetGR(struct _Unwind_Context *context, int index, 258 uintptr_t new_value) { 259 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 260 cursor->setReg(index, new_value); 261 } 262 263 uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { 264 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 265 return cursor->getIP(); 266 } 267 268 uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *isSignalFrame) { 269 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 270 *isSignalFrame = cursor->isSignalFrame() ? 1 : 0; 271 return cursor->getIP(); 272 } 273 274 void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) { 275 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 276 cursor->setIP(new_value); 277 unw_proc_info_t info; 278 cursor->getInfo(&info); 279 cursor->setInfoBasedOnIPRegister(false); 280 } 281 282 uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) { 283 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 284 unw_proc_info_t frameInfo; 285 cursor->getInfo(&frameInfo); 286 return frameInfo.end_ip ? frameInfo.start_ip : 0; 287 } 288 289 uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { 290 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 291 unw_proc_info_t frameInfo; 292 cursor->getInfo(&frameInfo); 293 return frameInfo.end_ip ? frameInfo.lsda : 0; 294 } 295 296 _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { 297 NativeUnwindRegisters registers; 298 ThisUnwindCursor cursor(registers, sThisAddressSpace); 299 cursor.setInfoBasedOnIPRegister(); 300 301 // Walk each frame. 302 while (true) { 303 304 // Ask libuwind to get next frame (skip over first frame which is 305 // _Unwind_Backtrace()). 306 if (cursor.step() != UNW_STEP_SUCCESS) 307 return _URC_END_OF_STACK; 308 309 // Call trace function with this frame. 310 _Unwind_Reason_Code result = 311 (*callback)((struct _Unwind_Context *)(&cursor), ref); 312 if (result != _URC_NO_REASON) 313 return result; 314 } 315 } 316 317 uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { 318 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 319 return cursor->getSP(); 320 } 321 322 void *_Unwind_FindEnclosingFunction(void *pc) { 323 NativeUnwindRegisters registers; 324 ThisUnwindCursor cursor(registers, sThisAddressSpace); 325 326 unw_proc_info_t info; 327 cursor.setIP((uintptr_t)pc); 328 cursor.setInfoBasedOnIPRegister(); 329 330 cursor.getInfo(&info); 331 return info.end_ip ? (void *)info.start_ip : NULL; 332 } 333 334 void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases) { 335 NativeUnwindRegisters registers; 336 ThisUnwindCursor cursor(registers, sThisAddressSpace); 337 338 unw_proc_info_t info; 339 cursor.setIP((uintptr_t)pc); 340 cursor.setInfoBasedOnIPRegister(); 341 342 cursor.getInfo(&info); 343 if (info.end_ip == 0) 344 return NULL; 345 bases->tbase = 0; /* Not supported */ 346 bases->dbase = (void *)info.data_base; 347 bases->func = (void *)info.start_ip; 348 return (void *)info.unwind_info; 349 } 350 351 uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) { 352 ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; 353 unw_proc_info_t frameInfo; 354 cursor->getInfo(&frameInfo); 355 return frameInfo.data_base; 356 } 357 358 uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) { return 0; } 359 360 void __register_frame(const void *fde) { 361 MyCFIParser::pint_t pcStart, pcEnd; 362 363 MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd); 364 if (pcEnd == 0) 365 return; // Bad FDE. 366 367 sThisAddressSpace.addFDE(pcStart, pcEnd, (uintptr_t)fde); 368 } 369 370 void __register_frame_info(const void *ehframe, void *storage) { 371 sThisAddressSpace.setLazyReload(); 372 } 373 374 void __deregister_frame(const void *fde) { 375 MyCFIParser::pint_t pcStart, pcEnd; 376 377 MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd); 378 if (pcEnd == 0) 379 return; // Bad FDE. 380 381 sThisAddressSpace.removeFDE(pcStart, pcEnd, (uintptr_t)fde); 382 } 383 384 void *__deregister_frame_info(const void *ehFrameStart) { 385 sThisAddressSpace.removeDSO((LocalAddressSpace::pint_t)ehFrameStart); 386 return NULL; 387 } 388