mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-27 00:22:01 +02:00
lldb debugger: breakpoint handling (honour most brk-properties)
git-svn-id: trunk@58435 -
This commit is contained in:
parent
e23fd4d433
commit
c7974af7b9
@ -92,6 +92,7 @@ type
|
||||
procedure Cancel;
|
||||
function IsSuccess: Boolean;
|
||||
function IsCompleted: boolean;
|
||||
function IsRunning: boolean;
|
||||
procedure MarkAsSuccess; // calls DoInstructionFinished // releases the instruction
|
||||
procedure MarkAsFailed; // calls DoInstructionFinished // releases the instruction
|
||||
|
||||
@ -261,7 +262,7 @@ end;
|
||||
|
||||
{ TDBGInstruction }
|
||||
|
||||
function TDBGInstruction.GetCommandAsString: String;
|
||||
function TDBGInstruction.GetCommandAsString(): String;
|
||||
begin
|
||||
Result := FCommand;
|
||||
end;
|
||||
@ -342,6 +343,11 @@ begin
|
||||
Result := (FState = disComleted) or (FState = disFailed);
|
||||
end;
|
||||
|
||||
function TDBGInstruction.IsRunning: boolean;
|
||||
begin
|
||||
Result := (FState = disDataSent) or (FState = disContentReceived);
|
||||
end;
|
||||
|
||||
procedure TDBGInstruction.MarkAsSuccess;
|
||||
begin
|
||||
debugln(['TDBGInstruction.MarkAsSuccess SUCCESS ', Command]);
|
||||
|
@ -283,23 +283,36 @@ type
|
||||
TLldbBreakPoint = class(TDBGBreakPoint)
|
||||
private
|
||||
FBreakID: Integer;
|
||||
procedure BreakInstructionFinished(Sender: TObject);
|
||||
FCurrentInstruction: TLldbInstruction;
|
||||
FState: (bpDone, bpNeedSet, bpNeedDel);
|
||||
FUpdateState: set of (buEnabled, buCondition);
|
||||
procedure InstructionDeleteBreakFinished(Sender: TObject);
|
||||
procedure InstructionSetBreakFinished(Sender: TObject);
|
||||
procedure InstructionUpdateBreakFinished(Sender: TObject);
|
||||
procedure SetBreakPoint;
|
||||
procedure ReleaseBreakPoint;
|
||||
procedure UpdateProperties;
|
||||
procedure DoCurrentInstructionFinished;
|
||||
procedure CancelCurrentInstruction;
|
||||
protected
|
||||
procedure DoStateChange(const AOldState: TDBGState); override;
|
||||
procedure DoEndUpdate; override;
|
||||
procedure DoEnableChange; override;
|
||||
procedure DoExpressionChange; override;
|
||||
public
|
||||
// constructor Create(ACollection: TCollection); override;
|
||||
// destructor Destroy; override;
|
||||
destructor Destroy; override;
|
||||
// procedure DoLogExpression(const AnExpression: String); override;
|
||||
procedure SetLocation(const ASource: String; const ALine: Integer); override;
|
||||
// procedure SetWatch(const AData: String; const AScope: TDBGWatchPointScope;
|
||||
// const AKind: TDBGWatchPointKind); override;
|
||||
end;
|
||||
|
||||
{ TLldbBreakPoints }
|
||||
|
||||
TLldbBreakPoints = class(TDBGBreakPoints)
|
||||
protected
|
||||
// function FindById(AnId: Integer): TGDBMIBreakPoint;
|
||||
function FindById(AnId: Integer): TLldbBreakPoint;
|
||||
end;
|
||||
|
||||
{%endregion ^^^^^ BreakPoint ^^^^^ }
|
||||
@ -595,42 +608,192 @@ procedure TLldbBreakPoint.SetBreakPoint;
|
||||
var
|
||||
i: Integer;
|
||||
s: String;
|
||||
Instr: TLldbInstructionBreakSet;
|
||||
Instr: TLldbInstruction;
|
||||
begin
|
||||
debugln(['TLldbBreakPoint.SetBreakPoint ']);
|
||||
i := LastPos(PathDelim, Source);
|
||||
if i > 0 then
|
||||
s := Copy(Source, i+1, Length(Source))
|
||||
else
|
||||
s := Source;
|
||||
Instr := TLldbInstructionBreakSet.Create(s, Line);
|
||||
Instr.OnFinish := @BreakInstructionFinished;
|
||||
// TLldbDebugger(Debugger).QueueCommand();
|
||||
if not (Debugger.State in [dsPause, dsInternalPause, dsRun]) then
|
||||
exit;
|
||||
debugln(['TLldbBreakPoint.SetBreakPoint ']);
|
||||
if (FCurrentInstruction <> nil) then begin
|
||||
if FCurrentInstruction.IsRunning then begin
|
||||
FState := bpNeedSet;
|
||||
exit;
|
||||
end
|
||||
else begin
|
||||
CancelCurrentInstruction;
|
||||
end;
|
||||
end;
|
||||
FState := bpDone;
|
||||
|
||||
if FBreakID <> 0 then begin
|
||||
UpdateProperties;
|
||||
exit;
|
||||
end;
|
||||
|
||||
case Kind of
|
||||
bpkSource: begin
|
||||
i := LastPos(PathDelim, Source);
|
||||
if i > 0 then
|
||||
s := Copy(Source, i+1, Length(Source))
|
||||
else
|
||||
s := Source;
|
||||
Instr := TLldbInstructionBreakSet.Create(s, Line, not Enabled, Expression);
|
||||
end;
|
||||
bpkAddress: begin
|
||||
Instr := TLldbInstructionBreakSet.Create(Address, not Enabled, Expression);
|
||||
end;
|
||||
bpkData: begin
|
||||
if not Enabled then // do not set, if not enabled
|
||||
exit;
|
||||
// TODO: scope
|
||||
// TODO: apply , Expression, not Enabled
|
||||
Instr := TLldbInstructionWatchSet.Create(WatchData, WatchKind);
|
||||
end;
|
||||
end;
|
||||
|
||||
Instr.OnFinish := @InstructionSetBreakFinished;
|
||||
TLldbDebugger(Debugger).FDebugInstructionQueue.QueueInstruction(Instr);
|
||||
Instr.ReleaseReference;
|
||||
FCurrentInstruction := Instr;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.BreakInstructionFinished(Sender: TObject);
|
||||
procedure TLldbBreakPoint.InstructionSetBreakFinished(Sender: TObject);
|
||||
begin
|
||||
if TLldbInstructionBreakSet(Sender).IsSuccess then begin
|
||||
FBreakID := TLldbInstructionBreakSet(Sender).BreakId;
|
||||
SetValid(TLldbInstructionBreakSet(Sender).State);
|
||||
DoCurrentInstructionFinished;
|
||||
|
||||
if TLldbInstructionBreakOrWatchSet(Sender).IsSuccess then begin
|
||||
FBreakID := TLldbInstructionBreakOrWatchSet(Sender).BreakId;
|
||||
if FState <> bpNeedDel then
|
||||
SetValid(TLldbInstructionBreakOrWatchSet(Sender).State);
|
||||
end
|
||||
else
|
||||
SetValid(vsInvalid);
|
||||
|
||||
if FState = bpNeedDel then
|
||||
ReleaseBreakPoint;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.InstructionUpdateBreakFinished(Sender: TObject);
|
||||
begin
|
||||
DoCurrentInstructionFinished;
|
||||
|
||||
if FState = bpNeedSet then
|
||||
SetBreakPoint
|
||||
else
|
||||
if FState = bpNeedDel then
|
||||
ReleaseBreakPoint;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.InstructionDeleteBreakFinished(Sender: TObject);
|
||||
begin
|
||||
DoCurrentInstructionFinished;
|
||||
FBreakID := 0;
|
||||
|
||||
if FState = bpNeedSet then
|
||||
SetBreakPoint;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.ReleaseBreakPoint;
|
||||
var
|
||||
Instr: TLldbInstructionBreakDelete;
|
||||
Instr: TLldbInstruction;
|
||||
begin
|
||||
SetHitCount(0);
|
||||
if FBreakID <= 0 then exit;
|
||||
if not (Debugger.State in [dsPause, dsInternalPause, dsRun, dsStop]) then
|
||||
exit;
|
||||
if (FCurrentInstruction <> nil) then begin
|
||||
if (FCurrentInstruction is TLldbInstructionBreakDelete) or
|
||||
(FCurrentInstruction is TLldbInstructionWatchDelete)
|
||||
then
|
||||
exit;
|
||||
if FCurrentInstruction.IsRunning then begin
|
||||
FState := bpNeedDel;
|
||||
exit;
|
||||
end
|
||||
else begin
|
||||
CancelCurrentInstruction;
|
||||
end;
|
||||
end;
|
||||
FState := bpDone;
|
||||
|
||||
if FBreakID <= 0 then exit;
|
||||
SetHitCount(0);
|
||||
|
||||
case Kind of
|
||||
bpkSource, bpkAddress:
|
||||
Instr := TLldbInstructionBreakDelete.Create(FBreakID);
|
||||
bpkData:
|
||||
Instr := TLldbInstructionWatchDelete.Create(FBreakID);
|
||||
end;
|
||||
|
||||
Instr := TLldbInstructionBreakDelete.Create(FBreakID);
|
||||
// Instr.OnFinish := @BreakInstructionFinished;
|
||||
TLldbDebugger(Debugger).FDebugInstructionQueue.QueueInstruction(Instr);
|
||||
Instr.ReleaseReference;
|
||||
Instr.OnFinish := @InstructionDeleteBreakFinished;
|
||||
FCurrentInstruction := Instr;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.UpdateProperties;
|
||||
var
|
||||
Instr: TLldbInstruction;
|
||||
begin
|
||||
if not (Debugger.State in [dsPause, dsInternalPause, dsRun]) then
|
||||
exit;
|
||||
|
||||
if IsUpdating or (FUpdateState = []) then
|
||||
exit;
|
||||
|
||||
if (FCurrentInstruction <> nil) then begin
|
||||
if (FCurrentInstruction is TLldbInstructionBreakDelete) or
|
||||
(FCurrentInstruction is TLldbInstructionWatchDelete)
|
||||
then
|
||||
exit; // can not change deleted breakpoint
|
||||
if FCurrentInstruction.IsRunning then begin
|
||||
FState := bpNeedSet;
|
||||
exit;
|
||||
end
|
||||
else begin
|
||||
CancelCurrentInstruction;
|
||||
end;
|
||||
end;
|
||||
FState := bpDone;
|
||||
|
||||
if FBreakID <= 0 then begin
|
||||
SetBreakPoint;
|
||||
exit;
|
||||
end;
|
||||
|
||||
case Kind of
|
||||
bpkSource, bpkAddress:
|
||||
if buCondition in FUpdateState
|
||||
then Instr := TLldbInstructionBreakModify.Create(FBreakID, not Enabled, Expression)
|
||||
else Instr := TLldbInstructionBreakModify.Create(FBreakID, not Enabled);
|
||||
bpkData:
|
||||
if buCondition in FUpdateState then begin
|
||||
if Enabled
|
||||
then SetBreakPoint
|
||||
else ReleaseBreakPoint;
|
||||
exit;
|
||||
end
|
||||
else Instr := TLldbInstructionWatchModify.Create(FBreakID, Expression);
|
||||
end;
|
||||
|
||||
TLldbDebugger(Debugger).FDebugInstructionQueue.QueueInstruction(Instr);
|
||||
Instr.OnFinish := @InstructionUpdateBreakFinished;
|
||||
FCurrentInstruction := Instr;
|
||||
|
||||
FUpdateState := [];
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.DoCurrentInstructionFinished;
|
||||
begin
|
||||
if FCurrentInstruction <> nil then begin
|
||||
FCurrentInstruction.OnFinish := nil;
|
||||
ReleaseRefAndNil(FCurrentInstruction);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.CancelCurrentInstruction;
|
||||
begin
|
||||
if FCurrentInstruction <> nil then begin
|
||||
FCurrentInstruction.OnFinish := nil;
|
||||
FCurrentInstruction.Cancel;
|
||||
ReleaseRefAndNil(FCurrentInstruction);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.DoStateChange(const AOldState: TDBGState);
|
||||
@ -640,8 +803,7 @@ begin
|
||||
dsRun: if AOldState = dsInit then begin
|
||||
// Disabled data breakpoints: wait until enabled
|
||||
// Disabled other breakpoints: Give to LLDB to see if they are valid
|
||||
if (Kind <> bpkData) or Enabled then
|
||||
SetBreakpoint;
|
||||
SetBreakpoint;
|
||||
end;
|
||||
dsStop: begin
|
||||
if FBreakID > 0
|
||||
@ -650,6 +812,39 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.DoEndUpdate;
|
||||
begin
|
||||
inherited DoEndUpdate;
|
||||
UpdateProperties;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.DoEnableChange;
|
||||
begin
|
||||
inherited DoEnableChange;
|
||||
if Kind = bpkData then begin
|
||||
if Enabled
|
||||
then SetBreakPoint
|
||||
else ReleaseBreakPoint;
|
||||
exit;
|
||||
end;
|
||||
|
||||
FUpdateState := FUpdateState + [buEnabled];
|
||||
UpdateProperties;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.DoExpressionChange;
|
||||
begin
|
||||
inherited DoExpressionChange;
|
||||
FUpdateState := FUpdateState + [buCondition];
|
||||
UpdateProperties;
|
||||
end;
|
||||
|
||||
destructor TLldbBreakPoint.Destroy;
|
||||
begin
|
||||
DoCurrentInstructionFinished;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TLldbBreakPoint.SetLocation(const ASource: String;
|
||||
const ALine: Integer);
|
||||
begin
|
||||
@ -658,6 +853,20 @@ begin
|
||||
SetBreakPoint;
|
||||
end;
|
||||
|
||||
{ TLldbBreakPoints }
|
||||
|
||||
function TLldbBreakPoints.FindById(AnId: Integer): TLldbBreakPoint;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to Count - 1 do begin
|
||||
Result := TLldbBreakPoint(Items[i]);
|
||||
if Result.FBreakID = AnId then
|
||||
exit;
|
||||
end;
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
{%region
|
||||
*****
|
||||
***** Register
|
||||
@ -1051,6 +1260,74 @@ begin
|
||||
end;
|
||||
|
||||
procedure TLldbDebugger.DoAfterLineReceived(var ALine: String);
|
||||
procedure DoBreakPointHit(AReason: String);
|
||||
var
|
||||
i, BrkId: Integer;
|
||||
BreakPoint: TLldbBreakPoint;
|
||||
CanContinue: Boolean;
|
||||
begin
|
||||
i := pos('.', AReason);
|
||||
if i = 0 then i := Length(AReason)+1;
|
||||
BrkId := StrToIntDef(copy(AReason, 12, i-12), -1);
|
||||
debugln(['DoBreakPointHit ', AReason, ' / ', BrkId]);
|
||||
|
||||
if (BrkId >= 0) then
|
||||
BreakPoint := TLldbBreakPoints(BreakPoints).FindById(BrkId)
|
||||
else
|
||||
BreakPoint := nil;
|
||||
|
||||
if Assigned(EventLogHandler) then
|
||||
EventLogHandler.LogEventBreakPointHit(Breakpoint, FCurrentLocation);
|
||||
|
||||
if BreakPoint <> nil then begin
|
||||
if (BreakPoint.Valid = vsPending) then
|
||||
BreakPoint.SetPendingToValid(vsValid);
|
||||
|
||||
try
|
||||
BreakPoint.AddReference;
|
||||
|
||||
// Important: The Queue must be unlocked
|
||||
// BreakPoint.Hit may evaluate stack and expressions
|
||||
// SetDebuggerState may evaluate data for Snapshot
|
||||
CanContinue := False;
|
||||
BreakPoint.Hit(CanContinue);
|
||||
if CanContinue
|
||||
then begin
|
||||
// Important trigger State => as snapshot is taken in TDebugManager.DebuggerChangeState
|
||||
SetState(dsInternalPause);
|
||||
// TODO: handle continue stepping
|
||||
// TODO: wait for SetLocation / lldb sents the frame info in the next output line
|
||||
LldbRun;
|
||||
end
|
||||
else begin
|
||||
SetState(dsPause);
|
||||
end;
|
||||
|
||||
finally
|
||||
BreakPoint.ReleaseReference;
|
||||
end;
|
||||
|
||||
end
|
||||
else
|
||||
if (State = dsRun)
|
||||
then begin
|
||||
debugln(['********** WARNING: breakpoint hit, but nothing known about it ABreakId=', BrkId]);
|
||||
//case FTheDebugger.OnFeedback
|
||||
// (self, Format(gdbmiWarningUnknowBreakPoint,
|
||||
// [LineEnding, GDBMIBreakPointReasonNames[AReason]]),
|
||||
// List.Text, ftWarning, [frOk, frStop]
|
||||
// )
|
||||
//of
|
||||
// frOk: begin
|
||||
SetState(dsPause);
|
||||
// end;
|
||||
// frStop: begin
|
||||
// FTheDebugger.Stop;
|
||||
// end;
|
||||
//end;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
Instr: TLldbInstructionTargetDelete;
|
||||
found: TStringArray;
|
||||
@ -1068,8 +1345,11 @@ begin
|
||||
FCurrentStackFrame := 0;
|
||||
FDebugInstructionQueue.SetKnownThreadAndFrame(FCurrentThreadId, 0);
|
||||
Threads.CurrentThreads.CurrentThreadId := FCurrentThreadId;
|
||||
SetState(dsPause);
|
||||
ALine := '';
|
||||
if StrStartsWith(found[1], 'breakpoint ') then
|
||||
DoBreakPointHit(found[1])
|
||||
else
|
||||
SetState(dsPause);
|
||||
end;
|
||||
|
||||
// Process 8888 exited with status = 0 (0x00000000)
|
||||
|
@ -102,21 +102,38 @@ type
|
||||
constructor Create();
|
||||
end;
|
||||
|
||||
{ TLldbInstructionBreakSet }
|
||||
{ TLldbInstructionBreakOrWatchSet }
|
||||
|
||||
TLldbInstructionBreakSet = class(TLldbInstruction)
|
||||
TLldbInstructionBreakOrWatchSet = class(TLldbInstruction)
|
||||
private
|
||||
FBreakId: Integer;
|
||||
FState: TValidState;
|
||||
protected
|
||||
function ProcessInputFromDbg(const AData: String): Boolean; override;
|
||||
public
|
||||
constructor Create(AFileName: String; ALine: Integer);
|
||||
constructor Create(AMethod: String);
|
||||
property BreakId: Integer read FBreakId;
|
||||
property State: TValidState read FState;
|
||||
end;
|
||||
|
||||
{ TLldbInstructionBreakSet }
|
||||
|
||||
TLldbInstructionBreakSet = class(TLldbInstructionBreakOrWatchSet)
|
||||
public
|
||||
constructor Create(AFileName: String; ALine: Integer; ADisabled: Boolean = False; AConditon: String = '');
|
||||
constructor Create(AMethod: String; ADisabled: Boolean = False; AConditon: String = '');
|
||||
constructor Create(AnAddress: TDBGPtr; ADisabled: Boolean = False; AConditon: String = '');
|
||||
end;
|
||||
|
||||
{ TLldbInstructionBreakModify }
|
||||
|
||||
TLldbInstructionBreakModify = class(TLldbInstruction)
|
||||
protected
|
||||
function ProcessInputFromDbg(const AData: String): Boolean; override;
|
||||
public
|
||||
constructor Create(AnId: Integer; ADisabled: Boolean);
|
||||
constructor Create(AnId: Integer; ADisabled: Boolean; AConditon: String);
|
||||
end;
|
||||
|
||||
{ TLldbInstructionBreakDelete }
|
||||
|
||||
TLldbInstructionBreakDelete = class(TLldbInstruction)
|
||||
@ -126,6 +143,31 @@ type
|
||||
constructor Create(AnId: Integer);
|
||||
end;
|
||||
|
||||
{ TLldbInstructionWatchSet }
|
||||
|
||||
TLldbInstructionWatchSet = class(TLldbInstructionBreakOrWatchSet)
|
||||
public
|
||||
constructor Create(AWatch: String; AKind: TDBGWatchPointKind);
|
||||
end;
|
||||
|
||||
{ TLldbInstructionWatchModify }
|
||||
|
||||
TLldbInstructionWatchModify = class(TLldbInstruction)
|
||||
protected
|
||||
function ProcessInputFromDbg(const AData: String): Boolean; override;
|
||||
public
|
||||
constructor Create(AnId: Integer; AConditon: String = '');
|
||||
end;
|
||||
|
||||
{ TLldbInstructionWatchDelete }
|
||||
|
||||
TLldbInstructionWatchDelete = class(TLldbInstruction)
|
||||
protected
|
||||
function ProcessInputFromDbg(const AData: String): Boolean; override;
|
||||
public
|
||||
constructor Create(AnId: Integer);
|
||||
end;
|
||||
|
||||
{ TLldbInstructionThreadSelect }
|
||||
|
||||
TLldbInstructionThreadSelect = class(TLldbInstruction)
|
||||
@ -226,6 +268,43 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
{ TLldbInstructionBreakOrWatchSet }
|
||||
|
||||
function TLldbInstructionBreakOrWatchSet.ProcessInputFromDbg(const AData: String
|
||||
): Boolean;
|
||||
var
|
||||
i: Integer;
|
||||
found, found2: TStringArray;
|
||||
begin
|
||||
Result := True;
|
||||
if StrMatches(AData, ['Breakpoint ',': ', ''], found) then begin
|
||||
i := StrToIntDef(found[0], -1);
|
||||
if i = -1 then begin
|
||||
MarkAsFailed;
|
||||
exit;
|
||||
end;
|
||||
FBreakId:= i;
|
||||
|
||||
if StrContains(found[1], 'pending') then
|
||||
FState := vsPending
|
||||
else
|
||||
if StrMatches(found[1], ['', ' locations'], found2) then begin
|
||||
if StrToIntDef(found2[0], 0) > 0 then
|
||||
FState := vsValid;
|
||||
end
|
||||
else
|
||||
if StrStartsWith(found[1], 'where = ') then
|
||||
FState := vsValid;
|
||||
|
||||
MarkAsSuccess;
|
||||
end
|
||||
//Breakpoint 41: where = lazarus.exe`CREATE + 2029 at synedit.pp:2123, address = 0x00764d2d
|
||||
//Breakpoint 38: no locations (pending).
|
||||
//Breakpoint 34: 3 locations.
|
||||
else
|
||||
Result := inherited;
|
||||
end;
|
||||
|
||||
{ TLldbInstructionQueue }
|
||||
|
||||
function TLldbInstructionQueue.CheckForIgnoredError(const AData: String
|
||||
@ -437,52 +516,61 @@ end;
|
||||
|
||||
{ TLldbInstructionBreakSet }
|
||||
|
||||
function TLldbInstructionBreakSet.ProcessInputFromDbg(const AData: String
|
||||
): Boolean;
|
||||
var
|
||||
i: Integer;
|
||||
found, found2: TStringArray;
|
||||
begin
|
||||
Result := True;
|
||||
if StrMatches(AData, ['Breakpoint ',': ', ''], found) then begin
|
||||
i := StrToIntDef(found[0], -1);
|
||||
if i = -1 then begin
|
||||
MarkAsFailed;
|
||||
exit;
|
||||
end;
|
||||
FBreakId:= i;
|
||||
|
||||
if StrContains(found[1], 'pending') then
|
||||
FState := vsPending
|
||||
else
|
||||
if StrMatches(found[1], ['', ' locations'], found2) then begin
|
||||
if StrToIntDef(found2[0], 0) > 0 then
|
||||
FState := vsValid;
|
||||
end
|
||||
else
|
||||
if StrStartsWith(found[1], 'where = ') then
|
||||
FState := vsValid;
|
||||
|
||||
MarkAsSuccess;
|
||||
end
|
||||
//Breakpoint 41: where = lazarus.exe`CREATE + 2029 at synedit.pp:2123, address = 0x00764d2d
|
||||
//Breakpoint 38: no locations (pending).
|
||||
//Breakpoint 34: 3 locations.
|
||||
else
|
||||
Result := inherited;
|
||||
end;
|
||||
|
||||
constructor TLldbInstructionBreakSet.Create(AFileName: String; ALine: Integer);
|
||||
constructor TLldbInstructionBreakSet.Create(AFileName: String; ALine: Integer;
|
||||
ADisabled: Boolean; AConditon: String);
|
||||
begin
|
||||
FState := vsInvalid;
|
||||
if AConditon <> '' then AConditon := ' --condition ''' + AConditon + '''';
|
||||
if ADisabled then AConditon := AConditon + ' --disable';
|
||||
if pos(' ', AFileName) > 0 then
|
||||
AFileName := ''''+AFileName+'''';
|
||||
inherited Create(Format('breakpoint set --file %s --line %d', [AFileName, ALine]));
|
||||
inherited Create(Format('breakpoint set --file %s --line %d', [AFileName, ALine]) + AConditon);
|
||||
end;
|
||||
|
||||
constructor TLldbInstructionBreakSet.Create(AMethod: String);
|
||||
constructor TLldbInstructionBreakSet.Create(AMethod: String;
|
||||
ADisabled: Boolean; AConditon: String);
|
||||
begin
|
||||
inherited Create(Format('breakpoint set --func %s', [AMethod]));
|
||||
FState := vsInvalid;
|
||||
if AConditon <> '' then AConditon := ' --condition ''' + AConditon + '''';
|
||||
if ADisabled then AConditon := AConditon + ' --disable';
|
||||
inherited Create(Format('breakpoint set --func %s', [AMethod]) + AConditon);
|
||||
end;
|
||||
|
||||
constructor TLldbInstructionBreakSet.Create(AnAddress: TDBGPtr;
|
||||
ADisabled: Boolean; AConditon: String);
|
||||
begin
|
||||
FState := vsInvalid;
|
||||
if AConditon <> '' then AConditon := ' --condition ''' + AConditon + '''';
|
||||
if ADisabled then AConditon := AConditon + ' --disable';
|
||||
inherited Create(Format('breakpoint set --address %u', [AnAddress]) + AConditon);
|
||||
end;
|
||||
|
||||
{ TLldbInstructionBreakModify }
|
||||
|
||||
function TLldbInstructionBreakModify.ProcessInputFromDbg(const AData: String
|
||||
): Boolean;
|
||||
begin
|
||||
Result := inherited ProcessInputFromDbg(AData);
|
||||
if not Result then
|
||||
MarkAsSuccess;
|
||||
end;
|
||||
|
||||
constructor TLldbInstructionBreakModify.Create(AnId: Integer; ADisabled: Boolean
|
||||
);
|
||||
begin
|
||||
if ADisabled
|
||||
then inherited Create(Format('breakpoint modify --disable %d', [AnId]))
|
||||
else inherited Create(Format('breakpoint modify --enable %d', [AnId]));
|
||||
end;
|
||||
|
||||
constructor TLldbInstructionBreakModify.Create(AnId: Integer;
|
||||
ADisabled: Boolean; AConditon: String);
|
||||
begin
|
||||
AConditon := ' --condition ''' + AConditon + '''';
|
||||
if ADisabled
|
||||
then AConditon := ' --disable' + AConditon
|
||||
else AConditon := ' --enable' + AConditon;
|
||||
inherited Create(Format('breakpoint modify %s %d', [AConditon, AnId]));
|
||||
end;
|
||||
|
||||
{ TLldbInstructionBreakDelete }
|
||||
@ -505,6 +593,54 @@ begin
|
||||
inherited Create(Format('breakpoint delete %d', [AnId]));
|
||||
end;
|
||||
|
||||
{ TLldbInstructionWatchSet }
|
||||
|
||||
constructor TLldbInstructionWatchSet.Create(AWatch: String;
|
||||
AKind: TDBGWatchPointKind);
|
||||
begin
|
||||
case AKind of
|
||||
wpkWrite: inherited Create(Format('watchpoint set variable -w write %s', [AWatch]));
|
||||
wpkRead: inherited Create(Format('watchpoint set variable -w read %s', [AWatch]));
|
||||
wpkReadWrite: inherited Create(Format('watchpoint set variable -w read_write %s', [AWatch]));
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TLldbInstructionWatchModify }
|
||||
|
||||
function TLldbInstructionWatchModify.ProcessInputFromDbg(const AData: String
|
||||
): Boolean;
|
||||
begin
|
||||
Result := inherited ProcessInputFromDbg(AData);
|
||||
if not Result then
|
||||
MarkAsSuccess;
|
||||
end;
|
||||
|
||||
constructor TLldbInstructionWatchModify.Create(AnId: Integer; AConditon: String
|
||||
);
|
||||
begin
|
||||
inherited Create(Format('watchpoint modify --condition ''%s'' %d', [AConditon, AnId]));
|
||||
end;
|
||||
|
||||
{ TLldbInstructionWatchDelete }
|
||||
|
||||
function TLldbInstructionWatchDelete.ProcessInputFromDbg(const AData: String
|
||||
): Boolean;
|
||||
begin
|
||||
Result := inherited ProcessInputFromDbg(AData);
|
||||
|
||||
if not Result then // if Result=true then self is destroyed;
|
||||
MarkAsSuccess;
|
||||
Result := true;
|
||||
|
||||
//TODO: "error: No breakpoints exist to be deleted."
|
||||
// prevent from failing other instruction
|
||||
end;
|
||||
|
||||
constructor TLldbInstructionWatchDelete.Create(AnId: Integer);
|
||||
begin
|
||||
inherited Create(Format('watchpoint delete %d', [AnId]));
|
||||
end;
|
||||
|
||||
{ TLldbInstructionThreadSelect }
|
||||
|
||||
function TLldbInstructionThreadSelect.ProcessInputFromDbg(const AData: String
|
||||
|
Loading…
Reference in New Issue
Block a user