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