diff options
author | Jason Molenda <jmolenda@apple.com> | 2015-01-13 06:07:07 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 2015-01-13 06:07:07 +0000 |
commit | fcb91c19dc22f7637e0b2bc2d2008743eb384062 (patch) | |
tree | e4326c51543e1e5bbbfa4b03de1296e02989f93b | |
parent | 81b38e4468013332ea955b09612d6e0a9da44d1b (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.h | 3 | ||||
-rw-r--r-- | source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp | 53 | ||||
-rw-r--r-- | source/Utility/RegisterNumber.cpp | 6 |
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() |