FpDebug: Check result of ReadThreadState. Do not use invalid data (on windows this lead to nil deref crash)

git-svn-id: trunk@61891 -
This commit is contained in:
martin 2019-09-16 21:49:25 +00:00
parent bb55284e92
commit 4137324e48
3 changed files with 42 additions and 19 deletions

View File

@ -1720,7 +1720,7 @@ begin
exit; exit;
t := GetInstructionPointerRegisterValue; t := GetInstructionPointerRegisterValue;
if Process.HasInsertedBreakInstructionAtLocation(t - 1) then begin if (t <> 0) and Process.HasInsertedBreakInstructionAtLocation(t - 1) then begin
(* There is a chance, that the code jumped to this Addr, instead of executing the breakpoint. (* There is a chance, that the code jumped to this Addr, instead of executing the breakpoint.
But if the next signal for this thread is a breakpoint at this address, then But if the next signal for this thread is a breakpoint at this address, then
it must be handled (even if the breakpoint has been removed since) it must be handled (even if the breakpoint has been removed since)
@ -1760,14 +1760,17 @@ begin
t := GetInstructionPointerRegisterValue; t := GetInstructionPointerRegisterValue;
Result := ( (FPausedAtRemovedBreakPointState = rbFound) and Result := ( (FPausedAtRemovedBreakPointState = rbFound) and
(FPausedAtRemovedBreakPointAddress = t) ) or (FPausedAtRemovedBreakPointAddress = t) ) or
Process.HasInsertedBreakInstructionAtLocation(t - 1); ( (t <> 0) and Process.HasInsertedBreakInstructionAtLocation(t - 1) );
debugln(['####### CHECK ',result, ' for id ', ID, ' stored ', FPausedAtRemovedBreakPointState=rbFound, ' ',FPausedAtRemovedBreakPointAddress=t, ' ',dbghex(t), ' ', dbghex(FPausedAtRemovedBreakPointAddress)]); debugln(['####### CHECK ',result, ' for id ', ID, ' stored ', FPausedAtRemovedBreakPointState=rbFound, ' ',FPausedAtRemovedBreakPointAddress=t, ' ',dbghex(t), ' ', dbghex(FPausedAtRemovedBreakPointAddress)]);
end; end;
procedure TDbgThread.CheckAndResetInstructionPointerAfterBreakpoint; procedure TDbgThread.CheckAndResetInstructionPointerAfterBreakpoint;
var
t: TDBGPtr;
begin begin
// todo: check that the breakpoint is NOT in the temp removed list // todo: check that the breakpoint is NOT in the temp removed list
if HasInsertedBreakInstructionAtLocation(GetInstructionPointerRegisterValue - 1) t := GetInstructionPointerRegisterValue;
if (t <> 0) and HasInsertedBreakInstructionAtLocation(t - 1)
then begin then begin
FPausedAtRemovedBreakPointState := rbFound; FPausedAtRemovedBreakPointState := rbFound;
ResetInstructionPointerAfterBreakpoint; ResetInstructionPointerAfterBreakpoint;

View File

@ -510,7 +510,7 @@ begin
else else
if wstopsig(AWaitedStatus) = SIGTRAP then begin if wstopsig(AWaitedStatus) = SIGTRAP then begin
ReadThreadState; if ReadThreadState then
CheckAndResetInstructionPointerAfterBreakpoint; CheckAndResetInstructionPointerAfterBreakpoint;
Result := True; Result := True;
// TODO: main loop should search all threads for breakpoints // TODO: main loop should search all threads for breakpoints
@ -541,7 +541,8 @@ end;
function TDbgLinuxThread.ResetInstructionPointerAfterBreakpoint: boolean; function TDbgLinuxThread.ResetInstructionPointerAfterBreakpoint: boolean;
begin begin
ReadThreadState; if not ReadThreadState then
exit(False);
result := true; result := true;
if FDidResetInstructionPointer then if FDidResetInstructionPointer then
exit; exit;
@ -653,7 +654,8 @@ end;
procedure TDbgLinuxThread.LoadRegisterValues; procedure TDbgLinuxThread.LoadRegisterValues;
begin begin
ReadThreadState; if not ReadThreadState then
exit;
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);
@ -706,7 +708,9 @@ end;
function TDbgLinuxThread.GetInstructionPointerRegisterValue: TDbgPtr; function TDbgLinuxThread.GetInstructionPointerRegisterValue: TDbgPtr;
begin begin
ReadThreadState; Result := 0;
if not ReadThreadState then
exit;
if Process.Mode=dm32 then if Process.Mode=dm32 then
result := FUserRegs.regs32[eip] result := FUserRegs.regs32[eip]
else else
@ -715,7 +719,9 @@ end;
function TDbgLinuxThread.GetStackBasePointerRegisterValue: TDbgPtr; function TDbgLinuxThread.GetStackBasePointerRegisterValue: TDbgPtr;
begin begin
ReadThreadState; Result := 0;
if not ReadThreadState then
exit;
if Process.Mode=dm32 then if Process.Mode=dm32 then
result := FUserRegs.regs32[ebp] result := FUserRegs.regs32[ebp]
else else
@ -724,7 +730,9 @@ end;
function TDbgLinuxThread.GetStackPointerRegisterValue: TDbgPtr; function TDbgLinuxThread.GetStackPointerRegisterValue: TDbgPtr;
begin begin
ReadThreadState; Result := 0;
if not ReadThreadState then
exit;
if Process.Mode=dm32 then if Process.Mode=dm32 then
result := FUserRegs.regs32[UESP] result := FUserRegs.regs32[UESP]
else else

View File

@ -1183,7 +1183,8 @@ end;
procedure TDbgWinThread.LoadRegisterValues; procedure TDbgWinThread.LoadRegisterValues;
begin begin
if FCurrentContext = nil then if FCurrentContext = nil then
ReadThreadState; if not ReadThreadState then
exit;
{$ifdef cpui386} {$ifdef cpui386}
with FCurrentContext^.def do with FCurrentContext^.def do
begin begin
@ -1364,7 +1365,8 @@ end;
procedure TDbgWinThread.SetSingleStep; procedure TDbgWinThread.SetSingleStep;
begin begin
if FCurrentContext = nil then if FCurrentContext = nil then
ReadThreadState; if not ReadThreadState then
exit;
{$ifdef cpux86_64} {$ifdef cpux86_64}
if (TDbgWinProcess(Process).FBitness = b32) then if (TDbgWinProcess(Process).FBitness = b32) then
FCurrentContext^.WOW.EFlags := FCurrentContext^.WOW.EFlags or FLAG_TRACE_BIT // TODO WOW_FLAG.... FCurrentContext^.WOW.EFlags := FCurrentContext^.WOW.EFlags or FLAG_TRACE_BIT // TODO WOW_FLAG....
@ -1404,9 +1406,10 @@ function TDbgWinThread.AddWatchpoint(AnAddr: TDBGPtr): integer;
end; end;
begin begin
if FCurrentContext = nil then
ReadThreadState;
result := -1; result := -1;
if FCurrentContext = nil then
if not ReadThreadState then
exit;
{$ifdef cpux86_64} {$ifdef cpux86_64}
if (TDbgWinProcess(Process).FBitness = b32) then begin if (TDbgWinProcess(Process).FBitness = b32) then begin
with FCurrentContext^.WOW do with FCurrentContext^.WOW do
@ -1475,8 +1478,10 @@ function TDbgWinThread.RemoveWatchpoint(AnId: integer): boolean;
end; end;
begin begin
Result := False;
if FCurrentContext = nil then if FCurrentContext = nil then
ReadThreadState; if not ReadThreadState then
exit;
{$ifdef cpux86_64} {$ifdef cpux86_64}
if (TDbgWinProcess(Process).FBitness = b32) then begin if (TDbgWinProcess(Process).FBitness = b32) then begin
with FCurrentContext^.WOW do with FCurrentContext^.WOW do
@ -1551,7 +1556,8 @@ begin
exit; exit;
if FCurrentContext = nil then if FCurrentContext = nil then
ReadThreadState; if not ReadThreadState then
exit;
{$ifdef cpui386} {$ifdef cpui386}
Dec(Context^.def.Eip); Dec(Context^.def.Eip);
@ -1587,8 +1593,10 @@ end;
function TDbgWinThread.GetInstructionPointerRegisterValue: TDbgPtr; function TDbgWinThread.GetInstructionPointerRegisterValue: TDbgPtr;
begin begin
Result := 0;
if FCurrentContext = nil then if FCurrentContext = nil then
ReadThreadState; if not ReadThreadState then
exit;
{$ifdef cpui386} {$ifdef cpui386}
Result := FCurrentContext^.def.Eip; Result := FCurrentContext^.def.Eip;
{$else} {$else}
@ -1601,8 +1609,10 @@ end;
function TDbgWinThread.GetStackBasePointerRegisterValue: TDbgPtr; function TDbgWinThread.GetStackBasePointerRegisterValue: TDbgPtr;
begin begin
Result := 0;
if FCurrentContext = nil then if FCurrentContext = nil then
ReadThreadState; if not ReadThreadState then
exit;
{$ifdef cpui386} {$ifdef cpui386}
Result := FCurrentContext^.def.Ebp; Result := FCurrentContext^.def.Ebp;
{$else} {$else}
@ -1615,8 +1625,10 @@ end;
function TDbgWinThread.GetStackPointerRegisterValue: TDbgPtr; function TDbgWinThread.GetStackPointerRegisterValue: TDbgPtr;
begin begin
Result := 0;
if FCurrentContext = nil then if FCurrentContext = nil then
ReadThreadState; if not ReadThreadState then
exit;
{$ifdef cpui386} {$ifdef cpui386}
Result := FCurrentContext^.def.Esp; Result := FCurrentContext^.def.Esp;
{$else} {$else}