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