forked from OSchip/llvm-project
Some eh_frame unwind instructions will define a return address register;
when you want to find the caller's saved pc, you look up the return address register and use that. On arm, for instance, this would be the contents of the link register (lr). If the eh_frame CIE defines an RA, record that fact in the UnwindPlan. When we're finding a saved register, if it's the pc, lok for the location of the return address register instead. <rdar://problem/12062310> llvm-svn: 162167
This commit is contained in:
parent
0128f9bad7
commit
8eba46c68a
|
@ -75,7 +75,7 @@ private:
|
|||
lldb_private::UnwindPlan::Row initial_row;
|
||||
|
||||
CIE(dw_offset_t offset) : cie_offset(offset), version (-1), code_align (0),
|
||||
data_align (0), return_addr_reg_num (-1), inst_offset (0),
|
||||
data_align (0), return_addr_reg_num (LLDB_INVALID_REGNUM), inst_offset (0),
|
||||
inst_length (0), ptr_encoding (0), initial_row() {}
|
||||
};
|
||||
|
||||
|
|
|
@ -348,6 +348,7 @@ public:
|
|||
m_row_list (),
|
||||
m_plan_valid_address_range (),
|
||||
m_register_kind (reg_kind),
|
||||
m_return_addr_register (LLDB_INVALID_REGNUM),
|
||||
m_source_name ()
|
||||
{
|
||||
}
|
||||
|
@ -381,6 +382,18 @@ public:
|
|||
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
|
||||
{
|
||||
|
@ -441,7 +454,9 @@ private:
|
|||
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
|
||||
// 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
|
||||
}; // class UnwindPlan
|
||||
|
||||
|
|
|
@ -1034,6 +1034,12 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
|||
return true;
|
||||
}
|
||||
|
||||
uint32_t pc_regnum;
|
||||
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum))
|
||||
{
|
||||
pc_regnum = LLDB_INVALID_REGNUM;
|
||||
}
|
||||
|
||||
// Look through the available UnwindPlans for the register location.
|
||||
|
||||
UnwindPlan::Row::RegisterLocation unwindplan_regloc;
|
||||
|
@ -1078,20 +1084,35 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
|||
UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
|
||||
unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind ();
|
||||
uint32_t row_regnum;
|
||||
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
|
||||
|
||||
// If we're fetching the saved pc and this UnwindPlan defines a ReturnAddress register (e.g. lr on arm),
|
||||
// look for the return address register number in the UnwindPlan's row.
|
||||
if (lldb_regnum == pc_regnum && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM)
|
||||
{
|
||||
if (log)
|
||||
row_regnum = m_full_unwind_plan_sp->GetReturnAddressRegister();
|
||||
if (log)
|
||||
{
|
||||
log->Printf("%*sFrame %u requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead",
|
||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, row_regnum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
|
||||
{
|
||||
if (unwindplan_registerkind == eRegisterKindGeneric)
|
||||
log->Printf("%*sFrame %u could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme",
|
||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
|
||||
lldb_regnum);
|
||||
else
|
||||
log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
|
||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
|
||||
lldb_regnum, (int) unwindplan_registerkind);
|
||||
if (log)
|
||||
{
|
||||
if (unwindplan_registerkind == eRegisterKindGeneric)
|
||||
log->Printf("%*sFrame %u could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme",
|
||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
|
||||
lldb_regnum);
|
||||
else
|
||||
log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
|
||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
|
||||
lldb_regnum, (int) unwindplan_registerkind);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
|
||||
|
|
|
@ -407,6 +407,7 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t offset, Address startaddr, Unwi
|
|||
UnwindPlan::RowSP row(cie_initial_row);
|
||||
|
||||
unwind_plan.SetRegisterKind (m_reg_kind);
|
||||
unwind_plan.SetReturnAddressRegister (cie->return_addr_reg_num);
|
||||
|
||||
UnwindPlan::Row::RegisterLocation reg_location;
|
||||
while (m_cfi_data.ValidOffset(offset) && offset < end_offset)
|
||||
|
|
Loading…
Reference in New Issue