FpDebug: Update internal breakpoints, if they failed to be set.

This commit is contained in:
Martin 2024-06-05 16:10:25 +02:00
parent 6d6f77a870
commit 00507e47df

View File

@ -461,8 +461,8 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure Clear; reintroduce; procedure Clear; reintroduce;
procedure AddLocation (const ALocation: TDBGPtr; const AInternalBreak: TFpInternalBreakpoint; AnIgnoreIfExists: Boolean = True); procedure AddLocation (const ALocation: TDBGPtr; const AnInternalBreak: TFpInternalBreakpoint; AnIgnoreIfExists: Boolean = True; AForceRetrySetting: Boolean = False);
procedure RemoveLocation(const ALocation: TDBGPtr; const AInternalBreak: TFpInternalBreakpoint); procedure RemoveLocation(const ALocation: TDBGPtr; const AnInternalBreak: TFpInternalBreakpoint);
function HasInsertedBreakInstructionAtLocation(const ALocation: TDBGPtr): Boolean; function HasInsertedBreakInstructionAtLocation(const ALocation: TDBGPtr): Boolean;
function GetInternalBreaksAtLocation(const ALocation: TDBGPtr): TFpInternalBreakpointArray; function GetInternalBreaksAtLocation(const ALocation: TDBGPtr): TFpInternalBreakpointArray;
@ -487,8 +487,8 @@ type
constructor Create(AProcess: TDbgProcess); constructor Create(AProcess: TDbgProcess);
function GetDataSize: integer; virtual; abstract; function GetDataSize: integer; virtual; abstract;
function InsertBreakInstructionCode(const ALocation: TDBGPtr; const AInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer): boolean; virtual; abstract; function InsertBreakInstructionCode(const ALocation: TDBGPtr; const AnInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer): boolean; virtual; abstract;
procedure RemoveBreakInstructionCode(const ALocation: TDBGPtr; const AInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer); virtual; abstract; procedure RemoveBreakInstructionCode(const ALocation: TDBGPtr; const AnInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer); virtual; abstract;
// When the debugger modifies the debuggee's code, it might be that the // When the debugger modifies the debuggee's code, it might be that the
// original value underneeth the breakpoint has to be changed. This function // original value underneeth the breakpoint has to be changed. This function
@ -529,8 +529,8 @@ type
public public
function GetDataSize: integer; override; function GetDataSize: integer; override;
function InsertBreakInstructionCode(const ALocation: TDBGPtr; const AInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer): boolean; override; function InsertBreakInstructionCode(const ALocation: TDBGPtr; const AnInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer): boolean; override;
procedure RemoveBreakInstructionCode(const ALocation: TDBGPtr; const AInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer); override; procedure RemoveBreakInstructionCode(const ALocation: TDBGPtr; const AnInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer); override;
// When the debugger modifies the debuggee's code, it might be that the // When the debugger modifies the debuggee's code, it might be that the
// original value underneeth the breakpoint has to be changed. This function // original value underneeth the breakpoint has to be changed. This function
@ -607,7 +607,15 @@ type
FLocation: TDBGPtrArray; FLocation: TDBGPtrArray;
FInternal: Boolean; FInternal: Boolean;
FState: TFpDbgBreakpointState; FState: TFpDbgBreakpointState;
FErrorSettingCount: integer;
FUpdateStateLock: integer;
FNeedUpdateState: boolean;
protected protected
procedure BeginUpdate;
procedure EndUpdate;
procedure TriggerUpdateState;
procedure AddErrorSetting(ALocation: TDBGPtr);
procedure RemoveErrorSetting(ALocation: TDBGPtr);
function GetState: TFpDbgBreakpointState; override; function GetState: TFpDbgBreakpointState; override;
procedure SetState(AState: TFpDbgBreakpointState); procedure SetState(AState: TFpDbgBreakpointState);
procedure UpdateState; virtual; procedure UpdateState; virtual;
@ -1408,7 +1416,8 @@ begin
end; end;
procedure TFpBreakPointMap.AddLocation(const ALocation: TDBGPtr; procedure TFpBreakPointMap.AddLocation(const ALocation: TDBGPtr;
const AInternalBreak: TFpInternalBreakpoint; AnIgnoreIfExists: Boolean); const AnInternalBreak: TFpInternalBreakpoint; AnIgnoreIfExists: Boolean;
AForceRetrySetting: Boolean);
var var
MapEntryPtr: PFpBreakPointMapEntry; MapEntryPtr: PFpBreakPointMapEntry;
Len, i: Integer; Len, i: Integer;
@ -1422,43 +1431,64 @@ begin
Len := Length(TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)); Len := Length(TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint));
if AnIgnoreIfExists then begin if AnIgnoreIfExists then begin
i := Len - 1; i := Len - 1;
while (i >= 0) and (TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[i] <> AInternalBreak) do while (i >= 0) and (TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[i] <> AnInternalBreak) do
dec(i); dec(i);
if i >= 0 then if i >= 0 then
exit; exit;
end; end;
SetLength(TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint), Len+1); SetLength(TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint), Len+1);
TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[Len] := AInternalBreak; TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[Len] := AnInternalBreak;
end end
else begin else begin
if AnIgnoreIfExists and (TFpInternalBreakpoint(MapEntryPtr^.InternalBreakPoint) = AInternalBreak) then if AnIgnoreIfExists and (TFpInternalBreakpoint(MapEntryPtr^.InternalBreakPoint) = AnInternalBreak) then
exit; exit;
MapEntryPtr^.IsBreakList := True; MapEntryPtr^.IsBreakList := True;
SetLength(BList, 2); SetLength(BList, 2);
BList[0] := TFpInternalBreakpoint(MapEntryPtr^.InternalBreakPoint); BList[0] := TFpInternalBreakpoint(MapEntryPtr^.InternalBreakPoint);
BList[1] := AInternalBreak; BList[1] := AnInternalBreak;
MapEntryPtr^.InternalBreakPoint := nil; MapEntryPtr^.InternalBreakPoint := nil;
TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint) := BList; TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint) := BList;
end; end;
if MapEntryPtr^.ErrorSetting then begin
if AForceRetrySetting then begin
FProcess.DoBeforeBreakLocationMapChange; // Only if a new breakpoint is set => memory changed
MapEntryPtr^.ErrorSetting := not TargetHandler.InsertBreakInstructionCode(ALocation, AnInternalBreak, @MapEntryPtr^.TargetHandlerData);
if MapEntryPtr^.ErrorSetting then begin
AnInternalBreak.AddErrorSetting(ALocation);
end
else
if MapEntryPtr^.IsBreakList then begin
debugln(DBG_VERBOSE or DBG_BREAKPOINTS, ['Retrying failed breakpoint updated multiple instances']);
for i := 0 to Length(TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)) - 1 do
if TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[i] <> AnInternalBreak then
TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[i].RemoveErrorSetting(ALocation);
end;
end
else begin
AnInternalBreak.AddErrorSetting(ALocation);
end;
end;
exit; exit;
end; end;
FillByte(FTmpDataPtr^, FDataSize, 0); FillByte(FTmpDataPtr^, FDataSize, 0);
FTmpDataPtr^.IsBreakList := False; FTmpDataPtr^.IsBreakList := False;
FTmpDataPtr^.InternalBreakPoint := AInternalBreak; FTmpDataPtr^.InternalBreakPoint := AnInternalBreak;
FProcess.DoBeforeBreakLocationMapChange; // Only if a new breakpoint is set => memory changed FProcess.DoBeforeBreakLocationMapChange; // Only if a new breakpoint is set => memory changed
MapEntryPtr^.ErrorSetting := not TargetHandler.InsertBreakInstructionCode(ALocation, AInternalBreak, @FTmpDataPtr^.TargetHandlerData); FTmpDataPtr^.ErrorSetting := not TargetHandler.InsertBreakInstructionCode(ALocation, AnInternalBreak, @FTmpDataPtr^.TargetHandlerData);
if FTmpDataPtr^.ErrorSetting then
AnInternalBreak.AddErrorSetting(ALocation);
Add(ALocation, FTmpDataPtr^); Add(ALocation, FTmpDataPtr^);
end; end;
procedure TFpBreakPointMap.RemoveLocation(const ALocation: TDBGPtr; procedure TFpBreakPointMap.RemoveLocation(const ALocation: TDBGPtr;
const AInternalBreak: TFpInternalBreakpoint); const AnInternalBreak: TFpInternalBreakpoint);
var var
MapEntryPtr: PFpBreakPointMapEntry; MapEntryPtr: PFpBreakPointMapEntry;
Len, i: Integer; Len, i: Integer;
@ -1473,7 +1503,7 @@ begin
if MapEntryPtr^.IsBreakList then begin if MapEntryPtr^.IsBreakList then begin
Len := Length(TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)); Len := Length(TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint));
i := Len - 1; i := Len - 1;
while (i >= 0) and (TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[i] <> AInternalBreak) do while (i >= 0) and (TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[i] <> AnInternalBreak) do
dec(i); dec(i);
if i < 0 then begin if i < 0 then begin
DebugLn(DBG_WARNINGS or DBG_BREAKPOINTS, ['Wrong break for loc ', FormatAddress(ALocation)]); DebugLn(DBG_WARNINGS or DBG_BREAKPOINTS, ['Wrong break for loc ', FormatAddress(ALocation)]);
@ -1484,20 +1514,25 @@ begin
TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[i], TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint)[i],
(Len - 1 - i) * sizeof(TFpInternalBreakpoint)); (Len - 1 - i) * sizeof(TFpInternalBreakpoint));
SetLength(TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint), Len-1); SetLength(TFpInternalBreakpointArray(MapEntryPtr^.InternalBreakPoint), Len-1);
if MapEntryPtr^.ErrorSetting then
AnInternalBreak.RemoveErrorSetting(ALocation);
if Len > 1 then if Len > 1 then
exit; exit;
end end
else else begin
if AInternalBreak <> TFpInternalBreakpoint(MapEntryPtr^.InternalBreakPoint) then begin if AnInternalBreak <> TFpInternalBreakpoint(MapEntryPtr^.InternalBreakPoint) then begin
DebugLn(DBG_WARNINGS or DBG_BREAKPOINTS, ['Wrong break for loc ', FormatAddress(ALocation)]); DebugLn(DBG_WARNINGS or DBG_BREAKPOINTS, ['Wrong break for loc ', FormatAddress(ALocation)]);
exit;
end;
exit; if MapEntryPtr^.ErrorSetting then
AnInternalBreak.RemoveErrorSetting(ALocation);
end; end;
FProcess.DoBeforeBreakLocationMapChange; // Only if a breakpoint is removed => memory changed FProcess.DoBeforeBreakLocationMapChange; // Only if a breakpoint is removed => memory changed
if not MapEntryPtr^.ErrorSetting then if not MapEntryPtr^.ErrorSetting then
TargetHandler.RemoveBreakInstructionCode(ALocation, AInternalBreak, @MapEntryPtr^.TargetHandlerData); TargetHandler.RemoveBreakInstructionCode(ALocation, AnInternalBreak, @MapEntryPtr^.TargetHandlerData);
Delete(ALocation); Delete(ALocation);
end; end;
@ -1746,7 +1781,7 @@ begin
end; end;
function TGenericBreakPointTargetHandler.InsertBreakInstructionCode(const ALocation: TDBGPtr; function TGenericBreakPointTargetHandler.InsertBreakInstructionCode(const ALocation: TDBGPtr;
const AInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer const AnInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer
): boolean; ): boolean;
var var
LocData: PInternalBreakLocationEntry absolute AnEntry; LocData: PInternalBreakLocationEntry absolute AnEntry;
@ -1765,7 +1800,7 @@ begin
end; end;
procedure TGenericBreakPointTargetHandler.RemoveBreakInstructionCode(const ALocation: TDBGPtr; procedure TGenericBreakPointTargetHandler.RemoveBreakInstructionCode(const ALocation: TDBGPtr;
const AInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer); const AnInternalBreak: TFpInternalBreakpoint; AnEntry: PFpBreakPointTargetHandlerDataPointer);
var var
LocData: PInternalBreakLocationEntry absolute AnEntry; LocData: PInternalBreakLocationEntry absolute AnEntry;
begin begin
@ -4091,6 +4126,38 @@ end;
{ TDbgBreak } { TDbgBreak }
procedure TFpInternalBreakpoint.BeginUpdate;
begin
inc(FUpdateStateLock);
end;
procedure TFpInternalBreakpoint.EndUpdate;
begin
dec(FUpdateStateLock);
if (FUpdateStateLock = 0) and FNeedUpdateState then
TriggerUpdateState;
end;
procedure TFpInternalBreakpoint.TriggerUpdateState;
begin
FNeedUpdateState := FUpdateStateLock > 0;
if FNeedUpdateState then
exit;
UpdateState;
end;
procedure TFpInternalBreakpoint.AddErrorSetting(ALocation: TDBGPtr);
begin
inc(FErrorSettingCount);
TriggerUpdateState;
end;
procedure TFpInternalBreakpoint.RemoveErrorSetting(ALocation: TDBGPtr);
begin
dec(FErrorSettingCount);
TriggerUpdateState;
end;
function TFpInternalBreakpoint.GetState: TFpDbgBreakpointState; function TFpInternalBreakpoint.GetState: TFpDbgBreakpointState;
begin begin
Result := FState; Result := FState;
@ -4107,7 +4174,7 @@ end;
procedure TFpInternalBreakpoint.UpdateState; procedure TFpInternalBreakpoint.UpdateState;
begin begin
if Length(FLocation) > 0 then if (Length(FLocation) > 0) and (FErrorSettingCount = 0) then
SetState(bksOk) SetState(bksOk)
else else
SetState(bksFailed); SetState(bksFailed);
@ -4118,6 +4185,7 @@ var
i, j: Integer; i, j: Integer;
a: TDBGPtr; a: TDBGPtr;
begin begin
BeginUpdate;
j := 0; j := 0;
for i := 0 to Length(FLocation) - 1 do begin for i := 0 to Length(FLocation) - 1 do begin
a := FLocation[i]; a := FLocation[i];
@ -4129,8 +4197,9 @@ begin
end; end;
if j < Length(FLocation) then begin if j < Length(FLocation) then begin
SetLength(FLocation, j); SetLength(FLocation, j);
UpdateState; TriggerUpdateState;
end; end;
EndUpdate;
end; end;
constructor TFpInternalBreakpoint.Create(const AProcess: TDbgProcess; constructor TFpInternalBreakpoint.Create(const AProcess: TDbgProcess;
@ -4141,9 +4210,11 @@ begin
FLocation := ALocation; FLocation := ALocation;
FEnabled := AnEnabled; FEnabled := AnEnabled;
FState := bksUnknown; FState := bksUnknown;
BeginUpdate;
if AnEnabled then if AnEnabled then
SetBreak; SetBreak;
UpdateState; TriggerUpdateState;
EndUpdate;
end; end;
destructor TFpInternalBreakpoint.Destroy; destructor TFpInternalBreakpoint.Destroy;
@ -4188,9 +4259,11 @@ begin
l := Length(FLocation); l := Length(FLocation);
SetLength(FLocation, l+1); SetLength(FLocation, l+1);
FLocation[l] := ALocation; FLocation[l] := ALocation;
BeginUpdate;
if Enabled then if Enabled then
Process.FBreakMap.AddLocation(ALocation, Self, True); Process.FBreakMap.AddLocation(ALocation, Self, True);
UpdateState; TriggerUpdateState;
EndUpdate;
end; end;
procedure TFpInternalBreakpoint.AddAddress(const ALocations: TDBGPtrArray); procedure TFpInternalBreakpoint.AddAddress(const ALocations: TDBGPtrArray);
@ -4200,6 +4273,7 @@ begin
l := Length(FLocation); l := Length(FLocation);
SetLength(FLocation, l + Length(ALocations)); SetLength(FLocation, l + Length(ALocations));
BeginUpdate;
if Enabled then begin if Enabled then begin
for i := 0 to Length(ALocations) - 1 do begin for i := 0 to Length(ALocations) - 1 do begin
FLocation[l + i] := ALocations[i]; FLocation[l + i] := ALocations[i];
@ -4210,7 +4284,8 @@ begin
for i := 0 to Length(ALocations) - 1 do for i := 0 to Length(ALocations) - 1 do
FLocation[l + i] := ALocations[i]; FLocation[l + i] := ALocations[i];
end; end;
UpdateState; TriggerUpdateState;
EndUpdate;
end; end;
procedure TFpInternalBreakpoint.RemoveAddress(const ALocation: TDBGPtr); procedure TFpInternalBreakpoint.RemoveAddress(const ALocation: TDBGPtr);
@ -4225,15 +4300,19 @@ begin
exit; exit;
FLocation[i] := FLocation[l]; FLocation[i] := FLocation[l];
SetLength(FLocation, l); SetLength(FLocation, l);
BeginUpdate;
Process.FBreakMap.RemoveLocation(ALocation, Self); Process.FBreakMap.RemoveLocation(ALocation, Self);
UpdateState; TriggerUpdateState;
EndUpdate;
end; end;
procedure TFpInternalBreakpoint.RemoveAllAddresses; procedure TFpInternalBreakpoint.RemoveAllAddresses;
begin begin
BeginUpdate;
ResetBreak; ResetBreak;
SetLength(FLocation, 0); SetLength(FLocation, 0);
UpdateState; TriggerUpdateState;
EndUpdate;
end; end;
procedure TFpInternalBreakpoint.ResetBreak; procedure TFpInternalBreakpoint.ResetBreak;
@ -4245,8 +4324,11 @@ begin
exit; exit;
FEnabled := False; FEnabled := False;
BeginUpdate;
for i := 0 to High(FLocation) do for i := 0 to High(FLocation) do
Process.FBreakMap.RemoveLocation(FLocation[i], Self); Process.FBreakMap.RemoveLocation(FLocation[i], Self);
TriggerUpdateState;
EndUpdate;
end; end;
procedure TFpInternalBreakpoint.SetBreak; procedure TFpInternalBreakpoint.SetBreak;
@ -4258,14 +4340,20 @@ begin
exit; exit;
FEnabled := True; FEnabled := True;
BeginUpdate;
for i := 0 to High(FLocation) do for i := 0 to High(FLocation) do
Process.FBreakMap.AddLocation(FLocation[i], Self, True); Process.FBreakMap.AddLocation(FLocation[i], Self, True);
TriggerUpdateState;
EndUpdate;
end; end;
{ TFpInternalBreakpointAtSymbol } { TFpInternalBreakpointAtSymbol }
procedure TFpInternalBreakpointAtSymbol.UpdateState; procedure TFpInternalBreakpointAtSymbol.UpdateState;
begin begin
if FErrorSettingCount > 0 then
SetState(bksFailed)
else
if Length(FLocation) > 0 then if Length(FLocation) > 0 then
SetState(bksOk) SetState(bksOk)
else else
@ -4317,6 +4405,9 @@ end;
procedure TFpInternalBreakpointAtFileLine.UpdateState; procedure TFpInternalBreakpointAtFileLine.UpdateState;
begin begin
if FErrorSettingCount > 0 then
SetState(bksFailed)
else
if Length(FLocation) > 0 then if Length(FLocation) > 0 then
SetState(bksOk) SetState(bksOk)
else else