From f366af309abd27cd8a2f828d236586c9f752f445 Mon Sep 17 00:00:00 2001 From: Tamas Berghammer Date: Tue, 30 Jun 2015 09:35:46 +0000 Subject: [PATCH] Ignore "push/pop {sp}" in emulation based unwinding These instructions confusing the unwind code because in case of a push it assumes that the original valu of a register is pushed to the stack what is not neccessarily true in case of SP. The same is true for the pop (in the opposite way). Differential revision: http://reviews.llvm.org/D10806 llvm-svn: 241051 --- .../InstEmulation/UnwindAssemblyInstEmulation.cpp | 11 ++++++++--- .../unwind/standard/TestStandardUnwind.py | 2 -- .../unwind/standard/hand_written/divmod.cpp | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 lldb/test/functionalities/unwind/standard/hand_written/divmod.cpp diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 0ce3682fb248..8f5d92697501 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -422,13 +422,17 @@ UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction, case EmulateInstruction::eContextPushRegisterOnStack: { uint32_t reg_num = LLDB_INVALID_REGNUM; - const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind(); + uint32_t generic_regnum = LLDB_INVALID_REGNUM; if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset) + { + const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind(); reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind]; + generic_regnum = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric]; + } else assert (!"unhandled case, add code to handle this!"); - if (reg_num != LLDB_INVALID_REGNUM) + if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) { if (m_pushed_regs.find (reg_num) == m_pushed_regs.end()) { @@ -570,7 +574,8 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, case EmulateInstruction::eContextPopRegisterOffStack: { const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; - if (reg_num != LLDB_INVALID_REGNUM) + const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric]; + if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) { m_curr_row->SetRegisterLocationToSame (reg_num, /*must_replace*/ false); m_curr_row_modified = true; diff --git a/lldb/test/functionalities/unwind/standard/TestStandardUnwind.py b/lldb/test/functionalities/unwind/standard/TestStandardUnwind.py index ad40cf5ebfd3..52296702feb8 100644 --- a/lldb/test/functionalities/unwind/standard/TestStandardUnwind.py +++ b/lldb/test/functionalities/unwind/standard/TestStandardUnwind.py @@ -40,8 +40,6 @@ class StandardUnwindTest(TestBase): "__memcpy_base", # Function reached by a fall through from the previous function "__memcpy_base_aligned", # Function reached by a fall through from the previous function "__subdf3", # __aeabi_ui2d jumps into the middle of the function. Possibly missing symbol? - "__aeabi_ldivmod", # llvm.org/pr23879 ("push {sp}" not handled correctly) - "__aeabi_uldivmod", # llvm.org/pr23879 ("push {sp}" not handled correctly) ] no_step_function_names = [ "__sync_fetch_and_add_4", # Calls into a special SO where we can't set a breakpoint diff --git a/lldb/test/functionalities/unwind/standard/hand_written/divmod.cpp b/lldb/test/functionalities/unwind/standard/hand_written/divmod.cpp new file mode 100644 index 000000000000..75df6ba89372 --- /dev/null +++ b/lldb/test/functionalities/unwind/standard/hand_written/divmod.cpp @@ -0,0 +1,15 @@ +//===-- divmod.cpp ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +int +main(int argc, char const *argv[]) +{ + signed long long a = 123456789, b = 12, c = a / b, d = a % b; + unsigned long long e = 123456789, f = 12, g = e / f, h = e % f; +}