mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 17:59:22 +02:00
LazDebuggerFp: move breakpoints to thread worker queue
git-svn-id: trunk@64536 -
This commit is contained in:
parent
54bf4844fc
commit
2ae82698cb
@ -348,6 +348,8 @@ type
|
|||||||
{ TFpDbgBreakpoint }
|
{ TFpDbgBreakpoint }
|
||||||
|
|
||||||
TFpDbgBreakpoint = class(TObject)
|
TFpDbgBreakpoint = class(TObject)
|
||||||
|
private
|
||||||
|
FFreeByDbgProcess: Boolean;
|
||||||
public
|
public
|
||||||
function Hit(const AThreadID: Integer; ABreakpointAddress: TDBGPtr): Boolean; virtual; abstract;
|
function Hit(const AThreadID: Integer; ABreakpointAddress: TDBGPtr): Boolean; virtual; abstract;
|
||||||
function HasLocation(const ALocation: TDBGPtr): Boolean; virtual; abstract;
|
function HasLocation(const ALocation: TDBGPtr): Boolean; virtual; abstract;
|
||||||
@ -358,6 +360,9 @@ type
|
|||||||
|
|
||||||
procedure SetBreak; virtual; abstract;
|
procedure SetBreak; virtual; abstract;
|
||||||
procedure ResetBreak; virtual; abstract;
|
procedure ResetBreak; virtual; abstract;
|
||||||
|
|
||||||
|
// FreeByDbgProcess: The breakpoint will be freed by TDbgProcess.Destroy
|
||||||
|
property FreeByDbgProcess: Boolean read FFreeByDbgProcess write FFreeByDbgProcess;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TFpInternalBreakBase }
|
{ TFpInternalBreakBase }
|
||||||
@ -1754,10 +1759,16 @@ begin
|
|||||||
FProcessID:=0;
|
FProcessID:=0;
|
||||||
SetLastLibraryUnloaded(nil);
|
SetLastLibraryUnloaded(nil);
|
||||||
|
|
||||||
for i := 0 to FBreakpointList.Count - 1 do
|
for i := 0 to FBreakpointList.Count - 1 do begin
|
||||||
FBreakpointList[i].FProcess := nil;
|
FBreakpointList[i].FProcess := nil;
|
||||||
for i := 0 to FWatchPointList.Count - 1 do
|
if FBreakpointList[i].FreeByDbgProcess then
|
||||||
|
FBreakpointList[i].Free;
|
||||||
|
end;
|
||||||
|
for i := 0 to FWatchPointList.Count - 1 do begin
|
||||||
FWatchPointList[i].FProcess := nil;
|
FWatchPointList[i].FProcess := nil;
|
||||||
|
if FWatchPointList[i].FreeByDbgProcess then
|
||||||
|
FWatchPointList[i].Free;
|
||||||
|
end;
|
||||||
FreeAndNil(FBreakpointList);
|
FreeAndNil(FBreakpointList);
|
||||||
FreeAndNil(FWatchPointList);
|
FreeAndNil(FWatchPointList);
|
||||||
//Assert(FBreakMap.Count=0, 'No breakpoints left');
|
//Assert(FBreakMap.Count=0, 'No breakpoints left');
|
||||||
|
@ -32,7 +32,7 @@ unit FpDebugDebugger;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, fgl, math, contnrs, process,
|
Classes, SysUtils, fgl, math, process,
|
||||||
Forms, Dialogs,
|
Forms, Dialogs,
|
||||||
Maps, LazLogger, LazUTF8,
|
Maps, LazLogger, LazUTF8,
|
||||||
DbgIntfBaseTypes, DbgIntfDebuggerBase,
|
DbgIntfBaseTypes, DbgIntfDebuggerBase,
|
||||||
@ -45,6 +45,7 @@ uses
|
|||||||
type
|
type
|
||||||
|
|
||||||
TFpDebugDebugger = class;
|
TFpDebugDebugger = class;
|
||||||
|
TFPBreakpoint = class;
|
||||||
|
|
||||||
(* WorkerThreads:
|
(* WorkerThreads:
|
||||||
The below subclasses implement ONLY work that is done in the MAIN THREAD.
|
The below subclasses implement ONLY work that is done in the MAIN THREAD.
|
||||||
@ -132,6 +133,28 @@ type
|
|||||||
constructor Create(ADebugger: TFpDebugDebuggerBase; AWatchValue: TWatchValue);
|
constructor Create(ADebugger: TFpDebugDebuggerBase; AWatchValue: TWatchValue);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPointSetUpdate }
|
||||||
|
|
||||||
|
TFpThreadWorkerBreakPointSetUpdate = class(TFpThreadWorkerBreakPointSet)
|
||||||
|
private
|
||||||
|
FDbgBreakPoint: TFPBreakpoint;
|
||||||
|
protected
|
||||||
|
procedure UpdateBrkPoint_DecRef(Data: PtrInt = 0); override;
|
||||||
|
public
|
||||||
|
constructor Create(ADebugger: TFpDebugDebuggerBase; ADbgBreakPoint: TFPBreakpoint); overload;
|
||||||
|
procedure AbortSetBreak; override;
|
||||||
|
procedure RemoveBreakPoint_DecRef; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPointRemoveUpdate }
|
||||||
|
|
||||||
|
TFpThreadWorkerBreakPointRemoveUpdate = class(TFpThreadWorkerBreakPointRemove)
|
||||||
|
protected
|
||||||
|
procedure DoUnQueued; override;
|
||||||
|
public
|
||||||
|
constructor Create(ADebugger: TFpDebugDebuggerBase; ADbgBreakPoint: TFPBreakpoint); overload;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDbgControllerStepOverOrFinallyCmd
|
{ TDbgControllerStepOverOrFinallyCmd
|
||||||
Step over with detection for finally blocks
|
Step over with detection for finally blocks
|
||||||
}
|
}
|
||||||
@ -278,8 +301,6 @@ type
|
|||||||
FCacheLocation, FCacheLocation2: TDBGPtr;
|
FCacheLocation, FCacheLocation2: TDBGPtr;
|
||||||
FCacheBoolean: boolean;
|
FCacheBoolean: boolean;
|
||||||
FCachePointer: pointer;
|
FCachePointer: pointer;
|
||||||
FCacheReadWrite: TDBGWatchPointKind;
|
|
||||||
FCacheScope: TDBGWatchPointScope;
|
|
||||||
FCacheThreadId, FCacheStackFrame: Integer;
|
FCacheThreadId, FCacheStackFrame: Integer;
|
||||||
FCacheContext: TFpDbgSymbolScope;
|
FCacheContext: TFpDbgSymbolScope;
|
||||||
//
|
//
|
||||||
@ -336,33 +357,22 @@ type
|
|||||||
function GetIsIdle: Boolean; override;
|
function GetIsIdle: Boolean; override;
|
||||||
function GetCommands: TDBGCommands; override;
|
function GetCommands: TDBGCommands; override;
|
||||||
|
|
||||||
procedure LockCommandProcessing; override;
|
|
||||||
procedure UnLockCommandProcessing; override;
|
|
||||||
protected
|
protected
|
||||||
// Helper vars to run in debug-thread
|
// Helper vars to run in debug-thread
|
||||||
FCallStackEntryListThread: TDbgThread;
|
FCallStackEntryListThread: TDbgThread;
|
||||||
FCallStackEntryListFrameRequired: Integer;
|
FCallStackEntryListFrameRequired: Integer;
|
||||||
procedure DoAddBreakLine;
|
|
||||||
procedure DoAddBreakFuncLib;
|
procedure DoAddBreakFuncLib;
|
||||||
procedure DoAddBreakLocation;
|
procedure DoAddBreakLocation;
|
||||||
procedure DoAddBWatch;
|
|
||||||
procedure DoReadData;
|
procedure DoReadData;
|
||||||
procedure DoReadPartialData;
|
procedure DoReadPartialData;
|
||||||
procedure DoPrepareCallStackEntryList;
|
|
||||||
procedure DoFreeBreakpoint;
|
|
||||||
procedure DoFindContext;
|
procedure DoFindContext;
|
||||||
procedure DoSetStackFrameForBasePtr;
|
procedure DoSetStackFrameForBasePtr;
|
||||||
//
|
//
|
||||||
function AddBreak(const ALocation: TDbgPtr; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload;
|
function AddBreak(const ALocation: TDbgPtr; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload;
|
||||||
function AddBreak(const AFileName: String; ALine: Cardinal; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload;
|
|
||||||
function AddBreak(const AFuncName: String; ALib: TDbgLibrary = nil; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload;
|
function AddBreak(const AFuncName: String; ALib: TDbgLibrary = nil; AnEnabled: Boolean = True): TFpDbgBreakpoint; overload;
|
||||||
function AddWatch(const ALocation: TDBGPtr; ASize: Cardinal; AReadWrite: TDBGWatchPointKind;
|
|
||||||
AScope: TDBGWatchPointScope): TFpDbgBreakpoint;
|
|
||||||
procedure FreeBreakpoint(const ABreakpoint: TFpDbgBreakpoint);
|
|
||||||
function ReadData(const AAdress: TDbgPtr; const ASize: Cardinal; out AData): Boolean; inline;
|
function ReadData(const AAdress: TDbgPtr; const ASize: Cardinal; out AData): Boolean; inline;
|
||||||
function ReadData(const AAdress: TDbgPtr; const ASize: Cardinal; out AData; out ABytesRead: Cardinal): Boolean; inline;
|
function ReadData(const AAdress: TDbgPtr; const ASize: Cardinal; out AData; out ABytesRead: Cardinal): Boolean; inline;
|
||||||
function ReadAddress(const AAdress: TDbgPtr; out AData: TDBGPtr): Boolean;
|
function ReadAddress(const AAdress: TDbgPtr; out AData: TDBGPtr): Boolean;
|
||||||
procedure PrepareCallStackEntryList(AFrameRequired: Integer = -1; AThread: TDbgThread = nil); inline;
|
|
||||||
function SetStackFrameForBasePtr(ABasePtr: TDBGPtr; ASearchAssert: boolean = False;
|
function SetStackFrameForBasePtr(ABasePtr: TDBGPtr; ASearchAssert: boolean = False;
|
||||||
CurAddr: TDBGPtr = 0): TDBGPtr;
|
CurAddr: TDBGPtr = 0): TDBGPtr;
|
||||||
function FindSymbolScope(AThreadId, AStackFrame: Integer): TFpDbgSymbolScope; inline;
|
function FindSymbolScope(AThreadId, AStackFrame: Integer): TFpDbgSymbolScope; inline;
|
||||||
@ -373,6 +383,8 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(const AExternalDebugger: String); override;
|
constructor Create(const AExternalDebugger: String); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
procedure LockCommandProcessing; override;
|
||||||
|
procedure UnLockCommandProcessing; override;
|
||||||
function GetLocationRec(AnAddress: TDBGPtr=0; AnAddrOffset: Integer = 0): TDBGLocationRec;
|
function GetLocationRec(AnAddress: TDBGPtr=0; AnAddrOffset: Integer = 0): TDBGLocationRec;
|
||||||
function GetLocation: TDBGLocationRec; override;
|
function GetLocation: TDBGLocationRec; override;
|
||||||
class function Caption: String; override;
|
class function Caption: String; override;
|
||||||
@ -487,6 +499,7 @@ type
|
|||||||
|
|
||||||
TFPBreakpoint = class(TDBGBreakPoint)
|
TFPBreakpoint = class(TDBGBreakPoint)
|
||||||
private
|
private
|
||||||
|
FThreadWorker: TFpThreadWorkerBreakPoint;
|
||||||
FSetBreakFlag: boolean;
|
FSetBreakFlag: boolean;
|
||||||
FResetBreakFlag: boolean;
|
FResetBreakFlag: boolean;
|
||||||
FInternalBreakpoint: FpDbgClasses.TFpDbgBreakpoint;
|
FInternalBreakpoint: FpDbgClasses.TFpDbgBreakpoint;
|
||||||
@ -504,14 +517,7 @@ type
|
|||||||
{ TFPBreakpoints }
|
{ TFPBreakpoints }
|
||||||
|
|
||||||
TFPBreakpoints = class(TDBGBreakPoints)
|
TFPBreakpoints = class(TDBGBreakPoints)
|
||||||
private
|
|
||||||
FDelayedRemoveBreakpointList: TObjectList;
|
|
||||||
protected
|
|
||||||
procedure DoStateChange(const AOldState: TDBGState); override;
|
|
||||||
procedure AddBreakpointToDelayedRemoveList(ABreakpoint: FpDbgClasses.TFpDbgBreakpoint);
|
|
||||||
public
|
public
|
||||||
constructor Create(const ADebugger: TDebuggerIntf; const ABreakPointClass: TDBGBreakPointClass);
|
|
||||||
destructor Destroy; override;
|
|
||||||
function Find(AIntBReakpoint: FpDbgClasses.TFpDbgBreakpoint): TDBGBreakPoint;
|
function Find(AIntBReakpoint: FpDbgClasses.TFpDbgBreakpoint): TDBGBreakPoint;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -977,6 +983,89 @@ begin
|
|||||||
FWatchValue.DisplayFormat, FWatchValue.RepeatCount, FWatchValue.EvaluateFlags);
|
FWatchValue.DisplayFormat, FWatchValue.RepeatCount, FWatchValue.EvaluateFlags);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPointSetUpdate }
|
||||||
|
|
||||||
|
procedure TFpThreadWorkerBreakPointSetUpdate.UpdateBrkPoint_DecRef(Data: PtrInt
|
||||||
|
);
|
||||||
|
var
|
||||||
|
WorkItem: TFpThreadWorkerBreakPointRemoveUpdate;
|
||||||
|
begin
|
||||||
|
assert(system.ThreadID = classes.MainThreadID, 'TFpThreadWorkerBreakPointSetUpdate.UpdateBrkPoint_DecRef: system.ThreadID = classes.MainThreadID');
|
||||||
|
|
||||||
|
if FDbgBreakPoint <> nil then begin
|
||||||
|
assert(FDbgBreakPoint.FThreadWorker = Self, 'TFpThreadWorkerBreakPointSetUpdate.UpdateBrkPoint_DecRef: FDbgBreakPoint.FThreadWorker = Self');
|
||||||
|
FDbgBreakPoint.FThreadWorker := nil;
|
||||||
|
DecRef;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
FResetBreakPoint := True;
|
||||||
|
|
||||||
|
if FResetBreakPoint then begin
|
||||||
|
if InternalBreakpoint <> nil then begin
|
||||||
|
WorkItem := TFpThreadWorkerBreakPointRemoveUpdate.Create(FDebugger, InternalBreakpoint);
|
||||||
|
FpDebugger.FWorkQueue.PushItem(WorkItem);
|
||||||
|
WorkItem.DecRef;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if FDbgBreakPoint <> nil then begin
|
||||||
|
assert(FDbgBreakPoint.FInternalBreakpoint = nil, 'TFpThreadWorkerBreakPointSetUpdate.UpdateBrkPoint_DecRef: FDbgBreakPoint.FInternalBreakpoint = nil');
|
||||||
|
FDbgBreakPoint.FInternalBreakpoint := InternalBreakpoint;
|
||||||
|
if not assigned(InternalBreakpoint) then
|
||||||
|
FDbgBreakPoint.FValid:=vsInvalid // pending?
|
||||||
|
else
|
||||||
|
FDbgBreakPoint.FValid:=vsValid;
|
||||||
|
end;
|
||||||
|
|
||||||
|
UnQueue_DecRef;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TFpThreadWorkerBreakPointSetUpdate.Create(
|
||||||
|
ADebugger: TFpDebugDebuggerBase; ADbgBreakPoint: TFPBreakpoint);
|
||||||
|
var
|
||||||
|
CurThreadId, CurStackFrame: Integer;
|
||||||
|
begin
|
||||||
|
FDbgBreakPoint := ADbgBreakPoint;
|
||||||
|
case ADbgBreakPoint.Kind of
|
||||||
|
bpkAddress: inherited Create(ADebugger, ADbgBreakPoint.Address);
|
||||||
|
bpkSource: inherited Create(ADebugger, ADbgBreakPoint.Source, ADbgBreakPoint.Line);
|
||||||
|
bpkData: begin
|
||||||
|
TFpDebugDebugger(ADebugger).GetCurrentThreadAndStackFrame(CurThreadId, CurStackFrame);
|
||||||
|
inherited Create(ADebugger, ADbgBreakPoint.WatchData, ADbgBreakPoint.WatchScope,
|
||||||
|
ADbgBreakPoint.WatchKind, CurStackFrame, CurThreadId);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFpThreadWorkerBreakPointSetUpdate.AbortSetBreak;
|
||||||
|
begin
|
||||||
|
FResetBreakPoint := True;
|
||||||
|
RequestStop;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFpThreadWorkerBreakPointSetUpdate.RemoveBreakPoint_DecRef;
|
||||||
|
begin
|
||||||
|
assert(system.ThreadID = classes.MainThreadID, 'TFpThreadWorkerBreakPointSetUpdate.RemoveBreakPoint_DecRef: system.ThreadID = classes.MainThreadID');
|
||||||
|
FDbgBreakPoint := nil;
|
||||||
|
UnQueue_DecRef;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPointRemoveUpdate }
|
||||||
|
|
||||||
|
procedure TFpThreadWorkerBreakPointRemoveUpdate.DoUnQueued;
|
||||||
|
begin
|
||||||
|
if FInternalBreakpoint = nil then
|
||||||
|
exit;
|
||||||
|
FInternalBreakpoint.FreeByDbgProcess := True;
|
||||||
|
inherited DoUnQueued;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TFpThreadWorkerBreakPointRemoveUpdate.Create(
|
||||||
|
ADebugger: TFpDebugDebuggerBase; ADbgBreakPoint: TFPBreakpoint);
|
||||||
|
begin
|
||||||
|
inherited Create(ADebugger, ADbgBreakPoint.FInternalBreakpoint);
|
||||||
|
end;
|
||||||
|
|
||||||
{ TDbgControllerStepOverFirstFinallyLineCmd }
|
{ TDbgControllerStepOverFirstFinallyLineCmd }
|
||||||
|
|
||||||
procedure TDbgControllerStepOverFirstFinallyLineCmd.DoResolveEvent(
|
procedure TDbgControllerStepOverFirstFinallyLineCmd.DoResolveEvent(
|
||||||
@ -1469,7 +1558,6 @@ end;
|
|||||||
|
|
||||||
procedure TFPLocals.RequestData(ALocals: TLocals);
|
procedure TFPLocals.RequestData(ALocals: TLocals);
|
||||||
var
|
var
|
||||||
AController: TDbgController;
|
|
||||||
WorkItem: TFpThreadWorkerLocalsUpdate;
|
WorkItem: TFpThreadWorkerLocalsUpdate;
|
||||||
begin
|
begin
|
||||||
if not FpDebugger.IsPausedAndValid then begin
|
if not FpDebugger.IsPausedAndValid then begin
|
||||||
@ -1484,48 +1572,6 @@ end;
|
|||||||
|
|
||||||
{ TFPBreakpoints }
|
{ TFPBreakpoints }
|
||||||
|
|
||||||
procedure TFPBreakpoints.DoStateChange(const AOldState: TDBGState);
|
|
||||||
var
|
|
||||||
ABrkPoint: FpDbgClasses.TFpDbgBreakpoint;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
inherited DoStateChange(AOldState);
|
|
||||||
if (Debugger.State in [dsPause, dsInternalPause, dsStop]) or
|
|
||||||
(TFpDebugDebugger(Debugger).FSendingEvents and (Debugger.State in [dsRun, dsInit]))
|
|
||||||
then
|
|
||||||
begin
|
|
||||||
if FDelayedRemoveBreakpointList.Count>0 then begin
|
|
||||||
debuglnEnter(DBG_BREAKPOINTS, ['TFPBreakpoints.DoStateChange REMOVE DELAYED']);
|
|
||||||
for i := FDelayedRemoveBreakpointList.Count-1 downto 0 do
|
|
||||||
begin
|
|
||||||
ABrkPoint := FpDbgClasses.TFpDbgBreakpoint(FDelayedRemoveBreakpointList[i]);
|
|
||||||
TFpDebugDebugger(Debugger).FDbgController.CurrentProcess.RemoveBreak(ABrkPoint);
|
|
||||||
TFpDebugDebugger(Debugger).FreeBreakpoint(ABrkPoint);
|
|
||||||
ABrkPoint := nil;
|
|
||||||
FDelayedRemoveBreakpointList.Delete(i);
|
|
||||||
end;
|
|
||||||
debuglnExit(DBG_BREAKPOINTS, ['<< TFPBreakpoints.DoStateChange REMOVE DELAYED ' ]);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TFPBreakpoints.AddBreakpointToDelayedRemoveList(ABreakpoint: FpDbgClasses.TFpDbgBreakpoint);
|
|
||||||
begin
|
|
||||||
FDelayedRemoveBreakpointList.Add(ABreakpoint);
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TFPBreakpoints.Create(const ADebugger: TDebuggerIntf; const ABreakPointClass: TDBGBreakPointClass);
|
|
||||||
begin
|
|
||||||
inherited create(ADebugger, ABreakPointClass);
|
|
||||||
FDelayedRemoveBreakpointList := TObjectList.Create(false);
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TFPBreakpoints.Destroy;
|
|
||||||
begin
|
|
||||||
FDelayedRemoveBreakpointList.Free;
|
|
||||||
inherited Destroy;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFPBreakpoints.Find(AIntBReakpoint: FpDbgClasses.TFpDbgBreakpoint): TDBGBreakPoint;
|
function TFPBreakpoints.Find(AIntBReakpoint: FpDbgClasses.TFpDbgBreakpoint): TDBGBreakPoint;
|
||||||
var
|
var
|
||||||
i: integer;
|
i: integer;
|
||||||
@ -1540,69 +1586,60 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPBreakpoint.SetBreak;
|
procedure TFPBreakpoint.SetBreak;
|
||||||
var
|
|
||||||
CurThreadId, CurStackFrame: Integer;
|
|
||||||
CurContext: TFpDbgSymbolScope;
|
|
||||||
WatchPasExpr: TFpPascalExpression;
|
|
||||||
R: TFpValue;
|
|
||||||
s: TFpDbgValueSize;
|
|
||||||
begin
|
begin
|
||||||
assert(FInternalBreakpoint=nil);
|
|
||||||
debuglnEnter(DBG_BREAKPOINTS, ['>> TFPBreakpoint.SetBreak ADD ',FSource,':',FLine,'/',dbghex(Address),' ' ]);
|
debuglnEnter(DBG_BREAKPOINTS, ['>> TFPBreakpoint.SetBreak ADD ',FSource,':',FLine,'/',dbghex(Address),' ' ]);
|
||||||
case Kind of
|
assert(FThreadWorker = nil, 'TFPBreakpoint.SetBreak: FThreadWorker = nil');
|
||||||
bpkAddress: FInternalBreakpoint := TFpDebugDebugger(Debugger).AddBreak(Address);
|
assert(FInternalBreakpoint=nil);
|
||||||
bpkSource: FInternalBreakpoint := TFpDebugDebugger(Debugger).AddBreak(Source, cardinal(Line));
|
|
||||||
bpkData: begin
|
FThreadWorker := TFpThreadWorkerBreakPointSetUpdate.Create(TFpDebugDebugger(Debugger), Self);
|
||||||
TFpDebugDebugger(Debugger).GetCurrentThreadAndStackFrame(CurThreadId, CurStackFrame);
|
TFpDebugDebugger(Debugger).FWorkQueue.PushItem(FThreadWorker);
|
||||||
CurContext := TFpDebugDebugger(Debugger).GetContextForEvaluate(CurThreadId, CurStackFrame);
|
|
||||||
if CurContext <> nil then begin
|
|
||||||
WatchPasExpr := TFpPascalExpression.Create(WatchData, CurContext);
|
|
||||||
R := WatchPasExpr.ResultValue; // Address and Size
|
|
||||||
// TODO: Cache current value
|
|
||||||
if WatchPasExpr.Valid and IsTargetNotNil(R.Address) and R.GetSize(s) then begin
|
|
||||||
// pass context
|
|
||||||
FInternalBreakpoint := TFpDebugDebugger(Debugger).AddWatch(R.Address.Address, SizeToFullBytes(s), WatchKind, WatchScope);
|
|
||||||
end;
|
|
||||||
WatchPasExpr.Free;
|
|
||||||
CurContext.ReleaseReference;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
debuglnExit(DBG_BREAKPOINTS, ['<< TFPBreakpoint.SetBreak ' ]);
|
|
||||||
FIsSet:=true;
|
FIsSet:=true;
|
||||||
if not assigned(FInternalBreakpoint) then
|
debuglnExit(DBG_BREAKPOINTS, ['<< TFPBreakpoint.SetBreak ' ]);
|
||||||
FValid:=vsInvalid // pending?
|
|
||||||
else
|
|
||||||
FValid:=vsValid;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFPBreakpoint.ResetBreak;
|
procedure TFPBreakpoint.ResetBreak;
|
||||||
|
var
|
||||||
|
WorkItem: TFpThreadWorkerBreakPointRemoveUpdate;
|
||||||
begin
|
begin
|
||||||
|
FIsSet:=false;
|
||||||
|
if FThreadWorker <> nil then begin
|
||||||
|
debugln(DBG_BREAKPOINTS, ['>> TFPBreakpoint.ResetBreak CANCEL / REMOVE ',FSource,':',FLine,'/',dbghex(Address),' ' ]);
|
||||||
|
assert(FThreadWorker is TFpThreadWorkerBreakPointSetUpdate, 'TFPBreakpoint.ResetBreak: FThreadWorker is TFpThreadWorkerBreakPointSetUpdate');
|
||||||
|
assert(FInternalBreakpoint = nil, 'TFPBreakpoint.ResetBreak: FInternalBreakpoint = nil');
|
||||||
|
FThreadWorker.AbortSetBreak;
|
||||||
|
FThreadWorker.RemoveBreakPoint_DecRef;
|
||||||
|
FThreadWorker.DecRef;
|
||||||
|
FThreadWorker := nil;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
// If Debugger is not assigned, the Controller's currentprocess is already
|
// If Debugger is not assigned, the Controller's currentprocess is already
|
||||||
// freed. And so are the corresponding InternalBreakpoint's.
|
// freed. And so are the corresponding InternalBreakpoint's.
|
||||||
if assigned(Debugger) and assigned(FInternalBreakpoint) then
|
if assigned(Debugger) and assigned(FInternalBreakpoint) then
|
||||||
begin
|
begin
|
||||||
debuglnEnter(DBG_BREAKPOINTS, ['>> TFPBreakpoint.ResetBreak REMOVE ',FSource,':',FLine,'/',dbghex(Address),' ' ]);
|
debuglnEnter(DBG_BREAKPOINTS, ['>> TFPBreakpoint.ResetBreak REMOVE ',FSource,':',FLine,'/',dbghex(Address),' ' ]);
|
||||||
TFpDebugDebugger(Debugger).FDbgController.CurrentProcess.RemoveBreak(FInternalBreakpoint);
|
WorkItem := TFpThreadWorkerBreakPointRemoveUpdate.Create(TFpDebugDebugger(Debugger), Self);
|
||||||
TFpDebugDebugger(Debugger).FreeBreakpoint(FInternalBreakpoint);
|
TFpDebugDebugger(Debugger).FWorkQueue.PushItem(WorkItem);
|
||||||
|
WorkItem.DecRef;
|
||||||
FInternalBreakpoint := nil;
|
FInternalBreakpoint := nil;
|
||||||
debuglnExit(DBG_BREAKPOINTS, ['<< TFPBreakpoint.ResetBreak ' ]);
|
debuglnExit(DBG_BREAKPOINTS, ['<< TFPBreakpoint.ResetBreak ' ]);
|
||||||
end;
|
end;
|
||||||
FIsSet:=false;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TFPBreakpoint.Destroy;
|
destructor TFPBreakpoint.Destroy;
|
||||||
begin
|
begin
|
||||||
if assigned(Debugger) and
|
(* No need to request a pause. This will run, as soon as the debugger gets to the next pause.
|
||||||
( (Debugger.State = dsRun) and (not TFpDebugDebugger(Debugger).FSendingEvents) ) and
|
If the next pause is a hit on this breakpoint, then it will be ignored
|
||||||
assigned(FInternalBreakpoint) then
|
*)
|
||||||
begin
|
ResetBreak;
|
||||||
TFPBreakpoints(Collection).AddBreakpointToDelayedRemoveList(FInternalBreakpoint);
|
|
||||||
FInternalBreakpoint:=nil;
|
if FThreadWorker <> nil then begin
|
||||||
// TFpDebugDebugger(Debugger).QuickPause;
|
FThreadWorker.AbortSetBreak;
|
||||||
end
|
FThreadWorker.RemoveBreakPoint_DecRef;
|
||||||
else
|
FThreadWorker.DecRef;
|
||||||
ResetBreak;
|
FThreadWorker := nil;
|
||||||
|
end;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1625,11 +1662,7 @@ begin
|
|||||||
end
|
end
|
||||||
else if Debugger.State = dsStop then
|
else if Debugger.State = dsStop then
|
||||||
begin
|
begin
|
||||||
debuglnEnter(DBG_BREAKPOINTS, ['>> TFPBreakpoint.DoStateChange REMOVE ',FSource,':',FLine,'/',dbghex(Address),' ' ]);
|
ResetBreak;
|
||||||
TFpDebugDebugger(Debugger).FreeBreakpoint(FInternalBreakpoint);
|
|
||||||
debuglnExit(DBG_BREAKPOINTS, ['<< TFPBreakpoint.DoStateChange ' ]);
|
|
||||||
FInternalBreakpoint := nil;
|
|
||||||
FIsSet:=false;
|
|
||||||
end;
|
end;
|
||||||
inherited DoStateChange(AOldState);
|
inherited DoStateChange(AOldState);
|
||||||
end;
|
end;
|
||||||
@ -1646,7 +1679,7 @@ begin
|
|||||||
else if not Enabled and FIsSet then
|
else if not Enabled and FIsSet then
|
||||||
FResetBreakFlag := True;
|
FResetBreakFlag := True;
|
||||||
end
|
end
|
||||||
else if (ADebugger.State = dsRun) and ((Enabled and not FIsSet) or (not Enabled and FIsSet)) then
|
else if (ADebugger.State = dsRun) and (Enabled and not FIsSet) then
|
||||||
ADebugger.QuickPause;
|
ADebugger.QuickPause;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
@ -2894,8 +2927,6 @@ var
|
|||||||
Context: TFpDbgSymbolScope;
|
Context: TFpDbgSymbolScope;
|
||||||
PasExpr: TFpPascalExpression;
|
PasExpr: TFpPascalExpression;
|
||||||
Opts: TFpInt3DebugBreakOptions;
|
Opts: TFpInt3DebugBreakOptions;
|
||||||
StackEntry: TDbgCallstackEntry;
|
|
||||||
s: String;
|
|
||||||
begin
|
begin
|
||||||
// If a user single steps to an excepiton handler, do not open the dialog (there is no continue possible)
|
// If a user single steps to an excepiton handler, do not open the dialog (there is no continue possible)
|
||||||
if AnEventType = deBreakpoint then
|
if AnEventType = deBreakpoint then
|
||||||
@ -2904,7 +2935,7 @@ begin
|
|||||||
|
|
||||||
if assigned(Breakpoint) then begin
|
if assigned(Breakpoint) then begin
|
||||||
ABreakPoint := TFPBreakpoints(BreakPoints).Find(Breakpoint);
|
ABreakPoint := TFPBreakpoints(BreakPoints).Find(Breakpoint);
|
||||||
if ABreakPoint <> nil then begin
|
if (ABreakPoint <> nil) and (ABreakPoint.Enabled) then begin
|
||||||
|
|
||||||
// TODO: parse expression when breakpoin is created / so invalid expressions do not need to be handled here
|
// TODO: parse expression when breakpoin is created / so invalid expressions do not need to be handled here
|
||||||
if ABreakPoint.Expression <> '' then begin
|
if ABreakPoint.Expression <> '' then begin
|
||||||
@ -2943,6 +2974,8 @@ begin
|
|||||||
'', ftInformation, [frOk]);
|
'', ftInformation, [frOk]);
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
continue := True; // removed or disabled breakpoint
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if (AnEventType = deHardCodedBreakpoint) and (FDbgController.CurrentThread <> nil) then begin
|
if (AnEventType = deHardCodedBreakpoint) and (FDbgController.CurrentThread <> nil) then begin
|
||||||
@ -3033,7 +3066,6 @@ var
|
|||||||
EvalFlags: TDBGEvaluateFlags;
|
EvalFlags: TDBGEvaluateFlags;
|
||||||
AConsoleTty, ResText: string;
|
AConsoleTty, ResText: string;
|
||||||
addr: TDBGPtrArray;
|
addr: TDBGPtrArray;
|
||||||
ResType: TDBGType;
|
|
||||||
Cmd: TDBGCommand;
|
Cmd: TDBGCommand;
|
||||||
WorkItem: TFpThreadWorkerControllerRun;
|
WorkItem: TFpThreadWorkerControllerRun;
|
||||||
AThreadId, AStackFrame: Integer;
|
AThreadId, AStackFrame: Integer;
|
||||||
@ -3317,8 +3349,7 @@ end;
|
|||||||
procedure TFpDebugDebugger.RunQuickPauseTasks(AForce: Boolean);
|
procedure TFpDebugDebugger.RunQuickPauseTasks(AForce: Boolean);
|
||||||
begin
|
begin
|
||||||
if AForce or
|
if AForce or
|
||||||
FQuickPause or
|
FQuickPause
|
||||||
(TFPBreakpoints(Breakpoints).FDelayedRemoveBreakpointList.Count > 0)
|
|
||||||
then
|
then
|
||||||
TFPBreakpoints(Breakpoints).DoStateChange(dsRun);
|
TFPBreakpoints(Breakpoints).DoStateChange(dsRun);
|
||||||
end;
|
end;
|
||||||
@ -3395,11 +3426,6 @@ begin
|
|||||||
Result := (FWorkQueue.Count = 0) or FIsIdle;
|
Result := (FWorkQueue.Count = 0) or FIsIdle;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpDebugDebugger.DoAddBreakLine;
|
|
||||||
begin
|
|
||||||
FCacheBreakpoint := TDbgInstance(FDbgController.CurrentProcess).AddBreak(FCacheFileName, FCacheLine, FCacheBoolean);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TFpDebugDebugger.DoAddBreakFuncLib;
|
procedure TFpDebugDebugger.DoAddBreakFuncLib;
|
||||||
begin
|
begin
|
||||||
if FCacheLib <> nil then
|
if FCacheLib <> nil then
|
||||||
@ -3416,11 +3442,6 @@ begin
|
|||||||
FCacheBreakpoint := FDbgController.CurrentProcess.AddBreak(FCacheLocation, FCacheBoolean);
|
FCacheBreakpoint := FDbgController.CurrentProcess.AddBreak(FCacheLocation, FCacheBoolean);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpDebugDebugger.DoAddBWatch;
|
|
||||||
begin
|
|
||||||
FCacheBreakpoint := FDbgController.CurrentProcess.AddWatch(FCacheLocation, FCacheLine, FCacheReadWrite, FCacheScope);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TFpDebugDebugger.DoReadData;
|
procedure TFpDebugDebugger.DoReadData;
|
||||||
begin
|
begin
|
||||||
FCacheBoolean:=FDbgController.CurrentProcess.ReadData(FCacheLocation, FCacheLine, FCachePointer^);
|
FCacheBoolean:=FDbgController.CurrentProcess.ReadData(FCacheLocation, FCacheLine, FCachePointer^);
|
||||||
@ -3431,16 +3452,6 @@ begin
|
|||||||
FCacheBoolean:=FDbgController.CurrentProcess.ReadData(FCacheLocation, FCacheLine, FCachePointer^, FCacheBytesRead);
|
FCacheBoolean:=FDbgController.CurrentProcess.ReadData(FCacheLocation, FCacheLine, FCachePointer^, FCacheBytesRead);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpDebugDebugger.DoPrepareCallStackEntryList;
|
|
||||||
begin
|
|
||||||
FCallStackEntryListThread.PrepareCallStackEntryList(FCallStackEntryListFrameRequired);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TFpDebugDebugger.DoFreeBreakpoint;
|
|
||||||
begin
|
|
||||||
FCacheBreakpoint.Free;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TFpDebugDebugger.DoFindContext;
|
procedure TFpDebugDebugger.DoFindContext;
|
||||||
begin
|
begin
|
||||||
FCacheContext := FDbgController.CurrentProcess.FindSymbolScope(FCacheThreadId, FCacheStackFrame);
|
FCacheContext := FDbgController.CurrentProcess.FindSymbolScope(FCacheThreadId, FCacheStackFrame);
|
||||||
@ -3473,22 +3484,6 @@ begin
|
|||||||
result := FDbgController.CurrentProcess.AddBreak(ALocation, AnEnabled);
|
result := FDbgController.CurrentProcess.AddBreak(ALocation, AnEnabled);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpDebugDebugger.AddBreak(const AFileName: String; ALine: Cardinal;
|
|
||||||
AnEnabled: Boolean): TFpDbgBreakpoint;
|
|
||||||
begin
|
|
||||||
if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
|
|
||||||
begin
|
|
||||||
FCacheFileName:=AFileName;
|
|
||||||
FCacheLine:=ALine;
|
|
||||||
FCacheBoolean:=AnEnabled;
|
|
||||||
FCacheBreakpoint := nil;
|
|
||||||
ExecuteInDebugThread(@DoAddBreakLine);
|
|
||||||
result := FCacheBreakpoint;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
result := TDbgInstance(FDbgController.CurrentProcess).AddBreak(AFileName, ALine, AnEnabled);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFpDebugDebugger.AddBreak(const AFuncName: String; ALib: TDbgLibrary;
|
function TFpDebugDebugger.AddBreak(const AFuncName: String; ALib: TDbgLibrary;
|
||||||
AnEnabled: Boolean): TFpDbgBreakpoint;
|
AnEnabled: Boolean): TFpDbgBreakpoint;
|
||||||
begin
|
begin
|
||||||
@ -3508,37 +3503,6 @@ begin
|
|||||||
result := TDbgInstance(FDbgController.CurrentProcess).AddBreak(AFuncName, AnEnabled);
|
result := TDbgInstance(FDbgController.CurrentProcess).AddBreak(AFuncName, AnEnabled);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpDebugDebugger.AddWatch(const ALocation: TDBGPtr; ASize: Cardinal;
|
|
||||||
AReadWrite: TDBGWatchPointKind; AScope: TDBGWatchPointScope
|
|
||||||
): TFpDbgBreakpoint;
|
|
||||||
begin
|
|
||||||
if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
|
|
||||||
begin
|
|
||||||
FCacheLocation:=ALocation;
|
|
||||||
FCacheLine:=ASize;
|
|
||||||
FCacheReadWrite:=AReadWrite;
|
|
||||||
FCacheScope:=AScope;
|
|
||||||
FCacheBreakpoint := nil;
|
|
||||||
ExecuteInDebugThread(@DoAddBWatch);
|
|
||||||
result := FCacheBreakpoint;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
result := FDbgController.CurrentProcess.AddWatch(ALocation, ASize, AReadWrite, AScope);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TFpDebugDebugger.FreeBreakpoint(
|
|
||||||
const ABreakpoint: TFpDbgBreakpoint);
|
|
||||||
begin
|
|
||||||
if ABreakpoint = nil then exit;
|
|
||||||
if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
|
|
||||||
begin
|
|
||||||
FCacheBreakpoint:=ABreakpoint;
|
|
||||||
ExecuteInDebugThread(@DoFreeBreakpoint);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
ABreakpoint.Free;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFpDebugDebugger.ReadData(const AAdress: TDbgPtr; const ASize: Cardinal; out AData): Boolean;
|
function TFpDebugDebugger.ReadData(const AAdress: TDbgPtr; const ASize: Cardinal; out AData): Boolean;
|
||||||
begin
|
begin
|
||||||
if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
|
if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
|
||||||
@ -3591,26 +3555,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpDebugDebugger.PrepareCallStackEntryList(AFrameRequired: Integer;
|
|
||||||
AThread: TDbgThread);
|
|
||||||
begin
|
|
||||||
if AThread = nil then
|
|
||||||
AThread := FDbgController.CurrentThread;
|
|
||||||
// In case of linux, check if required, before handind to other thread
|
|
||||||
if (AFrameRequired >= 0) and
|
|
||||||
(AThread.CallStackEntryList <> nil) and
|
|
||||||
(AFrameRequired < AThread.CallStackEntryList.Count) then
|
|
||||||
exit;
|
|
||||||
if FDbgController.CurrentProcess.RequiresExecutionInDebuggerThread then
|
|
||||||
begin
|
|
||||||
FCallStackEntryListThread := AThread;
|
|
||||||
FCallStackEntryListFrameRequired := AFrameRequired;
|
|
||||||
ExecuteInDebugThread(@DoPrepareCallStackEntryList);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
AThread.PrepareCallStackEntryList(AFrameRequired);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TFpDebugDebugger.SetStackFrameForBasePtr(ABasePtr: TDBGPtr;
|
function TFpDebugDebugger.SetStackFrameForBasePtr(ABasePtr: TDBGPtr;
|
||||||
ASearchAssert: boolean; CurAddr: TDBGPtr): TDBGPtr;
|
ASearchAssert: boolean; CurAddr: TDBGPtr): TDBGPtr;
|
||||||
const
|
const
|
||||||
|
@ -274,6 +274,51 @@ type
|
|||||||
procedure DoExecute; override;
|
procedure DoExecute; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPoint }
|
||||||
|
|
||||||
|
TFpThreadWorkerBreakPoint = class(TFpDbgDebggerThreadWorkerItem)
|
||||||
|
public
|
||||||
|
procedure RemoveBreakPoint_DecRef; virtual;
|
||||||
|
procedure AbortSetBreak; virtual;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPointSet }
|
||||||
|
|
||||||
|
TFpThreadWorkerBreakPointSet = class(TFpThreadWorkerBreakPoint)
|
||||||
|
private
|
||||||
|
FInternalBreakpoint: FpDbgClasses.TFpDbgBreakpoint;
|
||||||
|
FKind: TDBGBreakPointKind;
|
||||||
|
FAddress: TDBGPtr;
|
||||||
|
FSource: String;
|
||||||
|
FLine: Integer;
|
||||||
|
FStackFrame, FThreadId: Integer;
|
||||||
|
FWatchData: String;
|
||||||
|
FWatchScope: TDBGWatchPointScope;
|
||||||
|
FWatchKind: TDBGWatchPointKind;
|
||||||
|
protected
|
||||||
|
FResetBreakPoint: Boolean;
|
||||||
|
procedure UpdateBrkPoint_DecRef(Data: PtrInt = 0); virtual; abstract;
|
||||||
|
procedure DoExecute; override;
|
||||||
|
public
|
||||||
|
constructor Create(ADebugger: TFpDebugDebuggerBase; AnAddress: TDBGPtr);
|
||||||
|
constructor Create(ADebugger: TFpDebugDebuggerBase; ASource: String; ALine: Integer);
|
||||||
|
constructor Create(ADebugger: TFpDebugDebuggerBase;
|
||||||
|
AWatchData: String; AWatchScope: TDBGWatchPointScope; AWatchKind: TDBGWatchPointKind;
|
||||||
|
AStackFrame, AThreadId: Integer);
|
||||||
|
property InternalBreakpoint: FpDbgClasses.TFpDbgBreakpoint read FInternalBreakpoint;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPointRemove }
|
||||||
|
|
||||||
|
TFpThreadWorkerBreakPointRemove = class(TFpThreadWorkerBreakPoint)
|
||||||
|
protected
|
||||||
|
FInternalBreakpoint: FpDbgClasses.TFpDbgBreakpoint;
|
||||||
|
procedure DoExecute; override;
|
||||||
|
public
|
||||||
|
constructor Create(ADebugger: TFpDebugDebuggerBase; AnInternalBreakpoint: FpDbgClasses.TFpDbgBreakpoint);
|
||||||
|
property InternalBreakpoint: FpDbgClasses.TFpDbgBreakpoint read FInternalBreakpoint;
|
||||||
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{ TFpDbgDebggerThreadWorkerItem }
|
{ TFpDbgDebggerThreadWorkerItem }
|
||||||
@ -818,5 +863,100 @@ begin
|
|||||||
Queue(@UpdateWatch_DecRef);
|
Queue(@UpdateWatch_DecRef);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPoint }
|
||||||
|
|
||||||
|
procedure TFpThreadWorkerBreakPoint.RemoveBreakPoint_DecRef;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFpThreadWorkerBreakPoint.AbortSetBreak;
|
||||||
|
begin
|
||||||
|
//
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPointSet }
|
||||||
|
|
||||||
|
procedure TFpThreadWorkerBreakPointSet.DoExecute;
|
||||||
|
var
|
||||||
|
CurContext: TFpDbgSymbolScope;
|
||||||
|
WatchPasExpr: TFpPascalExpression;
|
||||||
|
R: TFpValue;
|
||||||
|
s: TFpDbgValueSize;
|
||||||
|
begin
|
||||||
|
case FKind of
|
||||||
|
bpkAddress:
|
||||||
|
FInternalBreakpoint := FDebugger.FDbgController.CurrentProcess.AddBreak(FAddress, True);
|
||||||
|
bpkSource:
|
||||||
|
FInternalBreakpoint := FDebugger.FDbgController.CurrentProcess.AddBreak(FSource, FLine, True);
|
||||||
|
bpkData: begin
|
||||||
|
CurContext := FDebugger.FDbgController.CurrentProcess.FindSymbolScope(FThreadId, FStackFrame);
|
||||||
|
if CurContext <> nil then begin
|
||||||
|
WatchPasExpr := TFpPascalExpression.Create(FWatchData, CurContext);
|
||||||
|
R := WatchPasExpr.ResultValue; // Address and Size
|
||||||
|
// TODO: Cache current value
|
||||||
|
if WatchPasExpr.Valid and IsTargetNotNil(R.Address) and R.GetSize(s) then begin
|
||||||
|
// pass context
|
||||||
|
FInternalBreakpoint := FDebugger.FDbgController.CurrentProcess.AddWatch(R.Address.Address, SizeToFullBytes(s), FWatchKind, FWatchScope);
|
||||||
|
end;
|
||||||
|
WatchPasExpr.Free;
|
||||||
|
CurContext.ReleaseReference;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if FResetBreakPoint then begin
|
||||||
|
FDebugger.FDbgController.CurrentProcess.RemoveBreak(FInternalBreakpoint);
|
||||||
|
FreeAndNil(FInternalBreakpoint);
|
||||||
|
end;
|
||||||
|
Queue(@UpdateBrkPoint_DecRef);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TFpThreadWorkerBreakPointSet.Create(ADebugger: TFpDebugDebuggerBase; AnAddress: TDBGPtr);
|
||||||
|
begin
|
||||||
|
FKind := bpkAddress;
|
||||||
|
FAddress := AnAddress;
|
||||||
|
inherited Create(ADebugger, twpUser);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TFpThreadWorkerBreakPointSet.Create(
|
||||||
|
ADebugger: TFpDebugDebuggerBase; ASource: String; ALine: Integer);
|
||||||
|
begin
|
||||||
|
FKind := bpkSource;
|
||||||
|
FSource := ASource;
|
||||||
|
FLine := ALine;
|
||||||
|
inherited Create(ADebugger, twpUser);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TFpThreadWorkerBreakPointSet.Create(
|
||||||
|
ADebugger: TFpDebugDebuggerBase; AWatchData: String;
|
||||||
|
AWatchScope: TDBGWatchPointScope; AWatchKind: TDBGWatchPointKind;
|
||||||
|
AStackFrame, AThreadId: Integer);
|
||||||
|
begin
|
||||||
|
FKind := bpkData;
|
||||||
|
FWatchData := AWatchData;
|
||||||
|
FWatchScope := AWatchScope;
|
||||||
|
FWatchKind := AWatchKind;
|
||||||
|
FStackFrame := AStackFrame;
|
||||||
|
FThreadId := AThreadId;
|
||||||
|
inherited Create(ADebugger, twpUser);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TFpThreadWorkerBreakPointRemove }
|
||||||
|
|
||||||
|
procedure TFpThreadWorkerBreakPointRemove.DoExecute;
|
||||||
|
begin
|
||||||
|
if (FDebugger.FDbgController <> nil) and (FDebugger.FDbgController.CurrentProcess <> nil) then
|
||||||
|
FDebugger.FDbgController.CurrentProcess.RemoveBreak(FInternalBreakpoint);
|
||||||
|
FreeAndNil(FInternalBreakpoint);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TFpThreadWorkerBreakPointRemove.Create(
|
||||||
|
ADebugger: TFpDebugDebuggerBase;
|
||||||
|
AnInternalBreakpoint: FpDbgClasses.TFpDbgBreakpoint);
|
||||||
|
begin
|
||||||
|
FInternalBreakpoint := AnInternalBreakpoint;
|
||||||
|
inherited Create(ADebugger, twpUser);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user