FpDebug: change HasBreakpointInfoForAddress, replace IP-1 by GetInstructionPointerForHasBreakpointInfoForAddress

This commit is contained in:
Martin 2024-02-13 20:58:07 +01:00
parent 2b3310eb90
commit e2e2f26c91
5 changed files with 48 additions and 15 deletions

View File

@ -276,6 +276,12 @@ type
function GetName: String; virtual;
function GetStackUnwinder: TDbgStackUnwinder; virtual; abstract;
(* The "HasBreakpointInfoForAddress" is used if a breakpoint was hit,
and removed while some DbgThread may still need to know it was there.
The address of interest is therefore where the breakpoint is.
Depending on the architecture the IP has to be adjusted.
*)
function GetInstructionPointerForHasBreakpointInfoForAddress: TDBGPtr; virtual;
public
constructor Create(const AProcess: TDbgProcess; const AID: Integer; const AHandle: THandle); virtual;
procedure DoBeforeProcessLoop;
@ -3358,7 +3364,7 @@ begin
then
exit;
if (AnAddr <> 0) and Process.HasInsertedBreakInstructionAtLocation(AnAddr - 1) then begin
if (AnAddr <> 0) and Process.HasInsertedBreakInstructionAtLocation(AnAddr) then begin
(* 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
it must be handled (even if the breakpoint has been removed since)
@ -3399,13 +3405,13 @@ end;
procedure TDbgThread.DoBeforeBreakLocationMapChange;
begin
StoreHasBreakpointInfoForAddress(GetInstructionPointerRegisterValue);
StoreHasBreakpointInfoForAddress(GetInstructionPointerForHasBreakpointInfoForAddress);
end;
procedure TDbgThread.ValidateRemovedBreakPointInfo;
begin
if (FStoredBreakpointInfoState <> rbUnknown) then
ClearHasBreakpointInfoForAddressMismatch(GetInstructionPointerRegisterValue);
ClearHasBreakpointInfoForAddressMismatch(GetInstructionPointerForHasBreakpointInfoForAddress);
end;
function TDbgThread.GetName: String;
@ -3413,6 +3419,11 @@ begin
Result := '';
end;
function TDbgThread.GetInstructionPointerForHasBreakpointInfoForAddress: TDBGPtr;
begin
Result := GetInstructionPointerRegisterValue;
end;
constructor TDbgThread.Create(const AProcess: TDbgProcess; const AID: Integer; const AHandle: THandle);
begin
FID := AID;
@ -3434,12 +3445,9 @@ begin
end;
function TDbgThread.HasInsertedBreakInstructionAtLocation(const ALocation: TDBGPtr): Boolean;
var
t: TDBGPtr;
begin
t := GetInstructionPointerRegisterValue;
Result := HasBreakpointInfoForAddressMismatch(t) or
( (t <> 0) and Process.HasInsertedBreakInstructionAtLocation(t - 1) );
Result := HasBreakpointInfoForAddressMismatch(ALocation) or
( (ALocation <> 0) and Process.HasInsertedBreakInstructionAtLocation(ALocation) );
end;
procedure TDbgThread.CheckAndResetInstructionPointerAfterBreakpoint;
@ -3448,17 +3456,17 @@ var
OVal: Byte;
begin
// todo: check that the breakpoint is NOT in the temp removed list
t := GetInstructionPointerRegisterValue;
t := GetInstructionPointerForHasBreakpointInfoForAddress;
if t = 0 then
exit;
if HasInsertedBreakInstructionAtLocation(t - 1)
if HasInsertedBreakInstructionAtLocation(t)
then begin
FStoredBreakpointInfoState := rbFound;
ResetInstructionPointerAfterBreakpoint;
end
else begin
// TODO: allow to skip this, while detaching
if FProcess.ReadData(t-1, 1, OVal) then
if FProcess.ReadData(t, 1, OVal) then
FPausedAtHardcodeBreakPoint := OVal = TDbgProcess.Int3;
end;
end;

View File

@ -10,6 +10,15 @@ uses
type
{ TDbgx86Thread }
TDbgx86Thread = class(TDbgThread)
protected
FHasResetInstructionPointerAfterBreakpoint: boolean;
function GetInstructionPointerForHasBreakpointInfoForAddress: TDBGPtr; override;
end;
{ TDbgStackUnwinderX86FramePointer }
TDbgStackUnwinderX86FramePointer = class(TDbgStackUnwinderX86Base)
@ -54,6 +63,15 @@ type
implementation
{ TDbgx86Thread }
function TDbgx86Thread.GetInstructionPointerForHasBreakpointInfoForAddress: TDBGPtr;
begin
Result := GetInstructionPointerRegisterValue;
if (Result <> 0) and not FHasResetInstructionPointerAfterBreakpoint then
Result := Result - 1;
end;
{ TDbgStackUnwinderX86FramePointer }
procedure TDbgStackUnwinderX86FramePointer.InitForThread(AThread: TDbgThread);

View File

@ -24,7 +24,7 @@ uses
UTF8Process,
{$ifdef FORCE_LAZLOGGER_DUMMY} LazLoggerDummy {$else} LazLoggerBase {$endif},
FpDbgCommon, FpdMemoryTools,
FpErrorMessages;
FpErrorMessages, FpDbgCpuX86;
type
x86_thread_state32_t = record
@ -102,7 +102,7 @@ type
{ TDbgDarwinThread }
TDbgDarwinThread = class(TDbgThread)
TDbgDarwinThread = class(TDbgx86Thread)
private
FThreadState32: x86_thread_state32_t;
FThreadState64: x86_thread_state64_t;

View File

@ -264,7 +264,7 @@ type
{ TDbgLinuxThread }
TDbgLinuxThread = class(TDbgThread)
TDbgLinuxThread = class(TDbgx86Thread)
private
FUserRegs: TUserRegs;
FStoredUserRegs: TUserRegs;
@ -591,6 +591,7 @@ begin
FUserRegsChanged:=false;
FRegisterValueListValid:=false;
FHasThreadState := Result;
FHasResetInstructionPointerAfterBreakpoint := False;
end;
function TDbgLinuxThread.RequestInternalPause: Boolean;
@ -701,6 +702,7 @@ begin
else
Dec(FUserRegs.regs64[rip]);
FUserRegsChanged:=true;
FHasResetInstructionPointerAfterBreakpoint := True;
end;
procedure TDbgLinuxThread.ApplyWatchPoints(AWatchPointData: TFpWatchPointData);
@ -764,6 +766,7 @@ begin
end;
FUserRegsChanged:=false;
end;
FHasResetInstructionPointerAfterBreakpoint := False;
end;
procedure TDbgLinuxThread.LoadRegisterValues;

View File

@ -132,7 +132,7 @@ type
{ TDbgWinThread }
TDbgWinThread = class(TDbgThread)
TDbgWinThread = class(TDbgx86Thread)
private type
TBreakPointState = (bsNone, bsInSingleStep);
private
@ -2017,6 +2017,7 @@ begin
FThreadContextChanged := False;
FThreadContextChangeFlags := [];
FCurrentContext := nil;
FHasResetInstructionPointerAfterBreakpoint := False;
end;
function TDbgWinThread.ResetInstructionPointerAfterBreakpoint: boolean;
@ -2030,6 +2031,7 @@ begin
if not ReadThreadState then
exit;
assert(not FHasResetInstructionPointerAfterBreakpoint, 'TDbgWinThread.ResetInstructionPointerAfterBreakpoint: not FHasResetInstructionPointerAfterBreakpoint');
{$ifdef cpui386}
if not CheckForHardcodeBreakPoint(FCurrentContext^.def.Eip - 1) then
dec(FCurrentContext^.def.Eip);
@ -2045,6 +2047,7 @@ begin
{$endif}
FThreadContextChanged := True;
FHasResetInstructionPointerAfterBreakpoint := True;
Result := True;
end;
@ -2067,6 +2070,7 @@ begin
//FThreadContextChanged := False; TODO: why was that not here?
FThreadContextChangeFlags := [];
FRegisterValueListValid:=False;
FHasResetInstructionPointerAfterBreakpoint := False;
end;
procedure TDbgWinThread.ClearExceptionSignal;