mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-14 14:19:22 +02:00
FpGdbmiDebugger: allow stepping to continue over exceptions / allow to step from excepitons (raise) to finally/except (include implicit finally)
git-svn-id: trunk@44769 -
This commit is contained in:
parent
e1881c3f4c
commit
c1899b0b90
@ -469,7 +469,7 @@ type
|
|||||||
private
|
private
|
||||||
FCanKillNow, FDidKillNow: Boolean;
|
FCanKillNow, FDidKillNow: Boolean;
|
||||||
protected
|
protected
|
||||||
function ProcessRunning(var AStoppedParams: String; out AResult: TGDBMIExecResult; ATimeOut: Integer = 0): Boolean;
|
function ProcessRunning(out AStoppedParams: String; out AResult: TGDBMIExecResult; ATimeOut: Integer = 0): Boolean;
|
||||||
function ParseBreakInsertError(var AText: String; out AnId: Integer): Boolean;
|
function ParseBreakInsertError(var AText: String; out AnId: Integer): Boolean;
|
||||||
function ProcessStopped(const {%H-}AParams: String; const {%H-}AIgnoreSigIntState: Boolean): Boolean; virtual;
|
function ProcessStopped(const {%H-}AParams: String; const {%H-}AIgnoreSigIntState: Boolean): Boolean; virtual;
|
||||||
public
|
public
|
||||||
@ -568,6 +568,7 @@ type
|
|||||||
|
|
||||||
TGDBMIInternalBreakPoint = class
|
TGDBMIInternalBreakPoint = class
|
||||||
private
|
private
|
||||||
|
FEnabled: Boolean;
|
||||||
FLineOffsFunction: string;
|
FLineOffsFunction: string;
|
||||||
// -break-insert name
|
// -break-insert name
|
||||||
FNameBreakID: Integer;
|
FNameBreakID: Integer;
|
||||||
@ -605,10 +606,14 @@ type
|
|||||||
function ClearId(ACmd: TGDBMIDebuggerCommand; AnId: Integer): Boolean;
|
function ClearId(ACmd: TGDBMIDebuggerCommand; AnId: Integer): Boolean;
|
||||||
function MatchAddr(AnAddr: TDBGPtr): boolean;
|
function MatchAddr(AnAddr: TDBGPtr): boolean;
|
||||||
function MatchId(AnId: Integer): boolean;
|
function MatchId(AnId: Integer): boolean;
|
||||||
function Enabled: boolean;
|
function IsBreakSet: boolean;
|
||||||
|
procedure EnableOrSetByAddr(ACmd: TGDBMIDebuggerCommand; SetNamedOnFail: Boolean = False);
|
||||||
|
procedure Enable(ACmd: TGDBMIDebuggerCommand);
|
||||||
|
procedure Disable(ACmd: TGDBMIDebuggerCommand);
|
||||||
property MainAddrFound: TDBGPtr read FMainAddrFound;
|
property MainAddrFound: TDBGPtr read FMainAddrFound;
|
||||||
property LineOffsFunction: string read FLineOffsFunction;
|
property LineOffsFunction: string read FLineOffsFunction;
|
||||||
property UseForceFlag: Boolean read FUseForceFlag write FUseForceFlag;
|
property UseForceFlag: Boolean read FUseForceFlag write FUseForceFlag;
|
||||||
|
property Enabled: Boolean read FEnabled;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TGDBMIWatches }
|
{ TGDBMIWatches }
|
||||||
@ -656,7 +661,9 @@ type
|
|||||||
FBreakErrorBreak: TGDBMIInternalBreakPoint;
|
FBreakErrorBreak: TGDBMIInternalBreakPoint;
|
||||||
FRunErrorBreak: TGDBMIInternalBreakPoint;
|
FRunErrorBreak: TGDBMIInternalBreakPoint;
|
||||||
FExceptionBreak: TGDBMIInternalBreakPoint;
|
FExceptionBreak: TGDBMIInternalBreakPoint;
|
||||||
|
FPopExceptStack, FCatchesBreak, FReRaiseBreak: TGDBMIInternalBreakPoint;
|
||||||
FPauseWaitState: TGDBMIPauseWaitState;
|
FPauseWaitState: TGDBMIPauseWaitState;
|
||||||
|
FStoppedReason: (srNone, srRaiseExcept, srReRaiseExcept, srPopExceptStack, srCatches);
|
||||||
FInExecuteCount: Integer;
|
FInExecuteCount: Integer;
|
||||||
FInIdle: Boolean;
|
FInIdle: Boolean;
|
||||||
FRunQueueOnUnlock: Boolean;
|
FRunQueueOnUnlock: Boolean;
|
||||||
@ -1737,6 +1744,9 @@ begin
|
|||||||
FTheDebugger.FExceptionBreak.Clear(Self);
|
FTheDebugger.FExceptionBreak.Clear(Self);
|
||||||
FTheDebugger.FBreakErrorBreak.Clear(Self);
|
FTheDebugger.FBreakErrorBreak.Clear(Self);
|
||||||
FTheDebugger.FRunErrorBreak.Clear(Self);
|
FTheDebugger.FRunErrorBreak.Clear(Self);
|
||||||
|
FTheDebugger.FPopExceptStack.Clear(Self);
|
||||||
|
FTheDebugger.FCatchesBreak.Clear(Self);
|
||||||
|
FTheDebugger.FReRaiseBreak.Clear(Self);
|
||||||
if DebuggerState = dsError then Exit;
|
if DebuggerState = dsError then Exit;
|
||||||
|
|
||||||
S := FTheDebugger.ConvertToGDBPath(UTF8ToSys(FTheDebugger.FileName), cgptExeName);
|
S := FTheDebugger.ConvertToGDBPath(UTF8ToSys(FTheDebugger.FileName), cgptExeName);
|
||||||
@ -2396,7 +2406,7 @@ end;
|
|||||||
|
|
||||||
{ TGDBMIDebuggerCommandExecuteBase }
|
{ TGDBMIDebuggerCommandExecuteBase }
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandExecuteBase.ProcessRunning(var AStoppedParams: String; out
|
function TGDBMIDebuggerCommandExecuteBase.ProcessRunning(out AStoppedParams: String; out
|
||||||
AResult: TGDBMIExecResult; ATimeOut: Integer): Boolean;
|
AResult: TGDBMIExecResult; ATimeOut: Integer): Boolean;
|
||||||
var
|
var
|
||||||
InLogWarning: Boolean;
|
InLogWarning: Boolean;
|
||||||
@ -2597,6 +2607,7 @@ begin
|
|||||||
InLogWarning := False;
|
InLogWarning := False;
|
||||||
FGotStopped := False;
|
FGotStopped := False;
|
||||||
FLogWarnings := '';
|
FLogWarnings := '';
|
||||||
|
AStoppedParams := '';
|
||||||
while FTheDebugger.DebugProcessRunning and not(FTheDebugger.State in [dsError, dsDestroying]) do
|
while FTheDebugger.DebugProcessRunning and not(FTheDebugger.State in [dsError, dsDestroying]) do
|
||||||
begin
|
begin
|
||||||
if ATimeOut > 0 then begin
|
if ATimeOut > 0 then begin
|
||||||
@ -4814,7 +4825,7 @@ function TGDBMIDebuggerCommandStartDebugging.DoExecute: Boolean;
|
|||||||
mtEntry: FTheDebugger.FMainAddrBreak.SetAtCustomAddr(Self, StrToQWordDef(EntryPoint, 0));
|
mtEntry: FTheDebugger.FMainAddrBreak.SetAtCustomAddr(Self, StrToQWordDef(EntryPoint, 0));
|
||||||
mtAddZero: FTheDebugger.FMainAddrBreak.SetAtLineOffs(Self, 0);
|
mtAddZero: FTheDebugger.FMainAddrBreak.SetAtLineOffs(Self, 0);
|
||||||
end;
|
end;
|
||||||
Result := FTheDebugger.FMainAddrBreak.Enabled;
|
Result := FTheDebugger.FMainAddrBreak.IsBreakSet;
|
||||||
end;
|
end;
|
||||||
begin
|
begin
|
||||||
case RunToMainState of
|
case RunToMainState of
|
||||||
@ -4905,7 +4916,7 @@ function TGDBMIDebuggerCommandStartDebugging.DoExecute: Boolean;
|
|||||||
FTheDebugger.FMainAddrBreak.Clear(Self);
|
FTheDebugger.FMainAddrBreak.Clear(Self);
|
||||||
while true do begin
|
while true do begin
|
||||||
SetMainBrk;
|
SetMainBrk;
|
||||||
if not FTheDebugger.FMainAddrBreak.Enabled
|
if not FTheDebugger.FMainAddrBreak.IsBreakSet
|
||||||
then begin
|
then begin
|
||||||
(* TODO:
|
(* TODO:
|
||||||
If no main break can be set, it may still be possible (desirable) to run
|
If no main break can be set, it may still be possible (desirable) to run
|
||||||
@ -5556,6 +5567,7 @@ function TGDBMIDebuggerCommandExecute.ProcessStopped(const AParams: String;
|
|||||||
ExceptInfo: TGDBMIExceptionInfo;
|
ExceptInfo: TGDBMIExceptionInfo;
|
||||||
ExceptItem: TBaseException;
|
ExceptItem: TBaseException;
|
||||||
begin
|
begin
|
||||||
|
FTheDebugger.FStoppedReason := srRaiseExcept;
|
||||||
if (FTheDebugger.Exceptions = nil) or FTheDebugger.Exceptions.IgnoreAll
|
if (FTheDebugger.Exceptions = nil) or FTheDebugger.Exceptions.IgnoreAll
|
||||||
then begin
|
then begin
|
||||||
Result := True; //ExecuteCommand('-exec-continue')
|
Result := True; //ExecuteCommand('-exec-continue')
|
||||||
@ -5863,6 +5875,7 @@ begin
|
|||||||
*)
|
*)
|
||||||
Result := False;
|
Result := False;
|
||||||
FTheDebugger.FInProcessStopped := True; // paused, but maybe state run
|
FTheDebugger.FInProcessStopped := True; // paused, but maybe state run
|
||||||
|
FTheDebugger.FStoppedReason := srNone;
|
||||||
|
|
||||||
List := TGDBMINameValueList.Create(AParams);
|
List := TGDBMINameValueList.Create(AParams);
|
||||||
List2 := nil;
|
List2 := nil;
|
||||||
@ -5971,6 +5984,27 @@ begin
|
|||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if FTheDebugger.FPopExceptStack.MatchId(BreakID)
|
||||||
|
then begin
|
||||||
|
FTheDebugger.FStoppedReason := srPopExceptStack;
|
||||||
|
Result := True;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if FTheDebugger.FCatchesBreak.MatchId(BreakID)
|
||||||
|
then begin
|
||||||
|
FTheDebugger.FStoppedReason := srCatches;
|
||||||
|
Result := True;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if FTheDebugger.FReRaiseBreak.MatchId(BreakID)
|
||||||
|
then begin
|
||||||
|
FTheDebugger.FStoppedReason := srReRaiseExcept;
|
||||||
|
Result := True;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
if (FStepBreakPoint > 0) and (BreakID = FStepBreakPoint)
|
if (FStepBreakPoint > 0) and (BreakID = FStepBreakPoint)
|
||||||
then begin
|
then begin
|
||||||
SetDebuggerState(dsPause);
|
SetDebuggerState(dsPause);
|
||||||
@ -6054,6 +6088,8 @@ end;
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
function TGDBMIDebuggerCommandExecute.DoExecute: Boolean;
|
function TGDBMIDebuggerCommandExecute.DoExecute: Boolean;
|
||||||
|
var
|
||||||
|
RunMode: (rmNormal, rmStepToFinally);
|
||||||
const
|
const
|
||||||
BreaKErrMsg = 'not insert breakpoint ';
|
BreaKErrMsg = 'not insert breakpoint ';
|
||||||
WatchErrMsg = 'not insert hardware watchpoint ';
|
WatchErrMsg = 'not insert hardware watchpoint ';
|
||||||
@ -6238,6 +6274,7 @@ const
|
|||||||
|
|
||||||
var
|
var
|
||||||
FP: TDBGPtr;
|
FP: TDBGPtr;
|
||||||
|
CurThreadId: Integer;
|
||||||
|
|
||||||
function DoContinueStepping: Boolean;
|
function DoContinueStepping: Boolean;
|
||||||
procedure DoEndStepping;
|
procedure DoEndStepping;
|
||||||
@ -6258,6 +6295,33 @@ var
|
|||||||
// TODO: the "break" breakpoint can stop on the current, instead of the next instruction
|
// TODO: the "break" breakpoint can stop on the current, instead of the next instruction
|
||||||
|
|
||||||
Result := False;
|
Result := False;
|
||||||
|
|
||||||
|
if RunMode = rmStepToFinally then begin
|
||||||
|
Result := FTheDebugger.FStoppedReason in [srPopExceptStack, srCatches];
|
||||||
|
if Result then
|
||||||
|
FCurrentExecCmd := ectStepOut;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if FTheDebugger.FStoppedReason = srReRaiseExcept then begin
|
||||||
|
FTheDebugger.FPopExceptStack.EnableOrSetByAddr(Self, True);
|
||||||
|
FTheDebugger.FCatchesBreak.EnableOrSetByAddr(Self, True);
|
||||||
|
FCurrentExecCmd := ectContinue;
|
||||||
|
Result := True;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
if FTheDebugger.FStoppedReason in [srPopExceptStack, srCatches] then begin
|
||||||
|
FTheDebugger.FPopExceptStack.Disable(Self);
|
||||||
|
FTheDebugger.FCatchesBreak.Disable(Self);
|
||||||
|
i := FindStackFrame(Fp, 0, 1);
|
||||||
|
if (i in [0, 1]) or (i = -2) // -2 already stepped out of the desired frame, enter dsPause
|
||||||
|
then begin
|
||||||
|
FCurrentExecCmd := ectStepOut; // ecStepOut will not offer a change to ContinueStepping
|
||||||
|
Result := True;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
case FExecType of
|
case FExecType of
|
||||||
ectContinue, ectRun:
|
ectContinue, ectRun:
|
||||||
begin
|
begin
|
||||||
@ -6278,8 +6342,8 @@ var
|
|||||||
ectStepOver, ectStepOverInstruction, ectStepOut, ectStepInto:
|
ectStepOver, ectStepOverInstruction, ectStepOut, ectStepInto:
|
||||||
begin
|
begin
|
||||||
Result := FStepBreakPoint > 0;
|
Result := FStepBreakPoint > 0;
|
||||||
if Result
|
if Result then
|
||||||
then exit;
|
exit;
|
||||||
|
|
||||||
i := -1;
|
i := -1;
|
||||||
if FP <> 0 then begin
|
if FP <> 0 then begin
|
||||||
@ -6304,6 +6368,8 @@ var
|
|||||||
FContext.ThreadContext := ccUseGlobal;
|
FContext.ThreadContext := ccUseGlobal;
|
||||||
FTheDebugger.QueueExecuteLock; // force queue
|
FTheDebugger.QueueExecuteLock; // force queue
|
||||||
try
|
try
|
||||||
|
// This messes up the Stack context of the queue.
|
||||||
|
FTheDebugger.FInstructionQueue.InvalidateThredAndFrame;
|
||||||
if (not ExecuteCommand('frame %d', [i], R, [cfNoStackContext])) or (R.State = dsError)
|
if (not ExecuteCommand('frame %d', [i], R, [cfNoStackContext])) or (R.State = dsError)
|
||||||
then i := -3; // error to user
|
then i := -3; // error to user
|
||||||
if (i < 0) or (not ExecuteCommand('break', [i], R, [cfNoStackContext])) or (R.State = dsError)
|
if (i < 0) or (not ExecuteCommand('break', [i], R, [cfNoStackContext])) or (R.State = dsError)
|
||||||
@ -6344,75 +6410,117 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function GetCurrentFp: TDBGPtr;
|
||||||
|
begin
|
||||||
|
FContext.ThreadContext := ccUseLocal;
|
||||||
|
FContext.StackContext := ccUseLocal;
|
||||||
|
FContext.StackFrame := 0;
|
||||||
|
FContext.ThreadId := CurThreadId;
|
||||||
|
Result := GetPtrValue('$fp', []);
|
||||||
|
FContext.ThreadContext := ccNotRequired;
|
||||||
|
FContext.StackContext := ccNotRequired;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DoExecCommand(AnExecCmd: TGDBMIExecCommandType; AnExecArg: String): Boolean;
|
||||||
|
var
|
||||||
|
UseMI: Boolean;
|
||||||
|
AFlags: TGDBMICommandFlags;
|
||||||
|
s: String;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
if AnExecCmd in [ectStepOut, ectReturn {, ectRunTo}] then begin
|
||||||
|
FContext.ThreadContext := ccUseLocal;
|
||||||
|
FContext.StackContext := ccUseLocal;
|
||||||
|
FContext.StackFrame := 0;
|
||||||
|
FContext.ThreadId := CurThreadId;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
FContext.ThreadContext := ccNotRequired;
|
||||||
|
FContext.StackContext := ccNotRequired;
|
||||||
|
end;
|
||||||
|
|
||||||
|
UseMI := not FTheDebugger.FCommandNoneMiState[AnExecCmd];
|
||||||
|
if UseMI then
|
||||||
|
s := GDBMIExecCommandMap[AnExecCmd] + AnExecArg
|
||||||
|
else
|
||||||
|
s := GDBMIExecCommandMapNoneMI[AnExecCmd] + AnExecArg;
|
||||||
|
|
||||||
|
AFlags := [];
|
||||||
|
if FTheDebugger.FAsyncModeEnabled and FTheDebugger.FCommandAsyncState[AnExecCmd] then
|
||||||
|
AFlags := [cfTryAsync];
|
||||||
|
|
||||||
|
if (UseMI) and (cfTryAsync in AFlags) and (DebuggerProperties.UseNoneMiRunCommands = gdnmFallback)
|
||||||
|
then begin
|
||||||
|
if not ExecuteCommand(s + ' &', FResult, []) then // Try MI in async
|
||||||
|
exit;
|
||||||
|
if (FResult.State = dsError) then begin
|
||||||
|
// Retry none MI
|
||||||
|
FTheDebugger.FCommandNoneMiState[AnExecCmd] := True;
|
||||||
|
s := GDBMIExecCommandMapNoneMI[AnExecCmd] + AnExecArg;
|
||||||
|
if not ExecuteCommand(s, FResult, AFlags) then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if not ExecuteCommand(s, FResult, AFlags) then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (cfTryAsync in AFlags) and (FResult.State <> dsError) then begin
|
||||||
|
if (rfAsyncFailed in FResult.Flags) then
|
||||||
|
FTheDebugger.FCommandAsyncState[AnExecCmd] := False
|
||||||
|
else
|
||||||
|
FTheDebugger.FCurrentCmdIsAsync := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
StoppedParams, RunWarnings: String;
|
StoppedParams, RunWarnings: String;
|
||||||
ContinueExecution, ContinueStep, UseMI: Boolean;
|
ContinueExecution, ContinueStep: Boolean;
|
||||||
NextExecCmdObj: TGDBMIDebuggerCommandExecute;
|
NextExecCmdObj: TGDBMIDebuggerCommandExecute;
|
||||||
R: TGDBMIExecResult;
|
R: TGDBMIExecResult;
|
||||||
s: String;
|
|
||||||
AFlags: TGDBMICommandFlags;
|
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Result := True;
|
||||||
FCanKillNow := False;
|
FCanKillNow := False;
|
||||||
FDidKillNow := False;
|
FDidKillNow := False;
|
||||||
FNextExecQueued := False;
|
FNextExecQueued := False;
|
||||||
FP := 0;
|
FP := 0;
|
||||||
|
CurThreadId := FTheDebugger.FCurrentThreadId;
|
||||||
|
if not FTheDebugger.FCurrentThreadIdValid then CurThreadId := 1; // TODO, but we need something
|
||||||
ContinueStep := False; // A step command was interupted, and is continued on breakpoint
|
ContinueStep := False; // A step command was interupted, and is continued on breakpoint
|
||||||
FStepBreakPoint := -1;
|
FStepBreakPoint := -1;
|
||||||
|
RunMode := rmNormal;
|
||||||
|
if (FExecType in [ectStepOver, ectStepInto, ectStepOut]) and
|
||||||
|
(FTheDebugger.FStoppedReason = srRaiseExcept)
|
||||||
|
then begin
|
||||||
|
RunMode := rmStepToFinally;
|
||||||
|
FCurrentExecCmd := ectContinue;
|
||||||
|
FTheDebugger.FPopExceptStack.EnableOrSetByAddr(Self, True);
|
||||||
|
FTheDebugger.FCatchesBreak.EnableOrSetByAddr(Self, True);
|
||||||
|
end;
|
||||||
|
if (FExecType in [ectRunTo, ectStepOver{, ectStepInto}, ectStepOut, ectStepOverInstruction {, ectStepIntoInstruction}]) then
|
||||||
|
FTheDebugger.FReRaiseBreak.EnableOrSetByAddr(Self, True)
|
||||||
|
else
|
||||||
|
FTheDebugger.FReRaiseBreak.Disable(Self);
|
||||||
|
|
||||||
try
|
try
|
||||||
repeat
|
repeat
|
||||||
FTheDebugger.CancelBeforeRun; // TODO: see comment on top of TGDBMIDebugger.QueueCommand
|
FTheDebugger.CancelBeforeRun; // TODO: see comment on top of TGDBMIDebugger.QueueCommand
|
||||||
FTheDebugger.QueueExecuteLock; // prevent other commands from executing
|
FTheDebugger.QueueExecuteLock; // prevent other commands from executing
|
||||||
try
|
try
|
||||||
if (not ContinueStep) and
|
if (not ContinueStep) and (not (RunMode in [rmStepToFinally])) and
|
||||||
(FExecType in [ectStepOver, ectStepInto, ectStepOut, ectStepOverInstruction, ectStepIntoInstruction])
|
(FExecType in [ectStepOver, ectStepInto, ectStepOut, ectStepOverInstruction, ectStepIntoInstruction])
|
||||||
then begin
|
then
|
||||||
FContext.ThreadContext := ccUseGlobal;
|
FP := GetCurrentFp;
|
||||||
FContext.StackContext := ccUseLocal;
|
|
||||||
FContext.StackFrame := 0;
|
|
||||||
FP := GetPtrValue('$fp', []);
|
|
||||||
FContext.ThreadContext := ccNotRequired;
|
|
||||||
FContext.StackContext := ccNotRequired;
|
|
||||||
end;
|
|
||||||
|
|
||||||
FTheDebugger.FCurrentStackFrameValid := False;
|
FTheDebugger.FCurrentStackFrameValid := False;
|
||||||
FTheDebugger.FCurrentThreadIdValid := False;
|
FTheDebugger.FCurrentThreadIdValid := False;
|
||||||
FTheDebugger.FCurrentCmdIsAsync := False;
|
FTheDebugger.FCurrentCmdIsAsync := False;
|
||||||
|
|
||||||
UseMI := not FTheDebugger.FCommandNoneMiState[FCurrentExecCmd];
|
if not DoExecCommand(FCurrentExecCmd, FCurrentExecArg) then
|
||||||
if UseMI then
|
exit;
|
||||||
s := GDBMIExecCommandMap[FCurrentExecCmd] + FCurrentExecArg
|
|
||||||
else
|
|
||||||
s := GDBMIExecCommandMapNoneMI[FCurrentExecCmd] + FCurrentExecArg;
|
|
||||||
|
|
||||||
AFlags := [];
|
|
||||||
if FTheDebugger.FAsyncModeEnabled and FTheDebugger.FCommandAsyncState[FCurrentExecCmd] then
|
|
||||||
AFlags := [cfTryAsync];
|
|
||||||
|
|
||||||
if (UseMI) and (cfTryAsync in AFlags) and (DebuggerProperties.UseNoneMiRunCommands = gdnmFallback)
|
|
||||||
then begin
|
|
||||||
if not ExecuteCommand(s + ' &', FResult, []) then // Try MI in asynic
|
|
||||||
exit;
|
|
||||||
if (FResult.State = dsError) then begin
|
|
||||||
// Retry none MI
|
|
||||||
FTheDebugger.FCommandNoneMiState[FCurrentExecCmd] := True;
|
|
||||||
s := GDBMIExecCommandMapNoneMI[FCurrentExecCmd] + FCurrentExecArg;
|
|
||||||
if not ExecuteCommand(s, FResult, AFlags) then
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if not ExecuteCommand(s, FResult, AFlags) then
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if (cfTryAsync in AFlags) and (FResult.State <> dsError) then begin
|
|
||||||
if (rfAsyncFailed in FResult.Flags) then
|
|
||||||
FTheDebugger.FCommandAsyncState[FCurrentExecCmd] := False
|
|
||||||
else
|
|
||||||
FTheDebugger.FCurrentCmdIsAsync := True;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if CheckResultForError(FResult)
|
if CheckResultForError(FResult)
|
||||||
then exit;
|
then exit;
|
||||||
@ -6446,6 +6554,7 @@ begin
|
|||||||
ContinueStep := False;
|
ContinueStep := False;
|
||||||
if StoppedParams <> ''
|
if StoppedParams <> ''
|
||||||
then ContinueExecution := ProcessStopped(StoppedParams, FTheDebugger.PauseWaitState = pwsInternal);
|
then ContinueExecution := ProcessStopped(StoppedParams, FTheDebugger.PauseWaitState = pwsInternal);
|
||||||
|
|
||||||
if ContinueExecution
|
if ContinueExecution
|
||||||
then begin
|
then begin
|
||||||
ContinueStep := DoContinueStepping; // will set dsPause, if step has finished
|
ContinueStep := DoContinueStepping; // will set dsPause, if step has finished
|
||||||
@ -6470,6 +6579,8 @@ begin
|
|||||||
if FStepBreakPoint > 0
|
if FStepBreakPoint > 0
|
||||||
then ExecuteCommand('-break-delete %d', [FStepBreakPoint], [cfNoThreadContext]);
|
then ExecuteCommand('-break-delete %d', [FStepBreakPoint], [cfNoThreadContext]);
|
||||||
FStepBreakPoint := -1;
|
FStepBreakPoint := -1;
|
||||||
|
FTheDebugger.FPopExceptStack.Disable(Self);
|
||||||
|
FTheDebugger.FCatchesBreak.Disable(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (not ContinueExecution) and (DebuggerState = dsRun) and
|
if (not ContinueExecution) and (DebuggerState = dsRun) and
|
||||||
@ -7203,6 +7314,9 @@ begin
|
|||||||
FBreakErrorBreak := TGDBMIInternalBreakPoint.Create('FPC_BREAK_ERROR');
|
FBreakErrorBreak := TGDBMIInternalBreakPoint.Create('FPC_BREAK_ERROR');
|
||||||
FRunErrorBreak := TGDBMIInternalBreakPoint.Create('FPC_RUNERROR');
|
FRunErrorBreak := TGDBMIInternalBreakPoint.Create('FPC_RUNERROR');
|
||||||
FExceptionBreak := TGDBMIInternalBreakPoint.Create('FPC_RAISEEXCEPTION');
|
FExceptionBreak := TGDBMIInternalBreakPoint.Create('FPC_RAISEEXCEPTION');
|
||||||
|
FPopExceptStack := TGDBMIInternalBreakPoint.Create('FPC_POPADDRSTACK');
|
||||||
|
FCatchesBreak := TGDBMIInternalBreakPoint.Create('FPC_CATCHES');
|
||||||
|
FReRaiseBreak := TGDBMIInternalBreakPoint.Create('FPC_RERAISE');
|
||||||
{$IFdef WITH_GDB_FORCE_EXCEPTBREAK}
|
{$IFdef WITH_GDB_FORCE_EXCEPTBREAK}
|
||||||
FBreakErrorBreak.UseForceFlag := True;
|
FBreakErrorBreak.UseForceFlag := True;
|
||||||
FRunErrorBreak.UseForceFlag := True;
|
FRunErrorBreak.UseForceFlag := True;
|
||||||
@ -7315,6 +7429,9 @@ begin
|
|||||||
FreeAndNil(FBreakErrorBreak);
|
FreeAndNil(FBreakErrorBreak);
|
||||||
FreeAndNil(FRunErrorBreak);
|
FreeAndNil(FRunErrorBreak);
|
||||||
FreeAndNil(FExceptionBreak);
|
FreeAndNil(FExceptionBreak);
|
||||||
|
FreeAndNil(FPopExceptStack);
|
||||||
|
FreeAndNil(FCatchesBreak);
|
||||||
|
FreeAndNil(FReRaiseBreak);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TGDBMIDebugger.Done;
|
procedure TGDBMIDebugger.Done;
|
||||||
@ -7419,6 +7536,9 @@ begin
|
|||||||
if not (State in [dsRun, dsPause, dsInit, dsInternalPause])
|
if not (State in [dsRun, dsPause, dsInit, dsInternalPause])
|
||||||
then FMaxLineForUnitCache.Clear;
|
then FMaxLineForUnitCache.Clear;
|
||||||
|
|
||||||
|
if not (State in [dsPause, dsInternalPause]) then
|
||||||
|
FStoppedReason := srNone;;
|
||||||
|
|
||||||
if State in [dsStop, dsError]
|
if State in [dsStop, dsError]
|
||||||
then begin
|
then begin
|
||||||
ClearSourceInfo;
|
ClearSourceInfo;
|
||||||
@ -11341,8 +11461,9 @@ var
|
|||||||
R: TGDBMIExecResult;
|
R: TGDBMIExecResult;
|
||||||
S: String;
|
S: String;
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Result := FMainAddrFound;
|
||||||
FMainAddrFound := 0;
|
if Result <> 0 then
|
||||||
|
exit;
|
||||||
if (not ACmd.ExecuteCommand('info address ' + FName, R)) or
|
if (not ACmd.ExecuteCommand('info address ' + FName, R)) or
|
||||||
(R.State = dsError)
|
(R.State = dsError)
|
||||||
then exit;
|
then exit;
|
||||||
@ -11373,6 +11494,7 @@ end;
|
|||||||
|
|
||||||
constructor TGDBMIInternalBreakPoint.Create(AName: string);
|
constructor TGDBMIInternalBreakPoint.Create(AName: string);
|
||||||
begin
|
begin
|
||||||
|
FMainAddrFound := 0;
|
||||||
FNameBreakID := -1;
|
FNameBreakID := -1;
|
||||||
FNameBreakAddr := 0;
|
FNameBreakAddr := 0;
|
||||||
FAddrBreakID := -1;
|
FAddrBreakID := -1;
|
||||||
@ -11383,6 +11505,7 @@ begin
|
|||||||
FLineOffsAddr := 0;
|
FLineOffsAddr := 0;
|
||||||
FUseForceFlag := False;
|
FUseForceFlag := False;
|
||||||
FName := AName;
|
FName := AName;
|
||||||
|
FEnabled := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(* Using -insert-break with a function name allows GDB to adjust the address
|
(* Using -insert-break with a function name allows GDB to adjust the address
|
||||||
@ -11423,6 +11546,7 @@ var
|
|||||||
A: TDBGPtr;
|
A: TDBGPtr;
|
||||||
begin
|
begin
|
||||||
if ACmd.DebuggerState = dsError then Exit;
|
if ACmd.DebuggerState = dsError then Exit;
|
||||||
|
if FAddrBreakID >= 0 then exit; // already set
|
||||||
|
|
||||||
A := GetInfoAddr(ACmd);
|
A := GetInfoAddr(ACmd);
|
||||||
InternalSetAddr(ACmd, A);
|
InternalSetAddr(ACmd, A);
|
||||||
@ -11494,11 +11618,54 @@ begin
|
|||||||
(AnId = FCustomID) or (AnId = FLineOffsID));
|
(AnId = FCustomID) or (AnId = FLineOffsID));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TGDBMIInternalBreakPoint.Enabled: boolean;
|
function TGDBMIInternalBreakPoint.IsBreakSet: boolean;
|
||||||
begin
|
begin
|
||||||
Result := (FNameBreakID >= 0) or (FAddrBreakID >= 0) or (FCustomID > 0) or (FLineOffsID > 0);
|
Result := (FNameBreakID >= 0) or (FAddrBreakID >= 0) or (FCustomID > 0) or (FLineOffsID > 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGDBMIInternalBreakPoint.EnableOrSetByAddr(ACmd: TGDBMIDebuggerCommand;
|
||||||
|
SetNamedOnFail: Boolean);
|
||||||
|
begin
|
||||||
|
if IsBreakSet then
|
||||||
|
Enable(ACmd)
|
||||||
|
else
|
||||||
|
SetByAddr(ACmd, SetNamedOnFail);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGDBMIInternalBreakPoint.Enable(ACmd: TGDBMIDebuggerCommand);
|
||||||
|
var
|
||||||
|
R: TGDBMIExecResult;
|
||||||
|
begin
|
||||||
|
if FEnabled then exit;
|
||||||
|
FEnabled := True;
|
||||||
|
|
||||||
|
if FNameBreakID >= 0 then
|
||||||
|
ACmd.ExecuteCommand('-break-enable %d', [FNameBreakID], R);
|
||||||
|
if FAddrBreakID >= 0 then
|
||||||
|
ACmd.ExecuteCommand('-break-enable %d', [FAddrBreakID], R);
|
||||||
|
if FCustomID >= 0 then
|
||||||
|
ACmd.ExecuteCommand('-break-enable %d', [FCustomID], R);
|
||||||
|
if FLineOffsID >= 0 then
|
||||||
|
ACmd.ExecuteCommand('-break-enable %d', [FLineOffsID], R);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TGDBMIInternalBreakPoint.Disable(ACmd: TGDBMIDebuggerCommand);
|
||||||
|
var
|
||||||
|
R: TGDBMIExecResult;
|
||||||
|
begin
|
||||||
|
if not FEnabled then exit;
|
||||||
|
FEnabled := False;
|
||||||
|
|
||||||
|
if FNameBreakID >= 0 then
|
||||||
|
ACmd.ExecuteCommand('-break-disable %d', [FNameBreakID], R);
|
||||||
|
if FAddrBreakID >= 0 then
|
||||||
|
ACmd.ExecuteCommand('-break-disable %d', [FAddrBreakID], R);
|
||||||
|
if FCustomID >= 0 then
|
||||||
|
ACmd.ExecuteCommand('-break-disable %d', [FCustomID], R);
|
||||||
|
if FLineOffsID >= 0 then
|
||||||
|
ACmd.ExecuteCommand('-break-disable %d', [FLineOffsID], R);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TGDBMIDebuggerSimpleCommand }
|
{ TGDBMIDebuggerSimpleCommand }
|
||||||
|
|
||||||
constructor TGDBMIDebuggerSimpleCommand.Create(AOwner: TGDBMIDebugger;
|
constructor TGDBMIDebuggerSimpleCommand.Create(AOwner: TGDBMIDebugger;
|
||||||
|
Loading…
Reference in New Issue
Block a user