1 //===------------------------- UnwindCursor.hpp ---------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
9 // C++ interface to lower levels of libuwind
10 //===----------------------------------------------------------------------===//
12 #ifndef __UNWINDCURSOR_HPP__
13 #define __UNWINDCURSOR_HPP__
19 #endif /* !defined(__minix) */
21 #include "AddressSpace.hpp"
22 #include "DwarfInstructions.hpp"
23 #include "Registers.hpp"
27 template <typename A
, typename R
> class UnwindCursor
{
29 UnwindCursor(R
®s
, A
&as
)
30 : fRegisters(regs
), fAddressSpace(as
), fUnwindInfoMissing(false),
31 fIsSignalFrame(false) {
32 memset(&fInfo
, 0, sizeof(fInfo
));
35 uint64_t getIP() const { return fRegisters
.getIP(); }
37 void setIP(uint64_t value
) { return fRegisters
.setIP(value
); }
39 uint64_t getSP() const { return fRegisters
.getSP(); }
41 void setSP(uint64_t value
) { return fRegisters
.setSP(value
); }
43 bool validReg(int regNum
) { return fRegisters
.validRegister(regNum
); }
45 uint64_t getReg(int regNum
) { return fRegisters
.getRegister(regNum
); }
47 void setReg(int regNum
, uint64_t value
) {
48 fRegisters
.setRegister(regNum
, value
);
52 // Bottom of stack is defined as having no more unwind info.
53 if (fUnwindInfoMissing
)
56 // Apply unwinding to register set.
57 switch (this->stepWithDwarfFDE()) {
59 return UNW_STEP_FAILED
;
62 case UNW_STEP_SUCCESS
:
63 this->setInfoBasedOnIPRegister(true);
64 if (fUnwindInfoMissing
)
68 setSP(getSP() + fInfo
.extra_args
);
69 return UNW_STEP_SUCCESS
;
71 __builtin_unreachable();
74 void getInfo(unw_proc_info_t
*info
) { *info
= fInfo
; }
76 bool isSignalFrame() { return fIsSignalFrame
; }
77 void setInfoBasedOnIPRegister(bool isReturnAddress
= false);
79 void jumpto() { fRegisters
.jumpto(); }
82 typedef typename
A::pint_t pint_t
;
83 typedef uint32_t EncodedUnwindInfo
;
85 bool getInfoFromDwarfSection(pint_t
, pint_t
, uint32_t, uint32_t);
87 step_result
stepWithDwarfFDE() {
88 return DwarfInstructions
<A
, R
>::stepWithDwarf(
89 fAddressSpace
, this->getIP(), fInfo
.unwind_info
, fRegisters
, &fInfo
);
92 unw_proc_info_t fInfo
;
95 bool fUnwindInfoMissing
;
99 template <typename A
, typename R
>
100 void UnwindCursor
<A
, R
>::setInfoBasedOnIPRegister(bool isReturnAddress
) {
101 pint_t pc
= this->getIP();
103 // If the last line of a function is a "throw", the compiler sometimes
104 // emits no instructions after the call to __cxa_throw. This means
105 // the return address is actually the start of the next function.
106 // To disambiguate this, back up the PC when we know it is a return
111 pint_t fdeStart
, data_base
;
112 if (!fAddressSpace
.findFDE(pc
, fdeStart
, data_base
)) {
113 fUnwindInfoMissing
= true;
116 fInfo
.data_base
= data_base
;
118 typename CFI_Parser
<A
, R
>::FDE_Info fdeInfo
;
119 typename CFI_Parser
<A
, R
>::CIE_Info cieInfo
;
120 CFI_Parser
<A
, R
>::decodeFDE(fAddressSpace
, fdeStart
, &fdeInfo
, &cieInfo
,
122 if (pc
< fdeInfo
.pcStart
|| pc
> fdeInfo
.pcEnd
) {
123 fUnwindInfoMissing
= true;
126 fInfo
.start_ip
= fdeInfo
.pcStart
;
128 typename CFI_Parser
<A
, R
>::PrologInfo prolog
;
129 if (!CFI_Parser
<A
, R
>::parseFDEInstructions(fAddressSpace
, fdeInfo
, cieInfo
,
130 pc
, &prolog
, &fInfo
)) {
131 fUnwindInfoMissing
= true;
134 // Save off parsed FDE info
135 fInfo
.end_ip
= fdeInfo
.pcEnd
;
136 fInfo
.lsda
= fdeInfo
.lsda
;
137 fInfo
.handler
= cieInfo
.personality
;
138 fInfo
.extra_args
= prolog
.spExtraArgSize
;
139 fInfo
.unwind_info
= fdeInfo
.fdeStart
;
142 }; // namespace _Unwind
144 #endif // __UNWINDCURSOR_HPP__