diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp index 81b7f138fe7ca..45d2f95433d5b 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp @@ -809,7 +809,7 @@ bool x86AssemblyInspectionEngine::local_branch_p ( // Branch target is before the start of this function return false; } - if (offset + next_pc_value > func_range.GetByteSize()) { + if (offset + next_pc_value >= func_range.GetByteSize()) { // Branch targets outside this function's bounds return false; } @@ -967,6 +967,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( bool in_epilogue = false; // we're in the middle of an epilogue sequence bool row_updated = false; // The UnwindPlan::Row 'row' has been updated + bool current_sp_offset_updated = + false; // current_sp_bytes_offset_from_fa has been updated this insn m_cur_insn = data + current_func_text_offset; if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset) @@ -1013,8 +1015,10 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( afa_value.SetUnspecified(); row_updated = true; } - if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) + if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) { current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset(); + current_sp_offset_updated = true; + } } else if (mov_rbx_rsp_pattern_p()) { @@ -1025,8 +1029,10 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( afa_value.SetUnspecified(); row_updated = true; } - if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) + if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) { current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset(); + current_sp_offset_updated = true; + } } // This is the start() function (or a pthread equivalent), it starts with a @@ -1039,6 +1045,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( else if (push_reg_p(machine_regno)) { current_sp_bytes_offset_from_fa += m_wordsize; + current_sp_offset_updated = true; // the PUSH instruction has moved the stack pointer - if the FA is set // in terms of the stack pointer, we need to add a new row of // instructions. @@ -1064,6 +1071,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( else if (pop_reg_p(machine_regno)) { current_sp_bytes_offset_from_fa -= m_wordsize; + current_sp_offset_updated = true; if (nonvolatile_reg_p(machine_regno) && machine_regno_to_lldb_regno(machine_regno, lldb_regno) && @@ -1091,6 +1099,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( else if (pop_misc_reg_p()) { current_sp_bytes_offset_from_fa -= m_wordsize; + current_sp_offset_updated = true; if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) { fa_value_ptr->SetIsRegisterPlusOffset( m_lldb_sp_regnum, current_sp_bytes_offset_from_fa); @@ -1126,6 +1135,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( } current_sp_bytes_offset_from_fa -= m_wordsize; + current_sp_offset_updated = true; if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) { fa_value_ptr->SetIsRegisterPlusOffset( @@ -1161,6 +1171,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( else if (sub_rsp_pattern_p(stack_offset)) { current_sp_bytes_offset_from_fa += stack_offset; + current_sp_offset_updated = true; if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) { fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa); row_updated = true; @@ -1169,6 +1180,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( else if (add_rsp_pattern_p(stack_offset)) { current_sp_bytes_offset_from_fa -= stack_offset; + current_sp_offset_updated = true; if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) { fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa); row_updated = true; @@ -1179,6 +1191,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( else if (push_extended_pattern_p() || push_imm_pattern_p() || push_misc_reg_p()) { current_sp_bytes_offset_from_fa += m_wordsize; + current_sp_offset_updated = true; if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) { fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa); row_updated = true; @@ -1187,6 +1200,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( else if (lea_rsp_pattern_p(stack_offset)) { current_sp_bytes_offset_from_fa -= stack_offset; + current_sp_offset_updated = true; if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) { fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa); row_updated = true; @@ -1206,6 +1220,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) { current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset; + current_sp_offset_updated = true; } } @@ -1219,6 +1234,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( } if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) { current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset; + current_sp_offset_updated = true; } } @@ -1251,6 +1267,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( row.reset(newrow); current_sp_bytes_offset_from_fa = prologue_completed_sp_bytes_offset_from_cfa; + current_sp_offset_updated = true; is_aligned = prologue_completed_is_aligned; saved_registers.clear(); @@ -1272,6 +1289,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( // global data else if (call_next_insn_pattern_p()) { current_sp_bytes_offset_from_fa += m_wordsize; + current_sp_offset_updated = true; if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) { fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa); row_updated = true; @@ -1304,7 +1322,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly( // We may change the sp value without adding a new Row necessarily -- keep // track of it either way. - if (!in_epilogue) { + if (!in_epilogue && current_sp_offset_updated) { prologue_completed_sp_bytes_offset_from_cfa = current_sp_bytes_offset_from_fa; prologue_completed_is_aligned = is_aligned; diff --git a/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp b/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp index 3ff57b4f97f17..f5bb3b6d64236 100644 --- a/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp +++ b/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp @@ -2859,16 +2859,17 @@ TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyMidFunctionEpilogues) { 0x90, // <+18>: nop // prologue setup back - 0x74, 0x7, // <+19>: je 6 <+27> + 0x74, 0x8, // <+19>: je 7 <+28> 0x48, 0x83, 0xc4, 0x70, // <+21>: addq $0x70, %rsp 0x5d, // <+25>: popq %rbp - 0xc3, // <+26>: retq // epilogue completed + 0x90, // <+26>: nop // mid-epilogue non-epilogue + 0xc3, // <+27>: retq // epilogue completed - 0x90, // <+27>: nop // prologue setup back + 0x90, // <+28>: nop // prologue setup back - 0x48, 0x83, 0xc4, 0x70, // <+28>: addq $0x70, %rsp - 0x5d, // <+32>: popq %rbp - 0xc3, // <+33>: retq // epilogue completed + 0x48, 0x83, 0xc4, 0x70, // <+29>: addq $0x70, %rsp + 0x5d, // <+33>: popq %rbp + 0xc3, // <+34>: retq // epilogue completed }; @@ -2898,8 +2899,8 @@ TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyMidFunctionEpilogues) { // Check that we've reinstated the stack frame setup // unwind instructions after a mid-function retq // row: CFA=ebp +8 => esp=CFA+0 eip=[CFA-8] - row_sp = unwind_plan.GetRowForFunctionOffset(27); - EXPECT_EQ(27ull, row_sp->GetOffset()); + row_sp = unwind_plan.GetRowForFunctionOffset(28); + EXPECT_EQ(28ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(wordsize * 2, row_sp->GetCFAValue().GetOffset()); @@ -2907,8 +2908,8 @@ TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyMidFunctionEpilogues) { // After last instruction in the function, verify that // the stack frame has been unwound // row: CFA=esp +4 => esp=CFA+0 eip=[CFA-4] - row_sp = unwind_plan.GetRowForFunctionOffset(33); - EXPECT_EQ(33ull, row_sp->GetOffset()); + row_sp = unwind_plan.GetRowForFunctionOffset(34); + EXPECT_EQ(34ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(wordsize, row_sp->GetCFAValue().GetOffset()); @@ -2940,8 +2941,8 @@ TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyMidFunctionEpilogues) { // Check that we've reinstated the stack frame setup // unwind instructions after a mid-function retq // row: CFA=rbp+16 => rsp=CFA+0 rip=[CFA-16] - row_sp = unwind_plan.GetRowForFunctionOffset(27); - EXPECT_EQ(27ull, row_sp->GetOffset()); + row_sp = unwind_plan.GetRowForFunctionOffset(28); + EXPECT_EQ(28ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(wordsize * 2, row_sp->GetCFAValue().GetOffset()); @@ -2949,8 +2950,8 @@ TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyMidFunctionEpilogues) { // After last instruction in the function, verify that // the stack frame has been unwound // row: CFA=rsp +8 => esp=CFA+0 rip=[CFA-8] - row_sp = unwind_plan.GetRowForFunctionOffset(33); - EXPECT_EQ(33ull, row_sp->GetOffset()); + row_sp = unwind_plan.GetRowForFunctionOffset(34); + EXPECT_EQ(34ull, row_sp->GetOffset()); EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp); EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true); EXPECT_EQ(wordsize, row_sp->GetCFAValue().GetOffset());