diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h --- a/lldb/include/lldb/Symbol/UnwindPlan.h +++ b/lldb/include/lldb/Symbol/UnwindPlan.h @@ -360,6 +360,25 @@ 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 @@ 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 --- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp @@ -384,6 +384,7 @@ 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 --- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -356,6 +356,7 @@ 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 --- a/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp +++ b/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp @@ -1824,6 +1824,7 @@ 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 --- a/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp +++ b/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp @@ -1940,6 +1940,7 @@ 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 --- a/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp +++ b/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp @@ -1225,6 +1225,7 @@ 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 --- a/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp +++ b/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp @@ -985,6 +985,7 @@ 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 --- a/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp +++ b/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp @@ -1156,6 +1156,7 @@ 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 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp @@ -900,6 +900,7 @@ 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 --- a/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp +++ b/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp @@ -1003,6 +1003,7 @@ 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 --- a/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp +++ b/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp @@ -389,6 +389,7 @@ 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 --- a/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp +++ b/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp @@ -652,6 +652,7 @@ 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 --- a/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp +++ b/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp @@ -887,6 +887,7 @@ 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 --- a/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp +++ b/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp @@ -767,6 +767,7 @@ 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 --- a/lldb/source/Symbol/UnwindPlan.cpp +++ b/lldb/source/Symbol/UnwindPlan.cpp @@ -217,6 +217,7 @@ 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 @@ 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 @@ 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::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 @@ 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 --- a/lldb/source/Target/RegisterContextUnwind.cpp +++ b/lldb/source/Target/RegisterContextUnwind.cpp @@ -542,6 +542,8 @@ 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 @@ 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 @@ *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 @@ 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 @@ (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 @@ 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 @@ 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