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).
This commit is contained in:
Martin 2023-01-24 11:38:34 +01:00
parent 4650dfa54a
commit ad9a460928

View File

@ -315,6 +315,7 @@ type
FIsTerminating: boolean; FIsTerminating: boolean;
FMasterPtyFd: cint; FMasterPtyFd: cint;
FCurrentThreadId: THandle; FCurrentThreadId: THandle;
FSingleSteppingThreadID: THandle;
// This breakpoint is triggered after dynamic libraries have been (un)loaded // This breakpoint is triggered after dynamic libraries have been (un)loaded
FSOLibEventBreakpoint: TFpDbgBreakpoint; FSOLibEventBreakpoint: TFpDbgBreakpoint;
{$ifndef VER2_6} {$ifndef VER2_6}
@ -1140,6 +1141,7 @@ constructor TDbgLinuxProcess.Create(const AFileName: string;
AProcessConfig: TDbgProcessConfig); AProcessConfig: TDbgProcessConfig);
begin begin
FMasterPtyFd:=-1; FMasterPtyFd:=-1;
FSingleSteppingThreadID := -1;
FPostponedSignals := TFpDbgLinuxSignalQueue.Create; FPostponedSignals := TFpDbgLinuxSignalQueue.Create;
inherited Create(AFileName, AnOsClasses, AMemManager, AProcessConfig); inherited Create(AFileName, AnOsClasses, AMemManager, AProcessConfig);
end; end;
@ -1525,6 +1527,7 @@ begin
{$IFDEF DebuglnLinuxDebugEvents} {$IFDEF DebuglnLinuxDebugEvents}
debuglnEnter(['>>>>> TDbgLinuxProcess.Continue TID:', AThread.ID, ' SingleStep:', SingleStep ]); try debuglnEnter(['>>>>> TDbgLinuxProcess.Continue TID:', AThread.ID, ' SingleStep:', SingleStep ]); try
{$ENDIF} {$ENDIF}
FSingleSteppingThreadID := -1;
// Terminating process and all threads // Terminating process and all threads
if FIsTerminating then begin if FIsTerminating then begin
@ -1558,10 +1561,10 @@ begin
ThreadToContinue.BeforeContinue; ThreadToContinue.BeforeContinue;
while (ThreadToContinue.GetInstructionPointerRegisterValue = IP) do begin while (ThreadToContinue.GetInstructionPointerRegisterValue = IP) do begin
fpseterrno(0);
{$IFDEF DebuglnLinuxDebugEvents} {$IFDEF DebuglnLinuxDebugEvents}
Debugln(FPDBG_LINUX, ['Single-stepping other TID: ', ThreadToContinue.ID]); Debugln(FPDBG_LINUX, ['Single-stepping other TID: ', ThreadToContinue.ID]);
{$ENDIF} {$ENDIF}
fpseterrno(0);
fpPTrace(PTRACE_SINGLESTEP, ThreadToContinue.ID, pointer(1), pointer(TDbgLinuxThread(ThreadToContinue).FExceptionSignal)); fpPTrace(PTRACE_SINGLESTEP, ThreadToContinue.ID, pointer(1), pointer(TDbgLinuxThread(ThreadToContinue).FExceptionSignal));
TDbgLinuxThread(ThreadToContinue).ResetPauseStates; TDbgLinuxThread(ThreadToContinue).ResetPauseStates;
@ -1569,7 +1572,7 @@ begin
if CheckNoError then begin if CheckNoError then begin
PID := fpWaitPid(ThreadToContinue.ID, WaitStatus, __WALL); PID := fpWaitPid(ThreadToContinue.ID, WaitStatus, __WALL);
if PID <> ThreadToContinue.ID then begin 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; break;
end; end;
if ThreadToContinue.NextIsSingleStep then begin if ThreadToContinue.NextIsSingleStep then begin
@ -1604,6 +1607,7 @@ begin
{$IFDEF DebuglnLinuxDebugEvents} {$IFDEF DebuglnLinuxDebugEvents}
Debugln(FPDBG_LINUX, ['Single-stepping current']); Debugln(FPDBG_LINUX, ['Single-stepping current']);
{$ENDIF} {$ENDIF}
FSingleSteppingThreadID := AThread.ID;
fpPTrace(PTRACE_SINGLESTEP, AThread.ID, pointer(1), pointer(TDbgLinuxThread(AThread).FExceptionSignal)); fpPTrace(PTRACE_SINGLESTEP, AThread.ID, pointer(1), pointer(TDbgLinuxThread(AThread).FExceptionSignal));
TDbgLinuxThread(AThread).ResetPauseStates; TDbgLinuxThread(AThread).ResetPauseStates;
Result := CheckNoError; Result := CheckNoError;
@ -1656,10 +1660,16 @@ begin
ThreadIdentifier:=-1; ThreadIdentifier:=-1;
ProcessIdentifier:=-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 If not FPostponedSignals.GetNextSignal(PID, FStatus) then
PID:=FpWaitPid(-1, FStatus, __WALL); PID:=FpWaitPid(-1, FStatus, __WALL);
RestoreTempBreakInstructionCodes; RestoreTempBreakInstructionCodes; // should only happen after single step, so all threads should be paused
result := PID<>-1; result := PID<>-1;
if not result then if not result then