1 //===------------------------- UnwindCursor.hpp ---------------------------===// 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 // C++ interface to lower levels of libuwind 10 //===----------------------------------------------------------------------===// 11 12 #ifndef __UNWINDCURSOR_HPP__ 13 #define __UNWINDCURSOR_HPP__ 14 15 #include <stdint.h> 16 #include <stdlib.h> 17 #if !defined(__minix) 18 #include <pthread.h> 19 #endif /* !defined(__minix) */ 20 21 #include "AddressSpace.hpp" 22 #include "DwarfInstructions.hpp" 23 #include "Registers.hpp" 24 25 namespace _Unwind { 26 27 template <typename A, typename R> class UnwindCursor { 28 public: 29 UnwindCursor(R ®s, A &as) 30 : fRegisters(regs), fAddressSpace(as), fUnwindInfoMissing(false), 31 fIsSignalFrame(false) { 32 memset(&fInfo, 0, sizeof(fInfo)); 33 } 34 35 uint64_t getIP() const { return fRegisters.getIP(); } 36 37 void setIP(uint64_t value) { return fRegisters.setIP(value); } 38 39 uint64_t getSP() const { return fRegisters.getSP(); } 40 41 void setSP(uint64_t value) { return fRegisters.setSP(value); } 42 43 bool validReg(int regNum) { return fRegisters.validRegister(regNum); } 44 45 uint64_t getReg(int regNum) { return fRegisters.getRegister(regNum); } 46 47 void setReg(int regNum, uint64_t value) { 48 fRegisters.setRegister(regNum, value); 49 } 50 51 step_result step() { 52 // Bottom of stack is defined as having no more unwind info. 53 if (fUnwindInfoMissing) 54 return UNW_STEP_END; 55 56 // Apply unwinding to register set. 57 switch (this->stepWithDwarfFDE()) { 58 case UNW_STEP_FAILED: 59 return UNW_STEP_FAILED; 60 case UNW_STEP_END: 61 return UNW_STEP_END; 62 case UNW_STEP_SUCCESS: 63 this->setInfoBasedOnIPRegister(true); 64 if (fUnwindInfoMissing) 65 return UNW_STEP_END; 66 67 if (fInfo.extra_args) 68 setSP(getSP() + fInfo.extra_args); 69 return UNW_STEP_SUCCESS; 70 } 71 __builtin_unreachable(); 72 } 73 74 void getInfo(unw_proc_info_t *info) { *info = fInfo; } 75 76 bool isSignalFrame() { return fIsSignalFrame; } 77 void setInfoBasedOnIPRegister(bool isReturnAddress = false); 78 79 void jumpto() { fRegisters.jumpto(); } 80 81 private: 82 typedef typename A::pint_t pint_t; 83 typedef uint32_t EncodedUnwindInfo; 84 85 bool getInfoFromDwarfSection(pint_t, pint_t, uint32_t, uint32_t); 86 87 step_result stepWithDwarfFDE() { 88 return DwarfInstructions<A, R>::stepWithDwarf( 89 fAddressSpace, this->getIP(), fInfo.unwind_info, fRegisters, &fInfo); 90 } 91 92 unw_proc_info_t fInfo; 93 R fRegisters; 94 A &fAddressSpace; 95 bool fUnwindInfoMissing; 96 bool fIsSignalFrame; 97 }; 98 99 template <typename A, typename R> 100 void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { 101 pint_t pc = this->getIP(); 102 103 // If the last line of a function is a "throw", the compiler sometimes 104 // emits no instructions after the call to __cxa_throw. This means 105 // the return address is actually the start of the next function. 106 // To disambiguate this, back up the PC when we know it is a return 107 // address. 108 if (isReturnAddress) 109 --pc; 110 111 pint_t fdeStart, data_base; 112 if (!fAddressSpace.findFDE(pc, fdeStart, data_base)) { 113 fUnwindInfoMissing = true; 114 return; 115 } 116 fInfo.data_base = data_base; 117 118 typename CFI_Parser<A, R>::FDE_Info fdeInfo; 119 typename CFI_Parser<A, R>::CIE_Info cieInfo; 120 CFI_Parser<A, R>::decodeFDE(fAddressSpace, fdeStart, &fdeInfo, &cieInfo, 121 &fInfo); 122 if (pc < fdeInfo.pcStart || pc > fdeInfo.pcEnd) { 123 fUnwindInfoMissing = true; 124 return; 125 } 126 fInfo.start_ip = fdeInfo.pcStart; 127 128 typename CFI_Parser<A, R>::PrologInfo prolog; 129 if (!CFI_Parser<A, R>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, 130 pc, &prolog, &fInfo)) { 131 fUnwindInfoMissing = true; 132 return; 133 } 134 // Save off parsed FDE info 135 fInfo.end_ip = fdeInfo.pcEnd; 136 fInfo.lsda = fdeInfo.lsda; 137 fInfo.handler = cieInfo.personality; 138 fInfo.extra_args = prolog.spExtraArgSize; 139 fInfo.unwind_info = fdeInfo.fdeStart; 140 } 141 142 }; // namespace _Unwind 143 144 #endif // __UNWINDCURSOR_HPP__ 145