mirror of https://gitlab.com/basile.b/dexed.git
#97, make breakpoints persistent
This commit is contained in:
parent
05210bb82d
commit
ec10156ea2
|
@ -19,8 +19,8 @@ type
|
||||||
*)
|
*)
|
||||||
ICEDebugger = interface(ICESingleService)
|
ICEDebugger = interface(ICESingleService)
|
||||||
function running: boolean;
|
function running: boolean;
|
||||||
procedure addBreakPoint(const fname: string; line: integer; kind: TBreakPointKind);
|
procedure addBreakPoint(const fname: string; line: integer; kind: TBreakPointKind = bpkBreak);
|
||||||
procedure removeBreakPoint(const fname: string; line: integer);
|
procedure removeBreakPoint(const fname: string; line: integer; kind: TBreakPointKind = bpkBreak);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Enumerates th e reason why debuging breaks.
|
// Enumerates th e reason why debuging breaks.
|
||||||
|
|
160
src/ce_gdb.pas
160
src/ce_gdb.pas
|
@ -234,6 +234,37 @@ type
|
||||||
|
|
||||||
// TODO-cGDB: assembly view
|
// TODO-cGDB: assembly view
|
||||||
|
|
||||||
|
// serializable breakpoint
|
||||||
|
TPersistentBreakPoint = class(TCollectionItem)
|
||||||
|
strict private
|
||||||
|
fFilename: string;
|
||||||
|
fLine: integer;
|
||||||
|
fKind: TBreakPointKind;
|
||||||
|
published
|
||||||
|
property filename: string read fFilename write fFilename;
|
||||||
|
property line: integer read fLine write fLine;
|
||||||
|
property kind: TBreakPointKind read fKind write fKind;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// allow to retrieve the breakpoints even if source is not openened.
|
||||||
|
TPersistentBreakPoints = class(TWritableLfmTextComponent)
|
||||||
|
strict private
|
||||||
|
fItems: TOwnedCollection;
|
||||||
|
procedure setItems(value: TOwnedCollection);
|
||||||
|
function getItem(index: integer): TPersistentBreakPoint;
|
||||||
|
function find(const fname: string; line: integer; kind: TBreakPointKind): boolean;
|
||||||
|
published
|
||||||
|
property items: TOwnedCollection read fItems write setItems;
|
||||||
|
public
|
||||||
|
constructor create(aOwner: TComponent); override;
|
||||||
|
destructor destroy; override;
|
||||||
|
function count: integer;
|
||||||
|
procedure clearFile(const fname: string);
|
||||||
|
procedure deleteItem(const fname: string; line: integer; kind: TBreakPointKind);
|
||||||
|
procedure addItem(const fname: string; line: integer; kind: TBreakPointKind);
|
||||||
|
property item[index: integer]: TPersistentBreakPoint read getItem; default;
|
||||||
|
end;
|
||||||
|
|
||||||
// Makes a category for shortcuts in the option editor.
|
// Makes a category for shortcuts in the option editor.
|
||||||
TCEDebugShortcuts = class(TPersistent)
|
TCEDebugShortcuts = class(TPersistent)
|
||||||
private
|
private
|
||||||
|
@ -368,7 +399,6 @@ type
|
||||||
fProj: ICECommonProject;
|
fProj: ICECommonProject;
|
||||||
fJson: TJsonObject;
|
fJson: TJsonObject;
|
||||||
fLog: TStringList;
|
fLog: TStringList;
|
||||||
fFileLineBrks: TStringList;
|
|
||||||
fDocHandler: ICEMultiDocHandler;
|
fDocHandler: ICEMultiDocHandler;
|
||||||
fMsg: ICEMessagesDisplay;
|
fMsg: ICEMessagesDisplay;
|
||||||
fGdb: TCEProcess;
|
fGdb: TCEProcess;
|
||||||
|
@ -379,6 +409,7 @@ type
|
||||||
fCatchPause: boolean;
|
fCatchPause: boolean;
|
||||||
fOptions: TCEDebugOptions;
|
fOptions: TCEDebugOptions;
|
||||||
fAddWatchPointKind: TAddWatchPointKind;
|
fAddWatchPointKind: TAddWatchPointKind;
|
||||||
|
fBreakPoints: TPersistentBreakPoints;
|
||||||
//
|
//
|
||||||
procedure optionsChangesApplied(sender: TObject);
|
procedure optionsChangesApplied(sender: TObject);
|
||||||
procedure menuDeclare(item: TMenuItem);
|
procedure menuDeclare(item: TMenuItem);
|
||||||
|
@ -420,8 +451,10 @@ type
|
||||||
//
|
//
|
||||||
function running: boolean;
|
function running: boolean;
|
||||||
function singleServiceName: string;
|
function singleServiceName: string;
|
||||||
procedure addBreakPoint(const fname: string; line: integer; kind: TBreakPointKind);
|
procedure addBreakPoint(const fname: string; line: integer;
|
||||||
procedure removeBreakPoint(const fname: string; line: integer);
|
kind: TBreakPointKind = bpkBReak);
|
||||||
|
procedure removeBreakPoint(const fname: string; line: integer;
|
||||||
|
kind: TBreakPointKind = bpkBreak);
|
||||||
procedure executeFromShortcut(sender: TObject);
|
procedure executeFromShortcut(sender: TObject);
|
||||||
public
|
public
|
||||||
constructor create(aOwner: TComponent); override;
|
constructor create(aOwner: TComponent); override;
|
||||||
|
@ -472,6 +505,7 @@ implementation
|
||||||
|
|
||||||
{$REGION TCEDebugOption --------------------------------------------------------}
|
{$REGION TCEDebugOption --------------------------------------------------------}
|
||||||
const optFname = 'gdbcommander.txt';
|
const optFname = 'gdbcommander.txt';
|
||||||
|
const bpFname = 'breakpoints.txt';
|
||||||
|
|
||||||
|
|
||||||
procedure TCEDebugShortcuts.assign(source: TPersistent);
|
procedure TCEDebugShortcuts.assign(source: TPersistent);
|
||||||
|
@ -614,6 +648,98 @@ begin
|
||||||
end;
|
end;
|
||||||
{$ENDREGION}
|
{$ENDREGION}
|
||||||
|
|
||||||
|
{$REGION TPersistentBreakpoints ------------------------------------------------}
|
||||||
|
|
||||||
|
constructor TPersistentBreakPoints.create(aOwner: TComponent);
|
||||||
|
var
|
||||||
|
fname: string;
|
||||||
|
begin
|
||||||
|
Inherited;
|
||||||
|
fItems := TOwnedCollection.Create(self, TPersistentBreakPoint);
|
||||||
|
fname := getCoeditDocPath + bpFname;
|
||||||
|
if fname.fileExists then
|
||||||
|
loadFromFile(fname);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TPersistentBreakPoints.destroy;
|
||||||
|
begin
|
||||||
|
if fItems.Count > 0 then
|
||||||
|
saveToFile(getCoeditDocPath + bpFname);
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPersistentBreakPoints.setItems(value: TOwnedCollection);
|
||||||
|
begin
|
||||||
|
fItems.Assign(value);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPersistentBreakPoints.getItem(index: integer): TPersistentBreakPoint;
|
||||||
|
begin
|
||||||
|
exit(TPersistentBreakPoint(fItems.Items[index]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPersistentBreakPoints.count: integer;
|
||||||
|
begin
|
||||||
|
exit(fItems.Count);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPersistentBreakPoints.find(const fname: string; line: integer; kind: TBreakPointKind): boolean;
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
b: TPersistentBreakPoint;
|
||||||
|
begin
|
||||||
|
result := false;
|
||||||
|
for i := 0 to fItems.Count-1 do
|
||||||
|
begin
|
||||||
|
b := item[i];
|
||||||
|
if (b.filename = fname) and (b.line = line) and (b.kind = kind) then
|
||||||
|
exit(true);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPersistentBreakPoints.addItem(const fname: string; line: integer; kind: TBreakPointKind);
|
||||||
|
var
|
||||||
|
b: TPersistentBreakPoint;
|
||||||
|
begin
|
||||||
|
if not find(fname, line, kind) then
|
||||||
|
begin
|
||||||
|
b := TPersistentBreakPoint(fItems.Add);
|
||||||
|
b.filename:=fname;
|
||||||
|
b.line:=line;
|
||||||
|
b.kind:=kind;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPersistentBreakPoints.deleteItem(const fname: string; line: integer; kind: TBreakPointKind);
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
b: TPersistentBreakPoint;
|
||||||
|
begin
|
||||||
|
for i := fItems.Count-1 downto 0 do
|
||||||
|
begin
|
||||||
|
b := item[i];
|
||||||
|
if (b.filename = fname) and (b.line = line) and (b.kind = kind) then
|
||||||
|
begin
|
||||||
|
fItems.Delete(i);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TPersistentBreakPoints.clearFile(const fname: string);
|
||||||
|
var
|
||||||
|
i: integer;
|
||||||
|
b: TPersistentBreakPoint;
|
||||||
|
begin
|
||||||
|
for i:= fItems.Count-1 downto 0 do
|
||||||
|
begin
|
||||||
|
b := item[i];
|
||||||
|
if b.filename = fname then
|
||||||
|
fItems.Delete(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$ENDREGION}
|
||||||
|
|
||||||
{$REGION TStackItem/TStackItems ------------------------------------------------}
|
{$REGION TStackItem/TStackItems ------------------------------------------------}
|
||||||
procedure TStackItem.setProperties(addr: PtrUint; fname, nme: string; lne: integer);
|
procedure TStackItem.setProperties(addr: PtrUint; fname, nme: string; lne: integer);
|
||||||
begin
|
begin
|
||||||
|
@ -915,7 +1041,6 @@ begin
|
||||||
fSyms := getSymStringExpander;
|
fSyms := getSymStringExpander;
|
||||||
fDocHandler:= getMultiDocHandler;
|
fDocHandler:= getMultiDocHandler;
|
||||||
fMsg:= getMessageDisplay;
|
fMsg:= getMessageDisplay;
|
||||||
fFileLineBrks:= TStringList.Create;
|
|
||||||
fLog := TStringList.Create;
|
fLog := TStringList.Create;
|
||||||
fInspState := TInspectableCPU.Create(@setGpr, @setSsr, @setFlag, @setFpr);
|
fInspState := TInspectableCPU.Create(@setGpr, @setSsr, @setFlag, @setFpr);
|
||||||
cpuVIewer.TIObject := fInspState;
|
cpuVIewer.TIObject := fInspState;
|
||||||
|
@ -926,6 +1051,7 @@ begin
|
||||||
fOptions.onChangesApplied:=@optionsChangesApplied;
|
fOptions.onChangesApplied:=@optionsChangesApplied;
|
||||||
Edit1.Items.Assign(fOptions.commandsHistory);
|
Edit1.Items.Assign(fOptions.commandsHistory);
|
||||||
fAddWatchPointKind := wpkWrite;
|
fAddWatchPointKind := wpkWrite;
|
||||||
|
fBreakPoints := TPersistentBreakPoints.create(self);
|
||||||
//
|
//
|
||||||
AssignPng(btnSendCom, 'ACCEPT');
|
AssignPng(btnSendCom, 'ACCEPT');
|
||||||
setState(gsNone);
|
setState(gsNone);
|
||||||
|
@ -936,7 +1062,6 @@ begin
|
||||||
fOutput.Free;
|
fOutput.Free;
|
||||||
fOptions.commandsHistory.Assign(edit1.Items);
|
fOptions.commandsHistory.Assign(edit1.Items);
|
||||||
fOptions.Free;
|
fOptions.Free;
|
||||||
fFileLineBrks.Free;
|
|
||||||
fLog.Free;
|
fLog.Free;
|
||||||
killGdb;
|
killGdb;
|
||||||
fInspState.Free;
|
fInspState.Free;
|
||||||
|
@ -1217,29 +1342,32 @@ var
|
||||||
lne: integer;
|
lne: integer;
|
||||||
knd: TBreakPointKind;
|
knd: TBreakPointKind;
|
||||||
begin
|
begin
|
||||||
fFileLineBrks.Clear;
|
|
||||||
for i:= 0 to fSubj.observersCount-1 do
|
for i:= 0 to fSubj.observersCount-1 do
|
||||||
begin
|
begin
|
||||||
obs := fSubj.observers[i] as ICEDebugObserver;
|
obs := fSubj.observers[i] as ICEDebugObserver;
|
||||||
for j := 0 to obs.debugQueryBpCount-1 do
|
for j := 0 to obs.debugQueryBpCount-1 do
|
||||||
begin
|
begin
|
||||||
obs.debugQueryBreakPoint(j, nme, lne, knd);
|
obs.debugQueryBreakPoint(j, nme, lne, knd);
|
||||||
{$PUSH}{$WARNINGS OFF}{$HINTS OFF}
|
fBreakPoints.addItem(nme, lne, knd);
|
||||||
fFileLineBrks.AddObject(nme, TObject(pointer(lne)));
|
|
||||||
{$POP}
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCEGdbWidget.addBreakPoint(const fname: string; line: integer; kind: TBreakPointKind);
|
procedure TCEGdbWidget.addBreakPoint(const fname: string; line: integer;
|
||||||
|
kind: TBreakPointKind = bpkBreak);
|
||||||
begin
|
begin
|
||||||
|
if assigned(fBreakPoints) then
|
||||||
|
fBreakPoints.addItem(fname, line, kind);
|
||||||
if fGdb.isNil or not fGdb.Running then
|
if fGdb.isNil or not fGdb.Running then
|
||||||
exit;
|
exit;
|
||||||
gdbCommand('break ' + fname + ':' + intToStr(line));
|
gdbCommand('break ' + fname + ':' + intToStr(line));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCEGdbWidget.removeBreakPoint(const fname: string; line: integer);
|
procedure TCEGdbWidget.removeBreakPoint(const fname: string; line: integer;
|
||||||
|
kind: TBreakPointKind = bpkBreak);
|
||||||
begin
|
begin
|
||||||
|
if assigned(fBreakPoints) then
|
||||||
|
fBreakPoints.deleteItem(fname, line, kind);
|
||||||
if fGdb.isNil or not fGdb.Running then
|
if fGdb.isNil or not fGdb.Running then
|
||||||
exit;
|
exit;
|
||||||
gdbCommand('clear ' + fname + ':' + intToStr(line));
|
gdbCommand('clear ' + fname + ':' + intToStr(line));
|
||||||
|
@ -1324,6 +1452,7 @@ var
|
||||||
str: string;
|
str: string;
|
||||||
gdb: string;
|
gdb: string;
|
||||||
i: integer;
|
i: integer;
|
||||||
|
b: TPersistentBreakPoint;
|
||||||
begin
|
begin
|
||||||
if not fDbgRunnable and (fProj = nil) then
|
if not fDbgRunnable and (fProj = nil) then
|
||||||
exit;
|
exit;
|
||||||
|
@ -1374,9 +1503,14 @@ begin
|
||||||
fgdb.execute;
|
fgdb.execute;
|
||||||
// file:line breakpoints
|
// file:line breakpoints
|
||||||
storeObserversBreakpoints;
|
storeObserversBreakpoints;
|
||||||
for i:= 0 to fFileLineBrks.Count-1 do
|
for i:= 0 to fBreakPoints.Count-1 do
|
||||||
begin
|
begin
|
||||||
str := 'break ' + fFileLineBrks.Strings[i] + ':' + intToStr(PtrUInt(fFileLineBrks.Objects[i])) + #10;
|
b := fBreakPoints[i];
|
||||||
|
case b.kind of
|
||||||
|
bpkBreak: str := 'break ' + b.filename + ':' + intToStr(b.line) + #10;
|
||||||
|
bpkWatch: {TODO-cGDB: put watchpoint from persistent};
|
||||||
|
end;
|
||||||
|
|
||||||
fGdb.Input.Write(str[1], str.length);
|
fGdb.Input.Write(str[1], str.length);
|
||||||
end;
|
end;
|
||||||
// break on druntime exceptions + any throw'
|
// break on druntime exceptions + any throw'
|
||||||
|
|
Loading…
Reference in New Issue