forked from OSchip/llvm-project
A change in how we search for saved register values unintentionally
allowed volatile registers to be returned up the stack. That leads to unexpected/incorrect values provided to the user and we need to avoid that. <rdar://problem/12714247> llvm-svn: 168123
This commit is contained in:
parent
234ba6f2cd
commit
aff2a269e3
|
@ -903,7 +903,7 @@ RegisterContextLLDB::IsSkipFrame () const
|
||||||
|
|
||||||
// Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value?
|
// Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value?
|
||||||
|
|
||||||
bool
|
enum UnwindLLDB::RegisterSearchResult
|
||||||
RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc)
|
RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc)
|
||||||
{
|
{
|
||||||
// Have we already found this register location?
|
// Have we already found this register location?
|
||||||
|
@ -914,7 +914,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
if (iterator != m_registers.end())
|
if (iterator != m_registers.end())
|
||||||
{
|
{
|
||||||
regloc = iterator->second;
|
regloc = iterator->second;
|
||||||
return true;
|
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,7 +937,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
|
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
|
||||||
regloc.location.inferred_value = m_cfa;
|
regloc.location.inferred_value = m_cfa;
|
||||||
m_registers[lldb_regnum] = regloc;
|
m_registers[lldb_regnum] = regloc;
|
||||||
return true;
|
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look through the available UnwindPlans for the register location.
|
// Look through the available UnwindPlans for the register location.
|
||||||
|
@ -955,7 +955,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
{
|
{
|
||||||
UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
|
UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
|
||||||
lldb_regnum, (int) unwindplan_registerkind);
|
lldb_regnum, (int) unwindplan_registerkind);
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
|
||||||
}
|
}
|
||||||
if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
|
if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
|
||||||
{
|
{
|
||||||
|
@ -993,7 +993,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
else
|
else
|
||||||
UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
|
UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
|
||||||
lldb_regnum, (int) unwindplan_registerkind);
|
lldb_regnum, (int) unwindplan_registerkind);
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1064,7 +1064,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
if (reg_info && abi->RegisterIsVolatile (reg_info))
|
if (reg_info && abi->RegisterIsVolatile (reg_info))
|
||||||
{
|
{
|
||||||
UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
|
UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,11 +1076,11 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
new_regloc.location.register_number = lldb_regnum;
|
new_regloc.location.register_number = lldb_regnum;
|
||||||
m_registers[lldb_regnum] = new_regloc;
|
m_registers[lldb_regnum] = new_regloc;
|
||||||
regloc = new_regloc;
|
regloc = new_regloc;
|
||||||
return true;
|
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unwindplan_regloc has valid contents about where to retrieve the register
|
// unwindplan_regloc has valid contents about where to retrieve the register
|
||||||
|
@ -1090,7 +1090,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved;
|
new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved;
|
||||||
m_registers[lldb_regnum] = new_regloc;
|
m_registers[lldb_regnum] = new_regloc;
|
||||||
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unwindplan_regloc.IsSame())
|
if (unwindplan_regloc.IsSame())
|
||||||
|
@ -1098,11 +1098,11 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
if (IsFrameZero ())
|
if (IsFrameZero ())
|
||||||
{
|
{
|
||||||
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1112,7 +1112,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
|
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
|
||||||
regloc.location.inferred_value = m_cfa + offset;
|
regloc.location.inferred_value = m_cfa + offset;
|
||||||
m_registers[lldb_regnum] = regloc;
|
m_registers[lldb_regnum] = regloc;
|
||||||
return true;
|
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unwindplan_regloc.IsAtCFAPlusOffset())
|
if (unwindplan_regloc.IsAtCFAPlusOffset())
|
||||||
|
@ -1121,7 +1121,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
|
regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
|
||||||
regloc.location.target_memory_location = m_cfa + offset;
|
regloc.location.target_memory_location = m_cfa + offset;
|
||||||
m_registers[lldb_regnum] = regloc;
|
m_registers[lldb_regnum] = regloc;
|
||||||
return true;
|
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unwindplan_regloc.IsInOtherRegister())
|
if (unwindplan_regloc.IsInOtherRegister())
|
||||||
|
@ -1131,12 +1131,12 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
|
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
|
||||||
{
|
{
|
||||||
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
|
||||||
}
|
}
|
||||||
regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
|
regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
|
||||||
regloc.location.register_number = row_regnum_in_lldb;
|
regloc.location.register_number = row_regnum_in_lldb;
|
||||||
m_registers[lldb_regnum] = regloc;
|
m_registers[lldb_regnum] = regloc;
|
||||||
return true;
|
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
|
if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
|
||||||
|
@ -1157,25 +1157,25 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
|
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
|
||||||
regloc.location.inferred_value = val;
|
regloc.location.inferred_value = val;
|
||||||
m_registers[lldb_regnum] = regloc;
|
m_registers[lldb_regnum] = regloc;
|
||||||
return true;
|
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
|
regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
|
||||||
regloc.location.target_memory_location = val;
|
regloc.location.target_memory_location = val;
|
||||||
m_registers[lldb_regnum] = regloc;
|
m_registers[lldb_regnum] = regloc;
|
||||||
return true;
|
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum);
|
UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum);
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
|
||||||
|
|
||||||
// FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.
|
// FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.
|
||||||
|
|
||||||
return false;
|
return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the Full unwindplan has been determined to be incorrect, this method will
|
// If the Full unwindplan has been determined to be incorrect, this method will
|
||||||
|
|
|
@ -131,7 +131,7 @@ private:
|
||||||
// If a non-volatile register (a "preserved" register) is requested mid-stack and no frames "below" the requested
|
// If a non-volatile register (a "preserved" register) is requested mid-stack and no frames "below" the requested
|
||||||
// stack have saved the register anywhere, it is safe to assume that frame 0's register values are still the same
|
// stack have saved the register anywhere, it is safe to assume that frame 0's register values are still the same
|
||||||
// as the requesting frame's.
|
// as the requesting frame's.
|
||||||
bool
|
lldb_private::UnwindLLDB::RegisterSearchResult
|
||||||
SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc);
|
SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -272,15 +272,21 @@ UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
|
||||||
// isn't saved by frame_num, none of the frames lower on the stack will have a useful value.
|
// isn't saved by frame_num, none of the frames lower on the stack will have a useful value.
|
||||||
if (pc_or_return_address_reg)
|
if (pc_or_return_address_reg)
|
||||||
{
|
{
|
||||||
if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc))
|
UnwindLLDB::RegisterSearchResult result;
|
||||||
|
result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
|
||||||
|
if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
while (frame_num >= 0)
|
while (frame_num >= 0)
|
||||||
{
|
{
|
||||||
if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc))
|
UnwindLLDB::RegisterSearchResult result;
|
||||||
|
result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
|
||||||
|
if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound)
|
||||||
return true;
|
return true;
|
||||||
|
if (result == UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile)
|
||||||
|
return false;
|
||||||
frame_num--;
|
frame_num--;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -30,6 +30,13 @@ public:
|
||||||
virtual
|
virtual
|
||||||
~UnwindLLDB() { }
|
~UnwindLLDB() { }
|
||||||
|
|
||||||
|
enum RegisterSearchResult
|
||||||
|
{
|
||||||
|
eRegisterFound = 0,
|
||||||
|
eRegisterNotFound,
|
||||||
|
eRegisterIsVolatile
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class lldb_private::RegisterContextLLDB;
|
friend class lldb_private::RegisterContextLLDB;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue