summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Molenda <jmolenda@apple.com>2015-01-13 06:07:07 +0000
committerJason Molenda <jmolenda@apple.com>2015-01-13 06:07:07 +0000
commitfcb91c19dc22f7637e0b2bc2d2008743eb384062 (patch)
treee4326c51543e1e5bbbfa4b03de1296e02989f93b
parent81b38e4468013332ea955b09612d6e0a9da44d1b (diff)
Add an additional check to UnwindAssembly_x86::AugmentUnwindPlanFromCallSite
which will verify if the eh_frame instructions include details about the prologue or not. Both clang and gcc include prologue instructions but there's no requirement for them to do so -- and I'm sure we'll have to interoperate with a compiler that doesn't generate prologue info at some point. I don't have any compilers that omit the prologue instructions so the testing was of the "makre sure augmented unwind info is still created". With an eh_frame without prologue, this code should reject the augmentation scheme altogether and we should fall back to using assembly instruction profiling. git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@225771 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/lldb/Utility/RegisterNumber.h3
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp53
-rw-r--r--source/Utility/RegisterNumber.cpp6
3 files changed, 45 insertions, 17 deletions
diff --git a/include/lldb/Utility/RegisterNumber.h b/include/lldb/Utility/RegisterNumber.h
index 46bed7cab..89d52fd4a 100644
--- a/include/lldb/Utility/RegisterNumber.h
+++ b/include/lldb/Utility/RegisterNumber.h
@@ -39,6 +39,9 @@ public:
operator == (RegisterNumber &rhs);
bool
+ operator != (RegisterNumber &rhs);
+
+ bool
IsValid () const;
uint32_t
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index 0cbc338b7..f86c56b44 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -1229,16 +1229,42 @@ UnwindAssembly_x86::AugmentUnwindPlanFromCallSite (AddressRange& func, Thread& t
UnwindPlan::RowSP first_row = unwind_plan.GetRowForFunctionOffset (0);
UnwindPlan::RowSP last_row = unwind_plan.GetRowForFunctionOffset (-1);
- // If the UnwindPlan correctly describes the prologue and the epilogue, then
- // we shouldn't do any augmentation (and risk messing up correct unwind instructions)
+ int wordsize = 8;
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ wordsize = process_sp->GetTarget().GetArchitecture().GetAddressByteSize();
+ }
- // See if the first row (which should be the register state on function entry)
- // and the last row (which should be the register state on function exit) match.
+ RegisterNumber sp_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ RegisterNumber pc_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- if (first_row != last_row && first_row->GetOffset() != last_row->GetOffset())
+ // Does this UnwindPlan describe the prologue? I want to see that the CFA is set
+ // in terms of the stack pointer plus an offset, and I want to see that rip is
+ // retrieved at the CFA-wordsize.
+ // 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)
+ {
+ return false;
+ }
+ UnwindPlan::Row::RegisterLocation first_row_pc_loc;
+ if (first_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), first_row_pc_loc) == false
+ || first_row_pc_loc.IsAtCFAPlusOffset() == false
+ || first_row_pc_loc.GetOffset() != -wordsize)
{
- RegisterNumber sp_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ return false;
+ }
+
+
+ // It looks like the prologue is described. Now check to see if the epilogue has the same
+ // unwind state.
+ if (first_row != last_row && first_row->GetOffset() != last_row->GetOffset())
+ {
// The first & last row have the same CFA register
// and the same CFA offset value
// and the CFA register is esp/rsp (the stack pointer).
@@ -1246,23 +1272,16 @@ 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->GetCFAType() == UnwindPlan::Row::CFAType::CFAIsRegisterPlusOffset
&& first_row->GetCFARegister() == last_row->GetCFARegister()
- && first_row->GetCFAOffset() == last_row->GetCFAOffset()
- && RegisterNumber (thread, unwind_plan.GetRegisterKind(), first_row->GetCFARegister()) == sp_regnum)
+ && first_row->GetCFAOffset() == last_row->GetCFAOffset())
{
- RegisterNumber pc_regnum (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
-
// Get the register locations for eip/rip from the first & last rows.
// Are they both CFA plus an offset? Is it the same offset?
- UnwindPlan::Row::RegisterLocation first_row_pc_loc;
UnwindPlan::Row::RegisterLocation last_row_pc_loc;
- if (first_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), first_row_pc_loc)
- && last_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), last_row_pc_loc))
+ if (last_row->GetRegisterInfo (pc_regnum.GetAsKind (unwind_plan.GetRegisterKind()), last_row_pc_loc))
{
- if (first_row_pc_loc.IsAtCFAPlusOffset()
- && last_row_pc_loc.IsAtCFAPlusOffset()
+ if (last_row_pc_loc.IsAtCFAPlusOffset()
&& first_row_pc_loc.GetOffset() == last_row_pc_loc.GetOffset())
{
@@ -1272,7 +1291,7 @@ UnwindAssembly_x86::AugmentUnwindPlanFromCallSite (AddressRange& func, Thread& t
// If so, we have an UnwindPlan that already describes the epilogue and we don't need
// to modify it at all.
- if (first_row_pc_loc.GetOffset() == -4 || first_row_pc_loc.GetOffset() == -8)
+ if (first_row_pc_loc.GetOffset() == -wordsize)
{
do_augment_unwindplan = false;
}
diff --git a/source/Utility/RegisterNumber.cpp b/source/Utility/RegisterNumber.cpp
index ba9afed47..8116cda10 100644
--- a/source/Utility/RegisterNumber.cpp
+++ b/source/Utility/RegisterNumber.cpp
@@ -101,6 +101,12 @@ RegisterNumber::operator == (RegisterNumber &rhs)
}
bool
+RegisterNumber::operator != (RegisterNumber &rhs)
+{
+ return !(*this == rhs);
+}
+
+bool
RegisterNumber::IsValid () const
{
return m_reg_ctx_sp.get()