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