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