From cb92b4acc285e1addf81ec964178fb44bbeb4686 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Sun, 6 Aug 2017 18:32:21 +0200 Subject: [PATCH 01/11] * debugger: Fire cbEVT_DEBUGGER_PAUSED event Fire the event if the debugger is paused and no future commands are in the queue. Don't send debugger commands within this event, or you will end in a endless loop --- src/plugins/debuggergdb/cdb_driver.cpp | 8 ++++++++ src/plugins/debuggergdb/gdb_driver.cpp | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/src/plugins/debuggergdb/cdb_driver.cpp b/src/plugins/debuggergdb/cdb_driver.cpp index d5b8c1e9a9..2e5adad031 100644 --- a/src/plugins/debuggergdb/cdb_driver.cpp +++ b/src/plugins/debuggergdb/cdb_driver.cpp @@ -409,6 +409,14 @@ void CDB_driver::ParseOutput(const wxString& output) if (notifyChange) NotifyCursorChanged(); + if(m_ProgramIsStopped) + { + // Notify debugger plugins for pause of debug session + PluginManager *plm = Manager::Get()->GetPluginManager(); + CodeBlocksEvent evt(cbEVT_DEBUGGER_PAUSED); + plm->NotifyPlugins(evt); + } + buffer.Clear(); } diff --git a/src/plugins/debuggergdb/gdb_driver.cpp b/src/plugins/debuggergdb/gdb_driver.cpp index 6b60ab3d0e..2a0bc8901b 100644 --- a/src/plugins/debuggergdb/gdb_driver.cpp +++ b/src/plugins/debuggergdb/gdb_driver.cpp @@ -1074,7 +1074,16 @@ void GDB_driver::ParseOutput(const wxString& output) } if (m_ProgramIsStopped) + { + if(m_DCmds.GetCount() == 0) + { + PluginManager *plm = Manager::Get()->GetPluginManager(); + CodeBlocksEvent evt(cbEVT_DEBUGGER_PAUSED); + plm->NotifyPlugins(evt); + } RunQueue(); + } + } From 4c621f1945714647b2cc7949dd6362905c133d4d Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 26 Sep 2017 00:00:08 +0200 Subject: [PATCH 02/11] * sdk: Add cbEVT_DEBUGGER_CONTINUED event for debugger SDK version not updated --- src/include/sdk_events.h | 2 ++ src/sdk/manager.cpp | 1 + src/sdk/sdk_events.cpp | 1 + 3 files changed, 4 insertions(+) diff --git a/src/include/sdk_events.h b/src/include/sdk_events.h index 5de966d7f1..e91214ee3b 100644 --- a/src/include/sdk_events.h +++ b/src/include/sdk_events.h @@ -432,6 +432,8 @@ extern EVTIMPORT const wxEventType cbEVT_DEBUGGER_STARTED; #define EVT_DEBUGGER_STARTED(fn) DECLARE_EVENT_TABLE_ENTRY( cbEVT_DEBUGGER_STARTED, -1, -1, (wxObjectEventFunction)(wxEventFunction)(CodeBlocksEventFunction)&fn, (wxObject *) NULL ), extern EVTIMPORT const wxEventType cbEVT_DEBUGGER_PAUSED; #define EVT_DEBUGGER_PAUSED(fn) DECLARE_EVENT_TABLE_ENTRY( cbEVT_DEBUGGER_PAUSED, -1, -1, (wxObjectEventFunction)(wxEventFunction)(CodeBlocksEventFunction)&fn, (wxObject *) NULL ), +extern EVTIMPORT const wxEventType cbEVT_DEBUGGER_CONTINUED; +#define cbEVT_DEBUGGER_CONTINUED(fn) DECLARE_EVENT_TABLE_ENTRY( cbEVT_DEBUGGER_CONTINUED, -1, -1, (wxObjectEventFunction)(wxEventFunction)(CodeBlocksEventFunction)&fn, (wxObject *) NULL ), extern EVTIMPORT const wxEventType cbEVT_DEBUGGER_FINISHED; #define EVT_DEBUGGER_FINISHED(fn) DECLARE_EVENT_TABLE_ENTRY( cbEVT_DEBUGGER_FINISHED, -1, -1, (wxObjectEventFunction)(wxEventFunction)(CodeBlocksEventFunction)&fn, (wxObject *) NULL ), diff --git a/src/sdk/manager.cpp b/src/sdk/manager.cpp index 0ee642ecb5..2e2f57029a 100644 --- a/src/sdk/manager.cpp +++ b/src/sdk/manager.cpp @@ -112,6 +112,7 @@ static wxString GetCodeblocksEventName(wxEventType type) else if (type==cbEVT_DEBUGGER_STARTED) name = _T("cbEVT_DEBUGGER_STARTED"); else if (type==cbEVT_DEBUGGER_STARTED) name = _T("cbEVT_DEBUGGER_STARTED"); else if (type==cbEVT_DEBUGGER_PAUSED) name = _T("cbEVT_DEBUGGER_PAUSED"); + else if (type==cbEVT_DEBUGGER_CONTINUED) name = _T("cbEVT_DEBUGGER_CONTINUED"); else if (type==cbEVT_DEBUGGER_FINISHED) name = _T("cbEVT_DEBUGGER_FINISHED"); else name = _("unknown CodeBlocksEvent"); diff --git a/src/sdk/sdk_events.cpp b/src/sdk/sdk_events.cpp index 35e646867f..b980875d29 100644 --- a/src/sdk/sdk_events.cpp +++ b/src/sdk/sdk_events.cpp @@ -156,6 +156,7 @@ const wxEventType cbEVT_COMPILE_FILE_REQUEST = wxNewEventType(); // debugger-related events const wxEventType cbEVT_DEBUGGER_STARTED = wxNewEventType(); const wxEventType cbEVT_DEBUGGER_PAUSED = wxNewEventType(); +const wxEventType cbEVT_DEBUGGER_CONTINUED = wxNewEventType(); const wxEventType cbEVT_DEBUGGER_FINISHED = wxNewEventType(); // logger-related events From 5240fe6ea19f3c8353491b2052c94e6f2c013216 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 10 Oct 2017 18:15:28 +0200 Subject: [PATCH 03/11] * debugger: Fire cbEVT_DEBUGGER_CONTINUED event Fire the event if the debugger is restarted by the user or a command --- src/plugins/debuggergdb/debuggergdb.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/plugins/debuggergdb/debuggergdb.cpp b/src/plugins/debuggergdb/debuggergdb.cpp index ddf830f58b..9cc48fd57b 100644 --- a/src/plugins/debuggergdb/debuggergdb.cpp +++ b/src/plugins/debuggergdb/debuggergdb.cpp @@ -1135,6 +1135,8 @@ void DebuggerGDB::RunCommand(int cmd) if (!m_pProcess) return; + bool debuggerContinued = false; + switch (cmd) { case CMD_CONTINUE: @@ -1145,6 +1147,7 @@ void DebuggerGDB::RunCommand(int cmd) Log(_("Continuing...")); m_State.GetDriver()->Continue(); m_State.GetDriver()->ResetCurrentFrame(); + debuggerContinued = true; } break; } @@ -1156,6 +1159,7 @@ void DebuggerGDB::RunCommand(int cmd) { m_State.GetDriver()->Step(); m_State.GetDriver()->ResetCurrentFrame(); + debuggerContinued = true; } break; } @@ -1173,6 +1177,7 @@ void DebuggerGDB::RunCommand(int cmd) m_State.GetDriver()->StepInstruction(); m_State.GetDriver()->ResetCurrentFrame(); m_State.GetDriver()->NotifyCursorChanged(); + debuggerContinued = true; } break; } @@ -1190,6 +1195,7 @@ void DebuggerGDB::RunCommand(int cmd) m_State.GetDriver()->StepIntoInstruction(); m_State.GetDriver()->ResetCurrentFrame(); m_State.GetDriver()->NotifyCursorChanged(); + debuggerContinued = true; } break; } @@ -1201,6 +1207,7 @@ void DebuggerGDB::RunCommand(int cmd) { m_State.GetDriver()->StepIn(); m_State.GetDriver()->ResetCurrentFrame(); + debuggerContinued = true; } break; } @@ -1212,6 +1219,7 @@ void DebuggerGDB::RunCommand(int cmd) { m_State.GetDriver()->StepOut(); m_State.GetDriver()->ResetCurrentFrame(); + debuggerContinued = true; } break; } @@ -1265,6 +1273,13 @@ void DebuggerGDB::RunCommand(int cmd) default: break; } + + if(debuggerContinued) + { + PluginManager *plm = Manager::Get()->GetPluginManager(); + CodeBlocksEvent evt(cbEVT_DEBUGGER_CONTINUED); + plm->NotifyPlugins(evt); + } } int DebuggerGDB::GetStackFrameCount() const From fe17f573d52db4ee75b6e851f778aa182e74a93c Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Fri, 6 Oct 2017 13:21:50 +0200 Subject: [PATCH 04/11] * sdk: Add pure virtual function AddMemoryRange() for creating memory range watches --- src/include/cbplugin.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/cbplugin.h b/src/include/cbplugin.h index 96468710d6..0821a91ea0 100644 --- a/src/include/cbplugin.h +++ b/src/include/cbplugin.h @@ -513,6 +513,7 @@ class PLUGIN_EXPORT cbDebuggerPlugin: public cbPlugin // watches virtual cb::shared_ptr AddWatch(const wxString& symbol) = 0; + virtual cb::shared_ptr AddMemoryRange(uint64_t address, uint64_t size, const wxString &id ) = 0; virtual void DeleteWatch(cb::shared_ptr watch) = 0; virtual bool HasWatch(cb::shared_ptr watch) = 0; virtual void ShowWatchProperties(cb::shared_ptr watch) = 0; From bf8482cb740c47e3c6fae3c15e92f1b793698a75 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Fri, 6 Oct 2017 17:52:35 +0200 Subject: [PATCH 05/11] * debugger: Add GDBMemoryRangeWatch class for internal storage of memory range watches --- src/plugins/debuggergdb/debugger_defs.cpp | 31 ++++++++++++++++++++ src/plugins/debuggergdb/debugger_defs.h | 35 ++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/plugins/debuggergdb/debugger_defs.cpp b/src/plugins/debuggergdb/debugger_defs.cpp index a208208cf0..9ecfaa9105 100644 --- a/src/plugins/debuggergdb/debugger_defs.cpp +++ b/src/plugins/debuggergdb/debugger_defs.cpp @@ -21,12 +21,15 @@ #include "debuggerdriver.h" #include +#include #if !defined(CB_TEST_PROJECT) const int DEBUGGER_CURSOR_CHANGED = wxNewId(); const int DEBUGGER_SHOW_FILE_LINE = wxNewId(); +const wxString GDBMemoryRangeWatch::emptyString = wxEmptyString; + DebuggerCmd::DebuggerCmd(DebuggerDriver* driver, const wxString& cmd, bool logToNormalLog) : m_Cmd(cmd), m_pDriver(driver), @@ -306,6 +309,34 @@ bool GDBWatch::GetForTooltip() const return m_forTooltip; } +GDBMemoryRangeWatch::GDBMemoryRangeWatch(uint64_t address, uint64_t size, const wxString& name) +{ + m_address = address; + m_size = size; + m_name = name; +}; + +bool GDBMemoryRangeWatch::SetValue(const wxString &value) +{ + if (m_value != value) + { + m_value = value; + MarkAsChanged(true); + } + return true; +} + +wxString GDBMemoryRangeWatch::MakeSymbolToAddress() const +{ + const int tmpBuffSize = 20; + char tmpAddress[tmpBuffSize]; + + memset(tmpAddress, 0, tmpBuffSize); + snprintf(tmpAddress, tmpBuffSize, "0x%" PRIx64 " ", GetAddress()); + + return wxString::FromUTF8(tmpAddress); +}; + bool IsPointerType(wxString type) { type.Trim(true); diff --git a/src/plugins/debuggergdb/debugger_defs.h b/src/plugins/debuggergdb/debugger_defs.h index 541d531647..5a02ab5b82 100644 --- a/src/plugins/debuggergdb/debugger_defs.h +++ b/src/plugins/debuggergdb/debugger_defs.h @@ -256,9 +256,42 @@ class GDBWatch : public cbWatch int m_array_count; bool m_is_array; bool m_forTooltip; - }; +}; + +class GDBMemoryRangeWatch : public cbWatch +{ + public: + GDBMemoryRangeWatch(uint64_t address, uint64_t size, const wxString& name); + + virtual ~GDBMemoryRangeWatch() {}; + public: + virtual void GetSymbol(wxString &symbol) const { symbol = m_name; }; + virtual void GetValue(wxString &value) const { value = m_value; }; + virtual bool SetValue(const wxString &value); + virtual void GetFullWatchString(wxString &full_watch) const { full_watch = wxEmptyString; }; + virtual void GetType(wxString &type) const { type = wxT("Memory range"); }; + virtual void SetType(const wxString &type) { }; + + virtual wxString const & GetDebugString() const { return emptyString; }; + + wxString MakeSymbolToAddress() const override; + bool IsPointerType() const override { return false; }; + + uint64_t GetAddress() const {return m_address;}; + uint64_t GetSize() const {return m_size;}; + + + private: + uint64_t m_address; + uint64_t m_size; + wxString m_name; + wxString m_value; + + static const wxString emptyString; +}; typedef std::vector > WatchesContainer; +typedef std::vector > MemoryRangeWatchesContainer; bool IsPointerType(wxString type); wxString CleanStringValue(wxString value); From 5a220d894eeb214e87d72dbdc7f5747fa3afc804 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Fri, 6 Oct 2017 17:13:12 +0200 Subject: [PATCH 06/11] * debugger: Implement functions for memory ranges Implement AddMemoryRange and modify DeleteWatch and HasWatch to be aware of memory watches --- src/plugins/debuggergdb/debuggergdb.cpp | 47 ++++++++++++++++++++++--- src/plugins/debuggergdb/debuggergdb.h | 4 +++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/plugins/debuggergdb/debuggergdb.cpp b/src/plugins/debuggergdb/debuggergdb.cpp index 9cc48fd57b..2e89cd18d4 100644 --- a/src/plugins/debuggergdb/debuggergdb.cpp +++ b/src/plugins/debuggergdb/debuggergdb.cpp @@ -2070,6 +2070,8 @@ void DebuggerGDB::OnCursorChanged(wxCommandEvent& WXUNUSED(event)) // update running threads if (dbg_manager->UpdateThreads()) RunCommand(CMD_RUNNINGTHREADS); + + m_State.GetDriver()->UpdateMemoryRangeWatches(m_memoryRange); } } } @@ -2085,6 +2087,18 @@ cb::shared_ptr DebuggerGDB::AddWatch(const wxString& symbol) return watch; } +cb::shared_ptr DebuggerGDB::AddMemoryRange(uint64_t address, uint64_t size, const wxString &id ) +{ + + cb::shared_ptr watch( new GDBMemoryRangeWatch(address, size, id)); + m_memoryRange.push_back(watch); + + if (m_pProcess) + m_State.GetDriver()->UpdateMemoryRangeWatch(m_memoryRange.back()); + + return watch; +} + void DebuggerGDB::AddWatchNoUpdate(const cb::shared_ptr &watch) { m_watches.push_back(watch); @@ -2094,7 +2108,18 @@ void DebuggerGDB::DeleteWatch(cb::shared_ptr watch) { WatchesContainer::iterator it = std::find(m_watches.begin(), m_watches.end(), watch); if (it != m_watches.end()) + { m_watches.erase(it); + return; + } + + MemoryRangeWatchesContainer::iterator mItr = std::find(m_memoryRange.begin(), m_memoryRange.end(), watch); + if (mItr != m_memoryRange.end()) + { + m_memoryRange.erase(mItr); + return; + } + } bool DebuggerGDB::HasWatch(cb::shared_ptr watch) @@ -2102,14 +2127,28 @@ bool DebuggerGDB::HasWatch(cb::shared_ptr watch) WatchesContainer::iterator it = std::find(m_watches.begin(), m_watches.end(), watch); if (it != m_watches.end()) return true; - else - return watch == m_localsWatch || watch == m_funcArgsWatch; + else if(watch == m_localsWatch || watch == m_funcArgsWatch) + return true; + + MemoryRangeWatchesContainer::iterator mItr = std::find(m_memoryRange.begin(), m_memoryRange.end(), watch); + if (mItr != m_memoryRange.end()) + return true; + + return false; +} + +bool DebuggerGDB::IsMemoryRangeWatch(cb::shared_ptr watch) +{ + MemoryRangeWatchesContainer::iterator mItr = std::find(m_memoryRange.begin(), m_memoryRange.end(), watch); + if (mItr != m_memoryRange.end()) + return true; + return false; } void DebuggerGDB::ShowWatchProperties(cb::shared_ptr watch) { - // not supported for child nodes! - if (watch->GetParent()) + // not supported for child nodes or memory ranges! + if (watch->GetParent() || IsMemoryRangeWatch(watch)) return; cb::shared_ptr real_watch = cb::static_pointer_cast(watch); diff --git a/src/plugins/debuggergdb/debuggergdb.h b/src/plugins/debuggergdb/debuggergdb.h index 7ddb4e5f1c..8a66917061 100644 --- a/src/plugins/debuggergdb/debuggergdb.h +++ b/src/plugins/debuggergdb/debuggergdb.h @@ -89,8 +89,10 @@ class DebuggerGDB : public cbDebuggerPlugin int GetExitCode() const { return m_LastExitCode; } cb::shared_ptr AddWatch(const wxString& symbol); + cb::shared_ptr AddMemoryRange(uint64_t address, uint64_t size, const wxString &id ); void DeleteWatch(cb::shared_ptr watch); bool HasWatch(cb::shared_ptr watch); + bool IsMemoryRangeWatch(cb::shared_ptr watch); void ShowWatchProperties(cb::shared_ptr watch); bool SetWatchValue(cb::shared_ptr watch, const wxString &value); void ExpandWatch(cb::shared_ptr watch); @@ -208,6 +210,8 @@ class DebuggerGDB : public cbDebuggerPlugin bool m_TemporaryBreak; WatchesContainer m_watches; + MemoryRangeWatchesContainer m_memoryRange; + cb::shared_ptr m_localsWatch, m_funcArgsWatch; wxString m_watchToDereferenceSymbol; wxObject *m_watchToDereferenceProperty; From e316ebd1b32f7dd9200dc343bc3efc4bc3e213bd Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Fri, 6 Oct 2017 17:54:45 +0200 Subject: [PATCH 07/11] * debugger: Define driver interface for memory watches --- src/plugins/debuggergdb/debuggerdriver.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/debuggergdb/debuggerdriver.h b/src/plugins/debuggergdb/debuggerdriver.h index 20e82a4f2b..62345092ad 100644 --- a/src/plugins/debuggergdb/debuggerdriver.h +++ b/src/plugins/debuggergdb/debuggerdriver.h @@ -105,6 +105,7 @@ class DebuggerDriver virtual void CPURegisters() = 0; virtual void SwitchToFrame(size_t number) = 0; virtual void SetVarValue(const wxString& var, const wxString& value) = 0; + virtual void SetMemoryRangeValue(uint64_t addr, const wxString& value) = 0; virtual void MemoryDump() = 0; virtual void RunningThreads() = 0; @@ -143,6 +144,9 @@ class DebuggerDriver virtual void UpdateWatch(cb::shared_ptr const &watch) = 0; virtual void UpdateWatchLocalsArgs(cb::shared_ptr const &watch, bool locals) = 0; + virtual void UpdateMemoryRangeWatches(MemoryRangeWatchesContainer &watches) = 0; + virtual void UpdateMemoryRangeWatch(const cb::shared_ptr &watch) = 0; + /** Attach to process */ virtual void Attach(int pid) = 0; /** Detach from running process. */ From c003e5d0d29160682421df2fb276cda601cbaf74 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 10 Oct 2017 17:58:15 +0200 Subject: [PATCH 08/11] * debugger: Add a command class for reading X bytes from memory location and store it in a memory watch --- src/plugins/debuggergdb/gdb_commands.h | 75 ++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/plugins/debuggergdb/gdb_commands.h b/src/plugins/debuggergdb/gdb_commands.h index a74ca17d7f..a036c60fd9 100644 --- a/src/plugins/debuggergdb/gdb_commands.h +++ b/src/plugins/debuggergdb/gdb_commands.h @@ -28,6 +28,8 @@ #include #include +#include + #include "debugger_defs.h" #include "debuggergdb.h" #include "gdb_driver.h" @@ -830,6 +832,79 @@ class GdbCmd_Watch : public DebuggerCmd } }; + +/** + * Command to read a X bytes from a specific address. + */ +class GdbCmd_MemoryRangeWatch : public DebuggerCmd +{ + cb::shared_ptr m_watch; + wxString m_ParseFunc; + public: + GdbCmd_MemoryRangeWatch(DebuggerDriver* driver, cb::shared_ptr watch) : + DebuggerCmd(driver), + m_watch(watch) + { + // wx2.8 does not support uint64_z for wxstring::printf + const size_t tmpBuffSize = 20; + char tmpAddr[tmpBuffSize]; + char tmpSize[tmpBuffSize]; + memset(tmpAddr, 0, tmpBuffSize); + memset(tmpSize, 0, tmpBuffSize); + snprintf(tmpAddr, tmpBuffSize, "0x%" PRIx64, m_watch->GetAddress()); + snprintf(tmpSize, tmpBuffSize, "%" PRIu64, m_watch->GetSize()); + + m_Cmd = wxString(wxT("x /")) << wxString::FromUTF8(tmpSize) << wxT("xb ") << wxString::FromUTF8(tmpAddr); + } + + void ParseOutput(const wxString& output) + { + // output is a series of: + // + // 0x22ffc0: 0xf0 0xff 0x22 0x00 0x4f 0x6d 0x81 0x7c + // or + // 0x85267a0 : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + + + wxArrayString lines = GetArrayFromString(output, _T('\n')); + wxString addr, memory; + std::vector data; + for (unsigned int i = 0; i < lines.GetCount(); ++i) + { + if (reExamineMemoryLine.Matches(lines[i])) + { + addr = reExamineMemoryLine.GetMatch(lines[i], 1); + memory = reExamineMemoryLine.GetMatch(lines[i], 2); + } + else + { + if (lines[i].First(_T(':')) == -1) + { + continue; + } + addr = lines[i].BeforeFirst(_T(':')); + memory = lines[i].AfterFirst(_T(':')); + } + + size_t pos = memory.find(_T('x')); + wxString hexbyte; + while (pos != wxString::npos) + { + hexbyte.clear(); + hexbyte << memory[pos + 1]; + hexbyte << memory[pos + 2]; + unsigned long value; + hexbyte.ToULong(&value,16); + data.push_back(static_cast(value)); + pos = memory.find(_T('x'), pos + 1); // skip current 'x' + } + } + wxString watchString; + watchString = wxString::From8BitData(data.data(), data.size()); + m_watch->SetValue(watchString); + } +}; + /** * Command to get a watched variable's type. */ From 1b13994bc39beb33e7c404bd1204fec7b7abfaea Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 10 Oct 2017 18:00:24 +0200 Subject: [PATCH 09/11] * debugger: GDB driver: implement memory range functions Implement * SetMemoryRangeValue(): Set a memory range from start address to x bytes at the value given in "value" parameter. The value is stored as binary and can be retrieved from "value" with wxString::To8BitData() and passed to "value" with wxString::From8BitData() * UpdateMemoryRangeWatches() * UpdateMemoryRangeWatch() Read the value of the memory at the specified address and update the watch accordingly --- src/plugins/debuggergdb/gdb_driver.cpp | 41 ++++++++++++++++++++++++++ src/plugins/debuggergdb/gdb_driver.h | 3 ++ 2 files changed, 44 insertions(+) diff --git a/src/plugins/debuggergdb/gdb_driver.cpp b/src/plugins/debuggergdb/gdb_driver.cpp index 2a0bc8901b..5c6e99cd96 100644 --- a/src/plugins/debuggergdb/gdb_driver.cpp +++ b/src/plugins/debuggergdb/gdb_driver.cpp @@ -524,6 +524,30 @@ void GDB_driver::SetVarValue(const wxString& var, const wxString& value) QueueCommand(new DebuggerCmd(this, wxString::Format(_T("set variable %s=%s"), var.c_str(), cleanValue.c_str()))); } +void GDB_driver::SetMemoryRangeValue(uint64_t addr, const wxString& value) +{ + size_t size = value.size(); + wxCharBuffer data = value.To8BitData(); + if(size == 0) + return; + + wxString dataStr = wxT("{"); + for (size_t i = 0; i < size; i++) + { + dataStr << wxString::Format(wxT("0x%x,"), (uint8_t) data[i]); + } + dataStr.RemoveLast(); + dataStr << wxT("}"); + wxString commandStr; + #ifdef __WXMSW__ + commandStr.Printf(wxT("set {char [%ul]} 0x%" PRIx64 "="), size, addr); + #else + commandStr.Printf(wxT("set {char [%zu]} 0x%" PRIx64 "="), size, addr); + #endif // __WXMSW__ + commandStr << dataStr; + QueueCommand(new DebuggerCmd(this, commandStr)); +} + void GDB_driver::MemoryDump() { QueueCommand(new GdbCmd_ExamineMemory(this)); @@ -658,12 +682,29 @@ void GDB_driver::UpdateWatches(cb::shared_ptr localsWatch, cb::shared_ } } +void GDB_driver::UpdateMemoryRangeWatches(MemoryRangeWatchesContainer &watches) +{ + for (MemoryRangeWatchesContainer::iterator it = watches.begin(); it != watches.end(); ++it) + { + MemoryRangeWatchesContainer::reference watch = *it; + if (watch->IsAutoUpdateEnabled()) + { + QueueCommand(new GdbCmd_MemoryRangeWatch(this, watch)); + } + } +} + void GDB_driver::UpdateWatch(const cb::shared_ptr &watch) { QueueCommand(new GdbCmd_FindWatchType(this, watch)); QueueCommand(new DbgCmd_UpdateWatchesTree(this)); } +void GDB_driver::UpdateMemoryRangeWatch(const cb::shared_ptr &watch) +{ + QueueCommand(new GdbCmd_MemoryRangeWatch(this, watch)); +} + void GDB_driver::UpdateWatchLocalsArgs(cb::shared_ptr const &watch, bool locals) { QueueCommand(new GdbCmd_LocalsFuncArgs(this, watch, locals)); diff --git a/src/plugins/debuggergdb/gdb_driver.h b/src/plugins/debuggergdb/gdb_driver.h index 3da1b52ebd..9c0775282a 100644 --- a/src/plugins/debuggergdb/gdb_driver.h +++ b/src/plugins/debuggergdb/gdb_driver.h @@ -37,6 +37,7 @@ class GDB_driver : public DebuggerDriver virtual void CPURegisters(); virtual void SwitchToFrame(size_t number); virtual void SetVarValue(const wxString& var, const wxString& value); + virtual void SetMemoryRangeValue(uint64_t addr, const wxString& value); virtual void MemoryDump(); virtual void Attach(int pid); virtual void Detach(); @@ -57,7 +58,9 @@ class GDB_driver : public DebuggerDriver virtual void EvaluateSymbol(const wxString& symbol, const wxRect& tipRect); virtual void UpdateWatches(cb::shared_ptr localsWatch, cb::shared_ptr funcArgsWatch, WatchesContainer &watches); + virtual void UpdateMemoryRangeWatches(MemoryRangeWatchesContainer &watches); virtual void UpdateWatch(const cb::shared_ptr &watch); + virtual void UpdateMemoryRangeWatch(const cb::shared_ptr &watch); virtual void UpdateWatchLocalsArgs(cb::shared_ptr const &watch, bool locals); virtual void ParseOutput(const wxString& output); virtual bool IsDebuggingStarted() const { return m_IsStarted; } From 61cccf7393809f1eecdebd0a48f9dbf46dd14cd2 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 10 Oct 2017 18:10:53 +0200 Subject: [PATCH 10/11] * debugger: CDB driver: Add stubs for memory range functions For this functions only stubs exist: SetMemoryRangeValue() UpdateMemoryRangeWatches() UpdateMemoryRangeWatch() --- src/plugins/debuggergdb/cdb_driver.cpp | 17 +++++++++++++++++ src/plugins/debuggergdb/cdb_driver.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/src/plugins/debuggergdb/cdb_driver.cpp b/src/plugins/debuggergdb/cdb_driver.cpp index 2e5adad031..e634745e6d 100644 --- a/src/plugins/debuggergdb/cdb_driver.cpp +++ b/src/plugins/debuggergdb/cdb_driver.cpp @@ -214,6 +214,11 @@ void CDB_driver::SetVarValue(cb_unused const wxString& var, cb_unused const wxSt NOT_IMPLEMENTED(); } +void CDB_driver::SetMemoryRangeValue(uint64_t addr, const wxString& value) +{ + NOT_IMPLEMENTED(); +} + void CDB_driver::MemoryDump() { NOT_IMPLEMENTED(); @@ -322,6 +327,18 @@ void CDB_driver::Attach(cb_unused int pid) // FIXME (obfuscated#): implement this } +void CDB_driver::UpdateMemoryRangeWatches(MemoryRangeWatchesContainer &watches) +{ + // FIXME (bluehazzard#): implement this + NOT_IMPLEMENTED(); +} + +void CDB_driver::UpdateMemoryRangeWatch(const cb::shared_ptr &watch) +{ + // FIXME (bluehazzard#): implement this + NOT_IMPLEMENTED(); +} + void CDB_driver::Detach() { QueueCommand(new CdbCmd_Detach(this)); diff --git a/src/plugins/debuggergdb/cdb_driver.h b/src/plugins/debuggergdb/cdb_driver.h index 604513d9a4..84024a7fef 100644 --- a/src/plugins/debuggergdb/cdb_driver.h +++ b/src/plugins/debuggergdb/cdb_driver.h @@ -35,6 +35,7 @@ class CDB_driver : public DebuggerDriver virtual void CPURegisters(); virtual void SwitchToFrame(size_t number); virtual void SetVarValue(const wxString& var, const wxString& value); + virtual void SetMemoryRangeValue(uint64_t addr, const wxString& value); virtual void MemoryDump(); virtual void Attach(int pid); virtual void Detach(); @@ -56,6 +57,8 @@ class CDB_driver : public DebuggerDriver virtual void UpdateWatches(cb::shared_ptr localsWatch, cb::shared_ptr funcArgsWatch, WatchesContainer &watches); virtual void UpdateWatch(cb::shared_ptr const &watch); + virtual void UpdateMemoryRangeWatches(MemoryRangeWatchesContainer &watches); + virtual void UpdateMemoryRangeWatch(const cb::shared_ptr &watch); virtual void UpdateWatchLocalsArgs(cb::shared_ptr const &watch, bool locals); virtual void ParseOutput(const wxString& output); virtual bool IsDebuggingStarted() const; From 0b92e255d4c996cb895f44371d1a9b0a12e633b0 Mon Sep 17 00:00:00 2001 From: bluehazzard Date: Tue, 10 Oct 2017 18:13:28 +0200 Subject: [PATCH 11/11] * debugger: Extend SetWatchValue() to accept memory range watches --- src/plugins/debuggergdb/debuggergdb.cpp | 46 ++++++++++++++++--------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/plugins/debuggergdb/debuggergdb.cpp b/src/plugins/debuggergdb/debuggergdb.cpp index 2e89cd18d4..4dd052ae6e 100644 --- a/src/plugins/debuggergdb/debuggergdb.cpp +++ b/src/plugins/debuggergdb/debuggergdb.cpp @@ -2159,31 +2159,45 @@ void DebuggerGDB::ShowWatchProperties(cb::shared_ptr watch) bool DebuggerGDB::SetWatchValue(cb::shared_ptr watch, const wxString &value) { + if (!m_State.HasDriver()) + return false; if (!HasWatch(cbGetRootWatch(watch))) return false; - if (!m_State.HasDriver()) - return false; + if (IsMemoryRangeWatch(watch)) + { + cb::shared_ptr temp_watch = std::dynamic_pointer_cast(watch); + uint64_t addr = temp_watch->GetAddress(); - wxString full_symbol; - cb::shared_ptr temp_watch = watch; - while (temp_watch) + DebuggerDriver* driver = m_State.GetDriver(); + driver->SetMemoryRangeValue(addr, value); + // TODO (bluehazzard#1#): I am not quite sure if this is the right place to update all memory ranges + driver->UpdateMemoryRangeWatches(m_memoryRange); + } + else { - wxString symbol; - temp_watch->GetSymbol(symbol); - temp_watch = temp_watch->GetParent(); - if (symbol.find(wxT('*')) != wxString::npos || symbol.find(wxT('&')) != wxString::npos) - symbol = wxT('(') + symbol + wxT(')'); + wxString full_symbol; + cb::shared_ptr temp_watch = watch; + while (temp_watch) + { + wxString symbol; + temp_watch->GetSymbol(symbol); + temp_watch = temp_watch->GetParent(); - if (full_symbol.empty()) - full_symbol = symbol; - else - full_symbol = symbol + wxT('.') + full_symbol; + if (symbol.find(wxT('*')) != wxString::npos || symbol.find(wxT('&')) != wxString::npos) + symbol = wxT('(') + symbol + wxT(')'); + + if (full_symbol.empty()) + full_symbol = symbol; + else + full_symbol = symbol + wxT('.') + full_symbol; + } + + DebuggerDriver* driver = m_State.GetDriver(); + driver->SetVarValue(full_symbol, value); } - DebuggerDriver* driver = m_State.GetDriver(); - driver->SetVarValue(full_symbol, value); DoWatches(); return true; }