mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 02:59:17 +02:00
LazDebuggerFp: Win64 -Monitor RtlRestoreContext to catch more unwind cases.
This commit is contained in:
parent
269079e11a
commit
c90fb08f85
@ -32,7 +32,7 @@ unit FpDebugDebugger;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, fgl, math, process,
|
Classes, {$IfDef WIN64}windows,{$EndIf} SysUtils, fgl, math, process,
|
||||||
Forms, Dialogs, syncobjs,
|
Forms, Dialogs, syncobjs,
|
||||||
Maps, LazLoggerBase, LazUTF8, lazCollections,
|
Maps, LazLoggerBase, LazUTF8, lazCollections,
|
||||||
DbgIntfBaseTypes, DbgIntfDebuggerBase,
|
DbgIntfBaseTypes, DbgIntfDebuggerBase,
|
||||||
@ -216,8 +216,8 @@ type
|
|||||||
TBreakPointLoc = (
|
TBreakPointLoc = (
|
||||||
bplRaise, bplReRaise, bplBreakError, bplRunError,
|
bplRaise, bplReRaise, bplBreakError, bplRunError,
|
||||||
bplPopExcept, bplCatches,
|
bplPopExcept, bplCatches,
|
||||||
bplRtlUnwind, bplFpcSpecific,
|
bplRtlUnwind, bplFpcSpecific, bplRtlRestoreContext,
|
||||||
bplSehW64Finally, bplSehW64Except,
|
bplSehW64Finally, bplSehW64Except, bplSehW64Unwound,
|
||||||
bplStepOut // Step out of Pop/Catches
|
bplStepOut // Step out of Pop/Catches
|
||||||
);
|
);
|
||||||
TBreakPointLocs = set of TBreakPointLoc;
|
TBreakPointLocs = set of TBreakPointLoc;
|
||||||
@ -2439,13 +2439,18 @@ begin
|
|||||||
FBreakPoints[bplFpcSpecific] := FDebugger.AddBreak('__FPC_specific_handler', nil, False);
|
FBreakPoints[bplFpcSpecific] := FDebugger.AddBreak('__FPC_specific_handler', nil, False);
|
||||||
FBreakPoints[bplSehW64Except] := FDebugger.AddBreak(0, False);
|
FBreakPoints[bplSehW64Except] := FDebugger.AddBreak(0, False);
|
||||||
FBreakPoints[bplSehW64Finally] := FDebugger.AddBreak(0, False);
|
FBreakPoints[bplSehW64Finally] := FDebugger.AddBreak(0, False);
|
||||||
|
FBreakPoints[bplSehW64Unwound] := FDebugger.AddBreak(0, False);
|
||||||
debuglnExit(DBG_BREAKPOINTS, ['<< TFpDebugDebugger.SetSoftwareExceptionBreakpoint ' ]);
|
debuglnExit(DBG_BREAKPOINTS, ['<< TFpDebugDebugger.SetSoftwareExceptionBreakpoint ' ]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpDebugExceptionStepping.DoNtDllLoaded(ALib: TDbgLibrary);
|
procedure TFpDebugExceptionStepping.DoNtDllLoaded(ALib: TDbgLibrary);
|
||||||
begin
|
begin
|
||||||
debugln(DBG_BREAKPOINTS, ['SetSoftwareExceptionBreakpoint RtlUnwind']);
|
debugln(DBG_BREAKPOINTS, ['SetSoftwareExceptionBreakpoint RtlUnwind']);
|
||||||
DisableBreaksDirect([bplRtlUnwind]);
|
DisableBreaksDirect([bplRtlUnwind, bplRtlRestoreContext]);
|
||||||
|
{$IfDef WIN64}
|
||||||
|
FreeAndNil(FBreakPoints[bplRtlRestoreContext]);
|
||||||
|
FBreakPoints[bplRtlRestoreContext] := FDebugger.AddBreak('RtlRestoreContext', ALib, False);
|
||||||
|
{$EndIf}
|
||||||
FBreakPoints[bplRtlUnwind].Free;
|
FBreakPoints[bplRtlUnwind].Free;
|
||||||
FBreakPoints[bplRtlUnwind] := FDebugger.AddBreak('RtlUnwindEx', ALib, False);
|
FBreakPoints[bplRtlUnwind] := FDebugger.AddBreak('RtlUnwindEx', ALib, False);
|
||||||
end;
|
end;
|
||||||
@ -2465,6 +2470,8 @@ begin
|
|||||||
// Running in debug thread
|
// Running in debug thread
|
||||||
EnableBreaksDirect(FBreakNewEnabled - FBreakEnabled);
|
EnableBreaksDirect(FBreakNewEnabled - FBreakEnabled);
|
||||||
DisableBreaksDirect(FBreakEnabled - FBreakNewEnabled);
|
DisableBreaksDirect(FBreakEnabled - FBreakNewEnabled);
|
||||||
|
if assigned(FBreakPoints[bplSehW64Unwound]) then
|
||||||
|
FBreakPoints[bplSehW64Unwound].RemoveAllAddresses;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpDebugExceptionStepping.ThreadProcessLoopCycle(
|
procedure TFpDebugExceptionStepping.ThreadProcessLoopCycle(
|
||||||
@ -2552,6 +2559,18 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
|
|
||||||
FDebugger.FDbgController.DefaultContext; // Make sure it is avail and cached / so it can be called outside the thread
|
FDebugger.FDbgController.DefaultContext; // Make sure it is avail and cached / so it can be called outside the thread
|
||||||
|
|
||||||
|
PC := CurrentThread.GetInstructionPointerRegisterValue;
|
||||||
|
if Assigned(FBreakPoints[bplSehW64Unwound]) and FBreakPoints[bplSehW64Unwound].HasLocation(PC)
|
||||||
|
then begin
|
||||||
|
FBreakPoints[bplSehW64Unwound].RemoveAllAddresses;
|
||||||
|
AFinishLoopAndSendEvents := AnIsFinished or (FState = esStepToFinally);
|
||||||
|
if AFinishLoopAndSendEvents then begin
|
||||||
|
AnEventType := deFinishedStep; // only step commands can end up here
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
if (FState = esSteppingFpcSpecialHandler) and
|
if (FState = esSteppingFpcSpecialHandler) and
|
||||||
(ACurCommand is TDbgControllerStepThroughFpcSpecialHandler) and
|
(ACurCommand is TDbgControllerStepThroughFpcSpecialHandler) and
|
||||||
(TDbgControllerStepThroughFpcSpecialHandler(ACurCommand).InteralFinished)
|
(TDbgControllerStepThroughFpcSpecialHandler(ACurCommand).InteralFinished)
|
||||||
@ -2576,7 +2595,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
DisableBreaksDirect([bplRtlUnwind, bplSehW64Finally]); // bplRtlUnwind must always be unset;
|
DisableBreaksDirect([bplRtlUnwind, bplSehW64Finally]); // bplRtlUnwind must always be unset;
|
||||||
|
|
||||||
PC := CurrentThread.GetInstructionPointerRegisterValue;
|
|
||||||
SP := CurrentThread.GetStackPointerRegisterValue;
|
SP := CurrentThread.GetStackPointerRegisterValue;
|
||||||
FAddressFrameListSehW64Except.RemoveOutOfScopeFrames(SP, FBreakPoints[bplSehW64Except]);
|
FAddressFrameListSehW64Except.RemoveOutOfScopeFrames(SP, FBreakPoints[bplSehW64Except]);
|
||||||
if ACurCommand is TDbgControllerStepOutCmd then
|
if ACurCommand is TDbgControllerStepOutCmd then
|
||||||
@ -2727,6 +2745,25 @@ begin
|
|||||||
FBreakPoints[bplSehW64Finally].SetBreak;
|
FBreakPoints[bplSehW64Finally].SetBreak;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
// bplRtlRestoreContext
|
||||||
|
if assigned(FBreakPoints[bplRtlRestoreContext]) and FBreakPoints[bplRtlRestoreContext].HasLocation(PC) then begin
|
||||||
|
AFinishLoopAndSendEvents := False;
|
||||||
|
if (CurrentCommand <> nil) and (CurrentCommand.Thread <> CurrentThread) then
|
||||||
|
exit;
|
||||||
|
debugln(FPDBG_COMMANDS, ['@ bplRtlRestoreContext ', DbgSName(CurrentCommand)]);
|
||||||
|
{$IfDef WIN64}
|
||||||
|
// RCX = TContext
|
||||||
|
Rcx := CurrentThread.RegisterValueList.FindRegisterByDwarfIndex(2).NumValue; // rsp at target
|
||||||
|
if (Rcx <> 0) then begin
|
||||||
|
if (not CurrentProcess.ReadAddress(Rcx + PtrUInt(@PCONTEXT(nil)^.Rip), Addr)) or (Addr = 0) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
FBreakPoints[bplSehW64Unwound].AddAddress(Addr);
|
||||||
|
FBreakPoints[bplSehW64Unwound].SetBreak;
|
||||||
|
end;
|
||||||
|
{$EndIf}
|
||||||
|
end
|
||||||
|
else
|
||||||
// bplRtlUnwind
|
// bplRtlUnwind
|
||||||
if assigned(FBreakPoints[bplRtlUnwind]) and FBreakPoints[bplRtlUnwind].HasLocation(PC) then begin
|
if assigned(FBreakPoints[bplRtlUnwind]) and FBreakPoints[bplRtlUnwind].HasLocation(PC) then begin
|
||||||
debugln(FPDBG_COMMANDS, ['@ bplRtlUnwind ', DbgSName(CurrentCommand)]);
|
debugln(FPDBG_COMMANDS, ['@ bplRtlUnwind ', DbgSName(CurrentCommand)]);
|
||||||
@ -2832,11 +2869,11 @@ begin
|
|||||||
st := FState;
|
st := FState;
|
||||||
FState := esNone;
|
FState := esNone;
|
||||||
DisableBreaks([bplPopExcept, bplCatches, bplFpcSpecific,
|
DisableBreaks([bplPopExcept, bplCatches, bplFpcSpecific,
|
||||||
bplReRaise,
|
bplReRaise, bplRtlRestoreContext,
|
||||||
bplRtlUnwind, bplStepOut]);
|
bplRtlUnwind, 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]);
|
EnableBreaks([bplReRaise, bplRtlRestoreContext]);
|
||||||
if ACommand in [dcStepOut] then
|
if ACommand in [dcStepOut] then
|
||||||
EnableBreaks([bplFpcSpecific]);
|
EnableBreaks([bplFpcSpecific]);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user