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 return UNW_STEP_SUCCESS; 65 } 66 __builtin_unreachable(); 67 } 68 69 void getInfo(unw_proc_info_t *info) { *info = fInfo; } 70 71 bool isSignalFrame() { return fIsSignalFrame; } 72 void setInfoBasedOnIPRegister(bool isReturnAddress = false); 73 74 void jumpto() { fRegisters.jumpto(); } 75 76 private: 77 typedef typename A::pint_t pint_t; 78 typedef uint32_t EncodedUnwindInfo; 79 80 bool getInfoFromDwarfSection(pint_t, pint_t, uint32_t, uint32_t); 81 82 step_result stepWithDwarfFDE() { 83 return DwarfInstructions<A, R>::stepWithDwarf( 84 fAddressSpace, this->getIP(), fInfo.unwind_info, fRegisters, &fInfo); 85 } 86 87 unw_proc_info_t fInfo; 88 R fRegisters; 89 A &fAddressSpace; 90 bool fUnwindInfoMissing; 91 bool fIsSignalFrame; 92 }; 93 94 template <typename A, typename R> 95 void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { 96 pint_t pc = this->getIP(); 97 98 // If the last line of a function is a "throw", the compiler sometimes 99 // emits no instructions after the call to __cxa_throw. This means 100 // the return address is actually the start of the next function. 101 // To disambiguate this, back up the PC when we know it is a return 102 // address. 103 if (isReturnAddress) 104 --pc; 105 106 pint_t fdeStart, data_base; 107 if (!fAddressSpace.findFDE(pc, fdeStart, data_base)) { 108 fUnwindInfoMissing = true; 109 return; 110 } 111 fInfo.data_base = data_base; 112 113 typename CFI_Parser<A, R>::FDE_Info fdeInfo; 114 typename CFI_Parser<A, R>::CIE_Info cieInfo; 115 CFI_Parser<A, R>::decodeFDE(fAddressSpace, fdeStart, &fdeInfo, &cieInfo, 116 &fInfo); 117 if (pc < fdeInfo.pcStart || pc > fdeInfo.pcEnd) { 118 fUnwindInfoMissing = true; 119 return; 120 } 121 fInfo.start_ip = fdeInfo.pcStart; 122 123 typename CFI_Parser<A, R>::PrologInfo prolog; 124 if (!CFI_Parser<A, R>::parseFDEInstructions(fAddressSpace, fdeInfo, cieInfo, 125 pc, &prolog, &fInfo)) { 126 fUnwindInfoMissing = true; 127 return; 128 } 129 // Save off parsed FDE info 130 fInfo.end_ip = fdeInfo.pcEnd; 131 fInfo.lsda = fdeInfo.lsda; 132 fInfo.handler = cieInfo.personality; 133 fInfo.extra_args = prolog.spExtraArgSize; 134 fInfo.unwind_info = fdeInfo.fdeStart; 135 } 136 137 }; // namespace _Unwind 138 139 #endif // __UNWINDCURSOR_HPP__ 140