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