aboutsummaryrefslogtreecommitdiff
path: root/include/lldb/Symbol/UnwindPlan.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/lldb/Symbol/UnwindPlan.h')
-rw-r--r--include/lldb/Symbol/UnwindPlan.h1044
1 files changed, 413 insertions, 631 deletions
diff --git a/include/lldb/Symbol/UnwindPlan.h b/include/lldb/Symbol/UnwindPlan.h
index 64c00bf12c27..dfcf55bc8864 100644
--- a/include/lldb/Symbol/UnwindPlan.h
+++ b/include/lldb/Symbol/UnwindPlan.h
@@ -18,10 +18,10 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
#include "lldb/Core/AddressRange.h"
-#include "lldb/Core/Stream.h"
#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -39,673 +39,455 @@ namespace lldb_private {
// Internally, the UnwindPlan is structured as a vector of register locations
// organized by code address in the function, showing which registers have been
-// saved at that point and where they are saved.
-// It can be thought of as the expanded table form of the DWARF CFI
+// saved at that point and where they are saved.
+// It can be thought of as the expanded table form of the DWARF CFI
// encoded information.
// Other unwind information sources will be converted into UnwindPlans before
-// being added to a FuncUnwinders object. The unwind source may be
-// an eh_frame FDE, a DWARF debug_frame FDE, or assembly language based
+// being added to a FuncUnwinders object. The unwind source may be
+// an eh_frame FDE, a DWARF debug_frame FDE, or assembly language based
// prologue analysis.
// The UnwindPlan is the canonical form of this information that the unwinder
// code will use when walking the stack.
class UnwindPlan {
public:
- class Row {
+ class Row {
+ public:
+ class RegisterLocation {
public:
- class RegisterLocation
- {
- public:
- enum RestoreType
- {
- unspecified, // not specified, we may be able to assume this
- // is the same register. gcc doesn't specify all
- // initial values so we really don't know...
- undefined, // reg is not available, e.g. volatile reg
- same, // reg is unchanged
- atCFAPlusOffset, // reg = deref(CFA + offset)
- isCFAPlusOffset, // reg = CFA + offset
- inOtherRegister, // reg = other reg
- atDWARFExpression, // reg = deref(eval(dwarf_expr))
- isDWARFExpression // reg = eval(dwarf_expr)
- };
-
- RegisterLocation() :
- m_type(unspecified),
- m_location()
- {
- }
-
- bool
- operator == (const RegisterLocation& rhs) const;
-
- bool
- operator != (const RegisterLocation &rhs) const
- {
- return !(*this == rhs);
- }
-
- void
- SetUnspecified()
- {
- m_type = unspecified;
- }
-
- void
- SetUndefined()
- {
- m_type = undefined;
- }
-
- void
- SetSame()
- {
- m_type = same;
- }
-
- bool
- IsSame () const
- {
- return m_type == same;
- }
-
- bool
- IsUnspecified () const
- {
- return m_type == unspecified;
- }
-
- bool
- IsUndefined () const
- {
- return m_type == undefined;
- }
-
- bool
- IsCFAPlusOffset () const
- {
- return m_type == isCFAPlusOffset;
- }
-
- bool
- IsAtCFAPlusOffset () const
- {
- return m_type == atCFAPlusOffset;
- }
-
- bool
- IsInOtherRegister () const
- {
- return m_type == inOtherRegister;
- }
-
- bool
- IsAtDWARFExpression () const
- {
- return m_type == atDWARFExpression;
- }
-
- bool
- IsDWARFExpression () const
- {
- return m_type == isDWARFExpression;
- }
-
- void
- SetAtCFAPlusOffset (int32_t offset)
- {
- m_type = atCFAPlusOffset;
- m_location.offset = offset;
- }
-
- void
- SetIsCFAPlusOffset (int32_t offset)
- {
- m_type = isCFAPlusOffset;
- m_location.offset = offset;
- }
-
- void
- SetInRegister (uint32_t reg_num)
- {
- m_type = inOtherRegister;
- m_location.reg_num = reg_num;
- }
-
- uint32_t
- GetRegisterNumber () const
- {
- if (m_type == inOtherRegister)
- return m_location.reg_num;
- return LLDB_INVALID_REGNUM;
- }
-
- RestoreType
- GetLocationType () const
- {
- return m_type;
- }
-
- int32_t
- GetOffset () const
- {
- if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
- return m_location.offset;
- return 0;
- }
-
- void
- GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const
- {
- if (m_type == atDWARFExpression || m_type == isDWARFExpression)
- {
- *opcodes = m_location.expr.opcodes;
- len = m_location.expr.length;
- }
- else
- {
- *opcodes = nullptr;
- len = 0;
- }
- }
-
- void
- SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len);
-
- void
- SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len);
-
- const uint8_t *
- GetDWARFExpressionBytes ()
- {
- if (m_type == atDWARFExpression || m_type == isDWARFExpression)
- return m_location.expr.opcodes;
- return nullptr;
- }
-
- int
- GetDWARFExpressionLength ()
- {
- if (m_type == atDWARFExpression || m_type == isDWARFExpression)
- return m_location.expr.length;
- return 0;
- }
-
- void
- Dump (Stream &s,
- const UnwindPlan* unwind_plan,
- const UnwindPlan::Row* row,
- Thread* thread,
- bool verbose) const;
-
- private:
- RestoreType m_type; // How do we locate this register?
- union
- {
- // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
- int32_t offset;
- // For m_type == inOtherRegister
- uint32_t reg_num; // The register number
- // For m_type == atDWARFExpression or m_type == isDWARFExpression
- struct {
- const uint8_t *opcodes;
- uint16_t length;
- } expr;
- } m_location;
- };
-
- class CFAValue
- {
- public:
- enum ValueType
- {
- unspecified, // not specified
- isRegisterPlusOffset, // CFA = register + offset
- isRegisterDereferenced, // CFA = [reg]
- isDWARFExpression // CFA = eval(dwarf_expr)
- };
-
- CFAValue() :
- m_type(unspecified),
- m_value()
- {
- }
-
- bool
- operator == (const CFAValue& rhs) const;
-
- bool
- operator != (const CFAValue &rhs) const
- {
- return !(*this == rhs);
- }
-
- void
- SetUnspecified()
- {
- m_type = unspecified;
- }
-
- bool
- IsUnspecified () const
- {
- return m_type == unspecified;
- }
-
- bool
- IsRegisterPlusOffset () const
- {
- return m_type == isRegisterPlusOffset;
- }
-
- void
- SetIsRegisterPlusOffset (uint32_t reg_num, int32_t offset)
- {
- m_type = isRegisterPlusOffset;
- m_value.reg.reg_num = reg_num;
- m_value.reg.offset = offset;
- }
-
- bool
- IsRegisterDereferenced () const
- {
- return m_type == isRegisterDereferenced;
- }
-
- void
- SetIsRegisterDereferenced (uint32_t reg_num)
- {
- m_type = isRegisterDereferenced;
- m_value.reg.reg_num = reg_num;
- }
-
- bool
- IsDWARFExpression () const
- {
- return m_type == isDWARFExpression;
- }
-
- void
- SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
- {
- m_type = isDWARFExpression;
- m_value.expr.opcodes = opcodes;
- m_value.expr.length = len;
- }
-
- uint32_t
- GetRegisterNumber () const
- {
- if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset)
- return m_value.reg.reg_num;
- return LLDB_INVALID_REGNUM;
- }
-
- ValueType
- GetValueType () const
- {
- return m_type;
- }
-
- int32_t
- GetOffset () const
- {
- if (m_type == isRegisterPlusOffset)
- return m_value.reg.offset;
- return 0;
- }
-
- void IncOffset (int32_t delta)
- {
- if (m_type == isRegisterPlusOffset)
- m_value.reg.offset += delta;
- }
-
- void SetOffset (int32_t offset)
- {
- if (m_type == isRegisterPlusOffset)
- m_value.reg.offset = offset;
- }
-
- void
- GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const
- {
- if (m_type == isDWARFExpression)
- {
- *opcodes = m_value.expr.opcodes;
- len = m_value.expr.length;
- }
- else
- {
- *opcodes = nullptr;
- len = 0;
- }
- }
-
- const uint8_t *
- GetDWARFExpressionBytes ()
- {
- if (m_type == isDWARFExpression)
- return m_value.expr.opcodes;
- return nullptr;
- }
-
- int
- GetDWARFExpressionLength ()
- {
- if (m_type == isDWARFExpression)
- return m_value.expr.length;
- return 0;
- }
-
- void
- Dump (Stream &s,
- const UnwindPlan* unwind_plan,
- Thread* thread) const;
-
- private:
- ValueType m_type; // How do we compute CFA value?
- union
- {
- struct {
- // For m_type == isRegisterPlusOffset or m_type == isRegisterDereferenced
- uint32_t reg_num; // The register number
- // For m_type == isRegisterPlusOffset
- int32_t offset;
- } reg;
- // For m_type == isDWARFExpression
- struct {
- const uint8_t *opcodes;
- uint16_t length;
- } expr;
- } m_value;
- }; // class CFAValue
+ enum RestoreType {
+ unspecified, // not specified, we may be able to assume this
+ // is the same register. gcc doesn't specify all
+ // initial values so we really don't know...
+ undefined, // reg is not available, e.g. volatile reg
+ same, // reg is unchanged
+ atCFAPlusOffset, // reg = deref(CFA + offset)
+ isCFAPlusOffset, // reg = CFA + offset
+ inOtherRegister, // reg = other reg
+ atDWARFExpression, // reg = deref(eval(dwarf_expr))
+ isDWARFExpression // reg = eval(dwarf_expr)
+ };
- public:
- Row ();
+ RegisterLocation() : m_type(unspecified), m_location() {}
- Row (const UnwindPlan::Row& rhs) = default;
+ bool operator==(const RegisterLocation &rhs) const;
- bool
- operator == (const Row &rhs) const;
+ bool operator!=(const RegisterLocation &rhs) const {
+ return !(*this == rhs);
+ }
- bool
- GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const;
-
- void
- SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location);
+ void SetUnspecified() { m_type = unspecified; }
- void
- RemoveRegisterInfo (uint32_t reg_num);
+ void SetUndefined() { m_type = undefined; }
- lldb::addr_t
- GetOffset() const
- {
- return m_offset;
- }
+ void SetSame() { m_type = same; }
- void
- SetOffset(lldb::addr_t offset)
- {
- m_offset = offset;
- }
+ bool IsSame() const { return m_type == same; }
- void
- SlideOffset(lldb::addr_t offset)
- {
- m_offset += offset;
- }
+ bool IsUnspecified() const { return m_type == unspecified; }
+
+ bool IsUndefined() const { return m_type == undefined; }
+
+ bool IsCFAPlusOffset() const { return m_type == isCFAPlusOffset; }
+
+ bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; }
+
+ bool IsInOtherRegister() const { return m_type == inOtherRegister; }
+
+ bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; }
+
+ bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
+
+ void SetAtCFAPlusOffset(int32_t offset) {
+ m_type = atCFAPlusOffset;
+ m_location.offset = offset;
+ }
+
+ void SetIsCFAPlusOffset(int32_t offset) {
+ m_type = isCFAPlusOffset;
+ m_location.offset = offset;
+ }
+
+ void SetInRegister(uint32_t reg_num) {
+ m_type = inOtherRegister;
+ m_location.reg_num = reg_num;
+ }
- CFAValue& GetCFAValue()
- {
- return m_cfa_value;
+ uint32_t GetRegisterNumber() const {
+ if (m_type == inOtherRegister)
+ return m_location.reg_num;
+ return LLDB_INVALID_REGNUM;
+ }
+
+ RestoreType GetLocationType() const { return m_type; }
+
+ int32_t GetOffset() const {
+ if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
+ return m_location.offset;
+ return 0;
+ }
+
+ void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
+ if (m_type == atDWARFExpression || m_type == isDWARFExpression) {
+ *opcodes = m_location.expr.opcodes;
+ len = m_location.expr.length;
+ } else {
+ *opcodes = nullptr;
+ len = 0;
+ }
+ }
+
+ void SetAtDWARFExpression(const uint8_t *opcodes, uint32_t len);
+
+ void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len);
+
+ const uint8_t *GetDWARFExpressionBytes() {
+ if (m_type == atDWARFExpression || m_type == isDWARFExpression)
+ return m_location.expr.opcodes;
+ return nullptr;
+ }
+
+ int GetDWARFExpressionLength() {
+ if (m_type == atDWARFExpression || m_type == isDWARFExpression)
+ return m_location.expr.length;
+ return 0;
+ }
+
+ void Dump(Stream &s, const UnwindPlan *unwind_plan,
+ const UnwindPlan::Row *row, Thread *thread, bool verbose) const;
+
+ private:
+ RestoreType m_type; // How do we locate this register?
+ union {
+ // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
+ int32_t offset;
+ // For m_type == inOtherRegister
+ uint32_t reg_num; // The register number
+ // For m_type == atDWARFExpression or m_type == isDWARFExpression
+ struct {
+ const uint8_t *opcodes;
+ uint16_t length;
+ } expr;
+ } m_location;
+ };
+
+ class CFAValue {
+ public:
+ enum ValueType {
+ unspecified, // not specified
+ isRegisterPlusOffset, // CFA = register + offset
+ isRegisterDereferenced, // CFA = [reg]
+ isDWARFExpression // CFA = eval(dwarf_expr)
+ };
+
+ CFAValue() : m_type(unspecified), m_value() {}
+
+ bool operator==(const CFAValue &rhs) const;
+
+ bool operator!=(const CFAValue &rhs) const { return !(*this == rhs); }
+
+ void SetUnspecified() { m_type = unspecified; }
+
+ bool IsUnspecified() const { return m_type == unspecified; }
+
+ bool IsRegisterPlusOffset() const {
+ return m_type == isRegisterPlusOffset;
+ }
+
+ void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset) {
+ m_type = isRegisterPlusOffset;
+ m_value.reg.reg_num = reg_num;
+ m_value.reg.offset = offset;
+ }
+
+ bool IsRegisterDereferenced() const {
+ return m_type == isRegisterDereferenced;
+ }
+
+ void SetIsRegisterDereferenced(uint32_t reg_num) {
+ m_type = isRegisterDereferenced;
+ m_value.reg.reg_num = reg_num;
+ }
+
+ bool IsDWARFExpression() const { return m_type == isDWARFExpression; }
+
+ void SetIsDWARFExpression(const uint8_t *opcodes, uint32_t len) {
+ m_type = isDWARFExpression;
+ m_value.expr.opcodes = opcodes;
+ m_value.expr.length = len;
+ }
+
+ uint32_t GetRegisterNumber() const {
+ if (m_type == isRegisterDereferenced || m_type == isRegisterPlusOffset)
+ return m_value.reg.reg_num;
+ return LLDB_INVALID_REGNUM;
+ }
+
+ ValueType GetValueType() const { return m_type; }
+
+ int32_t GetOffset() const {
+ if (m_type == isRegisterPlusOffset)
+ return m_value.reg.offset;
+ return 0;
+ }
+
+ void IncOffset(int32_t delta) {
+ if (m_type == isRegisterPlusOffset)
+ m_value.reg.offset += delta;
+ }
+
+ void SetOffset(int32_t offset) {
+ if (m_type == isRegisterPlusOffset)
+ m_value.reg.offset = offset;
+ }
+
+ void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
+ if (m_type == isDWARFExpression) {
+ *opcodes = m_value.expr.opcodes;
+ len = m_value.expr.length;
+ } else {
+ *opcodes = nullptr;
+ len = 0;
}
+ }
+
+ const uint8_t *GetDWARFExpressionBytes() {
+ if (m_type == isDWARFExpression)
+ return m_value.expr.opcodes;
+ return nullptr;
+ }
+
+ int GetDWARFExpressionLength() {
+ if (m_type == isDWARFExpression)
+ return m_value.expr.length;
+ return 0;
+ }
+
+ void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread) const;
+
+ private:
+ ValueType m_type; // How do we compute CFA value?
+ union {
+ struct {
+ // For m_type == isRegisterPlusOffset or m_type ==
+ // isRegisterDereferenced
+ uint32_t reg_num; // The register number
+ // For m_type == isRegisterPlusOffset
+ int32_t offset;
+ } reg;
+ // For m_type == isDWARFExpression
+ struct {
+ const uint8_t *opcodes;
+ uint16_t length;
+ } expr;
+ } m_value;
+ }; // class CFAValue
+
+ public:
+ Row();
+
+ Row(const UnwindPlan::Row &rhs) = default;
+
+ bool operator==(const Row &rhs) const;
+
+ bool GetRegisterInfo(uint32_t reg_num,
+ RegisterLocation &register_location) const;
+
+ void SetRegisterInfo(uint32_t reg_num,
+ const RegisterLocation register_location);
+
+ void RemoveRegisterInfo(uint32_t reg_num);
+
+ lldb::addr_t GetOffset() const { return m_offset; }
- bool
- SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num,
- int32_t offset,
+ void SetOffset(lldb::addr_t offset) { m_offset = offset; }
+
+ void SlideOffset(lldb::addr_t offset) { m_offset += offset; }
+
+ CFAValue &GetCFAValue() { return m_cfa_value; }
+
+ bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset,
bool can_replace);
- bool
- SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num,
- int32_t offset,
+ bool SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, int32_t offset,
bool can_replace);
- bool
- SetRegisterLocationToUndefined (uint32_t reg_num,
- bool can_replace,
+ bool SetRegisterLocationToUndefined(uint32_t reg_num, bool can_replace,
bool can_replace_only_if_unspecified);
- bool
- SetRegisterLocationToUnspecified (uint32_t reg_num,
- bool can_replace);
+ bool SetRegisterLocationToUnspecified(uint32_t reg_num, bool can_replace);
- bool
- SetRegisterLocationToRegister (uint32_t reg_num,
- uint32_t other_reg_num,
+ bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num,
bool can_replace);
- bool
- SetRegisterLocationToSame (uint32_t reg_num,
- bool must_replace);
+ bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace);
- void
- Clear ();
+ void Clear();
- void
- Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, lldb::addr_t base_addr) const;
+ void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread,
+ lldb::addr_t base_addr) const;
- protected:
- typedef std::map<uint32_t, RegisterLocation> collection;
- lldb::addr_t m_offset; // Offset into the function for this row
+ protected:
+ typedef std::map<uint32_t, RegisterLocation> collection;
+ lldb::addr_t m_offset; // Offset into the function for this row
- CFAValue m_cfa_value;
- collection m_register_locations;
- }; // class Row
+ CFAValue m_cfa_value;
+ collection m_register_locations;
+ }; // class Row
public:
- typedef std::shared_ptr<Row> RowSP;
-
- UnwindPlan (lldb::RegisterKind reg_kind) :
- m_row_list (),
- m_plan_valid_address_range (),
- m_register_kind (reg_kind),
- m_return_addr_register (LLDB_INVALID_REGNUM),
- m_source_name (),
- m_plan_is_sourced_from_compiler (eLazyBoolCalculate),
- m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate),
- m_lsda_address (),
- m_personality_func_addr ()
- {
- }
-
- // Performs a deep copy of the plan, including all the rows (expensive).
- UnwindPlan (const UnwindPlan &rhs) :
- m_plan_valid_address_range (rhs.m_plan_valid_address_range),
- m_register_kind (rhs.m_register_kind),
- m_return_addr_register (rhs.m_return_addr_register),
- m_source_name (rhs.m_source_name),
- m_plan_is_sourced_from_compiler (rhs.m_plan_is_sourced_from_compiler),
- m_plan_is_valid_at_all_instruction_locations (rhs.m_plan_is_valid_at_all_instruction_locations),
- m_lsda_address (rhs.m_lsda_address),
- m_personality_func_addr (rhs.m_personality_func_addr)
- {
- m_row_list.reserve (rhs.m_row_list.size());
- for (const RowSP &row_sp: rhs.m_row_list)
- m_row_list.emplace_back (new Row (*row_sp));
- }
-
- ~UnwindPlan() = default;
-
- void
- Dump (Stream& s, Thread* thread, lldb::addr_t base_addr) const;
-
- void
- AppendRow (const RowSP& row_sp);
-
- void
- InsertRow (const RowSP& row_sp, bool replace_existing = false);
-
- // Returns a pointer to the best row for the given offset into the function's instructions.
- // If offset is -1 it indicates that the function start is unknown - the final row in the UnwindPlan is returned.
- // In practice, the UnwindPlan for a function with no known start address will be the architectural default
- // UnwindPlan which will only have one row.
- UnwindPlan::RowSP
- GetRowForFunctionOffset (int offset) const;
-
- lldb::RegisterKind
- GetRegisterKind () const
- {
- return m_register_kind;
- }
-
- void
- SetRegisterKind (lldb::RegisterKind kind)
- {
- m_register_kind = kind;
- }
-
- void
- SetReturnAddressRegister (uint32_t regnum)
- {
- m_return_addr_register = regnum;
- }
-
- uint32_t
- GetReturnAddressRegister (void)
- {
- return m_return_addr_register;
- }
-
- uint32_t
- GetInitialCFARegister () const
- {
- if (m_row_list.empty())
- return LLDB_INVALID_REGNUM;
- return m_row_list.front()->GetCFAValue().GetRegisterNumber();
- }
-
- // This UnwindPlan may not be valid at every address of the function span.
- // For instance, a FastUnwindPlan will not be valid at the prologue setup
- // instructions - only in the body of the function.
- void
- SetPlanValidAddressRange (const AddressRange& range);
-
- const AddressRange &
- GetAddressRange () const
- {
- return m_plan_valid_address_range;
- }
-
- bool
- PlanValidAtAddress (Address addr);
-
- bool
- IsValidRowIndex (uint32_t idx) const;
-
- const UnwindPlan::RowSP
- GetRowAtIndex (uint32_t idx) const;
-
- const UnwindPlan::RowSP
- GetLastRow () const;
-
- lldb_private::ConstString
- GetSourceName () const;
-
- void
- SetSourceName (const char *);
-
- // Was this UnwindPlan emitted by a compiler?
- lldb_private::LazyBool
- GetSourcedFromCompiler () const
- {
- return m_plan_is_sourced_from_compiler;
- }
-
- // Was this UnwindPlan emitted by a compiler?
- void
- SetSourcedFromCompiler (lldb_private::LazyBool from_compiler)
- {
- m_plan_is_sourced_from_compiler = from_compiler;
- }
-
- // Is this UnwindPlan valid at all instructions? If not, then it is assumed valid at call sites,
- // e.g. for exception handling.
- lldb_private::LazyBool
- GetUnwindPlanValidAtAllInstructions () const
- {
- return m_plan_is_valid_at_all_instruction_locations;
- }
-
- // Is this UnwindPlan valid at all instructions? If not, then it is assumed valid at call sites,
- // e.g. for exception handling.
- void
- SetUnwindPlanValidAtAllInstructions (lldb_private::LazyBool valid_at_all_insn)
- {
- m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn;
- }
-
- int
- GetRowCount () const;
-
- void
- Clear()
- {
- m_row_list.clear();
- m_plan_valid_address_range.Clear();
- m_register_kind = lldb::eRegisterKindDWARF;
- m_source_name.Clear();
- m_plan_is_sourced_from_compiler = eLazyBoolCalculate;
- m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate;
- m_lsda_address.Clear();
- m_personality_func_addr.Clear();
- }
-
- const RegisterInfo *
- GetRegisterInfo (Thread* thread, uint32_t reg_num) const;
-
- Address
- GetLSDAAddress () const
- {
- return m_lsda_address;
- }
-
- void
- SetLSDAAddress (Address lsda_addr)
- {
- m_lsda_address = lsda_addr;
- }
-
- Address
- GetPersonalityFunctionPtr () const
- {
- return m_personality_func_addr;
- }
-
- void
- SetPersonalityFunctionPtr (Address presonality_func_ptr)
- {
- m_personality_func_addr = presonality_func_ptr;
- }
+ typedef std::shared_ptr<Row> RowSP;
+
+ UnwindPlan(lldb::RegisterKind reg_kind)
+ : m_row_list(), m_plan_valid_address_range(), m_register_kind(reg_kind),
+ m_return_addr_register(LLDB_INVALID_REGNUM), m_source_name(),
+ m_plan_is_sourced_from_compiler(eLazyBoolCalculate),
+ m_plan_is_valid_at_all_instruction_locations(eLazyBoolCalculate),
+ m_lsda_address(), m_personality_func_addr() {}
+
+ // Performs a deep copy of the plan, including all the rows (expensive).
+ UnwindPlan(const UnwindPlan &rhs)
+ : m_plan_valid_address_range(rhs.m_plan_valid_address_range),
+ m_register_kind(rhs.m_register_kind),
+ m_return_addr_register(rhs.m_return_addr_register),
+ m_source_name(rhs.m_source_name),
+ m_plan_is_sourced_from_compiler(rhs.m_plan_is_sourced_from_compiler),
+ m_plan_is_valid_at_all_instruction_locations(
+ rhs.m_plan_is_valid_at_all_instruction_locations),
+ m_lsda_address(rhs.m_lsda_address),
+ m_personality_func_addr(rhs.m_personality_func_addr) {
+ m_row_list.reserve(rhs.m_row_list.size());
+ for (const RowSP &row_sp : rhs.m_row_list)
+ m_row_list.emplace_back(new Row(*row_sp));
+ }
+
+ ~UnwindPlan() = default;
+
+ void Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const;
+
+ void AppendRow(const RowSP &row_sp);
+
+ void InsertRow(const RowSP &row_sp, bool replace_existing = false);
+
+ // Returns a pointer to the best row for the given offset into the function's
+ // instructions.
+ // If offset is -1 it indicates that the function start is unknown - the final
+ // row in the UnwindPlan is returned.
+ // In practice, the UnwindPlan for a function with no known start address will
+ // be the architectural default
+ // UnwindPlan which will only have one row.
+ UnwindPlan::RowSP GetRowForFunctionOffset(int offset) const;
+
+ lldb::RegisterKind GetRegisterKind() const { return m_register_kind; }
+
+ void SetRegisterKind(lldb::RegisterKind kind) { m_register_kind = kind; }
+
+ void SetReturnAddressRegister(uint32_t regnum) {
+ m_return_addr_register = regnum;
+ }
+
+ uint32_t GetReturnAddressRegister(void) { return m_return_addr_register; }
+
+ uint32_t GetInitialCFARegister() const {
+ if (m_row_list.empty())
+ return LLDB_INVALID_REGNUM;
+ return m_row_list.front()->GetCFAValue().GetRegisterNumber();
+ }
+
+ // This UnwindPlan may not be valid at every address of the function span.
+ // For instance, a FastUnwindPlan will not be valid at the prologue setup
+ // instructions - only in the body of the function.
+ void SetPlanValidAddressRange(const AddressRange &range);
+
+ const AddressRange &GetAddressRange() const {
+ return m_plan_valid_address_range;
+ }
+
+ bool PlanValidAtAddress(Address addr);
+
+ bool IsValidRowIndex(uint32_t idx) const;
+
+ const UnwindPlan::RowSP GetRowAtIndex(uint32_t idx) const;
+
+ const UnwindPlan::RowSP GetLastRow() const;
+
+ lldb_private::ConstString GetSourceName() const;
+
+ void SetSourceName(const char *);
+
+ // Was this UnwindPlan emitted by a compiler?
+ lldb_private::LazyBool GetSourcedFromCompiler() const {
+ return m_plan_is_sourced_from_compiler;
+ }
+
+ // Was this UnwindPlan emitted by a compiler?
+ void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler) {
+ m_plan_is_sourced_from_compiler = from_compiler;
+ }
+
+ // Is this UnwindPlan valid at all instructions? If not, then it is assumed
+ // valid at call sites,
+ // e.g. for exception handling.
+ lldb_private::LazyBool GetUnwindPlanValidAtAllInstructions() const {
+ return m_plan_is_valid_at_all_instruction_locations;
+ }
+
+ // Is this UnwindPlan valid at all instructions? If not, then it is assumed
+ // valid at call sites,
+ // e.g. for exception handling.
+ void SetUnwindPlanValidAtAllInstructions(
+ lldb_private::LazyBool valid_at_all_insn) {
+ m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn;
+ }
+
+ int GetRowCount() const;
+
+ void Clear() {
+ m_row_list.clear();
+ m_plan_valid_address_range.Clear();
+ m_register_kind = lldb::eRegisterKindDWARF;
+ m_source_name.Clear();
+ m_plan_is_sourced_from_compiler = eLazyBoolCalculate;
+ m_plan_is_valid_at_all_instruction_locations = eLazyBoolCalculate;
+ m_lsda_address.Clear();
+ m_personality_func_addr.Clear();
+ }
+
+ const RegisterInfo *GetRegisterInfo(Thread *thread, uint32_t reg_num) const;
+
+ Address GetLSDAAddress() const { return m_lsda_address; }
+
+ void SetLSDAAddress(Address lsda_addr) { m_lsda_address = lsda_addr; }
+
+ Address GetPersonalityFunctionPtr() const { return m_personality_func_addr; }
+
+ void SetPersonalityFunctionPtr(Address presonality_func_ptr) {
+ m_personality_func_addr = presonality_func_ptr;
+ }
private:
- typedef std::vector<RowSP> collection;
- collection m_row_list;
- AddressRange m_plan_valid_address_range;
- lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers are in terms of - will need to be
- // translated to lldb native reg nums at unwind time
- uint32_t m_return_addr_register; // The register that has the return address for the caller frame
- // e.g. the lr on arm
- lldb_private::ConstString m_source_name; // for logging, where this UnwindPlan originated from
- lldb_private::LazyBool m_plan_is_sourced_from_compiler;
- lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
-
- Address m_lsda_address; // Where the language specific data area exists in the module - used
- // in exception handling.
- Address m_personality_func_addr; // The address of a pointer to the personality function - used in
- // exception handling.
-}; // class UnwindPlan
+ typedef std::vector<RowSP> collection;
+ collection m_row_list;
+ AddressRange m_plan_valid_address_range;
+ lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers
+ // are in terms of - will need to be
+ // translated to lldb native reg nums at unwind time
+ uint32_t m_return_addr_register; // The register that has the return address
+ // for the caller frame
+ // e.g. the lr on arm
+ lldb_private::ConstString
+ m_source_name; // for logging, where this UnwindPlan originated from
+ lldb_private::LazyBool m_plan_is_sourced_from_compiler;
+ lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations;
+
+ Address m_lsda_address; // Where the language specific data area exists in the
+ // module - used
+ // in exception handling.
+ Address m_personality_func_addr; // The address of a pointer to the
+ // personality function - used in
+ // exception handling.
+}; // class UnwindPlan
} // namespace lldb_private