UnwindCursor.hpp revision 1.3.32.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 ®s, 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