summaryrefslogtreecommitdiff
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.h248
1 files changed, 190 insertions, 58 deletions
diff --git a/include/lldb/Symbol/UnwindPlan.h b/include/lldb/Symbol/UnwindPlan.h
index c482739cb8f6..bfc008a5b6bc 100644
--- a/include/lldb/Symbol/UnwindPlan.h
+++ b/include/lldb/Symbol/UnwindPlan.h
@@ -237,17 +237,178 @@ public:
} 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 = NULL;
+ len = 0;
+ }
+ }
+
+ const uint8_t *
+ GetDWARFExpressionBytes ()
+ {
+ if (m_type == isDWARFExpression)
+ return m_value.expr.opcodes;
+ return NULL;
+ }
+
+ 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) :
- m_offset (rhs.m_offset),
- m_cfa_type (rhs.m_cfa_type),
- m_cfa_reg_num (rhs.m_cfa_reg_num),
- m_cfa_offset (rhs.m_cfa_offset),
- m_register_locations (rhs.m_register_locations)
- {
- }
+
+ Row (const UnwindPlan::Row& rhs) = default;
bool
operator == (const Row &rhs) const;
@@ -279,47 +440,9 @@ public:
m_offset += offset;
}
- // How we can reconstruct the CFA address for this stack frame, at this location
- enum CFAType
- {
- CFAIsRegisterPlusOffset, // the CFA value in a register plus (or minus) an offset
- CFAIsRegisterDereferenced // the address in a register is dereferenced to get CFA value
- };
-
- CFAType
- GetCFAType () const
- {
- return m_cfa_type;
- }
-
- void
- SetCFAType (CFAType cfa_type)
+ CFAValue& GetCFAValue()
{
- m_cfa_type = cfa_type;
- }
-
- // If GetCFAType() is CFAIsRegisterPlusOffset, add GetCFAOffset to the reg value to get CFA value
- // If GetCFAType() is CFAIsRegisterDereferenced, dereference the addr in the reg to get CFA value
- uint32_t
- GetCFARegister () const
- {
- return m_cfa_reg_num;
- }
-
- void
- SetCFARegister (uint32_t reg_num);
-
- // This should not be used when GetCFAType() is CFAIsRegisterDereferenced; will return 0 in that case.
- int32_t
- GetCFAOffset () const
- {
- return m_cfa_offset;
- }
-
- void
- SetCFAOffset (int32_t offset)
- {
- m_cfa_offset = offset;
+ return m_cfa_value;
}
bool
@@ -360,14 +483,7 @@ public:
typedef std::map<uint32_t, RegisterLocation> collection;
lldb::addr_t m_offset; // Offset into the function for this row
- CFAType m_cfa_type;
-
- // If m_cfa_type == CFAIsRegisterPlusOffset, the CFA address is computed as m_cfa_reg_num + m_cfa_offset
- // If m_cfa_type == CFAIsRegisterDereferenced, the CFA address is computed as *(m_cfa_reg_num) - i.e. the
- // address in m_cfa_reg_num is dereferenced and the pointer value read is the CFA addr.
- uint32_t m_cfa_reg_num; // The Call Frame Address register number
- int32_t m_cfa_offset; // The offset from the CFA for this row
-
+ CFAValue m_cfa_value;
collection m_register_locations;
}; // class Row
@@ -388,6 +504,22 @@ public:
{
}
+ // 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 ()
{
}
@@ -437,7 +569,7 @@ public:
{
if (m_row_list.empty())
return LLDB_INVALID_REGNUM;
- return m_row_list.front()->GetCFARegister();
+ return m_row_list.front()->GetCFAValue().GetRegisterNumber();
}
// This UnwindPlan may not be valid at every address of the function span.