UnwindPlan::Row refactor -- add support for CFA set by a DWARF expression
Summary: This change refactors UnwindPlan::Row to be able to store the fact that the CFA is value is set by evaluating a dwarf expression (DW_CFA_def_cfa_expression). This is achieved by creating a new class CFAValue and moving all CFA setting/getting code there. Note that code using the new CFAValue::isDWARFExpression is not yet present and will be added in a follow-up patch. Therefore, this patch should not change the functionality in any way. Test Plan: Ran tests on Mac and Linux. No regressions detected. Reviewers: jasonmolenda, clayborg Subscribers: lldb-commits Differential Revision: http://reviews.llvm.org/D7755 llvm-svn: 230210
This commit is contained in:
parent
69963e72f3
commit
ab970f5e08
|
@ -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
|
||||
CFAValue& GetCFAValue()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
|
@ -437,7 +553,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.
|
||||
|
|
|
@ -587,7 +587,7 @@ ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
// Our Call Frame Address is the stack pointer value
|
||||
row->SetCFARegister (sp_reg_num);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 0);
|
||||
|
||||
// The previous PC is in the LR
|
||||
row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
|
||||
|
@ -613,8 +613,7 @@ ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
const int32_t ptr_size = 4;
|
||||
|
||||
row->SetCFARegister (fp_reg_num);
|
||||
row->SetCFAOffset (2 * ptr_size);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
|
||||
row->SetOffset (0);
|
||||
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
|
||||
|
|
|
@ -562,7 +562,7 @@ ABIMacOSX_arm64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
// Our previous Call Frame Address is the stack pointer
|
||||
row->SetCFARegister (sp_reg_num);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 0);
|
||||
|
||||
// Our previous PC is in the LR
|
||||
row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
|
||||
|
@ -589,8 +589,7 @@ ABIMacOSX_arm64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
const int32_t ptr_size = 8;
|
||||
|
||||
row->SetCFARegister (fp_reg_num);
|
||||
row->SetCFAOffset (2 * ptr_size);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
|
||||
row->SetOffset (0);
|
||||
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
|
||||
|
|
|
@ -746,8 +746,7 @@ ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
|
|||
uint32_t pc_reg_num = dwarf_eip;
|
||||
|
||||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
row->SetCFARegister (sp_reg_num);
|
||||
row->SetCFAOffset (4);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 4);
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
|
||||
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
|
||||
unwind_plan.AppendRow (row);
|
||||
|
@ -774,8 +773,7 @@ ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
const int32_t ptr_size = 4;
|
||||
|
||||
row->SetCFARegister (fp_reg_num);
|
||||
row->SetCFAOffset (2 * ptr_size);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (fp_reg_num, 2 * ptr_size);
|
||||
row->SetOffset (0);
|
||||
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
|
||||
|
|
|
@ -385,8 +385,7 @@ ABISysV_hexagon::CreateFunctionEntryUnwindPlan ( UnwindPlan &unwind_plan )
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
// Our Call Frame Address is the stack pointer value
|
||||
row->SetCFARegister(LLDB_REGNUM_GENERIC_SP);
|
||||
row->SetCFAOffset(4);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (LLDB_REGNUM_GENERIC_SP, 4);
|
||||
row->SetOffset(0);
|
||||
|
||||
// The previous PC is in the LR
|
||||
|
@ -410,8 +409,7 @@ ABISysV_hexagon::CreateDefaultUnwindPlan ( UnwindPlan &unwind_plan )
|
|||
|
||||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
row->SetCFARegister(LLDB_REGNUM_GENERIC_FP);
|
||||
row->SetCFAOffset(8);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (LLDB_REGNUM_GENERIC_FP, 8);
|
||||
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num,-8, true);
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num,-4, true);
|
||||
|
|
|
@ -985,7 +985,7 @@ ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
// Our Call Frame Address is the stack pointer value
|
||||
row->SetCFARegister (sp_reg_num);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (sp_reg_num, 0);
|
||||
|
||||
// The previous PC is in the LR
|
||||
row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
|
||||
|
@ -1011,8 +1011,7 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
const int32_t ptr_size = 4;
|
||||
row->SetCFARegister (sp_reg_num);
|
||||
row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced);
|
||||
row->GetCFAValue().SetIsRegisterDereferenced (sp_reg_num);
|
||||
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true);
|
||||
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
|
||||
|
|
|
@ -985,7 +985,7 @@ ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
// Our Call Frame Address is the stack pointer value
|
||||
row->SetCFARegister (sp_reg_num);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
|
||||
|
||||
// The previous PC is in the LR
|
||||
row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
|
||||
|
@ -1011,8 +1011,7 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
const int32_t ptr_size = 8;
|
||||
row->SetCFARegister (sp_reg_num);
|
||||
row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced);
|
||||
row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
|
||||
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
|
||||
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
|
||||
|
|
|
@ -1084,8 +1084,7 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
|
|||
uint32_t pc_reg_num = gcc_dwarf_rip;
|
||||
|
||||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
row->SetCFARegister (sp_reg_num);
|
||||
row->SetCFAOffset (8);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8);
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);
|
||||
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
|
||||
unwind_plan.AppendRow (row);
|
||||
|
@ -1112,8 +1111,7 @@ ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
const int32_t ptr_size = 8;
|
||||
row->SetCFARegister (gcc_dwarf_rbp);
|
||||
row->SetCFAOffset (2 * ptr_size);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_rbp, 2 * ptr_size);
|
||||
row->SetOffset (0);
|
||||
|
||||
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
|
||||
|
|
|
@ -13643,7 +13643,7 @@ EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
|
|||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
|
||||
// Our previous Call Frame Address is the stack pointer
|
||||
row->SetCFARegister (dwarf_sp);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (dwarf_sp, 0);
|
||||
|
||||
// Our previous PC is in the LR
|
||||
row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
|
||||
|
|
|
@ -349,7 +349,7 @@ EmulateInstructionARM64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
|
|||
const bool can_replace = false;
|
||||
|
||||
// Our previous Call Frame Address is the stack pointer
|
||||
row->SetCFARegister (arm64_dwarf::sp);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, 0);
|
||||
|
||||
// Our previous PC is in the LR
|
||||
row->SetRegisterLocationToRegister(arm64_dwarf::pc, arm64_dwarf::lr, can_replace);
|
||||
|
|
|
@ -599,7 +599,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
|
|||
|
||||
if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
|
||||
{
|
||||
UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());
|
||||
UnwindLogMsg ("failed to get cfa");
|
||||
m_frame_type = eNotAValidFrame;
|
||||
return;
|
||||
}
|
||||
|
@ -1577,7 +1577,7 @@ RegisterContextLLDB::TryFallbackUnwindPlan ()
|
|||
|
||||
UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
|
||||
|
||||
if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
|
||||
if (active_row && active_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::unspecified)
|
||||
{
|
||||
addr_t new_cfa;
|
||||
if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa)
|
||||
|
@ -1654,7 +1654,7 @@ RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan ()
|
|||
|
||||
UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
|
||||
|
||||
if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
|
||||
if (active_row && active_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::unspecified)
|
||||
{
|
||||
addr_t new_cfa;
|
||||
if (!ReadCFAValueForRow (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, new_cfa)
|
||||
|
@ -1683,57 +1683,69 @@ RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind,
|
|||
const UnwindPlan::RowSP &row,
|
||||
addr_t &cfa_value)
|
||||
{
|
||||
RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFARegister());
|
||||
RegisterValue reg_value;
|
||||
|
||||
cfa_value = LLDB_INVALID_ADDRESS;
|
||||
addr_t cfa_reg_contents;
|
||||
|
||||
if (ReadGPRValue (cfa_reg, cfa_reg_contents))
|
||||
switch (row->GetCFAValue().GetValueType())
|
||||
{
|
||||
if (row->GetCFAType() == UnwindPlan::Row::CFAIsRegisterDereferenced)
|
||||
case UnwindPlan::Row::CFAValue::isRegisterDereferenced:
|
||||
{
|
||||
const RegisterInfo *reg_info = GetRegisterInfoAtIndex (cfa_reg.GetAsKind (eRegisterKindLLDB));
|
||||
RegisterValue reg_value;
|
||||
if (reg_info)
|
||||
RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFAValue().GetRegisterNumber());
|
||||
if (ReadGPRValue (cfa_reg, cfa_reg_contents))
|
||||
{
|
||||
Error error = ReadRegisterValueFromMemory(reg_info,
|
||||
cfa_reg_contents,
|
||||
reg_info->byte_size,
|
||||
reg_value);
|
||||
if (error.Success ())
|
||||
const RegisterInfo *reg_info = GetRegisterInfoAtIndex (cfa_reg.GetAsKind (eRegisterKindLLDB));
|
||||
RegisterValue reg_value;
|
||||
if (reg_info)
|
||||
{
|
||||
cfa_value = reg_value.GetAsUInt64();
|
||||
UnwindLogMsg ("CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 ", CFA value is 0x%" PRIx64,
|
||||
cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
|
||||
cfa_reg_contents, cfa_value);
|
||||
return true;
|
||||
Error error = ReadRegisterValueFromMemory(reg_info,
|
||||
cfa_reg_contents,
|
||||
reg_info->byte_size,
|
||||
reg_value);
|
||||
if (error.Success ())
|
||||
{
|
||||
cfa_value = reg_value.GetAsUInt64();
|
||||
UnwindLogMsg ("CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64 ", CFA value is 0x%" PRIx64,
|
||||
cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
|
||||
cfa_reg_contents, cfa_value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
UnwindLogMsg ("Tried to deref reg %s (%d) [0x%" PRIx64 "] but memory read failed.",
|
||||
cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
|
||||
cfa_reg_contents);
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UnwindPlan::Row::CFAValue::isRegisterPlusOffset:
|
||||
{
|
||||
RegisterNumber cfa_reg (m_thread, row_register_kind, row->GetCFAValue().GetRegisterNumber());
|
||||
if (ReadGPRValue (cfa_reg, cfa_reg_contents))
|
||||
{
|
||||
if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || cfa_reg_contents == 1)
|
||||
{
|
||||
UnwindLogMsg ("Tried to deref reg %s (%d) [0x%" PRIx64 "] but memory read failed.",
|
||||
UnwindLogMsg ("Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64,
|
||||
cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
|
||||
cfa_reg_contents);
|
||||
cfa_reg_contents = LLDB_INVALID_ADDRESS;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 || cfa_reg_contents == 1)
|
||||
{
|
||||
UnwindLogMsg ("Got an invalid CFA register value - reg %s (%d), value 0x%" PRIx64,
|
||||
cfa_value = cfa_reg_contents + row->GetCFAValue().GetOffset();
|
||||
UnwindLogMsg ("CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 ", offset is %d",
|
||||
cfa_value,
|
||||
cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
|
||||
cfa_reg_contents);
|
||||
cfa_reg_contents = LLDB_INVALID_ADDRESS;
|
||||
return false;
|
||||
cfa_reg_contents, row->GetCFAValue().GetOffset());
|
||||
return true;
|
||||
}
|
||||
cfa_value = cfa_reg_contents + row->GetCFAOffset ();
|
||||
UnwindLogMsg ("CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64 ", offset is %d",
|
||||
cfa_value,
|
||||
cfa_reg.GetName(), cfa_reg.GetAsKind (eRegisterKindLLDB),
|
||||
cfa_reg_contents, row->GetCFAOffset ());
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
// TODO: handle isDWARFExpression
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -662,8 +662,8 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
|
|||
m_cfa_reg_info = *reg_info;
|
||||
const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
|
||||
assert (cfa_reg_num != LLDB_INVALID_REGNUM);
|
||||
m_curr_row->SetCFARegister(cfa_reg_num);
|
||||
m_curr_row->SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64());
|
||||
m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(cfa_reg_num, m_initial_sp -
|
||||
reg_value.GetAsUInt64());
|
||||
m_curr_row_modified = true;
|
||||
}
|
||||
break;
|
||||
|
@ -673,7 +673,9 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
|
|||
// subsequent adjustments to the stack pointer.
|
||||
if (!m_fp_is_cfa)
|
||||
{
|
||||
m_curr_row->SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64());
|
||||
m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
|
||||
m_curr_row->GetCFAValue().GetRegisterNumber(),
|
||||
m_initial_sp - reg_value.GetAsUInt64());
|
||||
m_curr_row_modified = true;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -630,8 +630,7 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
|
||||
// At the start of the function, find the CFA by adding wordsize to the SP register
|
||||
row->SetOffset (current_func_text_offset);
|
||||
row->SetCFARegister (m_lldb_sp_regnum);
|
||||
row->SetCFAOffset (m_wordsize);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum, m_wordsize);
|
||||
|
||||
// caller's stack pointer value before the call insn is the CFA address
|
||||
initial_regloc.SetIsCFAPlusOffset (0);
|
||||
|
@ -691,9 +690,9 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
if (push_rbp_pattern_p ())
|
||||
{
|
||||
current_sp_bytes_offset_from_cfa += m_wordsize;
|
||||
row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
|
||||
UnwindPlan::Row::RegisterLocation regloc;
|
||||
regloc.SetAtCFAPlusOffset (-row->GetCFAOffset());
|
||||
regloc.SetAtCFAPlusOffset (-row->GetCFAValue().GetOffset());
|
||||
row->SetRegisterInfo (m_lldb_fp_regnum, regloc);
|
||||
saved_registers[m_machine_fp_regnum] = true;
|
||||
row_updated = true;
|
||||
|
@ -701,7 +700,7 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
|
||||
else if (mov_rsp_rbp_pattern_p ())
|
||||
{
|
||||
row->SetCFARegister (m_lldb_fp_regnum);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_fp_regnum, row->GetCFAValue().GetOffset());
|
||||
row_updated = true;
|
||||
}
|
||||
|
||||
|
@ -717,9 +716,9 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
current_sp_bytes_offset_from_cfa += m_wordsize;
|
||||
// the PUSH instruction has moved the stack pointer - if the CFA is set in terms of the stack pointer,
|
||||
// we need to add a new row of instructions.
|
||||
if (row->GetCFARegister() == m_lldb_sp_regnum)
|
||||
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum)
|
||||
{
|
||||
row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
|
||||
row_updated = true;
|
||||
}
|
||||
// record where non-volatile (callee-saved, spilled) registers are saved on the stack
|
||||
|
@ -748,7 +747,8 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
|
||||
if (machine_regno == (int)m_machine_fp_regnum)
|
||||
{
|
||||
row->SetCFARegister (m_lldb_sp_regnum);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum,
|
||||
row->GetCFAValue().GetOffset());
|
||||
}
|
||||
|
||||
in_epilogue = true;
|
||||
|
@ -757,9 +757,10 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
|
||||
// the POP instruction has moved the stack pointer - if the CFA is set in terms of the stack pointer,
|
||||
// we need to add a new row of instructions.
|
||||
if (row->GetCFARegister() == m_lldb_sp_regnum)
|
||||
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum)
|
||||
{
|
||||
row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum,
|
||||
current_sp_bytes_offset_from_cfa);
|
||||
row_updated = true;
|
||||
}
|
||||
}
|
||||
|
@ -777,7 +778,7 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
// In the Row, we want to express this as the offset from the CFA. If the frame base
|
||||
// is rbp (like the above instruction), the CFA offset for rbp is probably 16. So we
|
||||
// want to say that the value is stored at the CFA address - 96.
|
||||
regloc.SetAtCFAPlusOffset (-(stack_offset + row->GetCFAOffset()));
|
||||
regloc.SetAtCFAPlusOffset (-(stack_offset + row->GetCFAValue().GetOffset()));
|
||||
|
||||
row->SetRegisterInfo (lldb_regno, regloc);
|
||||
|
||||
|
@ -787,9 +788,9 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
else if (sub_rsp_pattern_p (stack_offset))
|
||||
{
|
||||
current_sp_bytes_offset_from_cfa += stack_offset;
|
||||
if (row->GetCFARegister() == m_lldb_sp_regnum)
|
||||
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum)
|
||||
{
|
||||
row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
|
||||
row_updated = true;
|
||||
}
|
||||
}
|
||||
|
@ -797,9 +798,9 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
else if (add_rsp_pattern_p (stack_offset))
|
||||
{
|
||||
current_sp_bytes_offset_from_cfa -= stack_offset;
|
||||
if (row->GetCFARegister() == m_lldb_sp_regnum)
|
||||
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum)
|
||||
{
|
||||
row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
|
||||
row_updated = true;
|
||||
}
|
||||
in_epilogue = true;
|
||||
|
@ -833,9 +834,9 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
|||
else if (call_next_insn_pattern_p ())
|
||||
{
|
||||
current_sp_bytes_offset_from_cfa += m_wordsize;
|
||||
if (row->GetCFARegister() == m_lldb_sp_regnum)
|
||||
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum)
|
||||
{
|
||||
row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
|
||||
row_updated = true;
|
||||
}
|
||||
}
|
||||
|
@ -904,8 +905,8 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
|
|||
return false;
|
||||
uint32_t cfa_reg = m_exe_ctx.GetThreadPtr()->GetRegisterContext()
|
||||
->ConvertRegisterKindToRegisterNumber (unwind_plan.GetRegisterKind(),
|
||||
first_row->GetCFARegister());
|
||||
if (cfa_reg != m_lldb_sp_regnum || first_row->GetCFAOffset() != m_wordsize)
|
||||
first_row->GetCFAValue().GetRegisterNumber());
|
||||
if (cfa_reg != m_lldb_sp_regnum || first_row->GetCFAValue().GetOffset() != m_wordsize)
|
||||
return false;
|
||||
|
||||
UnwindPlan::RowSP original_last_row = unwind_plan.GetRowForFunctionOffset (-1);
|
||||
|
@ -985,7 +986,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
|
|||
// Inspect the instruction to check if we need a new row for it.
|
||||
cfa_reg = m_exe_ctx.GetThreadPtr()->GetRegisterContext()
|
||||
->ConvertRegisterKindToRegisterNumber (unwind_plan.GetRegisterKind(),
|
||||
row->GetCFARegister());
|
||||
row->GetCFAValue().GetRegisterNumber());
|
||||
if (cfa_reg == m_lldb_sp_regnum)
|
||||
{
|
||||
// CFA register is sp.
|
||||
|
@ -996,7 +997,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
|
|||
if (call_next_insn_pattern_p ())
|
||||
{
|
||||
row->SetOffset (offset);
|
||||
row->SetCFAOffset (m_wordsize + row->GetCFAOffset());
|
||||
row->GetCFAValue().IncOffset (m_wordsize);
|
||||
|
||||
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
|
||||
unwind_plan.InsertRow (new_row);
|
||||
|
@ -1009,7 +1010,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
|
|||
if (push_reg_p (regno))
|
||||
{
|
||||
row->SetOffset (offset);
|
||||
row->SetCFAOffset (m_wordsize + row->GetCFAOffset());
|
||||
row->GetCFAValue().IncOffset (m_wordsize);
|
||||
|
||||
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
|
||||
unwind_plan.InsertRow (new_row);
|
||||
|
@ -1024,7 +1025,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
|
|||
// So we ignore this case.
|
||||
|
||||
row->SetOffset (offset);
|
||||
row->SetCFAOffset (-m_wordsize + row->GetCFAOffset());
|
||||
row->GetCFAValue().IncOffset (-m_wordsize);
|
||||
|
||||
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
|
||||
unwind_plan.InsertRow (new_row);
|
||||
|
@ -1036,7 +1037,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
|
|||
if (push_imm_pattern_p ())
|
||||
{
|
||||
row->SetOffset (offset);
|
||||
row->SetCFAOffset (m_wordsize + row->GetCFAOffset());
|
||||
row->GetCFAValue().IncOffset (m_wordsize);
|
||||
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
|
||||
unwind_plan.InsertRow (new_row);
|
||||
unwind_plan_updated = true;
|
||||
|
@ -1048,7 +1049,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
|
|||
if (add_rsp_pattern_p (amount))
|
||||
{
|
||||
row->SetOffset (offset);
|
||||
row->SetCFAOffset (-amount + row->GetCFAOffset());
|
||||
row->GetCFAValue().IncOffset (-amount);
|
||||
|
||||
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
|
||||
unwind_plan.InsertRow (new_row);
|
||||
|
@ -1058,7 +1059,7 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
|
|||
if (sub_rsp_pattern_p (amount))
|
||||
{
|
||||
row->SetOffset (offset);
|
||||
row->SetCFAOffset (amount + row->GetCFAOffset());
|
||||
row->GetCFAValue().IncOffset (amount);
|
||||
|
||||
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
|
||||
unwind_plan.InsertRow (new_row);
|
||||
|
@ -1085,8 +1086,8 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
|
|||
&& ret_pattern_p ())
|
||||
{
|
||||
row->SetOffset (offset);
|
||||
row->SetCFARegister (first_row->GetCFARegister());
|
||||
row->SetCFAOffset (m_wordsize);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (
|
||||
first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
|
||||
|
||||
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
|
||||
unwind_plan.InsertRow (new_row);
|
||||
|
@ -1169,8 +1170,7 @@ AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_
|
|||
row->SetRegisterInfo (m_lldb_sp_regnum, sp_reginfo);
|
||||
|
||||
// Zero instructions into the function
|
||||
row->SetCFARegister (m_lldb_sp_regnum);
|
||||
row->SetCFAOffset (m_wordsize);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, m_wordsize);
|
||||
row->SetOffset (0);
|
||||
unwind_plan.AppendRow (row);
|
||||
UnwindPlan::Row *newrow = new UnwindPlan::Row;
|
||||
|
@ -1178,7 +1178,7 @@ AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_
|
|||
row.reset(newrow);
|
||||
|
||||
// push %rbp has executed - stack moved, rbp now saved
|
||||
row->SetCFAOffset (2 * m_wordsize);
|
||||
row->GetCFAValue().IncOffset (m_wordsize);
|
||||
fp_reginfo.SetAtCFAPlusOffset (2 * -m_wordsize);
|
||||
row->SetRegisterInfo (m_lldb_fp_regnum, fp_reginfo);
|
||||
row->SetOffset (1);
|
||||
|
@ -1189,8 +1189,7 @@ AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_
|
|||
row.reset(newrow);
|
||||
|
||||
// mov %rsp, %rbp has executed
|
||||
row->SetCFARegister (m_lldb_fp_regnum);
|
||||
row->SetCFAOffset (2 * m_wordsize);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_fp_regnum, 2 * m_wordsize);
|
||||
row->SetOffset (prologue_size); /// 3 or 4 bytes depending on arch
|
||||
unwind_plan.AppendRow (row);
|
||||
|
||||
|
@ -1300,9 +1299,10 @@ UnwindAssembly_x86::AugmentUnwindPlanFromCallSite (AddressRange& func, Thread& t
|
|||
// If there is no description of the prologue, don't try to augment this eh_frame
|
||||
// unwinder code, fall back to assembly parsing instead.
|
||||
|
||||
if (first_row->GetCFAType() != UnwindPlan::Row::CFAType::CFAIsRegisterPlusOffset
|
||||
|| RegisterNumber (thread, unwind_plan.GetRegisterKind(), first_row->GetCFARegister()) != sp_regnum
|
||||
|| first_row->GetCFAOffset() != wordsize)
|
||||
if (first_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::isRegisterPlusOffset
|
||||
|| RegisterNumber (thread, unwind_plan.GetRegisterKind(),
|
||||
first_row->GetCFAValue().GetRegisterNumber()) != sp_regnum
|
||||
|| first_row->GetCFAValue().GetOffset() != wordsize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1326,9 +1326,9 @@ UnwindAssembly_x86::AugmentUnwindPlanFromCallSite (AddressRange& func, Thread& t
|
|||
|
||||
// We're checking that both of them have an unwind rule like "CFA=esp+4" or CFA+rsp+8".
|
||||
|
||||
if (first_row->GetCFAType() == last_row->GetCFAType()
|
||||
&& first_row->GetCFARegister() == last_row->GetCFARegister()
|
||||
&& first_row->GetCFAOffset() == last_row->GetCFAOffset())
|
||||
if (first_row->GetCFAValue().GetValueType() == last_row->GetCFAValue().GetValueType()
|
||||
&& first_row->GetCFAValue().GetRegisterNumber() == last_row->GetCFAValue().GetRegisterNumber()
|
||||
&& first_row->GetCFAValue().GetOffset() == last_row->GetCFAValue().GetOffset())
|
||||
{
|
||||
// Get the register locations for eip/rip from the first & last rows.
|
||||
// Are they both CFA plus an offset? Is it the same offset?
|
||||
|
|
|
@ -720,8 +720,9 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi
|
|||
{
|
||||
case UNWIND_X86_64_MODE_RBP_FRAME:
|
||||
{
|
||||
row->SetCFARegister (translate_to_eh_frame_regnum_x86_64 (UNWIND_X86_64_REG_RBP));
|
||||
row->SetCFAOffset (2 * wordsize);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (
|
||||
translate_to_eh_frame_regnum_x86_64 (UNWIND_X86_64_REG_RBP),
|
||||
2 * wordsize);
|
||||
row->SetOffset (0);
|
||||
row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rbp, wordsize * -2, true);
|
||||
row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true);
|
||||
|
@ -809,16 +810,9 @@ CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &functi
|
|||
}
|
||||
}
|
||||
|
||||
if (mode == UNWIND_X86_64_MODE_STACK_IND)
|
||||
{
|
||||
row->SetCFAOffset (stack_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
row->SetCFAOffset (stack_size * wordsize);
|
||||
}
|
||||
int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND ? stack_size : stack_size * wordsize;
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (x86_64_eh_regnum::rsp, offset);
|
||||
|
||||
row->SetCFARegister (x86_64_eh_regnum::rsp);
|
||||
row->SetOffset (0);
|
||||
row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true);
|
||||
row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true);
|
||||
|
@ -1009,8 +1003,8 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function
|
|||
{
|
||||
case UNWIND_X86_MODE_EBP_FRAME:
|
||||
{
|
||||
row->SetCFARegister (translate_to_eh_frame_regnum_i386 (UNWIND_X86_REG_EBP));
|
||||
row->SetCFAOffset (2 * wordsize);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (
|
||||
translate_to_eh_frame_regnum_i386 (UNWIND_X86_REG_EBP), 2 * wordsize);
|
||||
row->SetOffset (0);
|
||||
row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::ebp, wordsize * -2, true);
|
||||
row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true);
|
||||
|
@ -1091,17 +1085,8 @@ CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function
|
|||
}
|
||||
}
|
||||
|
||||
row->SetCFARegister (i386_eh_regnum::esp);
|
||||
|
||||
if (mode == UNWIND_X86_MODE_STACK_IND)
|
||||
{
|
||||
row->SetCFAOffset (stack_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
row->SetCFAOffset (stack_size * wordsize);
|
||||
}
|
||||
|
||||
int32_t offset = mode == UNWIND_X86_MODE_STACK_IND ? stack_size : stack_size * wordsize;
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (i386_eh_regnum::esp, offset);
|
||||
row->SetOffset (0);
|
||||
row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true);
|
||||
row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true);
|
||||
|
|
|
@ -284,8 +284,7 @@ DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset)
|
|||
// register and offset.
|
||||
uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
|
||||
int op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
|
||||
cie_sp->initial_row.SetCFARegister (reg_num);
|
||||
cie_sp->initial_row.SetCFAOffset (op_offset);
|
||||
cie_sp->initial_row.GetCFAValue().SetIsRegisterPlusOffset (reg_num, op_offset);
|
||||
continue;
|
||||
}
|
||||
if (primary_opcode == DW_CFA_offset)
|
||||
|
@ -719,8 +718,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
|
|||
// register and offset.
|
||||
reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
|
||||
op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
|
||||
row->SetCFARegister (reg_num);
|
||||
row->SetCFAOffset (op_offset);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (reg_num, op_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -730,7 +728,8 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
|
|||
// number. The required action is to define the current CFA rule to
|
||||
// use the provided register (but to keep the old offset).
|
||||
reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
|
||||
row->SetCFARegister (reg_num);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (reg_num,
|
||||
row->GetCFAValue().GetOffset());
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -741,7 +740,8 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
|
|||
// the current CFA rule to use the provided offset (but
|
||||
// to keep the old register).
|
||||
op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
|
||||
row->SetCFAOffset (op_offset);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (
|
||||
row->GetCFAValue().GetRegisterNumber(), op_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -792,8 +792,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
|
|||
// that the second operand is signed and factored.
|
||||
reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
|
||||
op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
|
||||
row->SetCFARegister (reg_num);
|
||||
row->SetCFAOffset (op_offset);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (reg_num, op_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -803,7 +802,8 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr
|
|||
// offset. This instruction is identical to DW_CFA_def_cfa_offset
|
||||
// except that the operand is signed and factored.
|
||||
op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
|
||||
row->SetCFAOffset (op_offset);
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset (
|
||||
row->GetCFAValue().GetRegisterNumber(), op_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -94,31 +94,7 @@ UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_pla
|
|||
s.PutChar('=');
|
||||
if (m_type == atCFAPlusOffset)
|
||||
s.PutChar('[');
|
||||
if (verbose)
|
||||
s.Printf ("CFA%+d", m_location.offset);
|
||||
|
||||
if (unwind_plan && row)
|
||||
{
|
||||
const uint32_t cfa_reg = row->GetCFARegister();
|
||||
const RegisterInfo *cfa_reg_info = unwind_plan->GetRegisterInfo (thread, cfa_reg);
|
||||
const int32_t offset = row->GetCFAOffset() + m_location.offset;
|
||||
if (verbose)
|
||||
{
|
||||
if (cfa_reg_info)
|
||||
s.Printf (" (%s%+d)", cfa_reg_info->name, offset);
|
||||
else
|
||||
s.Printf (" (reg(%u)%+d)", cfa_reg, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cfa_reg_info)
|
||||
s.Printf ("%s", cfa_reg_info->name);
|
||||
else
|
||||
s.Printf ("reg(%u)", cfa_reg);
|
||||
if (offset != 0)
|
||||
s.Printf ("%+d", offset);
|
||||
}
|
||||
}
|
||||
s.Printf ("CFA%+d", m_location.offset);
|
||||
if (m_type == atCFAPlusOffset)
|
||||
s.PutChar(']');
|
||||
}
|
||||
|
@ -150,38 +126,83 @@ UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_pla
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DumpRegisterName (Stream &s, const UnwindPlan* unwind_plan, Thread *thread, uint32_t reg_num) {
|
||||
const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, reg_num);
|
||||
if (reg_info)
|
||||
s.PutCString (reg_info->name);
|
||||
else
|
||||
s.Printf ("reg(%u)", reg_num);
|
||||
}
|
||||
|
||||
bool
|
||||
UnwindPlan::Row::CFAValue::operator == (const UnwindPlan::Row::CFAValue& rhs) const
|
||||
{
|
||||
if (m_type == rhs.m_type)
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case unspecified:
|
||||
return true;
|
||||
|
||||
case isRegisterPlusOffset:
|
||||
return m_value.reg.offset == rhs.m_value.reg.offset;
|
||||
|
||||
case isRegisterDereferenced:
|
||||
return m_value.reg.reg_num == rhs.m_value.reg.reg_num;
|
||||
|
||||
case isDWARFExpression:
|
||||
if (m_value.expr.length == rhs.m_value.expr.length)
|
||||
return !memcmp (m_value.expr.opcodes, rhs.m_value.expr.opcodes, m_value.expr.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::CFAValue::Dump(Stream &s, const UnwindPlan* unwind_plan, Thread* thread) const
|
||||
{
|
||||
switch(m_type) {
|
||||
case isRegisterPlusOffset:
|
||||
DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
|
||||
s.Printf ("%+3d", m_value.reg.offset);
|
||||
break;
|
||||
case isRegisterDereferenced:
|
||||
s.PutChar ('[');
|
||||
DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
|
||||
s.PutChar (']');
|
||||
break;
|
||||
case isDWARFExpression:
|
||||
s.PutCString ("dwarf-expr");
|
||||
break;
|
||||
default:
|
||||
s.PutCString ("unspecified");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::Clear ()
|
||||
{
|
||||
m_cfa_type = CFAIsRegisterPlusOffset;
|
||||
m_cfa_value.SetUnspecified();
|
||||
m_offset = 0;
|
||||
m_cfa_reg_num = LLDB_INVALID_REGNUM;
|
||||
m_cfa_offset = 0;
|
||||
m_register_locations.clear();
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const
|
||||
{
|
||||
const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, GetCFARegister());
|
||||
|
||||
if (base_addr != LLDB_INVALID_ADDRESS)
|
||||
s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
|
||||
else
|
||||
s.Printf ("%4" PRId64 ": CFA=", GetOffset());
|
||||
|
||||
if (reg_info)
|
||||
s.Printf ("%s", reg_info->name);
|
||||
else
|
||||
s.Printf ("reg(%u)", GetCFARegister());
|
||||
s.Printf ("%+3d => ", GetCFAOffset ());
|
||||
m_cfa_value.Dump(s, unwind_plan, thread);
|
||||
s.Printf(" => ");
|
||||
for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx)
|
||||
{
|
||||
reg_info = unwind_plan->GetRegisterInfo (thread, idx->first);
|
||||
if (reg_info)
|
||||
s.Printf ("%s", reg_info->name);
|
||||
else
|
||||
s.Printf ("reg(%u)", idx->first);
|
||||
DumpRegisterName(s, unwind_plan, thread, idx->first);
|
||||
const bool verbose = false;
|
||||
idx->second.Dump(s, unwind_plan, this, thread, verbose);
|
||||
s.PutChar (' ');
|
||||
|
@ -191,9 +212,7 @@ UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread,
|
|||
|
||||
UnwindPlan::Row::Row() :
|
||||
m_offset (0),
|
||||
m_cfa_type (CFAIsRegisterPlusOffset),
|
||||
m_cfa_reg_num (LLDB_INVALID_REGNUM),
|
||||
m_cfa_offset (0),
|
||||
m_cfa_value (),
|
||||
m_register_locations ()
|
||||
{
|
||||
}
|
||||
|
@ -302,35 +321,11 @@ UnwindPlan::Row::SetRegisterLocationToSame (uint32_t reg_num, bool must_replace)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::SetCFARegister (uint32_t reg_num)
|
||||
{
|
||||
m_cfa_reg_num = reg_num;
|
||||
}
|
||||
|
||||
bool
|
||||
UnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const
|
||||
{
|
||||
if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset)
|
||||
return false;
|
||||
|
||||
if (m_cfa_type != rhs.m_cfa_type)
|
||||
return false;
|
||||
|
||||
if (m_cfa_type == CFAIsRegisterPlusOffset)
|
||||
{
|
||||
if (m_cfa_reg_num != rhs.m_cfa_reg_num)
|
||||
return false;
|
||||
if (m_cfa_offset != rhs.m_cfa_offset)
|
||||
return false;
|
||||
}
|
||||
if (m_cfa_type == CFAIsRegisterDereferenced)
|
||||
{
|
||||
if (m_cfa_reg_num != rhs.m_cfa_reg_num)
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_register_locations == rhs.m_register_locations;
|
||||
return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value &&
|
||||
m_register_locations == rhs.m_register_locations;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -439,7 +434,10 @@ UnwindPlan::PlanValidAtAddress (Address addr)
|
|||
|
||||
// If the 0th Row of unwind instructions is missing, or if it doesn't provide
|
||||
// a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan.
|
||||
if (GetRowAtIndex(0).get() == nullptr || GetRowAtIndex(0)->GetCFARegister() == LLDB_INVALID_REGNUM)
|
||||
// CFA set by a DWARF expression is not currently supported, so ignore that as well.
|
||||
if (GetRowAtIndex(0).get() == nullptr ||
|
||||
GetRowAtIndex(0)->GetCFAValue().GetValueType() == Row::CFAValue::unspecified ||
|
||||
GetRowAtIndex(0)->GetCFAValue().GetValueType() == Row::CFAValue::isDWARFExpression)
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
|
||||
if (log)
|
||||
|
|
Loading…
Reference in New Issue