LazDebuggerFp: Handle Win32-SEH for step-in/out/over

(cherry picked from commit 6e5c00bb59)
This commit is contained in:
Martin 2021-12-10 20:51:46 +01:00
parent 08764bb5db
commit 65133dd1cd

View File

@ -191,14 +191,14 @@ type
TDbgControllerStepThroughFpcSpecialHandler = class(TDbgControllerStepOverInstructionCmd) TDbgControllerStepThroughFpcSpecialHandler = class(TDbgControllerStepOverInstructionCmd)
private private
FAfterFinCallAddr: TDbgPtr; FAfterFinCallAddr: TDbgPtr;
FDone: Boolean; FDone, FIsLeave: Boolean;
FInteralFinished: Boolean; FInteralFinished: Boolean;
protected protected
procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); override; procedure DoResolveEvent(var AnEvent: TFPDEvent; AnEventThread: TDbgThread; out Finished: boolean); override;
procedure InternalContinue(AProcess: TDbgProcess; AThread: TDbgThread); override; procedure InternalContinue(AProcess: TDbgProcess; AThread: TDbgThread); override;
procedure Init; override; procedure Init; override;
public public
constructor Create(AController: TDbgController; AnAfterFinCallAddr: TDbgPtr); reintroduce; constructor Create(AController: TDbgController; AnAfterFinCallAddr: TDbgPtr; AnIsLeave: Boolean); reintroduce;
property InteralFinished: Boolean read FInteralFinished; property InteralFinished: Boolean read FInteralFinished;
end; end;
@ -220,6 +220,14 @@ type
bplRtlUnwind, bplFpcSpecific, bplRtlRestoreContext, bplRtlUnwind, bplFpcSpecific, bplRtlRestoreContext,
bplSehW64Finally, bplSehW64Except, bplSehW64Unwound, bplSehW64Finally, bplSehW64Except, bplSehW64Unwound,
{$ENDIF} {$ENDIF}
{$IFDEF MSWINDOWS} // 32 bit or WOW
bplFpcExceptHandler,
bplFpcFinallyHandler,
bplFpcLeaveHandler,
bplSehW32Except,
bplSehW32Finally,
{$ENDIF}
bplStepOut // Step out of Pop/Catches bplStepOut // Step out of Pop/Catches
); );
TBreakPointLocs = set of TBreakPointLoc; TBreakPointLocs = set of TBreakPointLoc;
@ -257,8 +265,14 @@ type
FBreakPoints: array[TBreakPointLoc] of TFpDbgBreakpoint; FBreakPoints: array[TBreakPointLoc] of TFpDbgBreakpoint;
FBreakEnabled: TBreakPointLocs; FBreakEnabled: TBreakPointLocs;
FBreakNewEnabled: TBreakPointLocs; FBreakNewEnabled: TBreakPointLocs;
{$IFDEF WIN64}
FAddressFrameListSehW64Except, FAddressFrameListSehW64Except,
FAddressFrameListSehW64Finally: TAddressFrameList; FAddressFrameListSehW64Finally: TAddressFrameList;
{$ENDIF}
{$IFDEF MSWINDOWS}
FAddressFrameListSehW32Except: TAddressFrameList;
FAddressFrameListSehW32Finally: TAddressFrameList;
{$ENDIF}
FState: TExceptStepState; FState: TExceptStepState;
function GetCurrentCommand: TDbgControllerCmd; inline; function GetCurrentCommand: TDbgControllerCmd; inline;
function GetCurrentProcess: TDbgProcess; inline; function GetCurrentProcess: TDbgProcess; inline;
@ -1172,19 +1186,29 @@ var
Instr: TDbgAsmInstruction; Instr: TDbgAsmInstruction;
begin begin
{ {
32bit
00000000004321D3 89E8 mov eax,ebp
00000000004321D5 E866FEFFFF call -$0000019A
64bit
00000001000374AE 4889C1 mov rcx,rax 00000001000374AE 4889C1 mov rcx,rax
00000001000374B1 488D15D3FFFFFF lea rdx,[rip-$0000002D] 00000001000374B1 488D15D3FFFFFF lea rdx,[rip-$0000002D]
00000001000374B8 4989E8 mov rax,rbp 00000001000374B8 4989E8 mov rax,rbp
00000001000374BB E89022FEFF call -$0001DD70 00000001000374BB E89022FEFF call -$0001DD70
} }
if (AThread = FThread) then begin if (AThread = FThread) then begin
Instr := NextInstruction; Instr := NextInstruction;
if Instr is TX86AsmInstruction then begin if Instr is TX86AsmInstruction then begin
case TX86AsmInstruction(Instr).X86OpCode of case TX86AsmInstruction(Instr).X86OpCode of
OPmov: OPmov:
if CompareText(TX86AsmInstruction(Instr).X86Instruction.Operand[2].Value, 'RBP') = 0 then if FProcess.Mode = dm32 then begin
FFinState := fsMov; if CompareText(TX86AsmInstruction(Instr).X86Instruction.Operand[2].Value, 'EBP') = 0 then
FFinState := fsMov;
end
else begin
if CompareText(TX86AsmInstruction(Instr).X86Instruction.Operand[2].Value, 'RBP') = 0 then
FFinState := fsMov;
end;
OPcall: OPcall:
if FFinState = fsMov then begin if FFinState = fsMov then begin
CheckForCallAndSetBreak; CheckForCallAndSetBreak;
@ -1239,8 +1263,12 @@ begin
RemoveHiddenBreak; RemoveHiddenBreak;
FInteralFinished := IsSteppedOut or FDone or ((not HasHiddenBreak) and (NextInstruction.IsReturnInstruction)); FInteralFinished := IsSteppedOut or FDone or ((not HasHiddenBreak) and (NextInstruction.IsReturnInstruction));
if FInteralFinished then if FInteralFinished then begin
RemoveHiddenBreak; RemoveHiddenBreak;
Finished := FIsLeave;
if Finished then
AnEvent := deFinishedStep;
end;
end; end;
procedure TDbgControllerStepThroughFpcSpecialHandler.InternalContinue( procedure TDbgControllerStepThroughFpcSpecialHandler.InternalContinue(
@ -1273,9 +1301,10 @@ begin
end; end;
constructor TDbgControllerStepThroughFpcSpecialHandler.Create( constructor TDbgControllerStepThroughFpcSpecialHandler.Create(
AController: TDbgController; AnAfterFinCallAddr: TDbgPtr); AController: TDbgController; AnAfterFinCallAddr: TDbgPtr; AnIsLeave: Boolean);
begin begin
FAfterFinCallAddr := AnAfterFinCallAddr; FAfterFinCallAddr := AnAfterFinCallAddr;
FIsLeave := AnIsLeave;
inherited Create(AController); inherited Create(AController);
end; end;
@ -2404,15 +2433,27 @@ end;
constructor TFpDebugExceptionStepping.Create(ADebugger: TFpDebugDebugger); constructor TFpDebugExceptionStepping.Create(ADebugger: TFpDebugDebugger);
begin begin
FDebugger := ADebugger; FDebugger := ADebugger;
{$IFDEF WIN64}
FAddressFrameListSehW64Except := TAddressFrameList.Create(True); FAddressFrameListSehW64Except := TAddressFrameList.Create(True);
FAddressFrameListSehW64Finally := TAddressFrameList.Create(True); FAddressFrameListSehW64Finally := TAddressFrameList.Create(True);
{$ENDIF}
{$IFDEF MSWINDOWS}
FAddressFrameListSehW32Except:= TAddressFrameList.Create(True);
FAddressFrameListSehW32Finally:= TAddressFrameList.Create(True);
{$ENDIF}
end; end;
destructor TFpDebugExceptionStepping.Destroy; destructor TFpDebugExceptionStepping.Destroy;
begin begin
inherited Destroy; inherited Destroy;
{$IFDEF WIN64}
FAddressFrameListSehW64Except.Destroy; FAddressFrameListSehW64Except.Destroy;
FAddressFrameListSehW64Finally.Destroy; FAddressFrameListSehW64Finally.Destroy;
{$ENDIF}
{$IFDEF MSWINDOWS}
FAddressFrameListSehW32Except.Destroy;
FAddressFrameListSehW32Finally.Destroy;
{$ENDIF}
end; end;
procedure TFpDebugExceptionStepping.DoProcessLoaded; procedure TFpDebugExceptionStepping.DoProcessLoaded;
@ -2426,24 +2467,38 @@ begin
FBreakPoints[bplReRaise] := FDebugger.AddBreak('FPC_RERAISE', nil, False); FBreakPoints[bplReRaise] := FDebugger.AddBreak('FPC_RERAISE', nil, False);
FBreakPoints[bplPopExcept] := FDebugger.AddBreak('FPC_POPADDRSTACK', nil, False); FBreakPoints[bplPopExcept] := FDebugger.AddBreak('FPC_POPADDRSTACK', nil, False);
FBreakPoints[bplCatches] := FDebugger.AddBreak('FPC_CATCHES', nil, False); FBreakPoints[bplCatches] := FDebugger.AddBreak('FPC_CATCHES', nil, False);
{$IFDEF MSWINDOWS}
if CurrentProcess.Mode = dm32 then begin
FBreakPoints[bplFpcExceptHandler] := FDebugger.AddBreak('__FPC_except_handler', nil, False);
FBreakPoints[bplFpcFinallyHandler] := FDebugger.AddBreak('__FPC_finally_handler', nil, False);
FBreakPoints[bplFpcLeaveHandler] := FDebugger.AddBreak('_FPC_leave', nil, False);
FBreakPoints[bplSehW32Except] := FDebugger.AddBreak(0, False);
FBreakPoints[bplSehW32Finally] := FDebugger.AddBreak(0, False);
{$IfDef WIN64} {$IfDef WIN64}
FBreakPoints[bplFpcSpecific] := FDebugger.AddBreak('__FPC_specific_handler', nil, False); end
FBreakPoints[bplSehW64Except] := FDebugger.AddBreak(0, False); else
FBreakPoints[bplSehW64Finally] := FDebugger.AddBreak(0, False); if CurrentProcess.Mode = dm64 then begin
FBreakPoints[bplSehW64Unwound] := FDebugger.AddBreak(0, False); FBreakPoints[bplFpcSpecific] := FDebugger.AddBreak('__FPC_specific_handler', nil, False);
FBreakPoints[bplSehW64Except] := FDebugger.AddBreak(0, False);
FBreakPoints[bplSehW64Finally] := FDebugger.AddBreak(0, False);
FBreakPoints[bplSehW64Unwound] := FDebugger.AddBreak(0, False);
{$EndIf} {$EndIf}
end;
{$ENDIF}
debuglnExit(DBG_BREAKPOINTS, ['<< TFpDebugDebugger.SetSoftwareExceptionBreakpoint ' ]); debuglnExit(DBG_BREAKPOINTS, ['<< TFpDebugDebugger.SetSoftwareExceptionBreakpoint ' ]);
end; end;
procedure TFpDebugExceptionStepping.DoNtDllLoaded(ALib: TDbgLibrary); procedure TFpDebugExceptionStepping.DoNtDllLoaded(ALib: TDbgLibrary);
begin begin
{$IFDEF WIN64} {$IFDEF WIN64}
debugln(DBG_BREAKPOINTS, ['SetSoftwareExceptionBreakpoint RtlUnwind']); if CurrentProcess.Mode = dm64 then begin
DisableBreaksDirect([bplRtlUnwind, bplRtlRestoreContext]); debugln(DBG_BREAKPOINTS, ['SetSoftwareExceptionBreakpoint RtlUnwind']);
FreeAndNil(FBreakPoints[bplRtlRestoreContext]); DisableBreaksDirect([bplRtlUnwind, bplRtlRestoreContext]);
FBreakPoints[bplRtlRestoreContext] := FDebugger.AddBreak('RtlRestoreContext', ALib, False); FreeAndNil(FBreakPoints[bplRtlRestoreContext]);
FBreakPoints[bplRtlUnwind].Free; FBreakPoints[bplRtlRestoreContext] := FDebugger.AddBreak('RtlRestoreContext', ALib, False);
FBreakPoints[bplRtlUnwind] := FDebugger.AddBreak('RtlUnwindEx', ALib, False); FBreakPoints[bplRtlUnwind].Free;
FBreakPoints[bplRtlUnwind] := FDebugger.AddBreak('RtlUnwindEx', ALib, False);
end;
{$ENDIF} {$ENDIF}
end; end;
@ -2484,11 +2539,11 @@ procedure TFpDebugExceptionStepping.ThreadProcessLoopCycle(
Result := TDbgControllerHiddenBreakStepBaseCmd(CurrentCommand).StoredStackFrameInfo.StoredStackFrame <= AFrameAddr; Result := TDbgControllerHiddenBreakStepBaseCmd(CurrentCommand).StoredStackFrameInfo.StoredStackFrame <= AFrameAddr;
end; end;
{$IFDEF WIN64} {$IFDEF MSWINDOWS}
procedure CheckSteppedOutFromW64SehFinally; procedure CheckSteppedOutFromW64SehFinally;
var var
sym: TFpSymbol; sym: TFpSymbol;
r: Boolean; r, IsLeave: Boolean;
begin begin
if (FState <> esNone) or (not(ACurCommand is TDbgControllerLineStepBaseCmd)) then if (FState <> esNone) or (not(ACurCommand is TDbgControllerLineStepBaseCmd)) then
exit; exit;
@ -2497,20 +2552,30 @@ procedure TFpDebugExceptionStepping.ThreadProcessLoopCycle(
exit; exit;
if (not TDbgControllerLineStepBaseCmd(ACurCommand).IsSteppedOut) then begin if (not TDbgControllerLineStepBaseCmd(ACurCommand).IsSteppedOut) then begin
{$IFDEF WIN64}
EnableBreaksDirect([bplFpcSpecific]); EnableBreaksDirect([bplFpcSpecific]);
{$ENDIF}
exit; exit;
end; end;
IsLeave := False;
sym := CurrentProcess.FindProcSymbol(CurrentThread.GetInstructionPointerRegisterValue); sym := CurrentProcess.FindProcSymbol(CurrentThread.GetInstructionPointerRegisterValue);
r := (sym <> nil) and (CompareText(sym.Name, '__FPC_SPECIFIC_HANDLER') <> 0) and if CurrentProcess.Mode = dm32 then begin
(sym.FileName <> ''); IsLeave := (CompareText(sym.Name, '_FPC_LEAVE') = 0);
r := (sym <> nil) and (sym.FileName <> '') and
(not IsLeave) and
(CompareText(sym.Name, '__FPC_FINALLY_HANDLER') <> 0);
end
else
r := (sym <> nil) and (CompareText(sym.Name, '__FPC_SPECIFIC_HANDLER') <> 0) and
(sym.FileName <> '');
sym.ReleaseReference; sym.ReleaseReference;
if r then if r then
exit; exit;
FState := esSteppingFpcSpecialHandler; FState := esSteppingFpcSpecialHandler;
AFinishLoopAndSendEvents := False; AFinishLoopAndSendEvents := False;
ACurCommand := TDbgControllerStepThroughFpcSpecialHandler.Create(DbgController, CurrentThread.GetInstructionPointerRegisterValue); ACurCommand := TDbgControllerStepThroughFpcSpecialHandler.Create(DbgController, CurrentThread.GetInstructionPointerRegisterValue, IsLeave);
end; end;
{$ENDIF} {$ENDIF}
@ -2523,13 +2588,17 @@ procedure TFpDebugExceptionStepping.ThreadProcessLoopCycle(
const const
MaxFinallyHandlerCnt = 256; // more finally in a single proc is not probable.... MaxFinallyHandlerCnt = 256; // more finally in a single proc is not probable....
var var
StepOutStackPos, ReturnAddress, Base, Addr, PC: TDBGPtr; StepOutStackPos, ReturnAddress, PC: TDBGPtr;
{$IFDEF WIN64} {$IFDEF WIN64}
Rdx, Rcx, R8, R9, SP, TargetSp, HData, ImgBase: TDBGPtr; Rdx, Rcx, R8, R9, TargetSp, HData, ImgBase: TDBGPtr;
i: Integer; i: Integer;
EFlags, Cnt: Cardinal; EFlags, Cnt: Cardinal;
FinallyData: Array of array [0..3] of DWORD; //TScopeRec FinallyData: Array of array [0..3] of DWORD; //TScopeRec
{$ENDIF} {$ENDIF}
{$IFDEF MSWINDOWS}
Base, Addr, SP: TDBGPtr;
Eax: TDBGPtr;
{$ENDIF}
o: Integer; o: Integer;
Frames: TFrameList; Frames: TFrameList;
n: String; n: String;
@ -2571,11 +2640,14 @@ begin
end; end;
{$ENDIF} {$ENDIF}
{$IFDEF WIN64}
if (FState = esSteppingFpcSpecialHandler) and if (FState = esSteppingFpcSpecialHandler) and
(ACurCommand is TDbgControllerStepThroughFpcSpecialHandler) and (ACurCommand is TDbgControllerStepThroughFpcSpecialHandler) and
(TDbgControllerStepThroughFpcSpecialHandler(ACurCommand).InteralFinished) (TDbgControllerStepThroughFpcSpecialHandler(ACurCommand).InteralFinished)
then begin then begin
if AnIsFinished then begin
exit; // stepped out of _FPC_LEAVE;
end
else
if TDbgControllerStepThroughFpcSpecialHandler(ACurCommand).FDone then begin if TDbgControllerStepThroughFpcSpecialHandler(ACurCommand).FDone then begin
FState := esNone; FState := esNone;
if ACurCommand.Thread = CurrentThread then if ACurCommand.Thread = CurrentThread then
@ -2592,9 +2664,8 @@ begin
exit; exit;
end end
else else
{$ENDIF}
if CurrentProcess.CurrentBreakpoint = nil then begin if CurrentProcess.CurrentBreakpoint = nil then begin
{$IFDEF WIN64} {$IFDEF MSWINDOWS}
CheckSteppedOutFromW64SehFinally; CheckSteppedOutFromW64SehFinally;
{$ENDIF} {$ENDIF}
exit; exit;
@ -2603,8 +2674,10 @@ begin
DisableBreaksDirect([bplRtlUnwind, bplSehW64Finally]); // bplRtlUnwind must always be unset; DisableBreaksDirect([bplRtlUnwind, bplSehW64Finally]); // bplRtlUnwind must always be unset;
{$ENDIF} {$ENDIF}
{$IFDEF WIN64} {$IFDEF MSWINDOWS}
SP := CurrentThread.GetStackPointerRegisterValue; SP := CurrentThread.GetStackPointerRegisterValue;
{$ENDIF}
{$IFDEF WIN64}
FAddressFrameListSehW64Except.RemoveOutOfScopeFrames(SP, FBreakPoints[bplSehW64Except]); FAddressFrameListSehW64Except.RemoveOutOfScopeFrames(SP, FBreakPoints[bplSehW64Except]);
if ACurCommand is TDbgControllerStepOutCmd then if ACurCommand is TDbgControllerStepOutCmd then
FAddressFrameListSehW64Finally.RemoveOutOfScopeFrames(SP+1, FBreakPoints[bplSehW64Finally]) // include current frame FAddressFrameListSehW64Finally.RemoveOutOfScopeFrames(SP+1, FBreakPoints[bplSehW64Finally]) // include current frame
@ -2674,6 +2747,114 @@ begin
// if not(FState = esStepToFinally) then // if not(FState = esStepToFinally) then
FState := esIgnoredRaise; FState := esIgnoredRaise;
end end
{$IFDEF MSWINDOWS}
(* ***** Win32 SEH Except ***** *)
else
if assigned(FBreakPoints[bplSehW32Except]) and FBreakPoints[bplSehW32Except].HasLocation(PC) then begin
debugln(FPDBG_COMMANDS, ['@ bplSehW32Except ', DbgSName(CurrentCommand)]);
AFinishLoopAndSendEvents := False;
//if (not (FState in [esStepToFinally])) and
// not(CurrentCommand is TDbgControllerHiddenBreakStepBaseCmd)
//then
// exit; // wrong command type / should not happen
if (FState = esIgnoredRaise) and
(not CheckCommandFinishesInFrame(CurrentThread.GetStackBasePointerRegisterValue))
then
exit;
AFinishLoopAndSendEvents := True; // Stop at this address
FState := esAtWSehExcept;
AnIsFinished := True;
AnEventType := deFinishedStep;
end
(* ***** Win32 SEH Finally ***** *)
else
if assigned(FBreakPoints[bplSehW32Finally]) and FBreakPoints[bplSehW32Finally].HasLocation(PC) then begin
debugln(FPDBG_COMMANDS, ['@ bplSehW32Finally ', DbgSName(CurrentCommand)]);
AFinishLoopAndSendEvents := False;
// At the start of a finally the BasePointer is in EAX // reg 0
Eax := CurrentThread.RegisterValueList.FindRegisterByDwarfIndex(0).NumValue;
FAddressFrameListSehW32Finally.RemoveOutOfScopeFrames(EAX, FBreakPoints[bplSehW32Finally]);
if (ACurCommand is TDbgControllerLineStepBaseCmd) and
not CheckCommandFinishesInFrame(Eax)
then
exit;
// step over proloque
ACurCommand := TDbgControllerStepOverFirstFinallyLineCmd.Create(DbgController);
FState := esStepSehFinallyProloque;
end
else
(* ***** Win32 SEH ExceptHandler ***** *)
if assigned(FBreakPoints[bplFpcExceptHandler]) and FBreakPoints[bplFpcExceptHandler].HasLocation(PC) then begin
debugln(FPDBG_COMMANDS, ['@ bplFpcExceptHandler ', DbgSName(CurrentCommand)]);
AFinishLoopAndSendEvents := False;
AnIsFinished := False;
(* TSEHFrame=record
Next: PSEHFrame;
Addr: Pointer;
_EBP: PtrUint;
HandlerArg: Pointer;
end;
*)
{$PUSH}{$Q-}{$R-}
if (not CurrentProcess.ReadAddress(SP + 8, Addr)) or (Addr = 0) then
exit;
if (not CurrentProcess.ReadAddress(Addr + 12, Addr)) or (Addr = 0) then
exit;
CurrentProcess.ReadAddress(Addr + 8, Base);
{$POP}
if Base <> 0 then
FAddressFrameListSehW32Except.Add(Addr, Base);
FBreakPoints[bplSehW32Except].AddAddress(Addr);
FBreakPoints[bplSehW32Except].SetBreak;
end
else
(* ***** Win32 SEH FinallyHandler ***** *)
if assigned(FBreakPoints[bplFpcFinallyHandler]) and FBreakPoints[bplFpcFinallyHandler].HasLocation(PC) then begin
debugln(FPDBG_COMMANDS, ['@ bplFpcFinallyHandler ', DbgSName(CurrentCommand)]);
AFinishLoopAndSendEvents := False;
AnIsFinished := False;
{$PUSH}{$Q-}{$R-}
if (not CurrentProcess.ReadAddress(SP + 8, Addr)) or (Addr = 0) then
exit;
if (not CurrentProcess.ReadAddress(Addr + 12, Addr)) or (Addr = 0) then
exit;
CurrentProcess.ReadAddress(Addr + 8, Base);
{$POP}
if Base <> 0 then
FAddressFrameListSehW32Finally.Add(Addr, Base);
FBreakPoints[bplSehW32Finally].AddAddress(Addr);
FBreakPoints[bplSehW32Finally].SetBreak;
end
else
(* ***** Win32 SEH LeaveHandler ***** *)
if assigned(FBreakPoints[bplFpcLeaveHandler]) and FBreakPoints[bplFpcLeaveHandler].HasLocation(PC) then begin
debugln(FPDBG_COMMANDS, ['@ bplFpcLeaveHandler ', DbgSName(CurrentCommand)]);
AFinishLoopAndSendEvents := False;
AnIsFinished := False;
{$PUSH}{$Q-}{$R-}
if (not CurrentProcess.ReadAddress(SP + 16, Addr)) or (Addr = 0) then
exit;
CurrentProcess.ReadAddress(Addr + 4, Base);
{$POP}
if Base <> 0 then
FAddressFrameListSehW32Finally.Add(Addr, Base);
FBreakPoints[bplSehW32Finally].AddAddress(Addr);
FBreakPoints[bplSehW32Finally].SetBreak;
end
{$ENDIF}
{$IFDEF WIN64} {$IFDEF WIN64}
else else
(* ***** Win64 SEH ***** *) (* ***** Win64 SEH ***** *)
@ -2832,6 +3013,8 @@ begin
ACurCommand := TDbgControllerStepOverFirstFinallyLineCmd.Create(DbgController); ACurCommand := TDbgControllerStepOverFirstFinallyLineCmd.Create(DbgController);
FState := esStepSehFinallyProloque; FState := esStepSehFinallyProloque;
end end
{$ENDIF}
{$IFDEF MSWINDOWS}
else else
CheckSteppedOutFromW64SehFinally CheckSteppedOutFromW64SehFinally
{$ENDIF} {$ENDIF}
@ -2884,13 +3067,21 @@ begin
st := FState; st := FState;
FState := esNone; FState := esNone;
DisableBreaks([bplPopExcept, bplCatches, bplReRaise, DisableBreaks([bplPopExcept, bplCatches, bplReRaise,
{$IFDEF MSWINDOWS}
{$IFDEF WIN64} {$IFDEF WIN64}
bplFpcSpecific, bplRtlRestoreContext, bplRtlUnwind, bplFpcSpecific, bplRtlRestoreContext, bplRtlUnwind,
{$ENDIF} {$ENDIF}
bplFpcExceptHandler ,bplFpcFinallyHandler, bplFpcLeaveHandler,
{$ENDIF}
bplStepOut]); bplStepOut]);
if ACommand in [dcStepInto, dcStepOver, dcStepOut, dcStepTo, dcRunTo, dcStepOverInstr{, dcStepIntoInstr}] then if ACommand in [dcStepInto, dcStepOver, dcStepOut, dcStepTo, dcRunTo, dcStepOverInstr{, dcStepIntoInstr}] then
EnableBreaks([bplReRaise{$IFDEF WIN64} , bplRtlRestoreContext, bplFpcSpecific {$ENDIF}]); EnableBreaks([bplReRaise
{$IFDEF MSWINDOWS}
{$IFDEF WIN64} , bplRtlRestoreContext, bplFpcSpecific {$ENDIF}
, bplFpcExceptHandler ,bplFpcFinallyHandler, bplFpcLeaveHandler
{$ENDIF}
]);
case st of case st of
esStoppedAtRaise: begin esStoppedAtRaise: begin
@ -2898,7 +3089,12 @@ begin
FState := esStepToFinally; FState := esStepToFinally;
ACommand := dcRun; ACommand := dcRun;
FDebugger.FDbgController.&ContinueRun; FDebugger.FDbgController.&ContinueRun;
EnableBreaks([bplPopExcept, bplCatches{$IFDEF WIN64} , bplFpcSpecific {$ENDIF}]); EnableBreaks([bplPopExcept, bplCatches
{$IFDEF MSWINDOWS}
{$IFDEF WIN64} , bplFpcSpecific {$ENDIF}
, bplFpcExceptHandler ,bplFpcFinallyHandler, bplFpcLeaveHandler
{$ENDIF}
]);
end end
end; end;
end; end;