]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Symbol/UnwindPlan.h
MFV r336960: 9256 zfs send space estimation off by > 10% on some datasets
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / Symbol / UnwindPlan.h
1 //===-- UnwindPlan.h --------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef liblldb_UnwindPlan_h
11 #define liblldb_UnwindPlan_h
12
13 // C Includes
14 // C++ Includes
15 #include <map>
16 #include <memory>
17 #include <vector>
18
19 // Other libraries and framework includes
20 // Project includes
21 #include "lldb/Core/AddressRange.h"
22 #include "lldb/Utility/ConstString.h"
23 #include "lldb/Utility/Stream.h"
24 #include "lldb/lldb-private.h"
25
26 namespace lldb_private {
27
28 // The UnwindPlan object specifies how to unwind out of a function - where
29 // this function saves the caller's register values before modifying them
30 // (for non-volatile aka saved registers) and how to find this frame's
31 // Canonical Frame Address (CFA).
32
33 // Most commonly, registers are saved on the stack, offset some bytes from
34 // the Canonical Frame Address, or CFA, which is the starting address of
35 // this function's stack frame (the CFA is same as the eh_frame's CFA,
36 // whatever that may be on a given architecture).
37 // The CFA address for the stack frame does not change during
38 // the lifetime of the function.
39
40 // Internally, the UnwindPlan is structured as a vector of register locations
41 // organized by code address in the function, showing which registers have been
42 // saved at that point and where they are saved.
43 // It can be thought of as the expanded table form of the DWARF CFI
44 // encoded information.
45
46 // Other unwind information sources will be converted into UnwindPlans before
47 // being added to a FuncUnwinders object.  The unwind source may be
48 // an eh_frame FDE, a DWARF debug_frame FDE, or assembly language based
49 // prologue analysis.
50 // The UnwindPlan is the canonical form of this information that the unwinder
51 // code will use when walking the stack.
52
53 class UnwindPlan {
54 public:
55   class Row {
56   public:
57     class RegisterLocation {
58     public:
59       enum RestoreType {
60         unspecified,       // not specified, we may be able to assume this
61                            // is the same register. gcc doesn't specify all
62                            // initial values so we really don't know...
63         undefined,         // reg is not available, e.g. volatile reg
64         same,              // reg is unchanged
65         atCFAPlusOffset,   // reg = deref(CFA + offset)
66         isCFAPlusOffset,   // reg = CFA + offset
67         inOtherRegister,   // reg = other reg
68         atDWARFExpression, // reg = deref(eval(dwarf_expr))
69         isDWARFExpression  // reg = eval(dwarf_expr)
70       };
71
72       RegisterLocation() : m_type(unspecified), m_location() {}
73
74       bool operator==(const RegisterLocation &rhs) const;
75
76       bool operator!=(const RegisterLocation &rhs) const {
77         return !(*this == rhs);
78       }
79
80       void SetUnspecified() { m_type = unspecified; }
81
82       void SetUndefined() { m_type = undefined; }
83
84       void SetSame() { m_type = same; }
85
86       bool IsSame() const { return m_type == same; }
87
88       bool IsUnspecified() const { return m_type == unspecified; }
89
90       bool IsUndefined() const { return m_type == undefined; }
91
92       bool IsCFAPlusOffset() const { return m_type == isCFAPlusOffset; }
93
94       bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; }
95
96       bool IsInOtherRegister() const { return m_type == inOtherRegister; }
97
98       bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; }
99
100       bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
101
102       void SetAtCFAPlusOffset(int32_t offset) {
103         m_type = atCFAPlusOffset;
104         m_location.offset = offset;
105       }
106
107       void SetIsCFAPlusOffset(int32_t offset) {
108         m_type = isCFAPlusOffset;
109         m_location.offset = offset;
110       }
111
112       void SetInRegister(uint32_t reg_num) {
113         m_type = inOtherRegister;
114         m_location.reg_num = reg_num;
115       }
116
117       uint32_t GetRegisterNumber() const {
118         if (m_type == inOtherRegister)
119           return m_location.reg_num;
120         return LLDB_INVALID_REGNUM;
121       }
122
123       RestoreType GetLocationType() const { return m_type; }
124
125       int32_t GetOffset() const {
126         if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
127           return m_location.offset;
128         return 0;
129       }
130
131       void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
132         if (m_type == atDWARFExpression || m_type == isDWARFExpression) {
133           *opcodes = m_location.expr.opcodes;
134           len = m_location.expr.length;
135         } else {
136           *opcodes = nullptr;
137           len = 0;
138         }
139       }
140
141       void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len);
142
143       void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len);
144
145       const uint8_t *GetDWARFExpressionBytes() {
146         if (m_type == atDWARFExpression || m_type == isDWARFExpression)
147           return m_location.expr.opcodes;
148         return nullptr;
149       }
150
151       int GetDWARFExpressionLength() {
152         if (m_type == atDWARFExpression || m_type == isDWARFExpression)
153           return m_location.expr.length;
154         return 0;
155       }
156
157       void Dump(Stream &s, const UnwindPlan *unwind_plan,
158                 const UnwindPlan::Row *row, Thread *thread, bool verbose) const;
159
160     private:
161       RestoreType m_type; // How do we locate this register?
162       union {
163         // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
164         int32_t offset;
165         // For m_type == inOtherRegister
166         uint32_t reg_num; // The register number
167         // For m_type == atDWARFExpression or m_type == isDWARFExpression
168         struct {
169           const uint8_t *opcodes;
170           uint16_t length;
171         } expr;
172       } m_location;
173     };
174
175     class CFAValue {
176     public:
177       enum ValueType {
178         unspecified,            // not specified
179         isRegisterPlusOffset,   // CFA = register + offset
180         isRegisterDereferenced, // CFA = [reg]
181         isDWARFExpression       // CFA = eval(dwarf_expr)
182       };
183
184       CFAValue() : m_type(unspecified), m_value() {}
185
186       bool operator==(const CFAValue &rhs) const;
187
188       bool operator!=(const CFAValue &rhs) const { return !(*this == rhs); }
189
190       void SetUnspecified() { m_type = unspecified; }
191
192       bool IsUnspecified() const { return m_type == unspecified; }
193
194       bool IsRegisterPlusOffset() const {
195         return m_type == isRegisterPlusOffset;
196       }
197
198       void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset) {
199         m_type = isRegisterPlusOffset;
200         m_value.reg.reg_num = reg_num;
201         m_value.reg.offset = offset;
202       }
203
204       bool IsRegisterDereferenced() const {
205         return m_type == isRegisterDereferenced;
206       }
207
208       void SetIsRegisterDereferenced(uint32_t reg_num) {
209         m_type = isRegisterDereferenced;
210         m_value.reg.reg_num = reg_num;
211       }
212
213       bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
214
215       void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) {
216         m_type = isDWARFExpression;
217         m_value.expr.opcodes = opcodes;
218         m_value.expr.length = len;
219       }
220
221       uint32_t GetRegisterNumber() const {
222         if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset)
223           return m_value.reg.reg_num;
224         return LLDB_INVALID_REGNUM;
225       }
226
227       ValueType GetValueType() const { return m_type; }
228
229       int32_t GetOffset() const {
230         if (m_type == isRegisterPlusOffset)
231           return m_value.reg.offset;
232         return 0;
233       }
234
235       void IncOffset(int32_t delta) {
236         if (m_type == isRegisterPlusOffset)
237           m_value.reg.offset += delta;
238       }
239
240       void SetOffset(int32_t offset) {
241         if (m_type == isRegisterPlusOffset)
242           m_value.reg.offset = offset;
243       }
244
245       void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
246         if (m_type == isDWARFExpression) {
247           *opcodes = m_value.expr.opcodes;
248           len = m_value.expr.length;
249         } else {
250           *opcodes = nullptr;
251           len = 0;
252         }
253       }
254
255       const uint8_t *GetDWARFExpressionBytes() {
256         if (m_type == isDWARFExpression)
257           return m_value.expr.opcodes;
258         return nullptr;
259       }
260
261       int GetDWARFExpressionLength() {
262         if (m_type == isDWARFExpression)
263           return m_value.expr.length;
264         return 0;
265       }
266
267       void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const;
268
269     private:
270       ValueType m_type; // How do we compute CFA value?
271       union {
272         struct {
273           // For m_type == isRegisterPlusOffset or m_type ==
274           // isRegisterDereferenced
275           uint32_t reg_num; // The register number
276           // For m_type == isRegisterPlusOffset
277           int32_t offset;
278         } reg;
279         // For m_type == isDWARFExpression
280         struct {
281           const uint8_t *opcodes;
282           uint16_t length;
283         } expr;
284       } m_value;
285     }; // class CFAValue
286
287   public:
288     Row();
289
290     Row(const UnwindPlan::Row &rhs) = default;
291
292     bool operator==(const Row &rhs) const;
293
294     bool GetRegisterInfo(uint32_t reg_num,
295                          RegisterLocation &register_location) const;
296
297     void SetRegisterInfo(uint32_t reg_num,
298                          const RegisterLocation register_location);
299
300     void RemoveRegisterInfo(uint32_t reg_num);
301
302     lldb::addr_t GetOffset() const { return m_offset; }
303
304     void SetOffset(lldb::addr_t offset) { m_offset = offset; }
305
306     void SlideOffset(lldb::addr_t offset) { m_offset += offset; }
307
308     CFAValue &GetCFAValue() { return m_cfa_value; }
309
310     bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset,
311                                               bool can_replace);
312
313     bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset,
314                                               bool can_replace);
315
316     bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace,
317                                         bool can_replace_only_if_unspecified);
318
319     bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace);
320
321     bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num,
322                                        bool can_replace);
323
324     bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace);
325
326     void Clear();
327
328     void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread,
329               lldb::addr_t base_addr) const;
330
331   protected:
332     typedef std::map<uint32_t, RegisterLocation> collection;
333     lldb::addr_t m_offset; // Offset into the function for this row
334
335     CFAValue m_cfa_value;
336     collection m_register_locations;
337   }; // class Row
338
339 public:
340   typedef std::shared_ptr<Row> RowSP;
341
342   UnwindPlan(lldb::RegisterKind reg_kind)
343       : m_row_list(), m_plan_valid_address_range(), m_register_kind(reg_kind),
344         m_return_addr_register(LLDB_INVALID_REGNUM), m_source_name(),
345         m_plan_is_sourced_from_compiler(eLazyBoolCalculate),
346         m_plan_is_valid_at_all_instruction_locations(eLazyBoolCalculate),
347         m_lsda_address(), m_personality_func_addr() {}
348
349   // Performs a deep copy of the plan, including all the rows (expensive).
350   UnwindPlan(const UnwindPlan &rhs)
351       : m_plan_valid_address_range(rhs.m_plan_valid_address_range),
352         m_register_kind(rhs.m_register_kind),
353         m_return_addr_register(rhs.m_return_addr_register),
354         m_source_name(rhs.m_source_name),
355         m_plan_is_sourced_from_compiler(rhs.m_plan_is_sourced_from_compiler),
356         m_plan_is_valid_at_all_instruction_locations(
357             rhs.m_plan_is_valid_at_all_instruction_locations),
358         m_lsda_address(rhs.m_lsda_address),
359         m_personality_func_addr(rhs.m_personality_func_addr) {
360     m_row_list.reserve(rhs.m_row_list.size());
361     for (const RowSP &row_sp : rhs.m_row_list)
362       m_row_list.emplace_back(new Row(*row_sp));
363   }
364
365   ~UnwindPlan() = default;
366
367   void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const;
368
369   void AppendRow(const RowSP &row_sp);
370
371   void InsertRow(const RowSP &row_sp, bool replace_existing = false);
372
373   // Returns a pointer to the best row for the given offset into the function's
374   // instructions.
375   // If offset is -1 it indicates that the function start is unknown - the final
376   // row in the UnwindPlan is returned.
377   // In practice, the UnwindPlan for a function with no known start address will
378   // be the architectural default
379   // UnwindPlan which will only have one row.
380   UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const;
381
382   lldb::RegisterKind GetRegisterKind() const { return m_register_kind; }
383
384   void SetRegisterKind(lldb::RegisterKind kind) { m_register_kind = kind; }
385
386   void SetReturnAddressRegister(uint32_t regnum) {
387     m_return_addr_register = regnum;
388   }
389
390   uint32_t GetReturnAddressRegister(void) { return m_return_addr_register; }
391
392   uint32_t GetInitialCFARegister() const {
393     if (m_row_list.empty())
394       return LLDB_INVALID_REGNUM;
395     return m_row_list.front()->GetCFAValue().GetRegisterNumber();
396   }
397
398   // This UnwindPlan may not be valid at every address of the function span.
399   // For instance, a FastUnwindPlan will not be valid at the prologue setup
400   // instructions - only in the body of the function.
401   void SetPlanValidAddressRange(const AddressRange &range);
402
403   const AddressRange &GetAddressRange() const {
404     return m_plan_valid_address_range;
405   }
406
407   bool PlanValidAtAddress(Address addr);
408
409   bool IsValidRowIndex(uint32_t idx) const;
410
411   const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const;
412
413   const UnwindPlan::RowSP GetLastRow() const;
414
415   lldb_private::ConstString GetSourceName() const;
416
417   void SetSourceName(const char *);
418
419   // Was this UnwindPlan emitted by a compiler?
420   lldb_private::LazyBool GetSourcedFromCompiler() const {
421     return m_plan_is_sourced_from_compiler;
422   }
423
424   // Was this UnwindPlan emitted by a compiler?
425   void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler) {
426     m_plan_is_sourced_from_compiler = from_compiler;
427   }
428
429   // Is this UnwindPlan valid at all instructions?  If not, then it is assumed
430   // valid at call sites,
431   // e.g. for exception handling.
432   lldb_private::LazyBool GetUnwindPlanValidAtAllInstructions() const {
433     return m_plan_is_valid_at_all_instruction_locations;
434   }
435
436   // Is this UnwindPlan valid at all instructions?  If not, then it is assumed
437   // valid at call sites,
438   // e.g. for exception handling.
439   void SetUnwindPlanValidAtAllInstructions(
440       lldb_private::LazyBool valid_at_all_insn) {
441     m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn;
442   }
443
444   int GetRowCount() const;
445
446   void Clear() {
447     m_row_list.clear();
448     m_plan_valid_address_range.Clear();
449     m_register_kind = lldb::eRegisterKindDWARF;
450     m_source_name.Clear();
451     m_plan_is_sourced_from_compiler = eLazyBoolCalculate;
452     m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate;
453     m_lsda_address.Clear();
454     m_personality_func_addr.Clear();
455   }
456
457   const RegisterInfo *GetRegisterInfo(Thread *thread, uint32_t reg_num) const;
458
459   Address GetLSDAAddress() const { return m_lsda_address; }
460
461   void SetLSDAAddress(Address lsda_addr) { m_lsda_address = lsda_addr; }
462
463   Address GetPersonalityFunctionPtr() const { return m_personality_func_addr; }
464
465   void SetPersonalityFunctionPtr(Address presonality_func_ptr) {
466     m_personality_func_addr = presonality_func_ptr;
467   }
468
469 private:
470   typedef std::vector<RowSP> collection;
471   collection m_row_list;
472   AddressRange m_plan_valid_address_range;
473   lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers
474                                       // are in terms of - will need to be
475   // translated to lldb native reg nums at unwind time
476   uint32_t m_return_addr_register; // The register that has the return address
477                                    // for the caller frame
478                                    // e.g. the lr on arm
479   lldb_private::ConstString
480       m_source_name; // for logging, where this UnwindPlan originated from
481   lldb_private::LazyBool m_plan_is_sourced_from_compiler;
482   lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
483
484   Address m_lsda_address; // Where the language specific data area exists in the
485                           // module - used
486                           // in exception handling.
487   Address m_personality_func_addr; // The address of a pointer to the
488                                    // personality function - used in
489                                    // exception handling.
490 };                                 // class UnwindPlan
491
492 } // namespace lldb_private
493
494 #endif // liblldb_UnwindPlan_h