From d9474064271271af78c2a1eecec6fe6ccc028918 Mon Sep 17 00:00:00 2001 From: Todd Fiala Date: Fri, 25 Jul 2014 01:15:34 +0000 Subject: [PATCH] Fix an x86 assembler stack unwind calculation for non-volatile registers. This change has the practical effect of fixing some backtrace scenarios that would fail with inferiors running on the Android Art host-side JVM under Linux x86_64 on Ubuntu 14.04. See this lldb-commits thread for more details: http://lists.cs.uiuc.edu/pipermail/lldb-commits/Week-of-Mon-20140721/011988.html Change by Tong Shen. Reviewed by Jason Molenda. Tested: Ubuntu 14.04 x86_64, clang-3.5-built lldb. MacOSX 10.10 Preview 4, Xcode 6 Beta 4-built lldb. llvm-svn: 213914 --- .../Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index ff7f758..caed968 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -373,6 +373,12 @@ bool AssemblyParse_x86::push_reg_p (int& regno) { // movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0] // movl %eax, -0xc(%ebp) [0x89 0x45 0xf4] + +// The offset value returned in rbp_offset will be positive -- +// but it must be subtraced from the frame base register to get +// the actual location. The positive value returned for the offset +// is a convention used elsewhere for CFA offsets et al. + bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset) { uint8_t *p = m_cur_insn_bytes; int src_reg_prefix_bit = 0; @@ -633,7 +639,13 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan) { row->SetOffset (current_func_text_offset + insn_len); UnwindPlan::Row::RegisterLocation regloc; - regloc.SetAtCFAPlusOffset (-row->GetCFAOffset()); + + // stack_offset for 'movq %r15, -80(%rbp)' will be 80. + // In the Row, we want to express this as the offset from the CFA. If the frame base + // is rbp (like the above instruction), the CFA offset for rbp is probably 16. So we + // want to say that the value is stored at the CFA address - 96. + regloc.SetAtCFAPlusOffset (-(stack_offset + row->GetCFAOffset())); + row->SetRegisterInfo (lldb_regno, regloc); unwind_plan.AppendRow (row); // Allocate a new Row, populate it with the existing Row contents. -- 2.7.4