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