From: Greg Clayton Date: Sun, 8 Jan 2012 05:54:35 +0000 (+0000) Subject: X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4abd6eaaa0a368cf28ad6de321ae1c149fd0b7a2;p=platform%2Fupstream%2Fllvm.git Fixed an ARM backtracing issue where if the previous frame was a thumb function and it was a tail call so that the current frame returned to an address that would fall into the next function, we would use the next function as the basis for how we unwound the previous frame's registers and of course get things wrong. We now fix the PC code address using the current ABI plug-in, and the ARM ABI plug-in has been modified to correctly fix the code address. So when we do the symbol context lookup, instead of taking an address like 0x1001 and decrementing 1, and looking up the symbol context for a frame, we now correctly fix 0x1001 to 0x1000, then decrement that by 1 to get the correct symbol context. I added a bunch more logging to "log enable lldb uwnind" to help us in the future. We now log the PC, FP and SP (if they are available), and we also dump the "active_row" that we find for unwinding a frame. llvm-svn: 147747 --- diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h index 722e38d..4709d79 100644 --- a/lldb/include/lldb/Target/ABI.h +++ b/lldb/include/lldb/Target/ABI.h @@ -76,6 +76,15 @@ public: virtual bool CodeAddressIsValid (lldb::addr_t pc) = 0; + virtual bool + FixCodeAddress (lldb::addr_t pc) + { + // Some targets might use bits in a code address to indicate + // a mode switch. ARM uses bit zero to signify a code address is + // thumb, so any ARM ABI plug-ins would strip those bits. + return pc; + } + virtual const RegisterInfo * GetRegisterInfoArray (uint32_t &count) = 0; diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h index 70809e0..5516b59 100644 --- a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h +++ b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h @@ -82,6 +82,14 @@ public: return pc <= UINT32_MAX; } + virtual bool + FixCodeAddress (lldb::addr_t pc) + { + // ARM uses bit zero to signify a code address is thumb, so we must + // strip bit zero in any code addresses. + return pc & ~(lldb::addr_t)1; + } + virtual const lldb_private::RegisterInfo * GetRegisterInfoArray (uint32_t &count); diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 4f927fe..0faa8cc 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -87,6 +87,8 @@ RegisterContextLLDB::InitializeZerothFrame() { StackFrameSP frame_sp (m_thread.GetStackFrameAtIndex (0)); + LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (m_thread.GetRegisterContext() == NULL) { m_frame_type = eNotAValidFrame; @@ -149,6 +151,13 @@ RegisterContextLLDB::InitializeZerothFrame() { active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); row_register_kind = m_full_unwind_plan_sp->GetRegisterKind (); + if (active_row && log) + { + StreamString active_row_strm; + active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(&m_thread.GetProcess().GetTarget())); + log->Printf("%*sFrame %u active row: %s", + m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str()); + } } if (active_row == NULL) @@ -157,6 +166,7 @@ RegisterContextLLDB::InitializeZerothFrame() return; } + addr_t cfa_regval; if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval)) { @@ -170,7 +180,13 @@ RegisterContextLLDB::InitializeZerothFrame() m_cfa = cfa_regval + cfa_offset; - LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (log) + { + log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)", + m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, + m_cfa, cfa_regval, cfa_offset); + } + // A couple of sanity checks.. if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1) @@ -232,6 +248,20 @@ RegisterContextLLDB::InitializeNonZerothFrame() m_frame_type = eNotAValidFrame; return; } + + if (log) + { + log->Printf("%*sFrame %u pc = 0x%16.16llx", + m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, pc); + addr_t reg_val; + if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val)) + log->Printf("%*sFrame %u fp = 0x%16.16llx", + m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val); + + if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val)) + log->Printf("%*sFrame %u sp = 0x%16.16llx", + m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, reg_val); + } // A pc of 0x0 means it's the end of the stack crawl if (pc == 0) @@ -239,6 +269,12 @@ RegisterContextLLDB::InitializeNonZerothFrame() m_frame_type = eNotAValidFrame; return; } + + // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs + // this will strip bit zero in case we read a PC from memory or from the LR. + ABI *abi = m_thread.GetProcess().GetABI().get(); + if (abi) + pc = abi->FixCodeAddress(pc); // Test the pc value to see if we know it's in an unmapped/non-executable region of memory. uint32_t permissions; @@ -277,7 +313,6 @@ RegisterContextLLDB::InitializeNonZerothFrame() log->Printf("%*sFrame %u using architectural default unwind method", m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); } - ABI *abi = m_thread.GetProcess().GetABI().get(); if (abi) { m_fast_unwind_plan_sp.reset (); @@ -452,6 +487,13 @@ RegisterContextLLDB::InitializeNonZerothFrame() { active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind (); + if (active_row && log) + { + StreamString active_row_strm; + active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(&m_thread.GetProcess().GetTarget())); + log->Printf("%*sFrame %u active row: %s", + m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str()); + } } else { @@ -460,6 +502,13 @@ RegisterContextLLDB::InitializeNonZerothFrame() { active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); row_register_kind = m_full_unwind_plan_sp->GetRegisterKind (); + if (active_row && log) + { + StreamString active_row_strm; + active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(&m_thread.GetProcess().GetTarget())); + log->Printf("%*sFrame %u active row: %s", + m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str()); + } } } @@ -485,6 +534,13 @@ RegisterContextLLDB::InitializeNonZerothFrame() m_cfa = cfa_regval + cfa_offset; + if (log) + { + log->Printf("%*sFrame %u cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)", + m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, + m_cfa, cfa_regval, cfa_offset); + } + // A couple of sanity checks.. if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1) {