From ad9a460928155182f42d1c759bd8dc1a27447650 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 24 Jan 2023 11:38:34 +0100 Subject: [PATCH] FpDebug, Linux: Improve stepping over breakpoint. When the signal for a newly launched thread was received while the single-step was still in progress, then "RestoreTempBreakInstructionCodes" failed (as the thread was still running), and the breakpoint (int3) ended up missing (no longer stopping at the breakpoint). --- components/fpdebug/fpdbglinuxclasses.pas | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/components/fpdebug/fpdbglinuxclasses.pas b/components/fpdebug/fpdbglinuxclasses.pas index 8f4757ca9e..73a6c67f52 100644 --- a/components/fpdebug/fpdbglinuxclasses.pas +++ b/components/fpdebug/fpdbglinuxclasses.pas @@ -315,6 +315,7 @@ type FIsTerminating: boolean; FMasterPtyFd: cint; FCurrentThreadId: THandle; + FSingleSteppingThreadID: THandle; // This breakpoint is triggered after dynamic libraries have been (un)loaded FSOLibEventBreakpoint: TFpDbgBreakpoint; {$ifndef VER2_6} @@ -1140,6 +1141,7 @@ constructor TDbgLinuxProcess.Create(const AFileName: string; AProcessConfig: TDbgProcessConfig); begin FMasterPtyFd:=-1; + FSingleSteppingThreadID := -1; FPostponedSignals := TFpDbgLinuxSignalQueue.Create; inherited Create(AFileName, AnOsClasses, AMemManager, AProcessConfig); end; @@ -1525,6 +1527,7 @@ begin {$IFDEF DebuglnLinuxDebugEvents} debuglnEnter(['>>>>> TDbgLinuxProcess.Continue TID:', AThread.ID, ' SingleStep:', SingleStep ]); try {$ENDIF} + FSingleSteppingThreadID := -1; // Terminating process and all threads if FIsTerminating then begin @@ -1558,10 +1561,10 @@ begin ThreadToContinue.BeforeContinue; while (ThreadToContinue.GetInstructionPointerRegisterValue = IP) do begin - fpseterrno(0); {$IFDEF DebuglnLinuxDebugEvents} Debugln(FPDBG_LINUX, ['Single-stepping other TID: ', ThreadToContinue.ID]); {$ENDIF} + fpseterrno(0); fpPTrace(PTRACE_SINGLESTEP, ThreadToContinue.ID, pointer(1), pointer(TDbgLinuxThread(ThreadToContinue).FExceptionSignal)); TDbgLinuxThread(ThreadToContinue).ResetPauseStates; @@ -1569,7 +1572,7 @@ begin if CheckNoError then begin PID := fpWaitPid(ThreadToContinue.ID, WaitStatus, __WALL); if PID <> ThreadToContinue.ID then begin - DebugLn(DBG_WARNINGS, ['Error single stepping other thread ', ThreadToContinue.ID, ' waitpid got ', PID, ', ',WaitStatus, ' err ', Errno]); + DebugLn(DBG_WARNINGS, ['XXXXX Error single stepping other thread ', ThreadToContinue.ID, ' waitpid got ', PID, ', ',WaitStatus, ' err ', Errno]); break; end; if ThreadToContinue.NextIsSingleStep then begin @@ -1604,6 +1607,7 @@ begin {$IFDEF DebuglnLinuxDebugEvents} Debugln(FPDBG_LINUX, ['Single-stepping current']); {$ENDIF} + FSingleSteppingThreadID := AThread.ID; fpPTrace(PTRACE_SINGLESTEP, AThread.ID, pointer(1), pointer(TDbgLinuxThread(AThread).FExceptionSignal)); TDbgLinuxThread(AThread).ResetPauseStates; Result := CheckNoError; @@ -1656,10 +1660,16 @@ begin ThreadIdentifier:=-1; ProcessIdentifier:=-1; + if FSingleSteppingThreadID <> -1 then begin + PID:=FpWaitPid(FSingleSteppingThreadID, FStatus, __WALL); + if PID <> FSingleSteppingThreadID then + DebugLn(DBG_WARNINGS, ['XXXXX Error: single stepping current thread ', FSingleSteppingThreadID, ' waitpid got ', PID, ', ',FStatus, ' err ', Errno]); + end + else If not FPostponedSignals.GetNextSignal(PID, FStatus) then PID:=FpWaitPid(-1, FStatus, __WALL); - RestoreTempBreakInstructionCodes; + RestoreTempBreakInstructionCodes; // should only happen after single step, so all threads should be paused result := PID<>-1; if not result then