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