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