/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Target/RegisterContextUnwind.h
Line | Count | Source |
1 | | //===-- RegisterContextUnwind.h ---------------------------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #ifndef LLDB_TARGET_REGISTERCONTEXTUNWIND_H |
10 | | #define LLDB_TARGET_REGISTERCONTEXTUNWIND_H |
11 | | |
12 | | #include <vector> |
13 | | |
14 | | #include "lldb/Symbol/SymbolContext.h" |
15 | | #include "lldb/Symbol/UnwindPlan.h" |
16 | | #include "lldb/Target/RegisterContext.h" |
17 | | #include "lldb/Target/RegisterNumber.h" |
18 | | #include "lldb/Target/UnwindLLDB.h" |
19 | | #include "lldb/lldb-private.h" |
20 | | |
21 | | namespace lldb_private { |
22 | | |
23 | | class UnwindLLDB; |
24 | | |
25 | | class RegisterContextUnwind : public lldb_private::RegisterContext { |
26 | | public: |
27 | | typedef std::shared_ptr<RegisterContextUnwind> SharedPtr; |
28 | | |
29 | | RegisterContextUnwind(lldb_private::Thread &thread, |
30 | | const SharedPtr &next_frame, |
31 | | lldb_private::SymbolContext &sym_ctx, |
32 | | uint32_t frame_number, |
33 | | lldb_private::UnwindLLDB &unwind_lldb); |
34 | | |
35 | 238k | ~RegisterContextUnwind() override = default; |
36 | | |
37 | | void InvalidateAllRegisters() override; |
38 | | |
39 | | size_t GetRegisterCount() override; |
40 | | |
41 | | const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; |
42 | | |
43 | | size_t GetRegisterSetCount() override; |
44 | | |
45 | | const lldb_private::RegisterSet *GetRegisterSet(size_t reg_set) override; |
46 | | |
47 | | bool ReadRegister(const lldb_private::RegisterInfo *reg_info, |
48 | | lldb_private::RegisterValue &value) override; |
49 | | |
50 | | bool WriteRegister(const lldb_private::RegisterInfo *reg_info, |
51 | | const lldb_private::RegisterValue &value) override; |
52 | | |
53 | | bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override; |
54 | | |
55 | | bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; |
56 | | |
57 | | uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, |
58 | | uint32_t num) override; |
59 | | |
60 | | bool IsValid() const; |
61 | | |
62 | | bool IsTrapHandlerFrame() const; |
63 | | |
64 | | bool GetCFA(lldb::addr_t &cfa); |
65 | | |
66 | | bool GetStartPC(lldb::addr_t &start_pc); |
67 | | |
68 | | bool ReadPC(lldb::addr_t &start_pc); |
69 | | |
70 | | // Indicates whether this frame *behaves* like frame zero -- the currently |
71 | | // executing frame -- or not. This can be true in the middle of the stack |
72 | | // above asynchronous trap handlers (sigtramp) for instance. |
73 | | bool BehavesLikeZerothFrame() const override; |
74 | | |
75 | | private: |
76 | | enum FrameType { |
77 | | eNormalFrame, |
78 | | eTrapHandlerFrame, |
79 | | eDebuggerFrame, // a debugger inferior function call frame; we get caller's |
80 | | // registers from debugger |
81 | | eSkipFrame, // The unwind resulted in a bogus frame but may get back on |
82 | | // track so we don't want to give up yet |
83 | | eNotAValidFrame // this frame is invalid for some reason - most likely it is |
84 | | // past the top (end) of the stack |
85 | | }; |
86 | | |
87 | | // UnwindLLDB needs to pass around references to RegisterLocations |
88 | | friend class UnwindLLDB; |
89 | | |
90 | | // Returns true if we have an unwind loop -- the same stack frame unwinding |
91 | | // multiple times. |
92 | | bool CheckIfLoopingStack(); |
93 | | |
94 | | // Indicates whether this frame is frame zero -- the currently |
95 | | // executing frame -- or not. |
96 | | bool IsFrameZero() const; |
97 | | |
98 | | void InitializeZerothFrame(); |
99 | | |
100 | | void InitializeNonZerothFrame(); |
101 | | |
102 | | SharedPtr GetNextFrame() const; |
103 | | |
104 | | SharedPtr GetPrevFrame() const; |
105 | | |
106 | | // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've |
107 | | // got one bogus frame at frame #1. |
108 | | // There is a good chance we'll get back on track if we follow the frame |
109 | | // pointer chain (or whatever is appropriate |
110 | | // on this ABI) so we allow one invalid frame to be in the stack. Ideally |
111 | | // we'll mark this frame specially at some |
112 | | // point and indicate to the user that the unwinder had a hiccup. Often when |
113 | | // this happens we will miss a frame of |
114 | | // the program's actual stack in the unwind and we want to flag that for the |
115 | | // user somehow. |
116 | | bool IsSkipFrame() const; |
117 | | |
118 | | /// Determines if a SymbolContext is a trap handler or not |
119 | | /// |
120 | | /// Given a SymbolContext, determines if this is a trap handler function |
121 | | /// aka asynchronous signal handler. |
122 | | /// |
123 | | /// \return |
124 | | /// Returns true if the SymbolContext is a trap handler. |
125 | | bool IsTrapHandlerSymbol(lldb_private::Process *process, |
126 | | const lldb_private::SymbolContext &m_sym_ctx) const; |
127 | | |
128 | | /// Check if the given unwind plan indicates a signal trap handler, and |
129 | | /// update frame type and symbol context if so. |
130 | | void PropagateTrapHandlerFlagFromUnwindPlan(lldb::UnwindPlanSP unwind_plan); |
131 | | |
132 | | // Provide a location for where THIS function saved the CALLER's register |
133 | | // value |
134 | | // Or a frame "below" this one saved it, i.e. a function called by this one, |
135 | | // preserved a register that this |
136 | | // function didn't modify/use. |
137 | | // |
138 | | // The RegisterLocation type may be set to eRegisterNotAvailable -- this will |
139 | | // happen for a volatile register |
140 | | // being queried mid-stack. Instead of floating frame 0's contents of that |
141 | | // register up the stack (which may |
142 | | // or may not be the value of that reg when the function was executing), we |
143 | | // won't return any value. |
144 | | // |
145 | | // If a non-volatile register (a "preserved" register) is requested mid-stack |
146 | | // and no frames "below" the requested |
147 | | // stack have saved the register anywhere, it is safe to assume that frame 0's |
148 | | // register values are still the same |
149 | | // as the requesting frame's. |
150 | | lldb_private::UnwindLLDB::RegisterSearchResult |
151 | | SavedLocationForRegister(uint32_t lldb_regnum, |
152 | | lldb_private::UnwindLLDB::RegisterLocation ®loc); |
153 | | |
154 | | bool ReadRegisterValueFromRegisterLocation( |
155 | | lldb_private::UnwindLLDB::RegisterLocation regloc, |
156 | | const lldb_private::RegisterInfo *reg_info, |
157 | | lldb_private::RegisterValue &value); |
158 | | |
159 | | bool WriteRegisterValueToRegisterLocation( |
160 | | lldb_private::UnwindLLDB::RegisterLocation regloc, |
161 | | const lldb_private::RegisterInfo *reg_info, |
162 | | const lldb_private::RegisterValue &value); |
163 | | |
164 | | /// If the unwind has to the caller frame has failed, try something else |
165 | | /// |
166 | | /// If lldb is using an assembly language based UnwindPlan for a frame and |
167 | | /// the unwind to the caller frame fails, try falling back to a generic |
168 | | /// UnwindPlan (architecture default unwindplan) to see if that might work |
169 | | /// better. This is mostly helping to work around problems where the |
170 | | /// assembly language inspection fails on hand-written assembly code. |
171 | | /// |
172 | | /// \return |
173 | | /// Returns true if a fallback unwindplan was found & was installed. |
174 | | bool TryFallbackUnwindPlan(); |
175 | | |
176 | | /// Switch to the fallback unwind plan unconditionally without any safety |
177 | | /// checks that it is providing better results than the normal unwind plan. |
178 | | /// |
179 | | /// The only time it is valid to call this method is if the full unwindplan is |
180 | | /// found to be fundamentally incorrect/impossible. |
181 | | /// |
182 | | /// Returns true if it was able to install the fallback unwind plan. |
183 | | bool ForceSwitchToFallbackUnwindPlan(); |
184 | | |
185 | | // Get the contents of a general purpose (address-size) register for this |
186 | | // frame |
187 | | // (usually retrieved from the next frame) |
188 | | bool ReadGPRValue(lldb::RegisterKind register_kind, uint32_t regnum, |
189 | | lldb::addr_t &value); |
190 | | |
191 | | bool ReadGPRValue(const RegisterNumber ®_num, lldb::addr_t &value); |
192 | | |
193 | | // Get the Frame Address register for a given frame. |
194 | | bool ReadFrameAddress(lldb::RegisterKind register_kind, |
195 | | UnwindPlan::Row::FAValue &fa, lldb::addr_t &address); |
196 | | |
197 | | lldb::UnwindPlanSP GetFastUnwindPlanForFrame(); |
198 | | |
199 | | lldb::UnwindPlanSP GetFullUnwindPlanForFrame(); |
200 | | |
201 | | void UnwindLogMsg(const char *fmt, ...) __attribute__((format(printf, 2, 3))); |
202 | | |
203 | | void UnwindLogMsgVerbose(const char *fmt, ...) |
204 | | __attribute__((format(printf, 2, 3))); |
205 | | |
206 | | bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp); |
207 | | |
208 | | lldb::addr_t GetReturnAddressHint(int32_t plan_offset); |
209 | | |
210 | | lldb_private::Thread &m_thread; |
211 | | |
212 | | /// |
213 | | // The following tell us how to retrieve the CALLER's register values (ie the |
214 | | // "previous" frame, aka the frame above) |
215 | | // i.e. where THIS frame saved them |
216 | | /// |
217 | | |
218 | | lldb::UnwindPlanSP m_fast_unwind_plan_sp; // may be NULL |
219 | | lldb::UnwindPlanSP m_full_unwind_plan_sp; |
220 | | lldb::UnwindPlanSP m_fallback_unwind_plan_sp; // may be NULL |
221 | | |
222 | | bool m_all_registers_available; // Can we retrieve all regs or just |
223 | | // nonvolatile regs? |
224 | | int m_frame_type; // enum FrameType |
225 | | |
226 | | lldb::addr_t m_cfa; |
227 | | lldb::addr_t m_afa; |
228 | | lldb_private::Address m_start_pc; |
229 | | lldb_private::Address m_current_pc; |
230 | | |
231 | | int m_current_offset; // how far into the function we've executed; -1 if |
232 | | // unknown |
233 | | // 0 if no instructions have been executed yet. |
234 | | |
235 | | // 0 if no instructions have been executed yet. |
236 | | // On architectures where the return address on the stack points |
237 | | // to the instruction after the CALL, this value will have 1 |
238 | | // subtracted from it. Else a function that ends in a CALL will |
239 | | // have an offset pointing into the next function's address range. |
240 | | // m_current_pc has the actual address of the "current" pc. |
241 | | int m_current_offset_backed_up_one; // how far into the function we've |
242 | | // executed; -1 if unknown |
243 | | |
244 | | bool m_behaves_like_zeroth_frame; // this frame behaves like frame zero |
245 | | |
246 | | lldb_private::SymbolContext &m_sym_ctx; |
247 | | bool m_sym_ctx_valid; // if ResolveSymbolContextForAddress fails, don't try to |
248 | | // use m_sym_ctx |
249 | | |
250 | | uint32_t m_frame_number; // What stack frame this RegisterContext is |
251 | | |
252 | | std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation> |
253 | | m_registers; // where to find reg values for this frame |
254 | | |
255 | | lldb_private::UnwindLLDB &m_parent_unwind; // The UnwindLLDB that is creating |
256 | | // this RegisterContextUnwind |
257 | | |
258 | | RegisterContextUnwind(const RegisterContextUnwind &) = delete; |
259 | | const RegisterContextUnwind & |
260 | | operator=(const RegisterContextUnwind &) = delete; |
261 | | }; |
262 | | |
263 | | } // namespace lldb_private |
264 | | |
265 | | #endif // LLDB_TARGET_REGISTERCONTEXTUNWIND_H |