diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h index 40814da3de4a..06c76ca80796 100644 --- a/lldb/include/lldb/Symbol/UnwindPlan.h +++ b/lldb/include/lldb/Symbol/UnwindPlan.h @@ -360,6 +360,25 @@ class UnwindPlan { bool SetRegisterLocationToSame(uint32_t reg_num, bool must_replace); + // When this UnspecifiedRegistersAreUndefined mode is + // set, any register that is not specified by this Row will + // be described as Undefined. + // This will prevent the unwinder from iterating down the + // stack looking for a spill location, or a live register value + // at frame 0. + // It would be used for an UnwindPlan row where we can't track + // spilled registers -- for instance a jitted stack frame where + // we have no unwind information or start address -- and registers + // MAY have been spilled and overwritten, so providing the + // spilled/live value from a newer frame may show an incorrect value. + void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef) { + m_unspecified_registers_are_undefined = unspec_is_undef; + } + + bool GetUnspecifiedRegistersAreUndefined() { + return m_unspecified_registers_are_undefined; + } + void Clear(); void Dump(Stream &s, const UnwindPlan *unwind_plan, Thread *thread, @@ -372,6 +391,7 @@ class UnwindPlan { FAValue m_cfa_value; FAValue m_afa_value; collection m_register_locations; + bool m_unspecified_registers_are_undefined; }; // class Row typedef std::shared_ptr RowSP; diff --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp index ea0c09a1596a..861310e3ea0c 100644 --- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp @@ -384,6 +384,7 @@ bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp index 5918e2ccb5fa..0f74c1f5c73b 100644 --- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -356,6 +356,7 @@ bool ABISysV_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp b/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp index 06c4590b7740..e429f3ee0cc4 100644 --- a/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp +++ b/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp @@ -1824,6 +1824,7 @@ bool ABIMacOSX_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp b/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp index 26b3152bed16..8a9be3fb67c7 100644 --- a/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp +++ b/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp @@ -1940,6 +1940,7 @@ bool ABISysV_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp b/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp index 47aaefd3b228..6794f7d07210 100644 --- a/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp +++ b/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp @@ -1225,6 +1225,7 @@ bool ABISysV_hexagon::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP, 8); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, -8, true); diff --git a/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp b/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp index d66e0926ad99..538ec06c3b0d 100644 --- a/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp +++ b/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp @@ -985,6 +985,7 @@ bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); diff --git a/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp b/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp index 5e72af076f66..7220508c75ff 100644 --- a/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp +++ b/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp @@ -1156,6 +1156,7 @@ bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp index d5605642d623..cfecf35da1ed 100644 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp @@ -900,6 +900,7 @@ bool ABISysV_ppc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); const int32_t ptr_size = 4; + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true); diff --git a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp index 603143190dc5..7cc9482e7c5d 100644 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp @@ -1003,6 +1003,7 @@ bool ABISysV_ppc64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); const int32_t ptr_size = 8; + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true); diff --git a/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp b/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp index 89112deb2c4a..461e4af599d3 100644 --- a/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp +++ b/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp @@ -389,6 +389,7 @@ bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp b/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp index 38d7364aaa51..7d2f0a64d679 100644 --- a/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp +++ b/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp @@ -652,6 +652,7 @@ bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp index 8d5614756a6a..196b45b3b6da 100644 --- a/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp +++ b/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp @@ -887,6 +887,7 @@ bool ABISysV_x86_64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { const int32_t ptr_size = 8; row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp index da241458840f..6c473c652c5f 100644 --- a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp +++ b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp @@ -767,6 +767,7 @@ bool ABIWindows_x86_64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { const int32_t ptr_size = 8; row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp index d24cabed14ce..d74c78f084af 100644 --- a/lldb/source/Symbol/UnwindPlan.cpp +++ b/lldb/source/Symbol/UnwindPlan.cpp @@ -217,6 +217,7 @@ void UnwindPlan::Row::Clear() { m_cfa_value.SetUnspecified(); m_afa_value.SetUnspecified(); m_offset = 0; + m_unspecified_registers_are_undefined = false; m_register_locations.clear(); } @@ -242,11 +243,11 @@ void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan, idx->second.Dump(s, unwind_plan, this, thread, verbose); s.PutChar(' '); } - s.EOL(); } UnwindPlan::Row::Row() - : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {} + : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations(), + m_unspecified_registers_are_undefined(false) {} bool UnwindPlan::Row::GetRegisterInfo( uint32_t reg_num, @@ -256,6 +257,10 @@ bool UnwindPlan::Row::GetRegisterInfo( register_location = pos->second; return true; } + if (m_unspecified_registers_are_undefined) { + register_location.SetUndefined(); + return true; + } return false; } @@ -348,10 +353,11 @@ bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num, } bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const { - return m_offset == rhs.m_offset && - m_cfa_value == rhs.m_cfa_value && - m_afa_value == rhs.m_afa_value && - m_register_locations == rhs.m_register_locations; + return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value && + m_afa_value == rhs.m_afa_value && + m_unspecified_registers_are_undefined == + rhs.m_unspecified_registers_are_undefined && + m_register_locations == rhs.m_register_locations; } void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) { @@ -552,6 +558,7 @@ void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const { for (pos = begin; pos != end; ++pos) { s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos)); (*pos)->Dump(s, this, thread, base_addr); + s.Printf("\n"); } } diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp index 991a3c821923..a677121d8279 100644 --- a/lldb/source/Target/RegisterContextUnwind.cpp +++ b/lldb/source/Target/RegisterContextUnwind.cpp @@ -542,6 +542,8 @@ void RegisterContextUnwind::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())); + UnwindLogMsg("Using fast unwind plan '%s'", + m_fast_unwind_plan_sp->GetSourceName().AsCString()); UnwindLogMsg("active row: %s", active_row_strm.GetData()); } } else { @@ -556,6 +558,8 @@ void RegisterContextUnwind::InitializeNonZerothFrame() { active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); + UnwindLogMsg("Using full unwind plan '%s'", + m_full_unwind_plan_sp->GetSourceName().AsCString()); UnwindLogMsg("active row: %s", active_row_strm.GetData()); } } @@ -662,13 +666,6 @@ UnwindPlanSP RegisterContextUnwind::GetFastUnwindPlanForFrame() { *m_thread.CalculateTarget(), m_thread); if (unwind_plan_sp) { if (unwind_plan_sp->PlanValidAtAddress(m_current_pc)) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); - if (log && log->GetVerbose()) { - if (m_fast_unwind_plan_sp) - UnwindLogMsgVerbose("frame, and has a fast UnwindPlan"); - else - UnwindLogMsgVerbose("frame"); - } m_frame_type = eNormalFrame; return unwind_plan_sp; } else { @@ -1147,6 +1144,7 @@ enum UnwindLLDB::RegisterSearchResult RegisterContextUnwind::SavedLocationForRegister( uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc) { RegisterNumber regnum(m_thread, eRegisterKindLLDB, lldb_regnum); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); // Have we already found this register location? if (!m_registers.empty()) { @@ -1179,8 +1177,17 @@ RegisterContextUnwind::SavedLocationForRegister( (int)unwindplan_registerkind); return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } + // The architecture default unwind plan marks unknown registers as + // Undefined so that we don't forward them up the stack when a + // jitted stack frame may have overwritten them. But when the + // arch default unwind plan is used as the Fast Unwind Plan, we + // need to recognize this & switch over to the Full Unwind Plan + // to see what unwind rule that (more knoweldgeable, probably) + // UnwindPlan has. If the full UnwindPlan says the register + // location is Undefined, then it really is. if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind), - unwindplan_regloc)) { + unwindplan_regloc) && + !unwindplan_regloc.IsUndefined()) { UnwindLogMsg( "supplying caller's saved %s (%d)'s location using FastUnwindPlan", regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB)); @@ -1191,8 +1198,11 @@ RegisterContextUnwind::SavedLocationForRegister( if (!have_unwindplan_regloc) { // m_full_unwind_plan_sp being NULL means that we haven't tried to find a // full UnwindPlan yet - if (!m_full_unwind_plan_sp) + bool got_new_full_unwindplan = false; + if (!m_full_unwind_plan_sp) { m_full_unwind_plan_sp = GetFullUnwindPlanForFrame(); + got_new_full_unwindplan = true; + } if (m_full_unwind_plan_sp) { RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric, @@ -1202,6 +1212,16 @@ RegisterContextUnwind::SavedLocationForRegister( m_full_unwind_plan_sp->GetRowForFunctionOffset(m_current_offset); unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind(); + if (got_new_full_unwindplan && active_row.get() && log) { + StreamString active_row_strm; + ExecutionContext exe_ctx(m_thread.shared_from_this()); + active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), + &m_thread, + m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr())); + UnwindLogMsg("Using full unwind plan '%s'", + m_full_unwind_plan_sp->GetSourceName().AsCString()); + UnwindLogMsg("active row: %s", active_row_strm.GetData()); + } RegisterNumber return_address_reg; // If we're fetching the saved pc and this UnwindPlan defines a