#97, make breakpoints persistent

This commit is contained in:
Basile Burg 2016-11-03 08:08:37 +01:00
parent 05210bb82d
commit ec10156ea2
No known key found for this signature in database
GPG Key ID: 1868039F415CB8CF
2 changed files with 149 additions and 15 deletions

View File

@ -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.

View File

@ -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'