From 609303c98366d6f49e32b7db4552162192f0a0ff Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Sun, 27 Nov 2016 14:43:57 +0100 Subject: [PATCH] #97, start asm view --- src/ce_gdb.lfm | 252 ++++++++++++++++++++++++++++--------------------- src/ce_gdb.pas | 122 ++++++++++++++++++++---- 2 files changed, 251 insertions(+), 123 deletions(-) diff --git a/src/ce_gdb.lfm b/src/ce_gdb.lfm index 7f14acdf..2d438507 100644 --- a/src/ce_gdb.lfm +++ b/src/ce_gdb.lfm @@ -1,9 +1,8 @@ inherited CEGdbWidget: TCEGdbWidget - Left = 640 + Left = 635 Height = 668 - Top = 213 + Top = 212 Width = 517 - ActiveControl = Back Caption = 'GDB commander' ClientHeight = 668 ClientWidth = 517 @@ -20,27 +19,27 @@ inherited CEGdbWidget: TCEGdbWidget ClientWidth = 517 object Panel1: TPanel[0] Left = 0 - Height = 394 - Top = 196 + Height = 385 + Top = 205 Width = 517 Align = alClient BevelOuter = bvNone - ClientHeight = 394 + ClientHeight = 385 ClientWidth = 517 TabOrder = 0 object GroupBox3: TGroupBox Left = 0 - Height = 197 - Top = 197 + Height = 179 + Top = 206 Width = 517 Align = alClient Caption = 'CPU' - ClientHeight = 167 + ClientHeight = 149 ClientWidth = 513 TabOrder = 0 object cpuVIewer: TTIPropertyGrid Left = 0 - Height = 167 + Height = 149 Hint = 'cpu registers' Top = 0 Width = 513 @@ -55,67 +54,103 @@ inherited CEGdbWidget: TCEGdbWidget ValueFont.Color = clMaroon end end - object GroupBox2: TGroupBox - Left = 0 - Height = 191 - Top = 0 - Width = 517 - Align = alTop - Caption = 'Variables' - ClientHeight = 161 - ClientWidth = 513 - TabOrder = 1 - object varList: TListView - Left = 2 - Height = 135 - Top = 24 - Width = 509 - Align = alClient - BorderSpacing.Around = 2 - Columns = < - item - AutoSize = True - Caption = 'Name' - Width = 47 - end - item - AutoSize = True - Caption = 'Value' - Width = 458 - end> - GridLines = True - HideSelection = False - ReadOnly = True - ScrollBars = ssAutoBoth - SortColumn = 0 - SortType = stText - TabOrder = 0 - ViewStyle = vsReport - end - object varListFlt: TListViewFilterEdit - Left = 2 - Height = 20 - Hint = 'locate variables' - Top = 2 - Width = 509 - ButtonWidth = 24 - NumGlyphs = 1 - Align = alTop - BorderSpacing.Around = 2 - MaxLength = 0 - TabOrder = 1 - OnChange = varListFltChange - end - end object Splitter4: TSplitter Cursor = crVSplit Left = 0 Height = 6 - Top = 191 + Top = 0 Width = 517 Align = alTop ResizeAnchor = akTop end + object PageControl2: TPageControl + Left = 0 + Height = 200 + Top = 6 + Width = 517 + ActivePage = TabSheet4 + Align = alTop + TabIndex = 1 + TabOrder = 2 + object TabSheet3: TTabSheet + Caption = 'Variables' + ClientHeight = 164 + ClientWidth = 509 + object varList: TListView + Left = 2 + Height = 138 + Top = 24 + Width = 505 + Align = alClient + BorderSpacing.Around = 2 + Columns = < + item + AutoSize = True + Caption = 'Name' + Width = 47 + end + item + AutoSize = True + Caption = 'Value' + Width = 454 + end> + GridLines = True + HideSelection = False + ReadOnly = True + ScrollBars = ssAutoBoth + SortColumn = 0 + SortType = stText + TabOrder = 0 + ViewStyle = vsReport + end + object varListFlt: TListViewFilterEdit + Left = 2 + Height = 20 + Hint = 'locate variables' + Top = 2 + Width = 505 + ButtonWidth = 24 + NumGlyphs = 1 + Align = alTop + BorderSpacing.Around = 2 + MaxLength = 0 + TabOrder = 1 + OnChange = varListFltChange + end + end + object TabSheet4: TTabSheet + Caption = 'Assembly' + ClientHeight = 164 + ClientWidth = 509 + object asmList: TListView + Left = 2 + Height = 160 + Top = 2 + Width = 505 + Align = alClient + AutoSort = False + BorderSpacing.Around = 2 + Columns = < + item + AutoSize = True + Caption = 'Address' + Width = 60 + end + item + AutoSize = True + Caption = 'Instruction' + Width = 441 + end> + GridLines = True + HideSelection = False + ReadOnly = True + ScrollBars = ssAutoBoth + SortColumn = 0 + TabOrder = 0 + ViewStyle = vsReport + end + end + end end object Panel3: TPanel[1] Left = 4 @@ -152,55 +187,62 @@ inherited CEGdbWidget: TCEGdbWidget TabOrder = 0 end end - object GroupBox1: TGroupBox[2] - Left = 0 - Height = 191 - Top = 0 - Width = 517 - Align = alTop - Caption = 'Call stack' - ClientHeight = 161 - ClientWidth = 513 - TabOrder = 2 - object lstCallStack: TListView - Left = 0 - Height = 161 - Hint = 'call stack' - Top = 0 - Width = 513 - Align = alClient - Columns = < - item - AutoSize = True - Caption = 'function' - Width = 62 - end - item - AutoSize = True - Caption = 'address' - Width = 59 - end - item - AutoSize = True - Caption = 'filename' - Width = 371 - end> - GridLines = True - ReadOnly = True - TabOrder = 0 - ViewStyle = vsReport - OnDblClick = lstCallStackDblClick - end - end - object Splitter3: TSplitter[3] + object Splitter3: TSplitter[2] Cursor = crVSplit Left = 0 Height = 5 - Top = 191 + Top = 200 Width = 517 Align = alTop ResizeAnchor = akTop end + object PageControl1: TPageControl[3] + Left = 0 + Height = 200 + Top = 0 + Width = 517 + ActivePage = TabSheet1 + Align = alTop + TabIndex = 0 + TabOrder = 3 + object TabSheet1: TTabSheet + Caption = 'Call stack' + ClientHeight = 164 + ClientWidth = 509 + object lstCallStack: TListView + Left = 0 + Height = 164 + Hint = 'call stack' + Top = 0 + Width = 509 + Align = alClient + Columns = < + item + AutoSize = True + Caption = 'function' + Width = 62 + end + item + AutoSize = True + Caption = 'address' + Width = 59 + end + item + AutoSize = True + Caption = 'filename' + Width = 367 + end> + GridLines = True + ReadOnly = True + TabOrder = 0 + ViewStyle = vsReport + OnDblClick = lstCallStackDblClick + end + end + object TabSheet2: TTabSheet + Caption = 'Thread list' + end + end end inherited toolbar: TCEToolBar Width = 509 diff --git a/src/ce_gdb.pas b/src/ce_gdb.pas index c7d6c8f7..50a23b13 100644 --- a/src/ce_gdb.pas +++ b/src/ce_gdb.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, RegExpr, ComCtrls, PropEdits, GraphPropEdits, RTTIGrids, Dialogs, ExtCtrls, Menus, Buttons, - StdCtrls, process, fpjson, typinfo, {$IFDEF UNIX}Unix,{$ENDIF} ListViewFilterEdit, + StdCtrls, process, fpjson, typinfo, Unix, ListViewFilterEdit, SynEdit, ce_common, ce_interfaces, ce_widget, ce_processes, ce_observer, ce_synmemo, ce_sharedres, ce_stringrange, ce_dsgncontrols, ce_dialogs, ce_dbgitf, ce_ddemangle, ce_writableComponent, EditBtn, strutils; @@ -330,9 +330,13 @@ type btnWatch: TCEToolButton; button4: TCEToolButton; Edit1: TComboBox; - GroupBox1: TGroupBox; - GroupBox2: TGroupBox; GroupBox3: TGroupBox; + PageControl1: TPageControl; + PageControl2: TPageControl; + TabSheet1: TTabSheet; + TabSheet2: TTabSheet; + TabSheet3: TTabSheet; + TabSheet4: TTabSheet; varList: TListView; lstCallStack: TListView; mnuReadW: TMenuItem; @@ -349,6 +353,7 @@ type Splitter2: TSplitter; Splitter3: TSplitter; Splitter4: TSplitter; + asmList: TListView; varListFlt: TListViewFilterEdit; procedure btnContClick(Sender: TObject); procedure btnVariablesClick(Sender: TObject); @@ -396,6 +401,10 @@ type fAddWatchPointKind: TAddWatchPointKind; fBreakPoints: TPersistentBreakPoints; fMenu: TMenuItem; + fLastFilename: string; + fLastFunction: string; + fLastOffset: string; + fLastLine: string; procedure updateMenu; procedure optionsChangesApplied(sender: TObject); procedure disableEditor; @@ -413,6 +422,7 @@ type procedure infoRegs; procedure infoStack; procedure infoVariables; + procedure infoAsm(const fname: string); procedure sendCustomCommand; procedure setGpr(reg: TCpuRegister; val: TCpuGprValue); procedure setFpr(reg: TFpuRegister; val: extended); @@ -1660,6 +1670,18 @@ end; procedure TCEGdbWidget.interpretJson; + procedure selectAsmInstr; + var + itm: TListItem; + begin + itm := asmList.FindCaption(0, fLastOffset, false, true, false); + if itm.isNotNil then + begin + itm.Selected:=true; + itm.MakeVisible(false); + end; + end; + procedure autoGetStuff; begin if fOptions.autoGetCallStack then @@ -1668,6 +1690,7 @@ procedure TCEGdbWidget.interpretJson; infoRegs; if fOptions.autoGetVariables then infoVariables; + selectAsmInstr; end; var @@ -1681,7 +1704,6 @@ var nme: string; reason: string; addr: PtrUint = 0; - fullname: string = ''; func:string = ''; line: integer = -1; // registers data @@ -1726,18 +1748,31 @@ begin obj := TJSONObject(fJson.Find('frame')); if obj.isNotNil and (obj.JSONType = jtObject) then begin + val := obj.Find('addr'); + if val.isNotNil then + fLastOffset:=val.AsString; val := obj.Find('fullname'); if val.isNotNil then - fullname := val.AsString; + fLastFilename := val.AsString; val := obj.Find('line'); if val.isNotNil then + begin line := val.AsInteger; - if fDocHandler.findDocument(fullname).isNil and fullname.fileExists then - fDocHandler.openDocument(fullname); + fLastLine := val.AsString; + end; + val := obj.Find('func'); + if val.isNotNil then + begin + if val.AsString <> fLastFunction then + infoAsm(fLastFilename); + fLastFunction := val.AsString; + end; + if fDocHandler.findDocument(fLastFilename).isNil and fLastFilename.fileExists then + fDocHandler.openDocument(fLastFilename); setState(gsPaused); autoGetStuff; readOutput; - subjDebugBreak(fSubj, fullname, line, brkreason); + subjDebugBreak(fSubj, fLastFilename, line, brkreason); end; end @@ -1762,27 +1797,37 @@ begin obj := TJSONObject(fJson.Find('frame')); if obj.isNotNil and (obj.JSONType = jtObject) then begin + val := obj.Find('addr'); + if val.isNotNil then + fLastOffset:=val.AsString; val := obj.Find('fullname'); if val.isNotNil then - fullname := val.AsString; + fLastFilename := val.AsString; val := obj.Find('line'); if val.isNotNil then line := val.AsInteger; + val := obj.Find('func'); + if val.isNotNil then + begin + if val.AsString <> fLastFunction then + infoAsm(fLastFilename); + fLastFunction := val.AsString; + end; end; if fCatchPause then begin fCatchPause := false; - if fDocHandler.findDocument(fullname).isNil and fullname.fileExists then - fDocHandler.openDocument(fullname); + if fDocHandler.findDocument(fLastFilename).isNil and fLastFilename.fileExists then + fDocHandler.openDocument(fLastFilename); autoGetStuff; setState(gsPaused); readOutput; - subjDebugBreak(fSubj, fullname, line, dbSignal); + subjDebugBreak(fSubj, fLastFilename, line, dbSignal); end else begin if dlgYesNo(format('The signal %s (%s) was received on line %d of file %s .' - + LineEnding + 'Do you wish to pause execution ?', [signame, sigmean, line, fullname]), + + LineEnding + 'Do you wish to pause execution ?', [signame, sigmean, line, fLastFilename]), 'Unexpected signal received') = mrNo then begin gdbCommand('continue', @gdboutJsonize); @@ -1790,12 +1835,12 @@ begin end else begin - if not fDocHandler.findDocument(fullname).isNil and fullname.fileExists then - fDocHandler.openDocument(fullname); + if not fDocHandler.findDocument(fLastFilename).isNil and fLastFilename.fileExists then + fDocHandler.openDocument(fLastFilename); autoGetStuff; setState(gsPaused); readOutput; - subjDebugBreak(fSubj, fullname, line, dbSignal); + subjDebugBreak(fSubj, fLastFilename, line, dbSignal); end; end; end @@ -1884,7 +1929,7 @@ begin break; val := obj.Find('fullname'); if val.isNotNil then - fullname:= val.AsString; + fLastFilename:= val.AsString; val := obj.Find('func'); if val.isNotNil then begin @@ -1899,7 +1944,7 @@ begin val := obj.Find('line'); if val.isNotNil then line := val.AsInteger; - fStackItems.addItem(addr, fullname, func, line); + fStackItems.addItem(addr, fLastFilename, func, line); end; fStackItems.assignToList(lstCallStack); end; @@ -1935,6 +1980,38 @@ begin varList.EndUpdate; end; + val := fJson.Find('asm_insns'); + if val.isNotNil and (val.JSONType = jtArray) then + begin + asmList.Clear; + asmList.BeginUpdate; + arr := TJSONArray(val); + for i := 0 to arr.Count-1 do + begin + obj := arr.Objects[i]; + val := obj.Find('address'); + if val.isNotNil then + nme := val.AsString; + //val := obj.Find('func-name'); + //val := obj.Find('offset'); + val := obj.Find('inst'); + if val.isNotNil then + begin + asmList.AddItem(nme, nil); + if nme = fLastOffset then + asmList.Selected := asmList.Items[asmList.Items.Count-1]; + if fOptions.autoDemangle then + asmList.Items[asmList.Items.Count-1].SubItems.Add(demangle(val.AsString)) + else + asmList.Items[asmList.Items.Count-1].SubItems.Add(val.AsString); + end; + end; + if asmList.Selected.isNotNil then + asmList.Selected.MakeVisible(false); + asmList.EndUpdate; + selectAsmInstr; + end; + if fOptions.showGdbOutput or fShowFromCustomCommand then begin fShowFromCustomCommand := false; @@ -2042,6 +2119,15 @@ begin gdbCommand('-stack-list-variables --skip-unavailable --simple-values'); end; +procedure TCEGdbWidget.infoAsm(const fname: string); +var + cmd: string; +begin + cmd := format('-data-disassemble -f %s -l %s -n -1 -- 0', [fname, fLastLine]); + //cmd := format('-data-disassemble -s %s -e $pc -- 0', [fLastOffset]); + gdbCommand(cmd, @gdboutJsonize); +end; + procedure TCEGdbWidget.btnStartClick(Sender: TObject); begin startDebugging;