[Lldb-commits] [lldb] r221788 - Add an alternative CFA type.
Justin Hibbits
jrh29 at alumni.cwru.edu
Wed Nov 12 07:14:03 PST 2014
Author: jhibbits
Date: Wed Nov 12 09:14:03 2014
New Revision: 221788
URL: http://llvm.org/viewvc/llvm-project?rev=221788&view=rev
Log:
Add an alternative CFA type.
Summary:
PowerPC handles the stack chain with the current stack pointer being a pointer
to the backchain (CFA). LLDB currently has no way of handling this, so this
adds a "CFA is dereferenced from a register" type.
Discussed with Jason Molenda, who also provided the initial patch for this.
Reviewers: jasonmolenda
Reviewed By: jasonmolenda
Subscribers: emaste, lldb-commits
Differential Revision: http://reviews.llvm.org/D6182
Modified:
lldb/trunk/include/lldb/Symbol/UnwindPlan.h
lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
lldb/trunk/source/Symbol/UnwindPlan.cpp
Modified: lldb/trunk/include/lldb/Symbol/UnwindPlan.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/UnwindPlan.h?rev=221788&r1=221787&r2=221788&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/UnwindPlan.h (original)
+++ lldb/trunk/include/lldb/Symbol/UnwindPlan.h Wed Nov 12 09:14:03 2014
@@ -58,13 +58,13 @@ public:
atDWARFExpression, // reg = deref(eval(dwarf_expr))
isDWARFExpression // reg = eval(dwarf_expr)
};
-
+
RegisterLocation() :
m_type(unspecified),
m_location()
{
}
-
+
bool
operator == (const RegisterLocation& rhs) const;
@@ -242,6 +242,7 @@ public:
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)
@@ -275,12 +276,50 @@ 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)
+ {
+ m_cfa_type = cfa_type;
+ }
+
+ // This should be used when GetCFAType() returns CFAIsRegisterPlusOffset
uint32_t
GetCFARegister () const
{
return m_cfa_reg_num;
}
+ // This should be used when GetCFAType() is set to CFAIsRegisterPlusOffset
+ void
+ SetCFARegister (uint32_t reg_num);
+
+ // This should be used when GetCFAType() returns CFAIsRegisterPlusOffset
+ int32_t
+ GetCFAOffset () const
+ {
+ return m_cfa_offset;
+ }
+
+ // This should be used when GetCFAType() is set to CFAIsRegisterPlusOffset
+ void
+ SetCFAOffset (int32_t offset)
+ {
+ m_cfa_offset = offset;
+ }
+
bool
SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num,
int32_t offset,
@@ -309,23 +348,6 @@ public:
SetRegisterLocationToSame (uint32_t reg_num,
bool must_replace);
-
-
- void
- SetCFARegister (uint32_t reg_num);
-
- int32_t
- GetCFAOffset () const
- {
- return m_cfa_offset;
- }
-
- void
- SetCFAOffset (int32_t offset)
- {
- m_cfa_offset = offset;
- }
-
void
Clear ();
@@ -335,8 +357,13 @@ public:
protected:
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 following ivars are used
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
+
collection m_register_locations;
}; // class Row
Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp?rev=221788&r1=221787&r2=221788&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp Wed Nov 12 09:14:03 2014
@@ -232,7 +232,6 @@ RegisterContextLLDB::InitializeZerothFra
m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
UnwindPlan::RowSP active_row;
- int cfa_offset = 0;
lldb::RegisterKind row_register_kind = eRegisterKindGeneric;
if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{
@@ -254,18 +253,13 @@ RegisterContextLLDB::InitializeZerothFra
}
- addr_t cfa_regval = LLDB_INVALID_ADDRESS;
- if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
+ if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
{
UnwindLogMsg ("could not read CFA register for this frame.");
m_frame_type = eNotAValidFrame;
return;
}
- cfa_offset = active_row->GetCFAOffset ();
- m_cfa = cfa_regval + cfa_offset;
-
- UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan",
(uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
(uint64_t) m_cfa,
@@ -378,14 +372,11 @@ RegisterContextLLDB::InitializeNonZeroth
m_all_registers_available = false;
m_current_offset = -1;
m_current_offset_backed_up_one = -1;
- addr_t cfa_regval = LLDB_INVALID_ADDRESS;
RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
if (row.get())
{
- uint32_t cfa_regnum = row->GetCFARegister();
- int cfa_offset = row->GetCFAOffset();
- if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
+ if (!ReadCFAValueForRow (row_register_kind, row, m_cfa))
{
UnwindLogMsg ("failed to get cfa value");
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
@@ -394,19 +385,18 @@ RegisterContextLLDB::InitializeNonZeroth
}
return;
}
- m_cfa = cfa_regval + cfa_offset;
// A couple of sanity checks..
- if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
+ if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1)
{
UnwindLogMsg ("could not find a valid cfa address");
m_frame_type = eNotAValidFrame;
return;
}
- // cfa_regval should point into the stack memory; if we can query memory region permissions,
+ // m_cfa should point into the stack memory; if we can query memory region permissions,
// see if the memory is allocated & readable.
- if (process->GetLoadAddressPermissions(cfa_regval, permissions)
+ if (process->GetLoadAddressPermissions(m_cfa, permissions)
&& (permissions & ePermissionsReadable) == 0)
{
m_frame_type = eNotAValidFrame;
@@ -600,8 +590,7 @@ RegisterContextLLDB::InitializeNonZeroth
return;
}
- addr_t cfa_regval = LLDB_INVALID_ADDRESS;
- if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
+ if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
{
UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());
m_frame_type = eNotAValidFrame;
@@ -609,12 +598,11 @@ RegisterContextLLDB::InitializeNonZeroth
}
cfa_offset = active_row->GetCFAOffset ();
- m_cfa = cfa_regval + cfa_offset;
- UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
+ UnwindLogMsg ("m_cfa = 0x%16.16" PRIx64 " (cfa_offset = %i)", m_cfa, cfa_offset);
// A couple of sanity checks..
- if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
+ if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == (addr_t)cfa_offset || m_cfa == (addr_t)cfa_offset + 1)
{
UnwindLogMsg ("could not find a valid cfa address");
m_frame_type = eNotAValidFrame;
@@ -1478,11 +1466,8 @@ RegisterContextLLDB::TryFallbackUnwindPl
{
m_registers.clear();
m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
- addr_t cfa_regval = LLDB_INVALID_ADDRESS;
- if (ReadGPRValue (m_fallback_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval))
- {
- m_cfa = cfa_regval + active_row->GetCFAOffset ();
- }
+ m_cfa = LLDB_INVALID_ADDRESS;
+ ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(), active_row, m_cfa);
UnwindLogMsg ("trying to unwind from this function with the UnwindPlan '%s' because UnwindPlan '%s' failed.",
m_fallback_unwind_plan_sp->GetSourceName().GetCString(),
@@ -1493,6 +1478,38 @@ RegisterContextLLDB::TryFallbackUnwindPl
return true;
}
+bool
+RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind,
+ const UnwindPlan::RowSP &row,
+ addr_t &value)
+{
+ uint32_t cfa_regnum = row->GetCFARegister();
+ RegisterValue reg_value;
+ addr_t tmp;
+
+ value = LLDB_INVALID_ADDRESS;
+
+ if (ReadGPRValue (row_register_kind, cfa_regnum, value))
+ {
+ if (row->GetCFAType() == UnwindPlan::Row::CFAIsRegisterDereferenced)
+ {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(cfa_regnum);
+ RegisterValue reg_value;
+ tmp = value;
+ Error error = ReadRegisterValueFromMemory(reg_info,
+ value,
+ reg_info->byte_size,
+ reg_value);
+ value = reg_value.GetAsUInt64();
+ UnwindLogMsg("dereferenced address: 0x%16.16" PRIx64 " yields: %lx", tmp, value);
+ return error.Success();
+ }
+ value = value + row->GetCFAOffset ();
+ return true;
+ }
+ return false;
+}
+
// Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that
// this frame called. e.g.
//
Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h?rev=221788&r1=221787&r2=221788&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.h Wed Nov 12 09:14:03 2014
@@ -333,6 +333,10 @@ private:
bool
ReadGPRValue (lldb::RegisterKind register_kind, uint32_t regnum, lldb::addr_t &value);
+ // Get the CFA register for a given frame.
+ bool
+ ReadCFAValueForRow (lldb::RegisterKind register_kind, const UnwindPlan::RowSP &row, lldb::addr_t &value);
+
lldb::UnwindPlanSP
GetFastUnwindPlanForFrame ();
Modified: lldb/trunk/source/Symbol/UnwindPlan.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/UnwindPlan.cpp?rev=221788&r1=221787&r2=221788&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/UnwindPlan.cpp (original)
+++ lldb/trunk/source/Symbol/UnwindPlan.cpp Wed Nov 12 09:14:03 2014
@@ -153,6 +153,7 @@ UnwindPlan::Row::RegisterLocation::Dump
void
UnwindPlan::Row::Clear ()
{
+ m_cfa_type = CFAIsRegisterPlusOffset;
m_offset = 0;
m_cfa_reg_num = LLDB_INVALID_REGNUM;
m_cfa_offset = 0;
@@ -189,10 +190,11 @@ UnwindPlan::Row::Dump (Stream& s, const
}
UnwindPlan::Row::Row() :
- m_offset(0),
- m_cfa_reg_num(LLDB_INVALID_REGNUM),
- m_cfa_offset(0),
- m_register_locations()
+ m_offset (0),
+ m_cfa_type (CFAIsRegisterPlusOffset),
+ m_cfa_reg_num (LLDB_INVALID_REGNUM),
+ m_cfa_offset (0),
+ m_register_locations ()
{
}
@@ -301,6 +303,23 @@ UnwindPlan::Row::operator == (const Unwi
{
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;
}
More information about the lldb-commits
mailing list