diff --git a/uppsrc/HexView/HexView.cpp b/uppsrc/HexView/HexView.cpp index 4a0f15f57..b5c3f455b 100644 --- a/uppsrc/HexView/HexView.cpp +++ b/uppsrc/HexView/HexView.cpp @@ -52,7 +52,7 @@ void HexViewInfo::Paint(Draw& w) { Size sz = GetSize(); w.DrawRect(sz, SColorLtFace); - if(mode < 1) + if(mode < 1 || empty) return; Size fsz = GetTextSize("X", font); char h[17]; @@ -149,11 +149,15 @@ void HexView::Paint(Draw& w) { Size sz = GetSize(); w.DrawRect(sz, SColorPaper); + if(!total) { + w.DrawText(Zx(10), Zx(10), "No data", ArialZ(20).Italic(), SRed()); + return; + } int y = 0; - int64 adr = sc; + uint64 adr = sc; while(y < sz.cy) { char h[17]; - FormatHex(h, adr, IsLongMode() ? 16 : 8); + FormatHex(h, adr + start, IsLongMode() ? 16 : 8); w.DrawText(0, y, h, font); int x = (IsLongMode() ? 17 : 9) * fsz.cx; int tx = x + columns * fcx3; @@ -212,9 +216,10 @@ void HexView::MouseWheel(Point, int zdelta, dword) void HexView::SetSb() { sbm = 0; - while((total >> sbm) > (1 << 30)) + uint64 sz = total; + while((sz >> sbm) > (1 << 30)) sbm++; - sb.SetTotal(int(total >> sbm) / columns + 2); + sb.SetTotal(int(sz >> sbm) / columns + 2); sb.SetPage(int(rows >> sbm)); sb.Set(int(sc >> sbm) / columns + 1); } @@ -228,7 +233,16 @@ void HexView::Layout() SetSb(); } -void HexView::SetTotal(int64 _total) +void HexView::SetStart(uint64 start_) +{ + start = start_; + Layout(); + SetSb(); + Refresh(); + RefreshInfo(); +} + +void HexView::SetTotal(uint64 _total) { total = _total; Layout(); @@ -237,9 +251,9 @@ void HexView::SetTotal(int64 _total) RefreshInfo(); } -void HexView::SetSc(int64 address) +void HexView::SetSc(uint64 address) { - sc = minmax(address, (int64)0, total); + sc = minmax(address, start, total); SetSb(); Refresh(); } @@ -256,14 +270,19 @@ void HexView::Scroll() void HexView::RefreshInfo() { - info.SetPos(cursor, IsLongMode()); - for(int i = 0; i < 80; i++) - info.Set(i, Byte(cursor + i)); + if(total) { + info.SetPos(cursor + start, IsLongMode()); + for(int i = 0; i < 80; i++) + info.Set(i, Byte(cursor + i)); + } + else + info.SetEmpty(); } -void HexView::SetCursor(int64 _cursor) +void HexView::SetCursor(uint64 _cursor) { cursor = _cursor; + if(cursor > total) cursor = total - 1; if(cursor < 0) @@ -294,7 +313,7 @@ void HexView::LeftDown(Point p, dword) x = p.x - x; int q = x / fcx3; if(x - q * fcx3 < 2 * fsz.cx && q < columns) { - int64 c = sc + rowi * columns + q; + uint64 c = sc + rowi * columns + q; if(c < total) SetCursor(c); } @@ -303,7 +322,7 @@ void HexView::LeftDown(Point p, dword) if(p.x >= tx) { int q = (p.x - tx) / fsz.cx; if(q >= 0 && q < columns) { - int64 c = sc + rowi * columns + q; + uint64 c = sc + rowi * columns + q; if(c < total) SetCursor(c); } @@ -383,7 +402,7 @@ void HexView::StdGoto(const String& s) if(p.Char2('0', 'x') || p.Char('$') || p.Char('#')) n = 16; if(p.IsNumber(n)) { - int64 a = p.ReadNumber(n); + uint64 a = p.ReadNumber(n); if(a >= 0 && a < total) { SetCursor(a); SetSc(a); @@ -435,7 +454,7 @@ void HexView::CharsetMenu(Bar& bar) void HexView::StdMenu(Bar& bar) { - bar.Add("Go to..", THISBACK(Goto)) + bar.Add("Go to..", [=] { WhenGotoDlg(); }) .Key(K_CTRL_G); bar.Add("Columns", THISBACK(ColumnsMenu)); bar.Add("Charset", THISBACK(CharsetMenu)); @@ -489,6 +508,7 @@ HexView::HexView() WhenBar = THISBACK(StdMenu); CtrlLayoutOKCancel(go, "Go to"); WhenGoto = THISBACK(StdGoto); + WhenGotoDlg = THISBACK(Goto); } } diff --git a/uppsrc/HexView/HexView.h b/uppsrc/HexView/HexView.h index c45f27a83..61a792c9f 100644 --- a/uppsrc/HexView/HexView.h +++ b/uppsrc/HexView/HexView.h @@ -17,11 +17,13 @@ private: int data[80]; int mode; bool longmode; + bool empty = false; void PrintValue(Draw& w, int x, int y, int bytes, bool be); public: - void SetPos(int64 p, bool lm) { pos = p; longmode = lm; } + void SetEmpty() { empty = true; Refresh(); } + void SetPos(int64 p, bool lm) { pos = p; longmode = lm; empty = false; Refresh(); } void Set(int i, int d) { ASSERT(i >= 0 && i < 80); data[i] = d; Refresh(); } void SetMode(int m); int GetMode() const { return mode; } @@ -45,7 +47,10 @@ private: int fixed; int columns, rows, bytes; int sbm; - int64 sc, cursor, total; + uint64 sc = 0; + uint64 cursor = 0; + uint64 total = 0; + uint64 start = 0; byte charset; ScrollBar sb; @@ -66,24 +71,26 @@ public: Event WhenBar; Event WhenGoto; + Event<> WhenGotoDlg; - void ColumnsMenu(Bar& bar); - void CharsetMenu(Bar& bar); - void InfoMenu(Bar& bar); - void StdMenu(Bar& bar); + void ColumnsMenu(Bar& bar); + void CharsetMenu(Bar& bar); + void InfoMenu(Bar& bar); + void StdMenu(Bar& bar); - void StdGoto(const String& text); + void StdGoto(const String& text); - void GotoAddHistory() { go.text.AddHistory(); } + void GotoAddHistory() { go.text.AddHistory(); } - bool IsLongMode() const { return total > 0xffffffff; } - void SetTotal(int64 _total); - void SetSc(int64 address); - int64 GetSc() const { return sc; } - void SetCursor(int64 address); - int64 GetCursor() const { return cursor; } + bool IsLongMode() const { return total > 0xffffffff; } + void SetStart(uint64 start); + void SetTotal(uint64 _total); + void SetSc(uint64 address); + uint64 GetSc() const { return sc; } + void SetCursor(uint64 address); + uint64 GetCursor() const { return cursor; } - void SerializeSettings(Stream& s); + void SerializeSettings(Stream& s); HexView& SetFont(Font fnt); HexView& Charset(byte chrset) { charset = chrset; Refresh(); return *this; } diff --git a/uppsrc/ide/Debuggers/Debuggers.upp b/uppsrc/ide/Debuggers/Debuggers.upp index bc7dddebf..e085d1976 100644 --- a/uppsrc/ide/Debuggers/Debuggers.upp +++ b/uppsrc/ide/Debuggers/Debuggers.upp @@ -20,6 +20,7 @@ file GdbCmd.cpp, GdbData.cpp, Gdb.cpp, + GdbMem.cpp, GdbUtils.h, GdbUtils.cpp, PDB readonly separator, diff --git a/uppsrc/ide/Debuggers/Gdb.cpp b/uppsrc/ide/Debuggers/Gdb.cpp index 2ddc638b8..44af7fce9 100644 --- a/uppsrc/ide/Debuggers/Gdb.cpp +++ b/uppsrc/ide/Debuggers/Gdb.cpp @@ -617,27 +617,40 @@ void Gdb::Periodic() Gdb::Gdb() : gdb_utils(GdbUtilsFactory().Create()) { + auto Mem = [=](Bar& bar, ArrayCtrl& h) { + String s = h.GetKey(); + if(s.GetCount()) { + if(!IsAlpha(*s)) + s = '(' + s + ')'; + bar.Add("Memory at &&" + s, [=] { tab.Set(memory); MemoryLoad('&' + s, 2048, true); }); + bar.Add("Memory at " + s, [=] { tab.Set(memory); MemoryLoad(s, 2048, true); }); + } + }; locals.NoHeader(); locals.AddColumn("", 1); locals.AddColumn("", 6); locals.EvenRowColor(); locals.WhenSel = THISBACK1(SetTree, &locals); + locals.WhenBar = [=](Bar& bar) { Mem(bar, locals); }; watches.NoHeader(); watches.AddColumn("", 1).Edit(watchedit); watches.AddColumn("", 6); watches.Inserting().Removing(); watches.EvenRowColor(); watches.WhenSel = THISBACK1(SetTree, &watches); + watches.WhenBar = [=](Bar& bar) { Mem(bar, watches); }; autos.NoHeader(); autos.AddColumn("", 1); autos.AddColumn("", 6); autos.EvenRowColor(); autos.WhenSel = THISBACK1(SetTree, &autos); + autos.WhenBar = [=](Bar& bar) { Mem(bar, autos); }; self.NoHeader(); self.AddColumn("", 1); self.AddColumn("", 6); self.EvenRowColor(); self.WhenSel = THISBACK1(SetTree, &self); + self.WhenBar = [=](Bar& bar) { Mem(bar, self); }; cpu.Columns(3); cpu.ItemHeight(Courier(Ctrl::HorzLayoutZoom(12)).GetCy()); @@ -647,11 +660,13 @@ Gdb::Gdb() tab.Add(watches.SizePos(), "Watches"); tab.Add(self.SizePos(), "this"); tab.Add(cpu.SizePos(), "CPU"); - pane.Add(threads.LeftPosZ(250, 150).TopPos(2)); + tab.Add(memory.SizePos(), "Memory"); + pane.Add(threads.LeftPosZ(330, 150).TopPos(2)); + memory.WhenGotoDlg = [=] { MemoryGoto(); }; int bcx = min(EditField::GetStdHeight(), DPI(16)); - pane.Add(frame.HSizePos(Zx(404), 2 * bcx).TopPos(2)); + pane.Add(frame.HSizePos(Zx(484), 2 * bcx).TopPos(2)); pane.Add(frame_up.RightPos(bcx, bcx).TopPos(2, EditField::GetStdHeight())); frame_up.SetImage(DbgImg::FrameUp()); frame_up << [=] { FrameUpDown(-1); }; diff --git a/uppsrc/ide/Debuggers/Gdb.h b/uppsrc/ide/Debuggers/Gdb.h index 8dcd86fd3..01fe8aafb 100644 --- a/uppsrc/ide/Debuggers/Gdb.h +++ b/uppsrc/ide/Debuggers/Gdb.h @@ -76,7 +76,10 @@ public: void SetTree(ArrayCtrl *a); void OnTreeBar(Bar& bar); void OnTreeExpand(int node); - + void MemoryGoto(); + void MemoryLoad(const String& adr, int count, bool showerror); + void Memory(); + void OnValueCopyToClipboard(const Value& val); Value ObtainValueFromTreeCursor(int cursor) const; @@ -86,12 +89,12 @@ public: void CopyDisas(); void BreakRunning(); - + bool Create(One&& host, const String& exefile, const String& cmdline, bool console); TimeCallback periodic; // Period check for killed console void Periodic(); - + virtual ~Gdb() override; Gdb(); @@ -118,7 +121,14 @@ protected: StaticRect pane; Splitter split; TreeCtrl tree; - + struct GdbHexView : HexView { + uint64 start; + Vector data; + + virtual int Byte(int64 i) { return i >= 0 && i < data.GetCount() ? data[(int)i] : 0; } + } + memory; + VectorMap expression_cache; WithQuickwatchLayout quickwatch; diff --git a/uppsrc/ide/Debuggers/Gdb.lay b/uppsrc/ide/Debuggers/Gdb.lay index 4735fc196..a8bbfd1fd 100644 --- a/uppsrc/ide/Debuggers/Gdb.lay +++ b/uppsrc/ide/Debuggers/Gdb.lay @@ -5,3 +5,12 @@ LAYOUT(QuickwatchLayout, 400, 372) ITEM(Button, cancel, SetLabel(t_("Cancel")).RightPosZ(76, 64).BottomPosZ(6, 22)) END_LAYOUT +LAYOUT(GotoMemoryLayout, 384, 64) + ITEM(Label, dv___0, SetLabel(t_("Address")).LeftPosZ(8, 48).TopPosZ(8, 19)) + ITEM(EditString, adr, LeftPosZ(60, 208).TopPosZ(8, 19)) + ITEM(Label, dv___2, SetLabel(t_("bytes")).LeftPosZ(276, 36).TopPosZ(8, 19)) + ITEM(WithDropChoice, count, LeftPosZ(312, 64).TopPosZ(8, 19)) + ITEM(Button, ok, SetLabel(t_("OK")).HCenterPosZ(64, 84).BottomPosZ(6, 22)) + ITEM(Button, cancel, SetLabel(t_("Cancel")).RightPosZ(8, 64).BottomPosZ(6, 22)) +END_LAYOUT + diff --git a/uppsrc/ide/Debuggers/GdbData.cpp b/uppsrc/ide/Debuggers/GdbData.cpp index 5b988656c..d18f4dab2 100644 --- a/uppsrc/ide/Debuggers/GdbData.cpp +++ b/uppsrc/ide/Debuggers/GdbData.cpp @@ -280,6 +280,7 @@ void Gdb::ObtainData() case 2: Watches(); break; case 3: Self(); break; case 4: Cpu(); break; + case 5: Memory(); break; } } diff --git a/uppsrc/ide/Debuggers/GdbMem.cpp b/uppsrc/ide/Debuggers/GdbMem.cpp new file mode 100644 index 000000000..b6bdd9baa --- /dev/null +++ b/uppsrc/ide/Debuggers/GdbMem.cpp @@ -0,0 +1,53 @@ +#include "Debuggers.h" + +void Gdb::MemoryGoto() +{ + WithGotoMemoryLayout dlg; + CtrlLayoutOKCancel(dlg, "Memory view"); + dlg.count <<= memory.data.GetCount(); + dlg.count.AddList(1024); + dlg.count.AddList(2048); + dlg.count.AddList(4096); + dlg.count <<= 2048; + dlg.adr <<= FormatHex((void *)memory.start); + if(dlg.Execute() != IDOK) + return; + MemoryLoad(~dlg.adr, ~dlg.count, true); +} + +void Gdb::MemoryLoad(const String& adr, int count, bool showerror) +{ + memory.start = 0; + memory.data.Clear(); + String error; + for(String s : Split(FastCmd("x /" + AsString(clamp(count, 1, 1024*1024)) + "xb " + adr), '\n')) { + if(IsNull(error)) + error = TrimBoth(s); + CParser p(s); + while(!p.IsEof()) + if(p.Char2('0', 'x') && p.IsNumber(16)) { + uint64 a = p.ReadNumber(16); + if(!memory.start) + memory.start = a; + while(!p.IsEof()) + if(p.Char2('0', 'x') && p.IsNumber(16)) + memory.data.Add((byte)p.ReadNumber(16)); + else + p.SkipTerm(); + } + else + p.SkipTerm(); + } + if(showerror && !memory.start && error.GetCount()) + Exclamation("\1" + error); + memory.SetStart(memory.start); + memory.SetTotal(memory.data.GetCount()); + memory.SetSc(0); + memory.SetCursor(0); +} + +void Gdb::Memory() +{ + if(memory.data.GetCount()) + MemoryLoad("0x" + FormatIntHex((void *)memory.start), memory.data.GetCount(), false); +}