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