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