mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-05 14:18:18 +02:00
FpDebug: Detect internal forwarding jumps, and avoid stopping at them
git-svn-id: trunk@63033 -
This commit is contained in:
parent
944fd0d817
commit
ea30b6f6b9
@ -405,6 +405,7 @@ type
|
||||
function IsCallInstruction: boolean; virtual;
|
||||
function IsReturnInstruction: boolean; virtual;
|
||||
function IsLeaveStackFrame: boolean; virtual;
|
||||
function IsJumpInstruction(IncludeConditional: Boolean = True; IncludeUncoditional: Boolean = True): boolean; virtual;
|
||||
function InstructionLength: Integer; virtual;
|
||||
end;
|
||||
|
||||
@ -1294,6 +1295,12 @@ begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TDbgAsmInstruction.IsJumpInstruction(IncludeConditional: Boolean;
|
||||
IncludeUncoditional: Boolean): boolean;
|
||||
begin
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TDbgAsmInstruction.InstructionLength: Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
|
@ -79,6 +79,8 @@ type
|
||||
FIsSteppedOut: Boolean;
|
||||
FHiddenBreakpoint: TFpInternalBreakpoint;
|
||||
FHiddenBreakAddr, FHiddenBreakInstrPtr, FHiddenBreakFrameAddr, FHiddenBreakStackPtrAddr: TDBGPtr;
|
||||
FWasAtJumpInstruction: Boolean;
|
||||
FJumpPadCount: Integer;
|
||||
function GetIsSteppedOut: Boolean;
|
||||
protected
|
||||
function IsAtHiddenBreak: Boolean; inline;
|
||||
@ -88,6 +90,8 @@ type
|
||||
procedure SetHiddenBreak(AnAddr: TDBGPtr);
|
||||
procedure RemoveHiddenBreak;
|
||||
function CheckForCallAndSetBreak: boolean; // True, if break is newly set
|
||||
procedure StoreWasAtJumpInstruction;
|
||||
function IsAtJumpPad: Boolean;
|
||||
|
||||
procedure Init; override;
|
||||
procedure InternalContinue(AProcess: TDbgProcess; AThread: TDbgThread); virtual; abstract;
|
||||
@ -477,6 +481,22 @@ begin
|
||||
{$POP}
|
||||
end;
|
||||
|
||||
procedure TDbgControllerHiddenBreakStepBaseCmd.StoreWasAtJumpInstruction;
|
||||
begin
|
||||
FWasAtJumpInstruction := NextInstruction.IsJumpInstruction;
|
||||
end;
|
||||
|
||||
function TDbgControllerHiddenBreakStepBaseCmd.IsAtJumpPad: Boolean;
|
||||
begin
|
||||
Result := FWasAtJumpInstruction and
|
||||
NextInstruction.IsJumpInstruction(False) and
|
||||
not FController.FCurrentThread.IsAtStartOfLine; // TODO: check for lines with line=0
|
||||
if Result then
|
||||
inc(FJumpPadCount);
|
||||
if FJumpPadCount > 2 then
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
procedure TDbgControllerHiddenBreakStepBaseCmd.Init;
|
||||
begin
|
||||
FStoredStackPointer := FThread.GetStackPointerRegisterValue;
|
||||
@ -499,6 +519,8 @@ begin
|
||||
r := NextInstruction.IsReturnInstruction
|
||||
else
|
||||
r := False;
|
||||
|
||||
FWasAtJumpInstruction := False;
|
||||
InternalContinue(AProcess, AThread);
|
||||
if r and
|
||||
(FHiddenBreakpoint = nil)
|
||||
@ -621,6 +643,8 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
if FState <> siRunningStepOut then
|
||||
StoreWasAtJumpInstruction;
|
||||
FProcess.Continue(FProcess, FThread, FState <> siRunningStepOut);
|
||||
end;
|
||||
|
||||
@ -644,6 +668,8 @@ begin
|
||||
|
||||
if (FState = siSteppingCurrent) then begin
|
||||
Finished := HasSteppedAwayFromOriginLine;
|
||||
if Finished then
|
||||
Finished := not IsAtJumpPad;
|
||||
end
|
||||
else begin
|
||||
// we stepped into
|
||||
@ -689,6 +715,9 @@ begin
|
||||
assert(FProcess=AProcess, 'TDbgControllerStepOverLineCmd.DoContinue: FProcess=AProcess');
|
||||
if (AThread = FThread) then
|
||||
CheckForCallAndSetBreak;
|
||||
|
||||
if FHiddenBreakpoint = nil then
|
||||
StoreWasAtJumpInstruction;
|
||||
FProcess.Continue(FProcess, FThread, FHiddenBreakpoint = nil);
|
||||
end;
|
||||
|
||||
@ -710,10 +739,14 @@ begin
|
||||
if IsAtOrOutOfHiddenBreakFrame then
|
||||
RemoveHiddenBreak;
|
||||
|
||||
if FHiddenBreakpoint <> nil then
|
||||
Finished := False
|
||||
else
|
||||
if FHiddenBreakpoint <> nil then begin
|
||||
Finished := False;
|
||||
end
|
||||
else begin
|
||||
Finished := HasSteppedAwayFromOriginLine;
|
||||
if Finished then
|
||||
Finished := not IsAtJumpPad;
|
||||
end;
|
||||
|
||||
if Finished then
|
||||
AnEvent := deFinishedStep
|
||||
|
@ -224,6 +224,7 @@ type
|
||||
function IsCallInstruction: boolean; override;
|
||||
function IsReturnInstruction: boolean; override;
|
||||
function IsLeaveStackFrame: boolean; override;
|
||||
function IsJumpInstruction(IncludeConditional: Boolean = True; IncludeUncoditional: Boolean = True): boolean; override;
|
||||
function InstructionLength: Integer; override;
|
||||
function X86OpCode: TOpCode;
|
||||
property X86Instruction: TInstruction read FInstruction; // only valid after call to X86OpCode
|
||||
@ -446,6 +447,36 @@ begin
|
||||
Result := (FInstruction.OpCode = OPleave);
|
||||
end;
|
||||
|
||||
function TX86AsmInstruction.IsJumpInstruction(IncludeConditional: Boolean;
|
||||
IncludeUncoditional: Boolean): boolean;
|
||||
var
|
||||
a: PByte;
|
||||
begin
|
||||
(* Excluding
|
||||
E1, E2 loop
|
||||
E3 JCXZ Jump short if eCX register is 0
|
||||
*)
|
||||
Result := False;
|
||||
ReadCode;
|
||||
if diCodeReadError in FFlags then
|
||||
exit;
|
||||
a := @FCodeBin[0];
|
||||
|
||||
if IncludeConditional and (a^ in [$70..$7F]) then
|
||||
exit(True);
|
||||
if IncludeConditional and (a^ = $0F) and (a[1] in [$80..$8F]) then
|
||||
exit(True);
|
||||
|
||||
if IncludeUncoditional and (a^ in [$E9..$EB]) then
|
||||
exit(True);
|
||||
|
||||
if IncludeUncoditional and (a^ in [$FF]) then begin
|
||||
Disassemble;
|
||||
exit(FInstruction.OpCode = OPjmp);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
function TX86AsmInstruction.InstructionLength: Integer;
|
||||
begin
|
||||
Disassemble;
|
||||
|
Loading…
Reference in New Issue
Block a user