From 8e513f8b527aadb6a9dfcc1d2ca2c43d2c9ec899 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Fri, 28 Oct 2016 14:11:17 +0200 Subject: [PATCH] #97, add support for watch points --- icons/other/camera_add.png | Bin 0 -> 800 bytes icons/other/camera_go.png | Bin 0 -> 809 bytes lazproj/coedit.lpi | 4 +- src/ce_dbgitf.pas | 7 +-- src/ce_gdb.lfm | 32 ++++++++++++++ src/ce_gdb.pas | 85 ++++++++++++++++++++++++++++++++++--- src/ce_synmemo.pas | 11 +++++ 7 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 icons/other/camera_add.png create mode 100644 icons/other/camera_go.png diff --git a/icons/other/camera_add.png b/icons/other/camera_add.png new file mode 100644 index 0000000000000000000000000000000000000000..08b5da9891cffe3ee397f528734dc5de406c1c53 GIT binary patch literal 800 zcmV+*1K<3KP)ZO`s5Iy)3 z^blxIm6b3;gecZ(Yy%rC)TwiGbGzG}ySMLLQF<%r!0&t)?)Uq?-}!y#FkRR2KTG1< z)YR0ya=9F+R;zWjT8&jI6_cVUW*#+7V-|}=wcG8l$HvA+dH%@ANFRlt)6>(NEEo(P z5=AlB+uIASh6o0tU*6*C#bZ#Hp5f8^4%l3sh{qGxvf1ooBHIXD`he*5dLvz3U3Qnt zg;Xkq)zwvOY;2&}(}9nl*AXk6L{HyoFvhU5vT|7v1dA-okR*xa^Z7FpbvmUa5x+Y1OiB>)5zs=MougiJ1+6WwY4=gHa4PK@44?hVMmi8@CoU=D$G!@wY3GShap^=L#b{X2m10@ z&n_7S#P06yyH=~!aMt6jM_MtX%EaAUrYSh0en(>Y1KRyIoa!IIQ2%*U${9ERlE#EA|+nOZ}Sdl>J2yu_f-k7Rrn5_KL;CX@F` zj-{cYfh{gBGG2holXvKL zj1ND@#GC7oMGIcMnkfta^5QgId$kgwRGSCYTsBsga!vU78>(_w3lYQgq=;Lm~?kll}x< zsTfRnC<;VuXxc_Wst3z_yv0nfuLV zGo~m?i>7Hrk|ax`(Xg^p*L7mE*<`2F`Eqh{a)RZLjg1Y_V>2F)@0022=@UH9m!r`r zm>LQ&Bf0h(x3Bj>{`L%y-}b}d9Y8vr884MePbk)oS&!K&zg1I2=eM67YCDh(scw zt$?Wo8K(oRKQpcS=llS9qiX2 z96<5lIf8nff>aqj?g6Z}Kc^((5rJ^1fI14R(E?SsgQF9&+wOqp6+l<9sH!;W?889U zFltQ^pGV$9`s({jz^bpWuOr$W!CJ)wNuXoWWn3E^hej1?x<*Ykuv5t*(sKz1asw+; z9QsN>1XjILshHz&l}Z@y?KRE$NF_7y_hJSLRiWw%6iq=@s^Oe}1P4kTA4V4-(3wtb zZEZcEN^Bh+9b|cVnJ|LxTTQ5%3a=wT!J0{yt8ByB-i6id0v0!xAS|6)Apd$yH=hRe zCN)>4tuO;a?m==fIEqi(iDiyMZh}+n{@4V; nyF}D;{j00000NkvXXu0mjf57}={ literal 0 HcmV?d00001 diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index 96462115..27478f7a 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -13,7 +13,7 @@ - + @@ -114,6 +114,8 @@ + + diff --git a/src/ce_dbgitf.pas b/src/ce_dbgitf.pas index 57430d1a..a997601d 100644 --- a/src/ce_dbgitf.pas +++ b/src/ce_dbgitf.pas @@ -10,8 +10,8 @@ uses type TBreakPointKind = ( - bpkBreak, // break - bpkTrace // a message is output + bpkBreak, // break point + bpkWatch // watch point ); (** @@ -28,7 +28,8 @@ type dbUnknown, // ? dbBreakPoint, // a break point is reached. dbSignal, // an unexpected signal is emitted. - dbStep // step to this line + dbStep, // step to this line + dbWatch // watchpoint reached ); (** * An implementer is informed about a debuging session. diff --git a/src/ce_gdb.lfm b/src/ce_gdb.lfm index 75171f14..0f9de9a4 100644 --- a/src/ce_gdb.lfm +++ b/src/ce_gdb.lfm @@ -258,6 +258,7 @@ inherited CEGdbWidget: TCEGdbWidget end object btnStart: TCEToolButton[9] Left = 1 + Hint = 'start debugging' Top = 0 Caption = 'btnStart' DropdownMenu = mnuProjRunnable @@ -266,6 +267,17 @@ inherited CEGdbWidget: TCEGdbWidget resourceName = 'POWER' scaledSeparator = False end + object btnWatch: TCEToolButton[10] + Left = 281 + Hint = 'add a watchpoint for the variable selected in the list' + Top = 0 + Caption = 'btnWatch' + DropdownMenu = mnuWatch + OnClick = btnWatchClick + Style = tbsDropDown + resourceName = 'CAMERA_ADD' + scaledSeparator = False + end end end object Splitter2: TSplitter[1] @@ -296,4 +308,24 @@ inherited CEGdbWidget: TCEGdbWidget OnClick = mnuSelRunnableClick end end + object mnuWatch: TPopupMenu[4] + left = 144 + top = 128 + object mnuReadW: TMenuItem + AutoCheck = True + Caption = 'On read' + OnClick = mnuReadWClick + end + object mnuWriteW: TMenuItem + AutoCheck = True + Caption = 'On write' + Checked = True + OnClick = mnuWriteWClick + end + object mnuReadWriteW: TMenuItem + AutoCheck = True + Caption = 'On read/write' + OnClick = mnuReadWriteWClick + end + end end diff --git a/src/ce_gdb.pas b/src/ce_gdb.pas index 562d3e2b..7c4082b1 100644 --- a/src/ce_gdb.pas +++ b/src/ce_gdb.pas @@ -300,6 +300,8 @@ type TGdbState = (gsNone, gsRunning, gsPaused); + TAddWatchPointKind = (wpkRead, wpkWrite, wpkReadWrite); + { TCEGdbWidget } TCEGdbWidget = class(TCEWidget, ICEProjectObserver, ICEDocumentObserver, ICEDebugger, ICEMainMenuProvider) btnContinue: TCEToolButton; @@ -311,12 +313,16 @@ type btnStack: TCEToolButton; btnStop: TCEToolButton; btnStart: TCEToolButton; + btnWatch: TCEToolButton; button4: TCEToolButton; Edit1: TComboBox; GroupBox1: TGroupBox; GroupBox2: TGroupBox; GroupBox3: TGroupBox; lstCallStack: TListView; + mnuReadW: TMenuItem; + mnuWriteW: TMenuItem; + mnuReadWriteW: TMenuItem; mnuSelProj: TMenuItem; mnuSelRunnable: TMenuItem; Panel1: TPanel; @@ -324,6 +330,7 @@ type btnSendCom: TSpeedButton; cpuVIewer: TTIPropertyGrid; mnuProjRunnable: TPopupMenu; + mnuWatch: TPopupMenu; Splitter2: TSplitter; Splitter3: TSplitter; Splitter4: TSplitter; @@ -338,15 +345,20 @@ type procedure btnStackClick(Sender: TObject); procedure btnStartClick(Sender: TObject); procedure btnStopClick(Sender: TObject); + procedure btnWatchClick(Sender: TObject); procedure Edit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); + procedure mnuReadWClick(Sender: TObject); + procedure mnuReadWriteWClick(Sender: TObject); procedure mnuSelProjClick(Sender: TObject); procedure mnuSelRunnableClick(Sender: TObject); + procedure mnuWriteWClick(Sender: TObject); protected procedure setToolBarFlat(value: boolean); override; procedure updateLoop; override; private fExe: string; fOutputName: string; + fShowFromCustomCommand: boolean; fUpdateMenu: boolean; fGdbState: TGdbState; fSubj: TCEDebugObserverSubject; @@ -364,6 +376,7 @@ type fStackItems: TStackItems; fCatchPause: boolean; fOptions: TCEDebugOptions; + fAddWatchPointKind: TAddWatchPointKind; // procedure optionsChangesApplied(sender: TObject); procedure menuDeclare(item: TMenuItem); @@ -843,6 +856,7 @@ begin fOptions:= TCEDebugOptions.create(self); fOptions.onChangesApplied:=@optionsChangesApplied; Edit1.Items.Assign(fOptions.commandsHistory); + fAddWatchPointKind := wpkWrite; // AssignPng(btnSendCom, 'ACCEPT'); setState(gsNone); @@ -1215,6 +1229,13 @@ begin mnuSelProj.Checked:=false; end; +procedure TCEGdbWidget.mnuWriteWClick(Sender: TObject); +begin + fAddWatchPointKind := wpkWrite; + mnuReadW.Checked:=false; + mnuReadWriteW.Checked:=false; +end; + procedure TCEGdbWidget.disableEditor; begin cpuVIewer.ItemIndex:=-1; @@ -1547,11 +1568,27 @@ begin begin reason := val.AsString; - if (reason = 'breakpoint-hit') or (reason = 'end-stepping-range') then + if (reason = 'breakpoint-hit') or (reason = 'end-stepping-range') or + (reason = 'watchpoint-trigger') then begin case reason of 'breakpoint-hit': brkreason := dbBreakPoint; 'end-stepping-range': brkreason := dbStep; + 'watchpoint-trigger': brkreason:= dbWatch; + end; + if brkreason = dbWatch then + begin + obj := TJSONObject(fJson.Find('wpt')); + if obj.isNotNil and (obj.JSONType = jtObject) then + begin + val := obj.Find('exp'); + if val.isNotNil then + begin + ValueListEditor1.FindRow(val.AsString, i); + if i <> -1 then + ValueListEditor1.Row:=i; + end; + end; end; obj := TJSONObject(fJson.Find('frame')); if obj.isNotNil and (obj.JSONType = jtObject) then @@ -1569,9 +1606,15 @@ begin readOutput; subjDebugBreak(fSubj, fullname, line, brkreason); end; - end + else if reason = 'watchpoint-scope' then + begin + gdbCommand('continue', @gdboutJsonize); + end + + // *stopped,reason="watchpoint-trigger",wpt={number="10",exp="h"},value={old="0",new="1"},frame={addr="0x000000000049fb7c",func="D main",args=[{name="args",value="..."}],file="/home/basile/Dev/dproj/Resource.d/src/resource.d",fullname="/home/basile/Dev/dproj/Resource.d/src/resource.d",line="47"},thread-id="1",stopped-threads="all",core="1" + else if reason = 'signal-received' then begin signame := 'unknown signal'; @@ -1731,6 +1774,7 @@ begin val := fJson.Find('variables'); if val.isNotNil and (val.JSONType = jtArray) then begin + i := ValueListEditor1.Row; ValueListEditor1.Clear; arr := TJSONArray(val); for i := 0 to arr.Count-1 do @@ -1748,10 +1792,13 @@ begin continue; ValueListEditor1.InsertRow(nme, val.AsString, false); end; + if (i <> -1) and (i <= ValueListEditor1.RowCount) then + ValueListEditor1.Row:=i; end; - if fOptions.showGdbOutput then + if fOptions.showGdbOutput or fShowFromCustomCommand then begin + fShowFromCustomCommand := false; arr := TJSONArray(fJson.Find('CLI')); if arr.isNotNil then for i := 0 to arr.Count-1 do @@ -1770,8 +1817,8 @@ begin fLog.Clear; fGdb.getFullLines(fLog); - //for str in fLog do - // fMsg.message(str, nil, amcMisc, amkAuto); + for str in fLog do + fMsg.message(str, nil, amcMisc, amkAuto); if flog.Text.isEmpty then exit; @@ -1916,6 +1963,19 @@ begin setState(gsNone); end; +procedure TCEGdbWidget.btnWatchClick(Sender: TObject); +const + cmd: array[TAddWatchPointKind] of string = ( + '-break-watch -r ','-break-watch ','-break-watch -a '); +var + nme: string; +begin + if ValueListEditor1.Row = -1 then + exit; + nme := ValueListEditor1.Keys[ValueListEditor1.Row]; + gdbCommand(cmd[fAddWatchPointKind] + nme); +end; + procedure TCEGdbWidget.btnSendComClick(Sender: TObject); begin sendCustomCommand; @@ -1927,6 +1987,20 @@ begin sendCustomCommand; end; +procedure TCEGdbWidget.mnuReadWClick(Sender: TObject); +begin + fAddWatchPointKind := wpkRead; + mnuWriteW.Checked:=false; + mnuReadWriteW.Checked:=false; +end; + +procedure TCEGdbWidget.mnuReadWriteWClick(Sender: TObject); +begin + fAddWatchPointKind := wpkReadWrite; + mnuReadW.Checked:=false; + mnuWriteW.Checked:=false; +end; + procedure TCEGdbWidget.sendCustomCommand; var cmd: string; @@ -1934,6 +2008,7 @@ begin cmd := edit1.Text; if cmd.isBlank or cmd.isEmpty then exit; + fShowFromCustomCommand := true; gdbCommand(cmd, @gdboutJsonize); if edit1.Items.IndexOf(cmd) = -1 then edit1.Items.Add(cmd); diff --git a/src/ce_synmemo.pas b/src/ce_synmemo.pas index 01a81361..df5c96cc 100644 --- a/src/ce_synmemo.pas +++ b/src/ce_synmemo.pas @@ -9,6 +9,7 @@ uses SynEdit, SynPluginSyncroEdit, SynCompletion, SynEditKeyCmds, LazSynEditText, SynHighlighterLFM, SynEditHighlighter, SynEditMouseCmds, SynEditFoldedView, SynEditMarks, SynEditTypes, SynHighlighterJScript, SynBeautifier, dialogs, + //SynEditMarkupFoldColoring, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls, ce_common, ce_writableComponent, ce_d2syn, ce_txtsyn, ce_dialogs, ce_sharedres, ce_dlang, ce_stringrange, ce_dbgitf, ce_observer; @@ -122,11 +123,15 @@ type giBulletBlack = 2, giBreak = 3, // break point reached giStep = 4, // step / signal / pause + giWatch = 5, // watch point reached giNone = high(byte) // remove ); + //TODO-cGDB: add a system allowing to define watch points + TCESynMemo = class(TSynEdit, ICEDebugObserver) private + //fIndentGuideMarkup: TSynEditMarkupFoldColors; fFilename: string; fDastWorxExename: string; fModified: boolean; @@ -741,6 +746,7 @@ begin fImages.AddResourceName(HINSTANCE, 'BULLET_BLACK'); fImages.AddResourceName(HINSTANCE, 'BREAKS'); fImages.AddResourceName(HINSTANCE, 'STEP'); + fImages.AddResourceName(HINSTANCE, 'CAMERA_GO'); fBreakPoints := TFPList.Create; // fPositions := TCESynMemoPositions.create(self); @@ -754,6 +760,9 @@ begin LineHighlightColor.Background := color - $080808; LineHighlightColor.Foreground := clNone; // + //fIndentGuideMarkup:= TSynEditMarkupFoldColors.Create(self); + //MarkupManager.AddMarkUp(fIndentGuideMarkup); + // fAutoCloseCurlyBrace:= autoCloseOnNewLineLexically; fAutoClosedPairs:= [autoCloseSquareBracket]; // @@ -769,6 +778,7 @@ destructor TCESynMemo.destroy; begin saveCache; // + //fIndentGuideMarkup.Free; EntitiesConnector.removeObserver(self); subjDocClosing(TCEMultiDocSubject(fMultiDocSubject), self); fMultiDocSubject.Free; @@ -2603,6 +2613,7 @@ begin case reason of dbBreakPoint: setGutterIcon(line, giBreak); dbStep, dbSignal: setGutterIcon(line, giStep); + dbWatch: setGutterIcon(line, giWatch); end; end; {$ENDREGION --------------------------------------------------------------------}