diff --git a/lldb/include/lldb/Symbol/FuncUnwinders.h b/lldb/include/lldb/Symbol/FuncUnwinders.h index 10e4d56995b4..6c4acb1be825 100644 --- a/lldb/include/lldb/Symbol/FuncUnwinders.h +++ b/lldb/include/lldb/Symbol/FuncUnwinders.h @@ -70,6 +70,13 @@ public: return m_range.ContainsFileAddress (addr); } + // When we're doing an unwind using the UnwindPlanAtNonCallSite and we find an + // impossible unwind condition, we know that the UnwindPlan is invalid. Calling + // this method on the FuncUnwinder will tell it to replace that UnwindPlan with + // the architectural default UnwindPlan so hopefully our stack walk will get past + // this frame. + void + InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& Thread); private: UnwindTable& m_unwind_table; diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h index f5d72665f824..7f277010c8aa 100644 --- a/lldb/include/lldb/Symbol/UnwindPlan.h +++ b/lldb/include/lldb/Symbol/UnwindPlan.h @@ -349,7 +349,9 @@ public: m_plan_valid_address_range (), m_register_kind (reg_kind), m_return_addr_register (LLDB_INVALID_REGNUM), - m_source_name () + m_source_name (), + m_plan_is_sourced_from_compiler (eLazyBoolCalculate), + m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate) { } @@ -432,6 +434,36 @@ public: void SetSourceName (const char *); + // Was this UnwindPlan emitted by a compiler? + lldb_private::LazyBool + GetSourcedFromCompiler () const + { + return m_plan_is_sourced_from_compiler; + } + + // Was this UnwindPlan emitted by a compiler? + void + SetSourcedFromCompiler (lldb_private::LazyBool from_compiler) + { + m_plan_is_sourced_from_compiler = from_compiler; + } + + // Is this UnwindPlan valid at all instructions? If not, then it is assumed valid at call sites, + // e.g. for exception handling. + lldb_private::LazyBool + GetUnwindPlanValidAtAllInstructions () const + { + return m_plan_is_valid_at_all_instruction_locations; + } + + // Is this UnwindPlan valid at all instructions? If not, then it is assumed valid at call sites, + // e.g. for exception handling. + void + SetUnwindPlanValidAtAllInstructions (lldb_private::LazyBool valid_at_all_insn) + { + m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn; + } + int GetRowCount () const; @@ -458,6 +490,8 @@ private: uint32_t m_return_addr_register; // The register that has the return address for the caller frame // e.g. the lr on arm lldb_private::ConstString m_source_name; // for logging, where this UnwindPlan originated from + lldb_private::LazyBool m_plan_is_sourced_from_compiler; + lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations; }; // class UnwindPlan } // namespace lldb_private diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index 391ee0fe00a5..08532f20873f 100644 --- a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -628,6 +628,8 @@ ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) // All other registers are the same. unwind_plan.SetSourceName ("arm at-func-entry default"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + return true; } @@ -651,9 +653,30 @@ ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("arm-apple-ios default unwind plan"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); + return true; } +// ARMv7 on iOS general purpose reg rules: +// r0-r3 not preserved (used for argument passing) +// r4-r6 preserved +// r7 preserved (frame pointer) +// r8 preserved +// r9 not preserved (usable as volatile scratch register with iOS 3.x and later) +// r10-r11 preserved +// r12 not presrved +// r13 preserved (stack pointer) +// r14 not preserved (link register) +// r15 preserved (pc) +// cpsr not preserved (different rules for different bits) + +// ARMv7 on iOS floating point rules: +// d0-d7 not preserved (aka s0-s15, q0-q3) +// d8-d15 preserved (aka s16-s31, q4-q7) +// d16-d31 not preserved (aka q8-q15) + bool ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info) { @@ -691,28 +714,28 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info) switch (name[1]) { case '0': - return name[2] == '\0'; // d0 + return name[2] == '\0'; // d0 is volatile case '1': switch (name[2]) { case '\0': - return true; // d1; + return true; // d1 is volatile case '6': case '7': case '8': case '9': - return name[3] == '\0'; // d16 - d19 + return name[3] == '\0'; // d16 - d19 are volatile default: break; } break; - + case '2': switch (name[2]) { case '\0': - return true; // d2; + return true; // d2 is volatile case '0': case '1': case '2': @@ -723,7 +746,7 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info) case '7': case '8': case '9': - return name[3] == '\0'; // d20 - d29 + return name[3] == '\0'; // d20 - d29 are volatile default: break; } @@ -733,10 +756,10 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info) switch (name[2]) { case '\0': - return true; // d3; + return true; // d3 is volatile case '0': case '1': - return name[3] == '\0'; // d30 - d31 + return name[3] == '\0'; // d30 - d31 are volatile default: break; } @@ -744,7 +767,61 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info) case '5': case '6': case '7': - return name[2] == '\0'; // d4 - d7 + return name[2] == '\0'; // d4 - d7 are volatile + + default: + break; + } + } + else if (name[0] == 's') + { + switch (name[1]) + { + case '0': + return name[2] == '\0'; // s0 is volatile + + case '1': + switch (name[2]) + { + case '\0': + return true; // s1 is volatile + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + return name[3] == '\0'; // s10 - s15 are volatile + default: + break; + } + break; + + case '2': + switch (name[2]) + { + case '\0': + return true; // s2 is volatile + default: + break; + } + break; + + case '3': + switch (name[2]) + { + case '\0': + return true; // s3 is volatile + default: + break; + } + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return name[2] == '\0'; // s4 - s9 are volatile default: break; diff --git a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 862ea398890f..111866732339 100644 --- a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -894,6 +894,7 @@ ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("i386 at-func-entry default"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); return true; } @@ -919,6 +920,8 @@ ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("i386 default unwind plan"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); return true; } diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 9b4c056d3967..0f82341e6d35 100644 --- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -1088,6 +1088,7 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("x86_64 at-func-entry default"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); return true; } @@ -1139,6 +1140,8 @@ ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("x86_64 default unwind plan"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); return true; } diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 4791df643980..ca2a6407e436 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -13613,9 +13613,7 @@ EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) // All other registers are the same. unwind_plan.SetSourceName ("EmulateInstructionARM"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); return true; } - - - - diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index e922add20ce4..d0d192830789 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -35,24 +35,24 @@ using namespace lldb; using namespace lldb_private; -RegisterContextLLDB::RegisterContextLLDB +RegisterContextLLDB::RegisterContextLLDB ( - Thread& thread, + Thread& thread, const SharedPtr &next_frame, SymbolContext& sym_ctx, uint32_t frame_number, UnwindLLDB& unwind_lldb ) : - RegisterContext (thread, frame_number), - m_thread(thread), + RegisterContext (thread, frame_number), + m_thread(thread), m_fast_unwind_plan_sp (), m_full_unwind_plan_sp (), m_all_registers_available(false), m_frame_type (-1), m_cfa (LLDB_INVALID_ADDRESS), - m_start_pc (), - m_current_pc (), - m_current_offset (0), + m_start_pc (), + m_current_pc (), + m_current_offset (0), m_current_offset_backed_up_one (0), m_sym_ctx(sym_ctx), m_sym_ctx_valid (false), @@ -73,8 +73,8 @@ RegisterContextLLDB::RegisterContextLLDB } // This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet - if (IsFrameZero() - || next_frame->m_frame_type == eSigtrampFrame + if (IsFrameZero() + || next_frame->m_frame_type == eSigtrampFrame || next_frame->m_frame_type == eDebuggerFrame) { m_all_registers_available = true; @@ -90,8 +90,6 @@ RegisterContextLLDB::InitializeZerothFrame() ExecutionContext exe_ctx(m_thread.shared_from_this()); RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext(); - LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (reg_ctx_sp.get() == NULL) { m_frame_type = eNotAValidFrame; @@ -124,11 +122,7 @@ RegisterContextLLDB::InitializeZerothFrame() ModuleSP pc_module_sp (m_current_pc.GetModule()); if (!m_current_pc.IsValid() || !pc_module_sp) { - if (log) - { - log->Printf("%*sFrame %u using architectural default unwind method", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); - } + UnwindLogMsg ("using architectural default unwind method"); } // We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us. @@ -140,7 +134,7 @@ RegisterContextLLDB::InitializeZerothFrame() AddressRange addr_range; m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range); - + static ConstString g_sigtramp_name ("_sigtramp"); if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == g_sigtramp_name) || (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == g_sigtramp_name)) @@ -182,8 +176,8 @@ RegisterContextLLDB::InitializeZerothFrame() // We've set m_frame_type and m_sym_ctx before these calls. m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame (); - m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); - + m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); + UnwindPlan::RowSP active_row; int cfa_offset = 0; int row_register_kind = -1; @@ -195,8 +189,7 @@ RegisterContextLLDB::InitializeZerothFrame() { StreamString active_row_strm; active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); - log->Printf("%*sFrame %u active row: %s", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str()); + UnwindLogMsg ("%s", active_row_strm.GetString().c_str()); } } @@ -206,7 +199,7 @@ RegisterContextLLDB::InitializeZerothFrame() return; } - + addr_t cfa_regval; if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval)) { @@ -220,23 +213,11 @@ RegisterContextLLDB::InitializeZerothFrame() 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); - } - - if (log) - { - log->Printf("%*sThread %d Frame %u initialized frame current pc is 0x%llx cfa is 0x%llx using %s UnwindPlan", - m_frame_number < 100 ? m_frame_number : 100, "", - m_thread.GetIndexID(), - m_frame_number, - (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), - (uint64_t) m_cfa, - m_full_unwind_plan_sp->GetSourceName().GetCString()); - } + UnwindLogMsg ("cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset); + UnwindLogMsg ("initialized frame current pc is 0x%llx cfa is 0x%llx using %s UnwindPlan", + (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), + (uint64_t) m_cfa, + m_full_unwind_plan_sp->GetSourceName().GetCString()); } // Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the RegisterContextLLDB "below" it @@ -246,13 +227,12 @@ void RegisterContextLLDB::InitializeNonZerothFrame() { LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (IsFrameZero ()) { m_frame_type = eNotAValidFrame; return; } - + if (!GetNextFrame().get() || !GetNextFrame()->IsValid()) { m_frame_type = eNotAValidFrame; @@ -267,27 +247,19 @@ RegisterContextLLDB::InitializeNonZerothFrame() addr_t pc; if (!ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc)) { - if (log) - { - log->Printf("%*sFrame %u could not get pc value", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); - } + UnwindLogMsg ("could not get pc value"); 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); + UnwindLogMsg ("pc = 0x%16.16llx", 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); - + UnwindLogMsg ("fp = 0x%16.16llx", 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); + UnwindLogMsg ("sp = 0x%16.16llx", reg_val); } // A pc of 0x0 means it's the end of the stack crawl @@ -296,11 +268,11 @@ RegisterContextLLDB::InitializeNonZerothFrame() m_frame_type = eNotAValidFrame; return; } - + ExecutionContext exe_ctx(m_thread.shared_from_this()); Process *process = exe_ctx.GetProcessPtr(); // 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. + // this will strip bit zero in case we read a PC from memory or from the LR. ABI *abi = process->GetABI().get(); if (abi) pc = abi->FixCodeAddress(pc); @@ -312,12 +284,8 @@ RegisterContextLLDB::InitializeNonZerothFrame() ModuleSP pc_module_sp (m_current_pc.GetModule()); if (!m_current_pc.IsValid() || !pc_module_sp) { - if (log) - { - log->Printf("%*sFrame %u using architectural default unwind method", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); - } - + UnwindLogMsg ("using architectural default unwind method"); + // Test the pc value to see if we know it's in an unmapped/non-executable region of memory. uint32_t permissions; if (process->GetLoadAddressPermissions(pc, permissions) @@ -329,11 +297,8 @@ RegisterContextLLDB::InitializeNonZerothFrame() // pc and see if we can get any further. if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsFrameZero()) { - if (log) - { - log->Printf("%*sFrame %u had a pc of 0x%llx which is not in executable memory but on frame 1 -- allowing it once.", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, (uint64_t) pc); - } + UnwindLogMsg ("had a pc of 0x%llx which is not in executable memory but on frame 1 -- allowing it once.", + (uint64_t) pc); m_frame_type = eSkipFrame; } else @@ -365,11 +330,7 @@ RegisterContextLLDB::InitializeNonZerothFrame() int cfa_offset = row->GetCFAOffset(); if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval)) { - if (log) - { - log->Printf("%*sFrame %u failed to get cfa value", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); - } + UnwindLogMsg ("failed to get cfa value"); if (m_frame_type != eSkipFrame) // don't override eSkipFrame { m_frame_type = eNormalFrame; @@ -381,11 +342,7 @@ RegisterContextLLDB::InitializeNonZerothFrame() // A couple of sanity checks.. if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1) { - if (log) - { - log->Printf("%*sFrame %u could not find a valid cfa address", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); - } + UnwindLogMsg ("could not find a valid cfa address"); m_frame_type = eNotAValidFrame; return; } @@ -401,21 +358,12 @@ RegisterContextLLDB::InitializeNonZerothFrame() } else { - if (log) - { - log->Printf("%*sFrame %u could not find a row for function offset zero", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); - } + UnwindLogMsg ("could not find a row for function offset zero"); m_frame_type = eNotAValidFrame; return; } - if (log) - { - log->Printf("%*sFrame %u initialized frame cfa is 0x%llx", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - (uint64_t) m_cfa); - } + UnwindLogMsg ("initialized frame cfa is 0x%llx", (uint64_t) m_cfa); return; } m_frame_type = eNotAValidFrame; @@ -456,7 +404,7 @@ RegisterContextLLDB::InitializeNonZerothFrame() // value is pointing to the next function, e.g. if a function ends with a CALL instruction. // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function // to the ABI plugin and consult that. - if (decr_pc_and_recompute_addr_range) + if (decr_pc_and_recompute_addr_range) { Address temporary_pc(m_current_pc); temporary_pc.SetOffset(m_current_pc.GetOffset() - 1); @@ -522,11 +470,10 @@ RegisterContextLLDB::InitializeNonZerothFrame() { StreamString active_row_strm; active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); - log->Printf("%*sFrame %u active row: %s", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str()); + UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str()); } } - else + else { m_full_unwind_plan_sp = GetFullUnwindPlanForFrame (); if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc)) @@ -537,8 +484,7 @@ RegisterContextLLDB::InitializeNonZerothFrame() { StreamString active_row_strm; active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); - log->Printf("%*sFrame %u active row: %s", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, active_row_strm.GetString().c_str()); + UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str()); } } } @@ -552,12 +498,7 @@ RegisterContextLLDB::InitializeNonZerothFrame() addr_t cfa_regval; if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval)) { - if (log) - { - log->Printf("%*sFrame %u failed to get cfa reg %d/%d", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - row_register_kind, active_row->GetCFARegister()); - } + UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister()); m_frame_type = eNotAValidFrame; return; } @@ -565,21 +506,12 @@ 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); - } + UnwindLogMsg ("cfa_regval = 0x%16.16llx (cfa_regval = 0x%16.16llx, cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset); // A couple of sanity checks.. if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1) - { - if (log) - { - log->Printf("%*sFrame %u could not find a valid cfa address", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); - } + { + UnwindLogMsg ("could not find a valid cfa address"); m_frame_type = eNotAValidFrame; return; } @@ -606,22 +538,14 @@ RegisterContextLLDB::InitializeNonZerothFrame() } if (repeating_frames && abi->FunctionCallsChangeCFA()) { - if (log) - { - log->Printf("%*sFrame %u same CFA address as next frame, assuming the unwind is looping - stopping", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); - } + UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping"); m_frame_type = eNotAValidFrame; return; } } - if (log) - { - log->Printf("%*sFrame %u initialized frame current pc is 0x%llx cfa is 0x%llx", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa); - } + UnwindLogMsg ("initialized frame current pc is 0x%llx cfa is 0x%llx", + (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa); } @@ -634,9 +558,9 @@ RegisterContextLLDB::IsFrameZero () const // Find a fast unwind plan for this frame, if possible. // -// On entry to this method, +// On entry to this method, // -// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct, +// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct, // 2. m_sym_ctx should already be filled in, and // 3. m_current_pc should have the current pc value for this frame // 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown @@ -657,7 +581,7 @@ RegisterContextLLDB::GetFastUnwindPlanForFrame () if (!func_unwinders_sp) return unwind_plan_sp; - // If we're in _sigtramp(), unwinding past this frame requires special knowledge. + // If we're in _sigtramp(), unwinding past this frame requires special knowledge. if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame) return unwind_plan_sp; @@ -669,16 +593,15 @@ RegisterContextLLDB::GetFastUnwindPlanForFrame () LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (log && log->GetVerbose()) { - const char *has_fast = ""; if (m_fast_unwind_plan_sp) - has_fast = ", and has a fast UnwindPlan"; - log->Printf("%*sFrame %u frame%s", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, has_fast); + UnwindLogMsgVerbose ("frame, and has a fast UnwindPlan"); + else + UnwindLogMsgVerbose ("frame"); } m_frame_type = eNormalFrame; return unwind_plan_sp; } - else + else { unwind_plan_sp.reset(); } @@ -686,9 +609,9 @@ RegisterContextLLDB::GetFastUnwindPlanForFrame () return unwind_plan_sp; } -// On entry to this method, +// On entry to this method, // -// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct, +// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct, // 2. m_sym_ctx should already be filled in, and // 3. m_current_pc should have the current pc value for this frame // 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown @@ -697,7 +620,6 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame () { UnwindPlanSP unwind_plan_sp; - LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); UnwindPlanSP arch_default_unwind_plan_sp; ExecutionContext exe_ctx(m_thread.shared_from_this()); Process *process = exe_ctx.GetProcessPtr(); @@ -709,12 +631,12 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () } bool behaves_like_zeroth_frame = false; - if (IsFrameZero () + if (IsFrameZero () || GetNextFrame()->m_frame_type == eSigtrampFrame || GetNextFrame()->m_frame_type == eDebuggerFrame) { behaves_like_zeroth_frame = true; - // If this frame behaves like a 0th frame (currently executing or + // If this frame behaves like a 0th frame (currently executing or // interrupted asynchronously), all registers can be retrieved. m_all_registers_available = true; } @@ -723,7 +645,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () // in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan // Also, if this Process can report on memory region attributes, any non-executable region means // we jumped through a bad function pointer - handle the same way as 0x0. - // Note, if the symbol context has a function for the symbol, then we don't need to do this check. + // Note, if the symbol context has a function for the symbol, then we don't need to do this check. if ((!m_sym_ctx_valid || m_sym_ctx.function == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid()) { @@ -784,12 +706,8 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { - if (log && log->GetVerbose()) - { - log->Printf("%*sFrame %u frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - unwind_plan_sp->GetSourceName().GetCString()); - } + UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it", + unwind_plan_sp->GetSourceName().GetCString()); return unwind_plan_sp; } } @@ -800,12 +718,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { - if (log && log->GetVerbose()) - { - log->Printf("%*sFrame %u frame uses %s for full UnwindPlan", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - unwind_plan_sp->GetSourceName().GetCString()); - } + UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); return unwind_plan_sp; } } @@ -814,36 +727,21 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame () unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { - if (log && log->GetVerbose()) - { - log->Printf("%*sFrame %u frame uses %s for full UnwindPlan", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - unwind_plan_sp->GetSourceName().GetCString()); - } + UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); return unwind_plan_sp; } - + // We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've // struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible. unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread); if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc)) { - if (log && log->GetVerbose()) - { - log->Printf("%*sFrame %u frame uses %s for full UnwindPlan", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - unwind_plan_sp->GetSourceName().GetCString()); - } + UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString()); return unwind_plan_sp; } // If nothing else, use the architectural default UnwindPlan and hope that does the job. - if (log && log->GetVerbose()) - { - log->Printf("%*sFrame %u frame uses %s for full UnwindPlan", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - arch_default_unwind_plan_sp->GetSourceName().GetCString()); - } + UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString()); return arch_default_unwind_plan_sp; } @@ -885,7 +783,7 @@ RegisterContextLLDB::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_ } bool -RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, +RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, const RegisterInfo *reg_info, RegisterValue &value) { @@ -898,11 +796,11 @@ RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::Unwind case UnwindLLDB::RegisterLocation::eRegisterInRegister: { const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); - + if (!other_reg_info) return false; - - if (IsFrameZero ()) + + if (IsFrameZero ()) { success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value); } @@ -915,7 +813,7 @@ RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::Unwind case UnwindLLDB::RegisterLocation::eRegisterValueInferred: success = value.SetUInt (regloc.location.inferred_value, reg_info->byte_size); break; - + case UnwindLLDB::RegisterLocation::eRegisterNotSaved: break; case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation: @@ -923,9 +821,9 @@ RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::Unwind break; case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { - Error error (ReadRegisterValueFromMemory(reg_info, - regloc.location.target_memory_location, - reg_info->byte_size, + Error error (ReadRegisterValueFromMemory(reg_info, + regloc.location.target_memory_location, + reg_info->byte_size, value)); success = error.Success(); } @@ -938,7 +836,7 @@ RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::Unwind } bool -RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, +RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, const RegisterInfo *reg_info, const RegisterValue &value) { @@ -946,13 +844,13 @@ RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindL return false; bool success = false; - + switch (regloc.type) { case UnwindLLDB::RegisterLocation::eRegisterInRegister: { const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number); - if (IsFrameZero ()) + if (IsFrameZero ()) { success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value); } @@ -970,9 +868,9 @@ RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindL break; case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation: { - Error error (WriteRegisterValueToMemory (reg_info, - regloc.location.target_memory_location, - reg_info->byte_size, + Error error (WriteRegisterValueToMemory (reg_info, + regloc.location.target_memory_location, + reg_info->byte_size, value)); success = error.Success(); } @@ -994,7 +892,7 @@ RegisterContextLLDB::IsValid () const // A skip frame is a bogus frame on the stack -- but one where we're likely to find a real frame farther // up the stack if we keep looking. It's always the second frame in an unwind (i.e. the first frame after // frame zero) where unwinding can be the trickiest. Ideally we'll mark up this frame in some way so the -// user knows we're displaying bad data and we may have skipped one frame of their real program in the +// user knows we're displaying bad data and we may have skipped one frame of their real program in the // process of getting back on track. bool @@ -1006,10 +904,8 @@ RegisterContextLLDB::IsSkipFrame () const // Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value? bool -RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, bool check_next_frame) +RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc) { - LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - // Have we already found this register location? if (!m_registers.empty()) { @@ -1022,11 +918,19 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat } } + static uint32_t sp_regnum = LLDB_INVALID_REGNUM; + static uint32_t pc_regnum = LLDB_INVALID_REGNUM; + static bool generic_registers_initialized = false; + if (!generic_registers_initialized) + { + m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum); + m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum); + generic_registers_initialized = true; + } + // Are we looking for the CALLER's stack pointer? The stack pointer is defined to be the same as THIS frame's // CFA so just return the CFA value. This is true on x86-32/x86-64 at least. - uint32_t sp_regnum; - if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum) - && sp_regnum == lldb_regnum) + if (sp_regnum != LLDB_INVALID_REGNUM && sp_regnum == lldb_regnum) { // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value) assert (sizeof (addr_t) <= sizeof (uint64_t)); @@ -1036,12 +940,6 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat return true; } - uint32_t pc_regnum; - if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum)) - { - pc_regnum = LLDB_INVALID_REGNUM; - } - // Look through the available UnwindPlans for the register location. UnwindPlan::Row::RegisterLocation unwindplan_regloc; @@ -1055,22 +953,13 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat uint32_t row_regnum; if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum)) { - if (log) - { - log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum, (int) unwindplan_registerkind); - } + UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme", + lldb_regnum, (int) unwindplan_registerkind); return false; } if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc)) { - if (log) - { - log->Printf("%*sFrame %u supplying caller's saved reg %d's location using FastUnwindPlan", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsg ("supplying caller's saved reg %d's location using FastUnwindPlan", lldb_regnum); have_unwindplan_regloc = true; } } @@ -1092,27 +981,18 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat if (lldb_regnum == pc_regnum && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM) { row_regnum = m_full_unwind_plan_sp->GetReturnAddressRegister(); - if (log) - { - log->Printf("%*sFrame %u requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, row_regnum); - } + UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead", + row_regnum); } else { if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum)) { - if (log) - { - if (unwindplan_registerkind == eRegisterKindGeneric) - log->Printf("%*sFrame %u could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - else - log->Printf("%*sFrame %u could not convert lldb regnum %d into %d RegisterKind reg numbering scheme", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum, (int) unwindplan_registerkind); - } + if (unwindplan_registerkind == eRegisterKindGeneric) + UnwindLogMsg ("could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme", lldb_regnum); + else + UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme", + lldb_regnum, (int) unwindplan_registerkind); return false; } } @@ -1120,22 +1000,62 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc)) { have_unwindplan_regloc = true; - if (log) - { - log->Printf("%*sFrame %u supplying caller's saved reg %d's location using %s UnwindPlan", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum, m_full_unwind_plan_sp->GetSourceName().GetCString()); + UnwindLogMsg ("supplying caller's saved reg %d's location using %s UnwindPlan", lldb_regnum, + m_full_unwind_plan_sp->GetSourceName().GetCString()); + } + + // If this architecture stores the return address in a register (it defines a Return Address register) + // and we're on a non-zero stack frame and the Full UnwindPlan says that the pc is stored in the + // RA registers (e.g. lr on arm), then we know that the full unwindplan is not trustworthy -- this + // is an impossible situation and the instruction emulation code has likely been misled. + // If this stack frame meets those criteria, we need to throw away the Full UnwindPlan that the + // instruction emulation came up with and fall back to the architecture's Default UnwindPlan so + // the stack walk can get past this point. + + // Special note: If the Full UnwindPlan was generated from the compiler, don't second-guess it + // when we're at a call site location. + + // arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering + uint32_t arch_default_ra_regnum = LLDB_INVALID_REGNUM; + if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, unwindplan_registerkind, arch_default_ra_regnum) + && arch_default_ra_regnum != LLDB_INVALID_REGNUM + && pc_regnum != LLDB_INVALID_REGNUM + && pc_regnum == lldb_regnum + && unwindplan_regloc.IsInOtherRegister() + && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum + && m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes + && !m_all_registers_available) + { + UnwindLogMsg ("%s UnwindPlan tried to restore the pc from the link register but this is a non-zero frame", + m_full_unwind_plan_sp->GetSourceName().GetCString()); + + // Throw away the full unwindplan; install the arch default unwindplan + InvalidateFullUnwindPlan(); + + // Now re-fetch the pc value we're searching for + uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM; + UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); + if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg) + && arch_default_pc_reg != LLDB_INVALID_REGNUM + && active_row + && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc)) + { + have_unwindplan_regloc = true; + } + else + { + have_unwindplan_regloc = false; } } } } - - + + ExecutionContext exe_ctx(m_thread.shared_from_this()); Process *process = exe_ctx.GetProcessPtr(); if (have_unwindplan_regloc == false) { - // If a volatile register is being requested, we don't want to forward the next frame's register contents + // If a volatile register is being requested, we don't want to forward the next frame's register contents // up the stack -- the register is not retrievable at this frame. ABI *abi = process ? process->GetABI().get() : NULL; if (abi) @@ -1143,14 +1063,9 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum); if (reg_info && abi->RegisterIsVolatile (reg_info)) { - if (log && log->GetVerbose ()) - { - log->Printf("%*sFrame %u did not supply reg location for %d because it is volatile", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum); return false; - } + } } if (IsFrameZero ()) @@ -1164,16 +1079,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat return true; } else - { - if (check_next_frame) - return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1); - } - if (log) - { - log->Printf("%*sFrame %u could not supply caller's reg %d location", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); return false; } @@ -1183,12 +1089,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat lldb_private::UnwindLLDB::RegisterLocation new_regloc; new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved; m_registers[lldb_regnum] = new_regloc; - if (log) - { - log->Printf("%*sFrame %u could not supply caller's reg %d location", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); return false; } @@ -1196,20 +1097,12 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat { if (IsFrameZero ()) { - if (log) - { - log->Printf("%*sFrame %u could not supply caller's reg %d location", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); return false; } else { - if (check_next_frame) - return m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1); - else - return false; + return false; } } @@ -1237,12 +1130,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat uint32_t row_regnum_in_lldb; if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb)) { - if (log) - { - log->Printf("%*sFrame %u could not supply caller's reg %d location", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); return false; } regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; @@ -1253,8 +1141,8 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression()) { - DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(), - unwindplan_regloc.GetDWARFExpressionLength(), + DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(), + unwindplan_regloc.GetDWARFExpressionLength(), process->GetByteOrder(), process->GetAddressByteSize()); DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength()); dwarfexpr.SetRegisterKind (unwindplan_registerkind); @@ -1279,28 +1167,69 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat return true; } } - if (log) - { - log->Printf("%*sFrame %u tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum); return false; } - if (log) - { - log->Printf("%*sFrame %u could not supply caller's reg %d location", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum); + + // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported. - - // assert ("UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported."); return false; } -// Retrieve a general purpose register value for THIS from, as saved by the NEXT frame, i.e. the frame that +// If the Full unwindplan has been determined to be incorrect, this method will +// replace it with the architecture's default unwindplna, if one is defined. +// It will also find the FuncUnwinders object for this function and replace the +// Full unwind method for the function there so we don't use the errant Full unwindplan +// again in the future of this debug session. +// We're most likely doing this because the Full unwindplan was generated by assembly +// instruction profiling and the profiler got something wrong. + +void +RegisterContextLLDB::InvalidateFullUnwindPlan () +{ + UnwindPlan::Row::RegisterLocation unwindplan_regloc; + ExecutionContext exe_ctx (m_thread.shared_from_this()); + Process *process = exe_ctx.GetProcessPtr(); + ABI *abi = process ? process->GetABI().get() : NULL; + if (abi) + { + UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp; + UnwindPlanSP arch_default_unwind_plan_sp; + arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); + abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp); + if (arch_default_unwind_plan_sp) + { + UnwindPlan::RowSP active_row = arch_default_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); + + if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM) + { + FuncUnwindersSP func_unwinders_sp; + if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule()) + { + func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx); + if (func_unwinders_sp) + { + func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread); + } + } + m_registers.clear(); + m_full_unwind_plan_sp = arch_default_unwind_plan_sp; + addr_t cfa_regval; + if (ReadGPRValue (arch_default_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval)) + { + m_cfa = cfa_regval + active_row->GetCFAOffset (); + } + + UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.", + original_full_unwind_plan_sp->GetSourceName().GetCString(), arch_default_unwind_plan_sp->GetSourceName().GetCString()); + } + } + } +} + +// Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that // this frame called. e.g. // // foo () { } @@ -1343,8 +1272,21 @@ RegisterContextLLDB::ReadGPRValue (int register_kind, uint32_t regnum, addr_t &v return false; } + bool pc_or_return_address = false; + uint32_t generic_regnum; + if (register_kind == eRegisterKindGeneric + && (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) + { + pc_or_return_address = true; + } + else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum) + && (generic_regnum == LLDB_REGNUM_GENERIC_PC || generic_regnum == LLDB_REGNUM_GENERIC_RA)) + { + pc_or_return_address = true; + } + lldb_private::UnwindLLDB::RegisterLocation regloc; - if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1)) + if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, pc_or_return_address)) { return false; } @@ -1361,33 +1303,22 @@ RegisterContextLLDB::ReadGPRValue (int register_kind, uint32_t regnum, addr_t &v bool RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) { - LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (!IsValid()) return false; const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; - if (log && log->GetVerbose ()) - { - log->Printf("%*sFrame %u looking for register saved location for reg %d", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum); // If this is the 0th frame, hand this over to the live register context if (IsFrameZero ()) { - if (log && log->GetVerbose ()) - { - log->Printf("%*sFrame %u passing along to the live register context for reg %d", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum); return m_thread.GetRegisterContext()->ReadRegister (reg_info, value); } lldb_private::UnwindLLDB::RegisterLocation regloc; // Find out where the NEXT frame saved THIS frame's register contents - if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1)) + if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false)) return false; return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value); @@ -1396,33 +1327,22 @@ RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue & bool RegisterContextLLDB::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value) { - LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (!IsValid()) return false; const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB]; - if (log && log->GetVerbose ()) - { - log->Printf("%*sFrame %u looking for register saved location for reg %d", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum); // If this is the 0th frame, hand this over to the live register context if (IsFrameZero ()) { - if (log && log->GetVerbose ()) - { - log->Printf("%*sFrame %u passing along to the live register context for reg %d", - m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, - lldb_regnum); - } + UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum); return m_thread.GetRegisterContext()->WriteRegister (reg_info, value); } lldb_private::UnwindLLDB::RegisterLocation regloc; // Find out where the NEXT frame saved THIS frame's register contents - if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1)) + if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false)) return false; return WriteRegisterValueToRegisterLocation (regloc, reg_info, value); @@ -1486,7 +1406,7 @@ RegisterContextLLDB::GetStartPC (addr_t& start_pc) if (!m_start_pc.IsValid()) { - return ReadPC (start_pc); + return ReadPC (start_pc); } start_pc = m_start_pc.GetLoadAddress (CalculateTarget().get()); return true; @@ -1507,12 +1427,12 @@ RegisterContextLLDB::ReadPC (addr_t& pc) // occur if code has jumped through a NULL pointer -- we want to be able to unwind past that frame to help // find the bug. - if (m_all_registers_available == false + if (m_all_registers_available == false && (pc == 0 || pc == 1)) { return false; } - else + else { return true; } @@ -1522,3 +1442,57 @@ RegisterContextLLDB::ReadPC (addr_t& pc) return false; } } + + +void +RegisterContextLLDB::UnwindLogMsg (const char *fmt, ...) +{ + LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (log) + { + va_list args; + va_start (args, fmt); + + char *logmsg; + if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL) + { + if (logmsg) + free (logmsg); + va_end (args); + return; + } + va_end (args); + + log->Printf ("%*sth%d/fr%u %s", + m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number, + logmsg); + free (logmsg); + } +} + +void +RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...) +{ + LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); + if (log && log->GetVerbose()) + { + va_list args; + va_start (args, fmt); + + char *logmsg; + if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL) + { + if (logmsg) + free (logmsg); + va_end (args); + return; + } + va_end (args); + + log->Printf ("%*sth%d/fr%u %s", + m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number, + logmsg); + free (logmsg); + } +} + diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h index 3a7aa67a8bbf..d659846f8a62 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -59,7 +59,7 @@ public: virtual bool WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); - + virtual bool ReadAllRegisterValues (lldb::DataBufferSP &data_sp); @@ -96,14 +96,14 @@ private: friend class UnwindLLDB; // Indicates whether this frame is frame zero -- the currently - // executing frame -- or not. + // executing frame -- or not. bool IsFrameZero () const; - void + void InitializeZerothFrame (); - void + void InitializeNonZerothFrame(); SharedPtr @@ -112,7 +112,7 @@ private: SharedPtr GetPrevFrame () const; - // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1. + // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1. // There is a good chance we'll get back on track if we follow the frame pointer chain (or whatever is appropriate // on this ABI) so we allow one invalid frame to be in the stack. Ideally we'll mark this frame specially at some // point and indicate to the user that the unwinder had a hiccup. Often when this happens we will miss a frame of @@ -124,32 +124,30 @@ private: // Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this // function didn't modify/use. // - // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register + // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register // being queried mid-stack. Instead of floating frame 0's contents of that register up the stack (which may // or may not be the value of that reg when the function was executing), we won't return any value. // // If a non-volatile register (a "preserved" register) is requested mid-stack and no frames "below" the requested // stack have saved the register anywhere, it is safe to assume that frame 0's register values are still the same // as the requesting frame's. - // - // NB this function takes a "check_next_frame" boolean which indicates whether it should call back to the - // containing UnwindLLDB object to iterate the search down the stack (true) or if this call should look for - // a register save for that reg in the current frame only (false). Allows UnwindLLDB to iterate through the - // RegisterContextLLDB's instead of using recursion to find saved register values. bool - SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, bool check_next_frame); + SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc); bool - ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, + ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); bool - WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, + WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc, const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); - // Get the contents of a general purpose (address-size) register for this frame + void + InvalidateFullUnwindPlan (); + + // Get the contents of a general purpose (address-size) register for this frame // (usually retrieved from the next frame) bool ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value); @@ -160,8 +158,14 @@ private: lldb::UnwindPlanSP GetFullUnwindPlanForFrame (); + void + UnwindLogMsg (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + + void + UnwindLogMsgVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + lldb_private::Thread& m_thread; - + /// // The following tell us how to retrieve the CALLER's register values (ie the "previous" frame, aka the frame above) // i.e. where THIS frame saved them @@ -182,7 +186,7 @@ private: int m_current_offset_backed_up_one; // how far into the function we've executed; -1 if unknown // 0 if no instructions have been executed yet. // On architectures where the return address on the stack points - // to the instruction after the CALL, this value will have 1 + // to the instruction after the CALL, this value will have 1 // subtracted from it. Else a function that ends in a CALL will // have an offset pointing into the next function's address range. // m_current_pc has the actual address of the "current" pc. diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp index 5581496ab6ba..587ec88a73dc 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -262,14 +262,24 @@ UnwindLLDB::GetRegisterContextForFrameNum (uint32_t frame_num) } bool -UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num) +UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_or_return_address_reg) { int64_t frame_num = starting_frame_num; if (frame_num >= m_frames.size()) return false; + + // Never interrogate more than one level while looking for the saved pc value. If the value + // isn't saved by frame_num, none of the frames lower on the stack will have a useful value. + if (pc_or_return_address_reg) + { + if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc)) + return true; + else + return false; + } while (frame_num >= 0) { - if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc, false)) + if (m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc)) return true; frame_num--; } diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h index 7d1c8a1f1466..26dc968beebd 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.h +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.h @@ -80,7 +80,7 @@ protected: // Iterate over the RegisterContextLLDB's in our m_frames vector, look for the first one that // has a saved location for this reg. bool - SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num); + SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_or_return_address_reg); private: diff --git a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index 94d5263aaeb9..7a18373e30fe 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -738,6 +738,8 @@ loopnext: } unwind_plan.SetSourceName ("assembly insn profiling"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); return true; } @@ -822,6 +824,9 @@ AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_ row.reset(newrow); unwind_plan.SetPlanValidAddressRange (func); + unwind_plan.SetSourceName ("fast unwind assembly profiling"); + unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); return true; } diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/lldb/source/Symbol/DWARFCallFrameInfo.cpp index 5bd5dd50f750..7dbd7117a09d 100644 --- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp +++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp @@ -371,11 +371,18 @@ DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t offset, Address startaddr, Unwi { unwind_plan.SetSourceName ("eh_frame CFI"); cie_offset = current_entry + 4 - cie_offset; + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); } else { unwind_plan.SetSourceName ("DWARF CFI"); + // In theory the debug_frame info should be valid at all call sites + // ("asynchronous unwind info" as it is sometimes called) but in practice + // gcc et al all emit call frame info for the prologue and call sites, but + // not for the epilogue or all the other locations during the function reliably. + unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); } + unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); const CIE *cie = GetCIE (cie_offset); assert (cie != NULL); diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp index 616bd614badd..07b2144e5286 100644 --- a/lldb/source/Symbol/FuncUnwinders.cpp +++ b/lldb/source/Symbol/FuncUnwinders.cpp @@ -236,3 +236,12 @@ FuncUnwinders::GetFunctionStartAddress () const return m_range.GetBaseAddress(); } +void +FuncUnwinders::InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& thread) +{ + UnwindPlanSP arch_default = GetUnwindPlanArchitectureDefault (thread); + if (arch_default && m_tried_unwind_at_call_site) + { + m_unwind_plan_call_site_sp = arch_default; + } +} diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp index 0a1ec6076d4e..9bccaa8ea8f3 100644 --- a/lldb/source/Symbol/UnwindPlan.cpp +++ b/lldb/source/Symbol/UnwindPlan.cpp @@ -153,7 +153,7 @@ void UnwindPlan::Row::Clear () { m_offset = 0; - m_cfa_reg_num = 0; + m_cfa_reg_num = LLDB_INVALID_REGNUM; m_cfa_offset = 0; m_register_locations.clear(); } @@ -189,7 +189,7 @@ UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, UnwindPlan::Row::Row() : m_offset(0), - m_cfa_reg_num(0), + m_cfa_reg_num(LLDB_INVALID_REGNUM), m_cfa_offset(0), m_register_locations() {