1296417Sdim//===-- UnwindPlan.h --------------------------------------------*- C++ -*-===//
2296417Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6296417Sdim//
7296417Sdim//===----------------------------------------------------------------------===//
8296417Sdim
9254721Semaste#ifndef liblldb_UnwindPlan_h
10254721Semaste#define liblldb_UnwindPlan_h
11254721Semaste
12296417Sdim#include <map>
13296417Sdim#include <memory>
14296417Sdim#include <vector>
15296417Sdim
16254721Semaste#include "lldb/Core/AddressRange.h"
17321369Sdim#include "lldb/Utility/ConstString.h"
18321369Sdim#include "lldb/Utility/Stream.h"
19314564Sdim#include "lldb/lldb-private.h"
20254721Semaste
21254721Semastenamespace lldb_private {
22254721Semaste
23341825Sdim// The UnwindPlan object specifies how to unwind out of a function - where this
24341825Sdim// function saves the caller's register values before modifying them (for non-
25341825Sdim// volatile aka saved registers) and how to find this frame's Canonical Frame
26344779Sdim// Address (CFA) or Aligned Frame Address (AFA).
27254721Semaste
28344779Sdim// CFA is a DWARF's Canonical Frame Address.
29341825Sdim// Most commonly, registers are saved on the stack, offset some bytes from the
30341825Sdim// Canonical Frame Address, or CFA, which is the starting address of this
31341825Sdim// function's stack frame (the CFA is same as the eh_frame's CFA, whatever that
32341825Sdim// may be on a given architecture). The CFA address for the stack frame does
33341825Sdim// not change during the lifetime of the function.
34254721Semaste
35344779Sdim// AFA is an artificially introduced Aligned Frame Address.
36344779Sdim// It is used only for stack frames with realignment (e.g. when some of the
37344779Sdim// locals has an alignment requirement higher than the stack alignment right
38344779Sdim// after the function call). It is used to access register values saved on the
39344779Sdim// stack after the realignment (and so they are inaccessible through the CFA).
40344779Sdim// AFA usually equals the stack pointer value right after the realignment.
41344779Sdim
42254721Semaste// Internally, the UnwindPlan is structured as a vector of register locations
43254721Semaste// organized by code address in the function, showing which registers have been
44341825Sdim// saved at that point and where they are saved. It can be thought of as the
45341825Sdim// expanded table form of the DWARF CFI encoded information.
46254721Semaste
47254721Semaste// Other unwind information sources will be converted into UnwindPlans before
48341825Sdim// being added to a FuncUnwinders object.  The unwind source may be an eh_frame
49341825Sdim// FDE, a DWARF debug_frame FDE, or assembly language based prologue analysis.
50254721Semaste// The UnwindPlan is the canonical form of this information that the unwinder
51254721Semaste// code will use when walking the stack.
52254721Semaste
53254721Semasteclass UnwindPlan {
54254721Semastepublic:
55314564Sdim  class Row {
56314564Sdim  public:
57314564Sdim    class RegisterLocation {
58254721Semaste    public:
59314564Sdim      enum RestoreType {
60314564Sdim        unspecified,       // not specified, we may be able to assume this
61314564Sdim                           // is the same register. gcc doesn't specify all
62314564Sdim                           // initial values so we really don't know...
63314564Sdim        undefined,         // reg is not available, e.g. volatile reg
64314564Sdim        same,              // reg is unchanged
65314564Sdim        atCFAPlusOffset,   // reg = deref(CFA + offset)
66314564Sdim        isCFAPlusOffset,   // reg = CFA + offset
67344779Sdim        atAFAPlusOffset,   // reg = deref(AFA + offset)
68344779Sdim        isAFAPlusOffset,   // reg = AFA + offset
69314564Sdim        inOtherRegister,   // reg = other reg
70314564Sdim        atDWARFExpression, // reg = deref(eval(dwarf_expr))
71314564Sdim        isDWARFExpression  // reg = eval(dwarf_expr)
72314564Sdim      };
73280031Sdim
74314564Sdim      RegisterLocation() : m_type(unspecified), m_location() {}
75280031Sdim
76314564Sdim      bool operator==(const RegisterLocation &rhs) const;
77254721Semaste
78314564Sdim      bool operator!=(const RegisterLocation &rhs) const {
79314564Sdim        return !(*this == rhs);
80314564Sdim      }
81254721Semaste
82314564Sdim      void SetUnspecified() { m_type = unspecified; }
83254721Semaste
84314564Sdim      void SetUndefined() { m_type = undefined; }
85309124Sdim
86314564Sdim      void SetSame() { m_type = same; }
87254721Semaste
88314564Sdim      bool IsSame() const { return m_type == same; }
89254721Semaste
90314564Sdim      bool IsUnspecified() const { return m_type == unspecified; }
91254721Semaste
92314564Sdim      bool IsUndefined() const { return m_type == undefined; }
93254721Semaste
94314564Sdim      bool IsCFAPlusOffset() const { return m_type == isCFAPlusOffset; }
95254721Semaste
96314564Sdim      bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; }
97254721Semaste
98344779Sdim      bool IsAFAPlusOffset() const { return m_type == isAFAPlusOffset; }
99344779Sdim
100344779Sdim      bool IsAtAFAPlusOffset() const { return m_type == atAFAPlusOffset; }
101344779Sdim
102314564Sdim      bool IsInOtherRegister() const { return m_type == inOtherRegister; }
103254721Semaste
104314564Sdim      bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; }
105254721Semaste
106314564Sdim      bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
107254721Semaste
108314564Sdim      void SetAtCFAPlusOffset(int32_t offset) {
109314564Sdim        m_type = atCFAPlusOffset;
110314564Sdim        m_location.offset = offset;
111314564Sdim      }
112254721Semaste
113314564Sdim      void SetIsCFAPlusOffset(int32_t offset) {
114314564Sdim        m_type = isCFAPlusOffset;
115314564Sdim        m_location.offset = offset;
116314564Sdim      }
117254721Semaste
118344779Sdim      void SetAtAFAPlusOffset(int32_t offset) {
119344779Sdim        m_type = atAFAPlusOffset;
120344779Sdim        m_location.offset = offset;
121344779Sdim      }
122344779Sdim
123344779Sdim      void SetIsAFAPlusOffset(int32_t offset) {
124344779Sdim        m_type = isAFAPlusOffset;
125344779Sdim        m_location.offset = offset;
126344779Sdim      }
127344779Sdim
128314564Sdim      void SetInRegister(uint32_t reg_num) {
129314564Sdim        m_type = inOtherRegister;
130314564Sdim        m_location.reg_num = reg_num;
131314564Sdim      }
132254721Semaste
133314564Sdim      uint32_t GetRegisterNumber() const {
134314564Sdim        if (m_type == inOtherRegister)
135314564Sdim          return m_location.reg_num;
136314564Sdim        return LLDB_INVALID_REGNUM;
137314564Sdim      }
138288943Sdim
139314564Sdim      RestoreType GetLocationType() const { return m_type; }
140288943Sdim
141314564Sdim      int32_t GetOffset() const {
142344779Sdim        switch(m_type)
143344779Sdim        {
144344779Sdim        case atCFAPlusOffset:
145344779Sdim        case isCFAPlusOffset:
146344779Sdim        case atAFAPlusOffset:
147344779Sdim        case isAFAPlusOffset:
148314564Sdim          return m_location.offset;
149344779Sdim        default:
150344779Sdim          return 0;
151344779Sdim        }
152314564Sdim      }
153288943Sdim
154314564Sdim      void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
155314564Sdim        if (m_type == atDWARFExpression || m_type == isDWARFExpression) {
156314564Sdim          *opcodes = m_location.expr.opcodes;
157314564Sdim          len = m_location.expr.length;
158314564Sdim        } else {
159314564Sdim          *opcodes = nullptr;
160314564Sdim          len = 0;
161314564Sdim        }
162314564Sdim      }
163288943Sdim
164314564Sdim      void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len);
165288943Sdim
166314564Sdim      void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len);
167288943Sdim
168314564Sdim      const uint8_t *GetDWARFExpressionBytes() {
169314564Sdim        if (m_type == atDWARFExpression || m_type == isDWARFExpression)
170314564Sdim          return m_location.expr.opcodes;
171314564Sdim        return nullptr;
172314564Sdim      }
173288943Sdim
174314564Sdim      int GetDWARFExpressionLength() {
175314564Sdim        if (m_type == atDWARFExpression || m_type == isDWARFExpression)
176314564Sdim          return m_location.expr.length;
177314564Sdim        return 0;
178314564Sdim      }
179288943Sdim
180314564Sdim      void Dump(Stream &s, const UnwindPlan *unwind_plan,
181314564Sdim                const UnwindPlan::Row *row, Thread *thread, bool verbose) const;
182288943Sdim
183314564Sdim    private:
184314564Sdim      RestoreType m_type; // How do we locate this register?
185314564Sdim      union {
186314564Sdim        // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
187314564Sdim        int32_t offset;
188314564Sdim        // For m_type == inOtherRegister
189314564Sdim        uint32_t reg_num; // The register number
190314564Sdim        // For m_type == atDWARFExpression or m_type == isDWARFExpression
191314564Sdim        struct {
192314564Sdim          const uint8_t *opcodes;
193314564Sdim          uint16_t length;
194314564Sdim        } expr;
195314564Sdim      } m_location;
196314564Sdim    };
197288943Sdim
198344779Sdim    class FAValue {
199314564Sdim    public:
200314564Sdim      enum ValueType {
201314564Sdim        unspecified,            // not specified
202344779Sdim        isRegisterPlusOffset,   // FA = register + offset
203344779Sdim        isRegisterDereferenced, // FA = [reg]
204360784Sdim        isDWARFExpression,      // FA = eval(dwarf_expr)
205360784Sdim        isRaSearch,             // FA = SP + offset + ???
206314564Sdim      };
207288943Sdim
208344779Sdim      FAValue() : m_type(unspecified), m_value() {}
209288943Sdim
210344779Sdim      bool operator==(const FAValue &rhs) const;
211288943Sdim
212344779Sdim      bool operator!=(const FAValue &rhs) const { return !(*this == rhs); }
213288943Sdim
214314564Sdim      void SetUnspecified() { m_type = unspecified; }
215288943Sdim
216314564Sdim      bool IsUnspecified() const { return m_type == unspecified; }
217288943Sdim
218360784Sdim      void SetRaSearch(int32_t offset) {
219360784Sdim        m_type = isRaSearch;
220360784Sdim        m_value.ra_search_offset = offset;
221360784Sdim      }
222360784Sdim
223314564Sdim      bool IsRegisterPlusOffset() const {
224314564Sdim        return m_type == isRegisterPlusOffset;
225314564Sdim      }
226288943Sdim
227314564Sdim      void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset) {
228314564Sdim        m_type = isRegisterPlusOffset;
229314564Sdim        m_value.reg.reg_num = reg_num;
230314564Sdim        m_value.reg.offset = offset;
231314564Sdim      }
232288943Sdim
233314564Sdim      bool IsRegisterDereferenced() const {
234314564Sdim        return m_type == isRegisterDereferenced;
235314564Sdim      }
236288943Sdim
237314564Sdim      void SetIsRegisterDereferenced(uint32_t reg_num) {
238314564Sdim        m_type = isRegisterDereferenced;
239314564Sdim        m_value.reg.reg_num = reg_num;
240314564Sdim      }
241288943Sdim
242314564Sdim      bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
243288943Sdim
244314564Sdim      void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) {
245314564Sdim        m_type = isDWARFExpression;
246314564Sdim        m_value.expr.opcodes = opcodes;
247314564Sdim        m_value.expr.length = len;
248314564Sdim      }
249288943Sdim
250314564Sdim      uint32_t GetRegisterNumber() const {
251314564Sdim        if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset)
252314564Sdim          return m_value.reg.reg_num;
253314564Sdim        return LLDB_INVALID_REGNUM;
254314564Sdim      }
255254721Semaste
256314564Sdim      ValueType GetValueType() const { return m_type; }
257288943Sdim
258314564Sdim      int32_t GetOffset() const {
259360784Sdim        switch (m_type) {
260360784Sdim          case isRegisterPlusOffset:
261360784Sdim            return m_value.reg.offset;
262360784Sdim          case isRaSearch:
263360784Sdim            return m_value.ra_search_offset;
264360784Sdim          default:
265360784Sdim            return 0;
266360784Sdim        }
267314564Sdim      }
268254721Semaste
269314564Sdim      void IncOffset(int32_t delta) {
270314564Sdim        if (m_type == isRegisterPlusOffset)
271314564Sdim          m_value.reg.offset += delta;
272314564Sdim      }
273280031Sdim
274314564Sdim      void SetOffset(int32_t offset) {
275314564Sdim        if (m_type == isRegisterPlusOffset)
276314564Sdim          m_value.reg.offset = offset;
277314564Sdim      }
278280031Sdim
279314564Sdim      void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
280314564Sdim        if (m_type == isDWARFExpression) {
281314564Sdim          *opcodes = m_value.expr.opcodes;
282314564Sdim          len = m_value.expr.length;
283314564Sdim        } else {
284314564Sdim          *opcodes = nullptr;
285314564Sdim          len = 0;
286254721Semaste        }
287314564Sdim      }
288254721Semaste
289314564Sdim      const uint8_t *GetDWARFExpressionBytes() {
290314564Sdim        if (m_type == isDWARFExpression)
291314564Sdim          return m_value.expr.opcodes;
292314564Sdim        return nullptr;
293314564Sdim      }
294254721Semaste
295314564Sdim      int GetDWARFExpressionLength() {
296314564Sdim        if (m_type == isDWARFExpression)
297314564Sdim          return m_value.expr.length;
298314564Sdim        return 0;
299314564Sdim      }
300254721Semaste
301314564Sdim      void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const;
302280031Sdim
303314564Sdim    private:
304314564Sdim      ValueType m_type; // How do we compute CFA value?
305314564Sdim      union {
306314564Sdim        struct {
307314564Sdim          // For m_type == isRegisterPlusOffset or m_type ==
308314564Sdim          // isRegisterDereferenced
309314564Sdim          uint32_t reg_num; // The register number
310314564Sdim          // For m_type == isRegisterPlusOffset
311314564Sdim          int32_t offset;
312314564Sdim        } reg;
313314564Sdim        // For m_type == isDWARFExpression
314314564Sdim        struct {
315314564Sdim          const uint8_t *opcodes;
316314564Sdim          uint16_t length;
317314564Sdim        } expr;
318360784Sdim        // For m_type == isRaSearch
319360784Sdim        int32_t ra_search_offset;
320314564Sdim      } m_value;
321344779Sdim    }; // class FAValue
322314564Sdim
323314564Sdim  public:
324314564Sdim    Row();
325314564Sdim
326314564Sdim    Row(const UnwindPlan::Row &rhs) = default;
327314564Sdim
328314564Sdim    bool operator==(const Row &rhs) const;
329314564Sdim
330314564Sdim    bool GetRegisterInfo(uint32_t reg_num,
331314564Sdim                         RegisterLocation &register_location) const;
332314564Sdim
333314564Sdim    void SetRegisterInfo(uint32_t reg_num,
334314564Sdim                         const RegisterLocation register_location);
335314564Sdim
336314564Sdim    void RemoveRegisterInfo(uint32_t reg_num);
337314564Sdim
338314564Sdim    lldb::addr_t GetOffset() const { return m_offset; }
339314564Sdim
340314564Sdim    void SetOffset(lldb::addr_t offset) { m_offset = offset; }
341314564Sdim
342314564Sdim    void SlideOffset(lldb::addr_t offset) { m_offset += offset; }
343314564Sdim
344344779Sdim    FAValue &GetCFAValue() { return m_cfa_value; }
345314564Sdim
346344779Sdim    FAValue &GetAFAValue() { return m_afa_value; }
347344779Sdim
348314564Sdim    bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset,
349254721Semaste                                              bool can_replace);
350254721Semaste
351314564Sdim    bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset,
352254721Semaste                                              bool can_replace);
353254721Semaste
354314564Sdim    bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace,
355254721Semaste                                        bool can_replace_only_if_unspecified);
356254721Semaste
357314564Sdim    bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace);
358254721Semaste
359314564Sdim    bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num,
360254721Semaste                                       bool can_replace);
361254721Semaste
362314564Sdim    bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace);
363254721Semaste
364314564Sdim    void Clear();
365254721Semaste
366314564Sdim    void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread,
367314564Sdim              lldb::addr_t base_addr) const;
368254721Semaste
369314564Sdim  protected:
370314564Sdim    typedef std::map<uint32_t, RegisterLocation> collection;
371314564Sdim    lldb::addr_t m_offset; // Offset into the function for this row
372280031Sdim
373344779Sdim    FAValue m_cfa_value;
374344779Sdim    FAValue m_afa_value;
375314564Sdim    collection m_register_locations;
376314564Sdim  }; // class Row
377254721Semaste
378254721Semastepublic:
379314564Sdim  typedef std::shared_ptr<Row> RowSP;
380254721Semaste
381314564Sdim  UnwindPlan(lldb::RegisterKind reg_kind)
382314564Sdim      : m_row_list(), m_plan_valid_address_range(), m_register_kind(reg_kind),
383314564Sdim        m_return_addr_register(LLDB_INVALID_REGNUM), m_source_name(),
384314564Sdim        m_plan_is_sourced_from_compiler(eLazyBoolCalculate),
385314564Sdim        m_plan_is_valid_at_all_instruction_locations(eLazyBoolCalculate),
386360784Sdim        m_plan_is_for_signal_trap(eLazyBoolCalculate),
387314564Sdim        m_lsda_address(), m_personality_func_addr() {}
388254721Semaste
389314564Sdim  // Performs a deep copy of the plan, including all the rows (expensive).
390314564Sdim  UnwindPlan(const UnwindPlan &rhs)
391314564Sdim      : m_plan_valid_address_range(rhs.m_plan_valid_address_range),
392314564Sdim        m_register_kind(rhs.m_register_kind),
393314564Sdim        m_return_addr_register(rhs.m_return_addr_register),
394314564Sdim        m_source_name(rhs.m_source_name),
395314564Sdim        m_plan_is_sourced_from_compiler(rhs.m_plan_is_sourced_from_compiler),
396314564Sdim        m_plan_is_valid_at_all_instruction_locations(
397314564Sdim            rhs.m_plan_is_valid_at_all_instruction_locations),
398314564Sdim        m_lsda_address(rhs.m_lsda_address),
399314564Sdim        m_personality_func_addr(rhs.m_personality_func_addr) {
400314564Sdim    m_row_list.reserve(rhs.m_row_list.size());
401314564Sdim    for (const RowSP &row_sp : rhs.m_row_list)
402314564Sdim      m_row_list.emplace_back(new Row(*row_sp));
403314564Sdim  }
404288943Sdim
405314564Sdim  ~UnwindPlan() = default;
406254721Semaste
407314564Sdim  void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const;
408254721Semaste
409314564Sdim  void AppendRow(const RowSP &row_sp);
410254721Semaste
411314564Sdim  void InsertRow(const RowSP &row_sp, bool replace_existing = false);
412276479Sdim
413314564Sdim  // Returns a pointer to the best row for the given offset into the function's
414341825Sdim  // instructions. If offset is -1 it indicates that the function start is
415341825Sdim  // unknown - the final row in the UnwindPlan is returned. In practice, the
416341825Sdim  // UnwindPlan for a function with no known start address will be the
417341825Sdim  // architectural default UnwindPlan which will only have one row.
418314564Sdim  UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const;
419254721Semaste
420314564Sdim  lldb::RegisterKind GetRegisterKind() const { return m_register_kind; }
421254721Semaste
422314564Sdim  void SetRegisterKind(lldb::RegisterKind kind) { m_register_kind = kind; }
423254721Semaste
424314564Sdim  void SetReturnAddressRegister(uint32_t regnum) {
425314564Sdim    m_return_addr_register = regnum;
426314564Sdim  }
427254721Semaste
428314564Sdim  uint32_t GetReturnAddressRegister(void) { return m_return_addr_register; }
429254721Semaste
430314564Sdim  uint32_t GetInitialCFARegister() const {
431314564Sdim    if (m_row_list.empty())
432314564Sdim      return LLDB_INVALID_REGNUM;
433314564Sdim    return m_row_list.front()->GetCFAValue().GetRegisterNumber();
434314564Sdim  }
435254721Semaste
436314564Sdim  // This UnwindPlan may not be valid at every address of the function span.
437314564Sdim  // For instance, a FastUnwindPlan will not be valid at the prologue setup
438314564Sdim  // instructions - only in the body of the function.
439314564Sdim  void SetPlanValidAddressRange(const AddressRange &range);
440254721Semaste
441314564Sdim  const AddressRange &GetAddressRange() const {
442314564Sdim    return m_plan_valid_address_range;
443314564Sdim  }
444254721Semaste
445314564Sdim  bool PlanValidAtAddress(Address addr);
446254721Semaste
447314564Sdim  bool IsValidRowIndex(uint32_t idx) const;
448254721Semaste
449314564Sdim  const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const;
450254721Semaste
451314564Sdim  const UnwindPlan::RowSP GetLastRow() const;
452254721Semaste
453314564Sdim  lldb_private::ConstString GetSourceName() const;
454254721Semaste
455314564Sdim  void SetSourceName(const char *);
456254721Semaste
457314564Sdim  // Was this UnwindPlan emitted by a compiler?
458314564Sdim  lldb_private::LazyBool GetSourcedFromCompiler() const {
459314564Sdim    return m_plan_is_sourced_from_compiler;
460314564Sdim  }
461254721Semaste
462314564Sdim  // Was this UnwindPlan emitted by a compiler?
463314564Sdim  void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler) {
464314564Sdim    m_plan_is_sourced_from_compiler = from_compiler;
465314564Sdim  }
466254721Semaste
467314564Sdim  // Is this UnwindPlan valid at all instructions?  If not, then it is assumed
468341825Sdim  // valid at call sites, e.g. for exception handling.
469314564Sdim  lldb_private::LazyBool GetUnwindPlanValidAtAllInstructions() const {
470314564Sdim    return m_plan_is_valid_at_all_instruction_locations;
471314564Sdim  }
472254721Semaste
473314564Sdim  // Is this UnwindPlan valid at all instructions?  If not, then it is assumed
474341825Sdim  // valid at call sites, e.g. for exception handling.
475314564Sdim  void SetUnwindPlanValidAtAllInstructions(
476314564Sdim      lldb_private::LazyBool valid_at_all_insn) {
477314564Sdim    m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn;
478314564Sdim  }
479254721Semaste
480360784Sdim  // Is this UnwindPlan for a signal trap frame?  If so, then its saved pc
481360784Sdim  // may have been set manually by the signal dispatch code and therefore
482360784Sdim  // not follow a call to the child frame.
483360784Sdim  lldb_private::LazyBool GetUnwindPlanForSignalTrap() const {
484360784Sdim    return m_plan_is_for_signal_trap;
485360784Sdim  }
486360784Sdim
487360784Sdim  void SetUnwindPlanForSignalTrap(lldb_private::LazyBool is_for_signal_trap) {
488360784Sdim    m_plan_is_for_signal_trap = is_for_signal_trap;
489360784Sdim  }
490360784Sdim
491314564Sdim  int GetRowCount() const;
492254721Semaste
493314564Sdim  void Clear() {
494314564Sdim    m_row_list.clear();
495314564Sdim    m_plan_valid_address_range.Clear();
496314564Sdim    m_register_kind = lldb::eRegisterKindDWARF;
497314564Sdim    m_source_name.Clear();
498314564Sdim    m_plan_is_sourced_from_compiler = eLazyBoolCalculate;
499314564Sdim    m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate;
500360784Sdim    m_plan_is_for_signal_trap = eLazyBoolCalculate;
501314564Sdim    m_lsda_address.Clear();
502314564Sdim    m_personality_func_addr.Clear();
503314564Sdim  }
504280031Sdim
505314564Sdim  const RegisterInfo *GetRegisterInfo(Thread *thread, uint32_t reg_num) const;
506280031Sdim
507314564Sdim  Address GetLSDAAddress() const { return m_lsda_address; }
508280031Sdim
509314564Sdim  void SetLSDAAddress(Address lsda_addr) { m_lsda_address = lsda_addr; }
510280031Sdim
511314564Sdim  Address GetPersonalityFunctionPtr() const { return m_personality_func_addr; }
512314564Sdim
513314564Sdim  void SetPersonalityFunctionPtr(Address presonality_func_ptr) {
514314564Sdim    m_personality_func_addr = presonality_func_ptr;
515314564Sdim  }
516314564Sdim
517254721Semasteprivate:
518314564Sdim  typedef std::vector<RowSP> collection;
519314564Sdim  collection m_row_list;
520314564Sdim  AddressRange m_plan_valid_address_range;
521314564Sdim  lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers
522314564Sdim                                      // are in terms of - will need to be
523314564Sdim  // translated to lldb native reg nums at unwind time
524314564Sdim  uint32_t m_return_addr_register; // The register that has the return address
525314564Sdim                                   // for the caller frame
526314564Sdim                                   // e.g. the lr on arm
527314564Sdim  lldb_private::ConstString
528314564Sdim      m_source_name; // for logging, where this UnwindPlan originated from
529314564Sdim  lldb_private::LazyBool m_plan_is_sourced_from_compiler;
530314564Sdim  lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
531360784Sdim  lldb_private::LazyBool m_plan_is_for_signal_trap;
532280031Sdim
533314564Sdim  Address m_lsda_address; // Where the language specific data area exists in the
534314564Sdim                          // module - used
535314564Sdim                          // in exception handling.
536314564Sdim  Address m_personality_func_addr; // The address of a pointer to the
537314564Sdim                                   // personality function - used in
538314564Sdim                                   // exception handling.
539314564Sdim};                                 // class UnwindPlan
540254721Semaste
541254721Semaste} // namespace lldb_private
542254721Semaste
543296417Sdim#endif // liblldb_UnwindPlan_h
544