FpDebug: More refactor internal breakpoints. Improve stopping other threads on Linux

git-svn-id: trunk@60214 -
This commit is contained in:
martin 2019-01-25 00:44:38 +00:00
parent 6f10746551
commit cfed0db10f

View File

@ -234,6 +234,7 @@ type
FHasExceptionSignal: Boolean; FHasExceptionSignal: Boolean;
FIsPaused, FInternalPauseRequested, FIsInInternalPause: boolean; FIsPaused, FInternalPauseRequested, FIsInInternalPause: boolean;
FIsSteppingBreakPoint: boolean; FIsSteppingBreakPoint: boolean;
FHasThreadState: boolean;
function GetDebugRegOffset(ind: byte): pointer; function GetDebugRegOffset(ind: byte): pointer;
function ReadDebugReg(ind: byte; out AVal: PtrUInt): boolean; function ReadDebugReg(ind: byte; out AVal: PtrUInt): boolean;
function WriteDebugReg(ind: byte; AVal: PtrUInt): boolean; function WriteDebugReg(ind: byte; AVal: PtrUInt): boolean;
@ -403,7 +404,10 @@ function TDbgLinuxThread.ReadThreadState: boolean;
var var
io: iovec; io: iovec;
begin begin
assert(FIsPaused, 'TDbgLinuxThread.ReadThreadState: FIsPaused');
result := true; result := true;
if FHasThreadState then
exit;
io.iov_base:=@(FUserRegs.regs32[0]); io.iov_base:=@(FUserRegs.regs32[0]);
io.iov_len:= sizeof(FUserRegs); io.iov_len:= sizeof(FUserRegs);
if fpPTrace(PTRACE_GETREGSET, ID, pointer(PtrUInt(NT_PRSTATUS)), @io) <> 0 then if fpPTrace(PTRACE_GETREGSET, ID, pointer(PtrUInt(NT_PRSTATUS)), @io) <> 0 then
@ -413,6 +417,7 @@ begin
end; end;
FUserRegsChanged:=false; FUserRegsChanged:=false;
FRegisterValueListValid:=false; FRegisterValueListValid:=false;
FHasThreadState := Result;
end; end;
function TDbgLinuxThread.RequestInternalPause: Boolean; function TDbgLinuxThread.RequestInternalPause: Boolean;
@ -476,6 +481,7 @@ begin
else else
if wstopsig(AWaitedStatus) = SIGTRAP then begin if wstopsig(AWaitedStatus) = SIGTRAP then begin
ReadThreadState;
CheckAndResetInstructionPointerAfterBreakpoint; CheckAndResetInstructionPointerAfterBreakpoint;
FHasExceptionSignal := False; // TODO: main loop should search all threads for breakpoints FHasExceptionSignal := False; // TODO: main loop should search all threads for breakpoints
end end
@ -498,10 +504,12 @@ begin
FIsInInternalPause := False; FIsInInternalPause := False;
FIsPaused := False; FIsPaused := False;
FExceptionSignal := 0; FExceptionSignal := 0;
FHasThreadState := False;
end; end;
function TDbgLinuxThread.ResetInstructionPointerAfterBreakpoint: boolean; function TDbgLinuxThread.ResetInstructionPointerAfterBreakpoint: boolean;
begin begin
ReadThreadState;
result := true; result := true;
if Process.Mode=dm32 then if Process.Mode=dm32 then
@ -609,6 +617,7 @@ end;
procedure TDbgLinuxThread.LoadRegisterValues; procedure TDbgLinuxThread.LoadRegisterValues;
begin begin
ReadThreadState;
if Process.Mode=dm32 then if Process.Mode=dm32 then
begin begin
FRegisterValueList.DbgRegisterAutoCreate['eax'].SetValue(FUserRegs.regs32[eax], IntToStr(FUserRegs.regs32[eax]),4,0); FRegisterValueList.DbgRegisterAutoCreate['eax'].SetValue(FUserRegs.regs32[eax], IntToStr(FUserRegs.regs32[eax]),4,0);
@ -661,6 +670,7 @@ end;
function TDbgLinuxThread.GetInstructionPointerRegisterValue: TDbgPtr; function TDbgLinuxThread.GetInstructionPointerRegisterValue: TDbgPtr;
begin begin
ReadThreadState;
if Process.Mode=dm32 then if Process.Mode=dm32 then
result := FUserRegs.regs32[eip] result := FUserRegs.regs32[eip]
else else
@ -669,6 +679,7 @@ end;
function TDbgLinuxThread.GetStackBasePointerRegisterValue: TDbgPtr; function TDbgLinuxThread.GetStackBasePointerRegisterValue: TDbgPtr;
begin begin
ReadThreadState;
if Process.Mode=dm32 then if Process.Mode=dm32 then
result := FUserRegs.regs32[ebp] result := FUserRegs.regs32[ebp]
else else
@ -677,6 +688,7 @@ end;
function TDbgLinuxThread.GetStackPointerRegisterValue: TDbgPtr; function TDbgLinuxThread.GetStackPointerRegisterValue: TDbgPtr;
begin begin
ReadThreadState;
if Process.Mode=dm32 then if Process.Mode=dm32 then
result := FUserRegs.regs32[UESP] result := FUserRegs.regs32[UESP]
else else
@ -985,17 +997,18 @@ begin
// check other threads if they need a singlestep // check other threads if they need a singlestep
for TDbgThread(ThreadToContinue) in FThreadMap do for TDbgThread(ThreadToContinue) in FThreadMap do
if (ThreadToContinue <> AThread) then begin if (ThreadToContinue <> AThread) and ThreadToContinue.FIsPaused then begin
IP := ThreadToContinue.GetInstructionPointerRegisterValue; IP := ThreadToContinue.GetInstructionPointerRegisterValue;
if HasInsertedBreakInstructionAtLocation(IP) then begin if HasInsertedBreakInstructionAtLocation(IP) then begin
TempRemoveBreakInstructionCode(IP); TempRemoveBreakInstructionCode(IP);
ThreadToContinue.BeforeContinue; ThreadToContinue.BeforeContinue;
while ThreadToContinue.GetInstructionPointerRegisterValue = IP do begin while (ThreadToContinue.GetInstructionPointerRegisterValue = IP) do begin
fpseterrno(0); fpseterrno(0);
fpPTrace(PTRACE_SINGLESTEP, ThreadToContinue.ID, pointer(1), pointer(wstopsig(TDbgLinuxThread(ThreadToContinue).FExceptionSignal))); fpPTrace(PTRACE_SINGLESTEP, ThreadToContinue.ID, pointer(1), pointer(wstopsig(TDbgLinuxThread(ThreadToContinue).FExceptionSignal)));
TDbgLinuxThread(ThreadToContinue).ResetPauseStates; // So BeforeContinue will not run again TDbgLinuxThread(ThreadToContinue).ResetPauseStates; // So BeforeContinue will not run again
ThreadToContinue.FIsPaused := True;
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
@ -1269,7 +1282,6 @@ begin
end; end;
end; end;
end; end;
end. end.