diff --git a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp index 280ec5ba37100..25803c9799ce4 100644 --- a/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ b/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -102,12 +102,7 @@ static Status PushToLinuxGuardedControlStack(addr_t return_addr, size_t wrote = thread.GetProcess()->WriteMemory(gcspr_el0, &return_addr, sizeof(return_addr), error); if ((wrote != sizeof(return_addr) || error.Fail())) { - // When PrepareTrivialCall fails, the register context is not restored, - // unlike when an expression fails to execute. This is arguably a bug, - // see https://github.com/llvm/llvm-project/issues/124269. - // For now we are handling this here specifically. We can assume this - // write will work as the one to decrement the register did. - reg_ctx->WriteRegisterFromUnsigned(gcspr_el0_info, gcspr_el0 + 8); + // gcspr_el0 will be restored by the ThreadPlan's DoTakedown. return Status("Failed to write new Guarded Control Stack entry."); } @@ -150,8 +145,6 @@ bool ABISysV_arm64::PrepareTrivialCall(Thread &thread, addr_t sp, if (args.size() > 8) return false; - // Do this first, as it's got the most chance of failing (though still very - // low). if (GetProcessSP()->GetTarget().GetArchitecture().GetTriple().isOSLinux()) { Status err = PushToLinuxGuardedControlStack(return_addr, reg_ctx, thread); // If we could not manage the GCS, the expression will certainly fail, diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp index 50dcb66b9719f..218111d4faf60 100644 --- a/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -174,8 +174,20 @@ void ThreadPlanCallFunction::ReportRegisterState(const char *message) { void ThreadPlanCallFunction::DoTakedown(bool success) { Log *log = GetLog(LLDBLog::Step); + Thread &thread = GetThread(); if (!m_valid) { + // If ConstructorSetup was succesfull but PrepareTrivialCall was not, + // we will have a saved register state and potentially modified registers. + // Restore those. + if (m_stored_thread_state.register_backup_sp) + if (!thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state)) + LLDB_LOGF( + log, + "ThreadPlanCallFunction(%p): Failed to restore register state from " + "invalid plan that contained a saved register state.", + static_cast(this)); + // Don't call DoTakedown if we were never valid to begin with. LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Log called on " @@ -185,7 +197,6 @@ void ThreadPlanCallFunction::DoTakedown(bool success) { } if (!m_takedown_done) { - Thread &thread = GetThread(); if (success) { SetReturnValue(); }