FpDebug: Stepping commands, refactor HiddenBreakpoint:

- Move to base-class
- No need to check for other breakpoints (fpdebug can now handle several brk at same address)
- Stop step-out, if break failed to set

git-svn-id: trunk@61880 -
This commit is contained in:
martin 2019-09-14 14:33:09 +00:00
parent 1c5491c441
commit 48f15f849d

View File

@ -56,12 +56,19 @@ type
procedure DoContinue(AProcess: TDbgProcess; AThread: TDbgThread); override; procedure DoContinue(AProcess: TDbgProcess; AThread: TDbgThread); override;
end; end;
{ TDbgControllerHiddenBreakStepCmd }
TDbgControllerHiddenBreakStepCmd = class(TDbgControllerCmd)
protected
FHiddenBreakpoint: TFpInternalBreakpoint;
procedure RemoveHiddenBreak;
public
destructor Destroy; override;
end;
{ TDbgControllerStepOverInstructionCmd } { TDbgControllerStepOverInstructionCmd }
TDbgControllerStepOverInstructionCmd = class(TDbgControllerCmd) TDbgControllerStepOverInstructionCmd = class(TDbgControllerHiddenBreakStepCmd)
private
FHiddenBreakpoint: TFpInternalBreakpoint;
FIsSet: boolean;
protected protected
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Handled, Finished: boolean); override; procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Handled, Finished: boolean); override;
public public
@ -70,7 +77,7 @@ type
{ TDbgControllerStepIntoLineCmd } { TDbgControllerStepIntoLineCmd }
TDbgControllerStepIntoLineCmd = class(TDbgControllerCmd) TDbgControllerStepIntoLineCmd = class(TDbgControllerHiddenBreakStepCmd)
private private
FStoredStackFrame: TDBGPtr; FStoredStackFrame: TDBGPtr;
FInto: boolean; FInto: boolean;
@ -80,14 +87,12 @@ type
FLastStackPointerValue: TDBGPtr; FLastStackPointerValue: TDBGPtr;
FLastStackBaseValue: TDBGPtr; FLastStackBaseValue: TDBGPtr;
FAssumedProcStartStackPointer: TDBGPtr; FAssumedProcStartStackPointer: TDBGPtr;
FHiddenBreakpoint: TFpInternalBreakpoint;
FInstCount: integer; FInstCount: integer;
protected protected
procedure Init; override; procedure Init; override;
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Handled, Finished: boolean); override; procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Handled, Finished: boolean); override;
public public
constructor Create(AController: TDbgController); override; constructor Create(AController: TDbgController); override;
destructor Destroy; override;
procedure DoContinue(AProcess: TDbgProcess; AThread: TDbgThread); override; procedure DoContinue(AProcess: TDbgProcess; AThread: TDbgThread); override;
end; end;
@ -105,9 +110,8 @@ type
{ TDbgControllerStepOutCmd } { TDbgControllerStepOutCmd }
TDbgControllerStepOutCmd = class(TDbgControllerCmd) TDbgControllerStepOutCmd = class(TDbgControllerHiddenBreakStepCmd)
private private
FHiddenBreakpoint: TFpInternalBreakpoint;
FIsSet: boolean; FIsSet: boolean;
FStepCount: Integer; FStepCount: Integer;
FStepOut: Boolean; FStepOut: Boolean;
@ -120,11 +124,11 @@ type
{ TDbgControllerRunToCmd } { TDbgControllerRunToCmd }
TDbgControllerRunToCmd = class(TDbgControllerCmd) TDbgControllerRunToCmd = class(TDbgControllerHiddenBreakStepCmd)
private private
FHiddenBreakpoint: TFpInternalBreakpoint;
FLocation: TDBGPtrArray; FLocation: TDBGPtrArray;
protected protected
procedure Init; override;
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Handled, Finished: boolean); override; procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Handled, Finished: boolean); override;
public public
constructor Create(AController: TDbgController; ALocation: TDBGPtrArray); constructor Create(AController: TDbgController; ALocation: TDBGPtrArray);
@ -282,6 +286,20 @@ begin
AnEvent := deFinishedStep; AnEvent := deFinishedStep;
end; end;
{ TDbgControllerHiddenBreakStepCmd }
procedure TDbgControllerHiddenBreakStepCmd.RemoveHiddenBreak;
begin
if assigned(FHiddenBreakpoint) then
FreeAndNil(FHiddenBreakpoint);
end;
destructor TDbgControllerHiddenBreakStepCmd.Destroy;
begin
RemoveHiddenBreak;
inherited Destroy;
end;
{ TDbgControllerStepOverInstructionCmd } { TDbgControllerStepOverInstructionCmd }
procedure TDbgControllerStepOverInstructionCmd.DoContinue(AProcess: TDbgProcess; AThread: TDbgThread); procedure TDbgControllerStepOverInstructionCmd.DoContinue(AProcess: TDbgProcess; AThread: TDbgThread);
@ -296,7 +314,7 @@ var
begin begin
assert(FProcess=AProcess, 'TDbgControllerStepOverInstructionCmd.DoContinue: FProcess=AProcess'); assert(FProcess=AProcess, 'TDbgControllerStepOverInstructionCmd.DoContinue: FProcess=AProcess');
if FIsSet then if FHiddenBreakpoint <> nil then
FProcess.Continue(FProcess, FThread, false) FProcess.Continue(FProcess, FThread, false)
else else
begin begin
@ -312,9 +330,7 @@ begin
if CallInstr then if CallInstr then
begin begin
ALocation := AThread.GetInstructionPointerRegisterValue+(PtrUInt(p)-PtrUInt(@codebin)); ALocation := AThread.GetInstructionPointerRegisterValue+(PtrUInt(p)-PtrUInt(@codebin));
if not AProcess.HasBreak(ALocation) then FHiddenBreakpoint := AProcess.AddInternalBreak(ALocation);
FHiddenBreakpoint := AProcess.AddInternalBreak(ALocation);
FIsSet:=true;
end; end;
FProcess.Continue(FProcess, FThread, not CallInstr); FProcess.Continue(FProcess, FThread, not CallInstr);
end; end;
@ -329,11 +345,7 @@ begin
if Finished then if Finished then
begin begin
AnEvent := deFinishedStep; AnEvent := deFinishedStep;
if assigned(FHiddenBreakpoint) then RemoveHiddenBreak;
begin
FController.FCurrentProcess.RemoveBreak(FHiddenBreakpoint);
FHiddenBreakpoint.Free;
end;
end; end;
end; end;
@ -354,16 +366,6 @@ begin
inherited Create(AController); inherited Create(AController);
end; end;
destructor TDbgControllerStepIntoLineCmd.Destroy;
begin
if assigned(FHiddenBreakpoint) then
begin
FController.CurrentProcess.RemoveBreak(FHiddenBreakpoint);
FreeAndNil(FHiddenBreakpoint);
end;
inherited Destroy;
end;
procedure TDbgControllerStepIntoLineCmd.DoContinue(AProcess: TDbgProcess; AThread: TDbgThread); procedure TDbgControllerStepIntoLineCmd.DoContinue(AProcess: TDbgProcess; AThread: TDbgThread);
var var
@ -387,8 +389,7 @@ begin
FInstCount := 0; FInstCount := 0;
ALocation := AThread.GetInstructionPointerRegisterValue+(PtrUInt(p)-PtrUInt(@codebin)); ALocation := AThread.GetInstructionPointerRegisterValue+(PtrUInt(p)-PtrUInt(@codebin));
if not AProcess.HasBreak(ALocation) then FHiddenBreakpoint := AProcess.AddInternalBreak(ALocation);
FHiddenBreakpoint := AProcess.AddInternalBreak(ALocation);
FProcess.Continue(FProcess, FThread, true); FProcess.Continue(FProcess, FThread, true);
exit; exit;
@ -447,8 +448,7 @@ begin
begin begin
FInto:=false; FInto:=false;
FInstCount:=0; FInstCount:=0;
FController.CurrentProcess.RemoveBreak(FHiddenBreakpoint); RemoveHiddenBreak;
FreeAndNil(FHiddenBreakpoint);
end end
else else
begin begin
@ -518,8 +518,7 @@ begin
(FController.NextOnlyStopOnStartLine or (FStoredStackFrame < FController.CurrentThread.GetStackBasePointerRegisterValue))) then (FController.NextOnlyStopOnStartLine or (FStoredStackFrame < FController.CurrentThread.GetStackBasePointerRegisterValue))) then
begin begin
AnEvent:=deInternalContinue; AnEvent:=deInternalContinue;
FHiddenBreakpoint:=nil; RemoveHiddenBreak;
FIsSet:=false;
Finished:=false; Finished:=false;
end; end;
end; end;
@ -539,8 +538,7 @@ begin
if AProcess.ReadAddress(StepOutStackPos, ReturnAddress) then if AProcess.ReadAddress(StepOutStackPos, ReturnAddress) then
begin begin
if not AProcess.HasBreak(ReturnAddress) then FHiddenBreakpoint := AProcess.AddInternalBreak(ReturnAddress)
FHiddenBreakpoint := AProcess.AddInternalBreak(ReturnAddress)
end end
else else
begin begin
@ -609,7 +607,7 @@ begin
// finished. // finished.
Finished := true Finished := true
else if FIsSet then else if FIsSet then
Finished := not (AnEvent in [deInternalContinue, deLoadLibrary]) Finished := (not (AnEvent in [deInternalContinue, deLoadLibrary])) or (FHiddenBreakpoint = nil)
else if (AnEvent in [deBreakpoint]) and not FProcess.HasBreak(FThread.GetInstructionPointerRegisterValue) then else if (AnEvent in [deBreakpoint]) and not FProcess.HasBreak(FThread.GetInstructionPointerRegisterValue) then
// Single-stepping, so continue silently. // Single-stepping, so continue silently.
AnEvent := deInternalContinue; AnEvent := deInternalContinue;
@ -617,10 +615,7 @@ begin
if Finished then if Finished then
begin begin
AnEvent := deFinishedStep; AnEvent := deFinishedStep;
if Assigned(FHiddenBreakpoint) then begin RemoveHiddenBreak;
FProcess.RemoveBreak(FHiddenBreakpoint);
FHiddenBreakpoint.Free;
end;
end; end;
Handled := Finished; Handled := Finished;
end; end;
@ -629,30 +624,29 @@ end;
constructor TDbgControllerRunToCmd.Create(AController: TDbgController; ALocation: TDBGPtrArray); constructor TDbgControllerRunToCmd.Create(AController: TDbgController; ALocation: TDBGPtrArray);
begin begin
inherited create(AController);
FLocation:=ALocation; FLocation:=ALocation;
inherited create(AController);
end; end;
procedure TDbgControllerRunToCmd.DoContinue(AProcess: TDbgProcess; AThread: TDbgThread); procedure TDbgControllerRunToCmd.DoContinue(AProcess: TDbgProcess; AThread: TDbgThread);
begin begin
assert(FProcess=AProcess, 'TDbgControllerRunToCmd.DoContinue: FProcess=AProcess'); assert(FProcess=AProcess, 'TDbgControllerRunToCmd.DoContinue: FProcess=AProcess');
if not assigned(FHiddenBreakpoint) then // and not AProcess.HasBreak(FLocation)
FHiddenBreakpoint := AProcess.AddInternalBreak(FLocation)
else
debugln(DBG_WARNINGS, 'TDbgControllerRunToCmd.DoContinue: Breakpoint already used');
FProcess.Continue(FProcess, FThread, False); FProcess.Continue(FProcess, FThread, False);
end; end;
procedure TDbgControllerRunToCmd.Init;
begin
inherited Init;
FHiddenBreakpoint := FProcess.AddInternalBreak(FLocation);
end;
procedure TDbgControllerRunToCmd.DoResolveEvent(var AnEvent: TFPDEvent; procedure TDbgControllerRunToCmd.DoResolveEvent(var AnEvent: TFPDEvent;
AnEventThread: TDbgThread; out Handled, Finished: boolean); AnEventThread: TDbgThread; out Handled, Finished: boolean);
begin begin
Finished := (AnEvent<>deInternalContinue); Finished := (AnEvent<>deInternalContinue);
Handled := Finished; Handled := Finished;
if Finished and assigned(FHiddenBreakpoint) then if Finished then begin
begin RemoveHiddenBreak;
FProcess.RemoveBreak(FHiddenBreakpoint);
FHiddenBreakpoint.Free;
AnEvent := deFinishedStep; AnEvent := deFinishedStep;
end; end;
end; end;