summaryrefslogtreecommitdiffstats
path: root/lldb/source/Symbol/UnwindPlan.cpp
diff options
context:
space:
mode:
authorPavel Labath <labath@google.com>2015-02-23 10:19:16 +0000
committerPavel Labath <labath@google.com>2015-02-23 10:19:16 +0000
commitab970f5e08a976d4ea1ae64e4b3b9ff15a88aeb9 (patch)
tree7e4399b8d089d63afa6bb2eaf4f86755c45975da /lldb/source/Symbol/UnwindPlan.cpp
parent69963e72f349efc75db5ce4310e8be9f630b750c (diff)
downloadbcm5719-llvm-ab970f5e08a976d4ea1ae64e4b3b9ff15a88aeb9.tar.gz
bcm5719-llvm-ab970f5e08a976d4ea1ae64e4b3b9ff15a88aeb9.zip
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
Diffstat (limited to 'lldb/source/Symbol/UnwindPlan.cpp')
-rw-r--r--lldb/source/Symbol/UnwindPlan.cpp138
1 files changed, 68 insertions, 70 deletions
diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp
index 87d0f49421c..d4b06d5c925 100644
--- a/lldb/source/Symbol/UnwindPlan.cpp
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -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)
OpenPOWER on IntegriCloud