Page 1 of 1

Patch: Reverse Debugging Menu

Posted: Thu Jun 12, 2014 6:50 am
by caibbor
Note: Since I'm a total git newb, this patch also includes my previous patch for adding "Select Next" and "Select Previous" to the Search menu.

If you're unfamiliar with reverse debugging with GDB, it's exactly what it sounds like. The only difference is that you first have to break somewhere and then exectue the "record" command, then continue. (recording is slow, just fyi). Then you can reverse-next/step/continue/etc up until the point where you began recording. "Set Exec Direction *" does exactly what it says. If you set it to reverse, the normal forward step/next/etc will instead work backward.

You can already reverse debug in codelite if you just throw the commands at GDB manually via the "debug command" pane, but this patch adds a slew of menu options to the debug menu as well as keyboard shortcuts. It's all documented here: GDB commands, GDB/MI commands.

I couldn't figure out how to disable menu items when the debugger isn't started, didn't look to deeply into it. Everything seems to work a-okay otherwise.

Note: the enable/disable hardware breakpoints is in there because one document claimed they must be disabled in order to use variable watches properly while reverse debugging. However, I have had no problems, that information may be antiquated.

todo:
* grey out all menu options when debugger is not active
* grey out all but "record" menu options when not recording
* "disable hardware breakpoints" should be a checkbox
* "set record direction to reverse" should be a checkbox
* "start/stop recording" should be a checkbox

the patch:

Code: Select all

diff --git a/Debugger/dbgcmd.h b/Debugger/dbgcmd.h
index 624a989..4936245 100644
--- a/Debugger/dbgcmd.h
+++ b/Debugger/dbgcmd.h
@@ -131,10 +131,11 @@ public:
 /**
  * this handler, handles the following commands:
  * -exec-run
- * -exec-continue
- * -exec-step
- * -exec-next
- * -exec-finish
+ * -exec-continue [--reverse]
+ * -exec-step [--reverse]
+ * -exec-next [--reverse]
+ * -exec-next-instruction [--reverse]
+ * -exec-finish [--reverse]
  */
 class DbgCmdHandlerAsyncCmd : public DbgCmdHandler
 {
diff --git a/Debugger/debuggergdb.cpp b/Debugger/debuggergdb.cpp
index a97f0ed..5112de9 100644
--- a/Debugger/debuggergdb.cpp
+++ b/Debugger/debuggergdb.cpp
@@ -323,6 +323,16 @@ bool DbgGdb::NextInstruction()
     return WriteCommand( wxT( "-exec-next-instruction" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
 }
 
+bool DbgGdb::ReverseNext()
+{
+    return WriteCommand( wxT( "-exec-next --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseNextInstruction()
+{
+    return WriteCommand( wxT( "-exec-next-instruction --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
 void DbgGdb::SetBreakpoints()
 {
     for ( size_t i=0; i< m_bpList.size(); i++ ) {
@@ -509,6 +519,51 @@ bool DbgGdb::StepOut()
     return WriteCommand( wxT( "-exec-finish" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
 }
 
+bool DbgGdb::Record()
+{
+    return WriteCommand( wxT( "record full" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::StopRecord()
+{
+    return WriteCommand( wxT( "record stop" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseContinue()
+{
+    return WriteCommand( wxT( "-exec-continue --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseStepIn()
+{
+    return WriteCommand( wxT( "-exec-step --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseStepOut()
+{
+    return WriteCommand( wxT( "-exec-finish --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::SetExecDirectionReverse()
+{
+    return WriteCommand( wxT( "set exec-direction reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::SetExecDirectionForward()
+{
+    return WriteCommand( wxT( "set exec-direction forward" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::DisableHardwareBreakpoints()
+{
+    return WriteCommand( wxT( "set can-use-hw-watchpoints 0" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::EnableHardwareBreakpoints()
+{
+    return WriteCommand( wxT( "set can-use-hw-watchpoints 1" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
 bool DbgGdb::IsRunning()
 {
     return m_gdbProcess != NULL;
diff --git a/Debugger/debuggergdb.h b/Debugger/debuggergdb.h
index 6aeb983..1f95761 100644
--- a/Debugger/debuggergdb.h
+++ b/Debugger/debuggergdb.h
@@ -132,6 +132,17 @@ public:
     virtual bool Next();
     virtual bool NextInstruction();
     virtual bool Continue();
+    virtual bool Record();
+    virtual bool StopRecord();
+    virtual bool ReverseStepIn();
+    virtual bool ReverseStepOut();
+    virtual bool ReverseNext();
+    virtual bool ReverseNextInstruction();
+    virtual bool ReverseContinue();
+    virtual bool SetExecDirectionReverse();
+    virtual bool SetExecDirectionForward();
+    virtual bool DisableHardwareBreakpoints();
+    virtual bool EnableHardwareBreakpoints();
     virtual bool QueryFileLine();
     virtual bool Disassemble(const wxString &filename, int lineNumber);
     virtual bool Interrupt();
diff --git a/Interfaces/debugger.h b/Interfaces/debugger.h
index b01a41e..181dca3 100644
--- a/Interfaces/debugger.h
+++ b/Interfaces/debugger.h
@@ -43,6 +43,17 @@ enum DebuggerCommands {
     DBG_STEPOUT,
     DBG_SHOW_CURSOR,
     DBG_NEXTI,
+    DBG_RECORD,
+    DBG_STOP_RECORD,
+    DBG_REVERSE_CONTINUE,
+    DBG_REVERSE_NEXT,
+    DBG_REVERSE_STEPIN,
+    DBG_REVERSE_STEPOUT,
+    DBG_REVERSE_NEXTI,
+    DBG_DISABLE_HARDWARE_BREAKPOINTS,
+    DBG_ENABLE_HARDWARE_BREAKPOINTS,
+    DBG_SET_EXEC_DIRECTION_REVERSE,
+    DBG_SET_EXEC_DIRECTION_FORWARD
 };
 
 // Breakpoint types. If you add more, LEditor::FillBPtoMarkerArray will also need altering
@@ -700,6 +711,55 @@ public:
      */
     virtual bool StepOut() = 0;
     /**
+     * \brief begin recording (for gdb reverse debuggubg)
+     */
+    virtual bool Record() = 0;
+    /**
+     * \brief stop recording (for gdb reverse debuggubg)
+     */
+    virtual bool StopRecord() = 0;
+    /**
+     * \brief step to next line
+     * \return true on success, false otherwise
+     */
+    virtual bool ReverseNext() = 0;
+    /**
+     * @brief perform "reverse next instruction" command
+     * @return true on success, false otherwise
+     */
+    virtual bool ReverseNextInstruction() = 0;
+    /**
+     * \brief reverse continue execution of the debugger, until next breakpoint is hit, or program terminates
+     * \return true on success, false otherwise
+     */
+    virtual bool ReverseContinue() = 0;
+    /**
+     * \brief reverse step into method
+     * \return true on success, false otherwise
+     */
+    virtual bool ReverseStepIn() = 0;
+    /**
+     * \brief reverse step out the current method (gdb's 'reverse-finish' command)
+     * \return true on success, false otherwise
+     */
+    virtual bool ReverseStepOut() = 0;
+    /**
+     * \brief set execution direction to reverse (gdb's '-exec-set exec-direction reverse' command)
+     */
+    virtual bool SetExecDirectionReverse() = 0;
+    /**
+     * \brief set execution direction to forward (gdb's '-exec-set exec-direction forward' command)
+     */
+    virtual bool SetExecDirectionForward() = 0;
+    /**
+     * \brief disable hardware breakpoints. This is necessary if you want to use watchpoints while executing the program in reverse.
+     */
+    virtual bool DisableHardwareBreakpoints() = 0;
+    /**
+     * \brief enable hardware breakpoints.
+     */
+    virtual bool EnableHardwareBreakpoints() = 0;
+    /**
      * \brief set break point at given file and line, or function
      */
     virtual bool Break(const BreakpointInfo& bp) = 0;
diff --git a/LiteEditor.workspace b/LiteEditor.workspace
index 4c8a82e..f756677 100644
--- a/LiteEditor.workspace
+++ b/LiteEditor.workspace
@@ -8,9 +8,9 @@
   </Ctags>
   <Project Name="wxsqlite3" Path="sdk/wxsqlite3/wxsqlite3.project" Active="No"/>
   <Project Name="plugin_sdk" Path="Plugin/plugin_sdk.project" Active="No"/>
-  <Project Name="LiteEditor" Path="LiteEditor/LiteEditor.project" Active="Yes"/>
+  <Project Name="LiteEditor" Path="LiteEditor/LiteEditor.project" Active="No"/>
   <Project Name="sqlite3" Path="sqlite3/sqlite3.project"/>
-  <Project Name="CodeLite" Path="CodeLite/CodeLite.project" Active="No"/>
+  <Project Name="CodeLite" Path="CodeLite/CodeLite.project" Active="Yes"/>
   <Project Name="DebuggerGDB" Path="Debugger/DebuggerGDB.project" Active="No"/>
   <Project Name="Interfaces" Path="Interfaces/Interfaces.project" Active="No"/>
   <Project Name="Gizmos" Path="Gizmos/Gizmos.project" Active="No"/>
@@ -48,7 +48,7 @@
   <Project Name="SpellCheck" Path="SpellChecker/SpellCheck.project" Active="No"/>
   <Project Name="hunspell" Path="SpellChecker/hunspell/hunspell.project" Active="No"/>
   <BuildMatrix>
-    <WorkspaceConfiguration Name="Win Release Unicode" Selected="yes">
+    <WorkspaceConfiguration Name="Win Release Unicode" Selected="no">
       <Project Name="abbreviation" ConfigName="WinReleaseUnicode"/>
       <Project Name="CallGraph" ConfigName="WinReleaseUnicode"/>
       <Project Name="CMakePlugin" ConfigName="WinReleaseUnicode"/>
@@ -165,7 +165,7 @@
       <Project Name="SpellCheck" ConfigName="DebugUnicode"/>
       <Project Name="hunspell" ConfigName="Debug"/>
     </WorkspaceConfiguration>
-    <WorkspaceConfiguration Name="CMake_Debug" Selected="no">
+    <WorkspaceConfiguration Name="CMake_Debug" Selected="yes">
       <Project Name="ZoomNavigator" ConfigName="WinReleaseUnicode"/>
       <Project Name="wxsqlite3" ConfigName="WinReleaseUnicode"/>
       <Project Name="wxshapeframework" ConfigName="WinReleaseUnicode"/>
diff --git a/LiteEditor/frame.cpp b/LiteEditor/frame.cpp
index 502d1fd..ceb6a40 100644
--- a/LiteEditor/frame.cpp
+++ b/LiteEditor/frame.cpp
@@ -340,6 +340,8 @@ BEGIN_EVENT_TABLE(clMainFrame, wxFrame)
 
     EVT_UPDATE_UI(wxID_FIND,                        clMainFrame::OnIncrementalSearchUI )
     EVT_UPDATE_UI(wxID_REPLACE,                     clMainFrame::OnFileExistUpdateUI   )
+    EVT_UPDATE_UI(XRCID("select_previous"),         clMainFrame::OnFileExistUpdateUI   )
+    EVT_UPDATE_UI(XRCID("select_next"),             clMainFrame::OnFileExistUpdateUI   )
     EVT_UPDATE_UI(XRCID("find_next"),               clMainFrame::OnFileExistUpdateUI   )
     EVT_UPDATE_UI(XRCID("find_previous"),           clMainFrame::OnFileExistUpdateUI   )
     EVT_UPDATE_UI(XRCID("find_next_at_caret"),      clMainFrame::OnFileExistUpdateUI   )
@@ -454,6 +456,18 @@ BEGIN_EVENT_TABLE(clMainFrame, wxFrame)
     EVT_MENU(XRCID("dbg_next"),                 clMainFrame::OnDebugCmd)
     EVT_MENU(XRCID("dbg_nexti"),                clMainFrame::OnDebugCmd)
     EVT_MENU(XRCID("show_cursor"),              clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_record"),               clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_stoprecord"),           clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_stepin"),       clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_next"),         clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_nexti"),        clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_stepout"),      clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_continue"),     clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_set_exec_forward"),     clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_set_exec_reverse"),     clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_disable_hardware_breakpoits"),  clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_enable_hardware_breakpoits"),   clMainFrame::OnDebugCmd)
+
     EVT_MENU(XRCID("add_breakpoint"),           clMainFrame::DispatchCommandEvent)
     EVT_MENU(XRCID("insert_breakpoint"),        clMainFrame::DispatchCommandEvent) // Toggles
     EVT_MENU(XRCID("disable_all_breakpoints"),  clMainFrame::DispatchCommandEvent)
@@ -3291,11 +3305,55 @@ void clMainFrame::OnDebugCmd(wxCommandEvent &e)
     } else if (e.GetId() == XRCID("show_cursor")) {
         cmd = DBG_SHOW_CURSOR;
         eventId = wxEVT_DBG_UI_SHOW_CURSOR;
-        
+
     } else if ( e.GetId() == XRCID("dbg_nexti")) {
         cmd = DBG_NEXTI;
         eventId = wxEVT_DBG_UI_NEXT_INST;
-        
+
+    } else if ( e.GetId() == XRCID("dbg_record")) {
+        cmd = DBG_RECORD;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_stoprecord")) {
+        cmd = DBG_STOP_RECORD;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_reverse_next")) {
+        cmd = DBG_REVERSE_NEXT;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_reverse_nexti")) {
+        cmd = DBG_REVERSE_NEXTI;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if (e.GetId() == XRCID("dbg_reverse_stepin")) {
+        cmd = DBG_REVERSE_STEPIN;
+        eventId = wxEVT_DBG_UI_STEP_IN;
+
+    } else if ( e.GetId() == XRCID("dbg_reverse_stepout")) {
+        cmd = DBG_REVERSE_STEPOUT;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_reverse_continue")) {
+        cmd = DBG_REVERSE_CONTINUE;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_set_exec_forward")) {
+        cmd = DBG_SET_EXEC_DIRECTION_FORWARD;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_set_exec_reverse")) {
+        cmd = DBG_SET_EXEC_DIRECTION_REVERSE;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_disable_hardware_breakpoits")) {
+        cmd = DBG_DISABLE_HARDWARE_BREAKPOINTS;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_enable_hardware_breakpoits")) {
+        cmd = DBG_ENABLE_HARDWARE_BREAKPOINTS;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
     }
     
     // ALlow the plugins to handle this command first
@@ -3321,7 +3379,18 @@ void clMainFrame::OnDebugCmdUI(wxUpdateUIEvent &e)
         e.GetId() == XRCID("dbg_stepout") ||
         e.GetId() == XRCID("dbg_next") ||
         e.GetId() == XRCID("dbg_nexti") ||
-        e.GetId() == XRCID("show_cursor")) {
+        e.GetId() == XRCID("show_cursor") ||
+        e.GetId() == XRCID("dbg_record") ||
+        e.GetId() == XRCID("dbg_stoprecord") ||
+        e.GetId() == XRCID("dbg_reverse_stepin") ||
+        e.GetId() == XRCID("dbg_reverse_next") ||
+        e.GetId() == XRCID("dbg_reverse_nexti") ||
+        e.GetId() == XRCID("dbg_reverse_stepout") ||
+        e.GetId() == XRCID("dbg_reverse_continue") ||
+        e.GetId() == XRCID("dbg_set_exec_forward") ||
+        e.GetId() == XRCID("dbg_set_exec_reverse") ||
+        e.GetId() == XRCID("dbg_disable_hardware_breakpoits") ||
+        e.GetId() == XRCID("dbg_enable_hardware_breakpoits")) {
         IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger();
         e.Enable(eventIsRunning.IsAnswer() || (dbgr && dbgr->IsRunning()) );
     }
diff --git a/LiteEditor/manager.cpp b/LiteEditor/manager.cpp
index a2205d3..af09565 100644
--- a/LiteEditor/manager.cpp
+++ b/LiteEditor/manager.cpp
@@ -2631,6 +2631,47 @@ void Manager::DbgDoSimpleCommand ( int cmd )
             clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
             dbgr->NextInstruction();
             break;
+        case DBG_REVERSE_NEXT:
+            clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+            clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+            dbgr->ReverseNext();
+            break;
+        case DBG_REVERSE_STEPIN:
+            clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+            clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+            dbgr->ReverseStepIn();
+            break;
+        case DBG_REVERSE_STEPOUT:
+            clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+            clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+            dbgr->ReverseStepOut();
+            break;
+        case DBG_REVERSE_NEXTI:
+            clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+            clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+            dbgr->ReverseNextInstruction();
+            break;
+        case DBG_DISABLE_HARDWARE_BREAKPOINTS:
+            dbgr->DisableHardwareBreakpoints();
+            break;
+        case DBG_ENABLE_HARDWARE_BREAKPOINTS:
+            dbgr->EnableHardwareBreakpoints();
+            break;
+        case DBG_SET_EXEC_DIRECTION_REVERSE:
+            dbgr->SetExecDirectionReverse();
+            break;
+        case DBG_SET_EXEC_DIRECTION_FORWARD:
+            dbgr->SetExecDirectionForward();
+            break;
+        case DBG_RECORD:
+            dbgr->Record();
+            break;
+        case DBG_STOP_RECORD:
+            dbgr->StopRecord();
+            break;
+        case DBG_REVERSE_CONTINUE:
+            dbgr->ReverseContinue();
+            break;
         default:
             break;
         }
diff --git a/LiteEditor/quickfindbar.cpp b/LiteEditor/quickfindbar.cpp
index fd7309a..f32534e 100644
--- a/LiteEditor/quickfindbar.cpp
+++ b/LiteEditor/quickfindbar.cpp
@@ -79,6 +79,8 @@ QuickFindBar::QuickFindBar(wxWindow* parent, wxWindowID id)
     wxTheApp->Connect(wxID_COPY,      wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
     wxTheApp->Connect(wxID_PASTE,     wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
     wxTheApp->Connect(wxID_SELECTALL, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
+    wxTheApp->Connect(XRCID("select_previous"),        wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnSelectPrevious),          NULL, this);
+    wxTheApp->Connect(XRCID("select_next"),            wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnSelectNext),          NULL, this);
     wxTheApp->Connect(XRCID("find_next"),              wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindNext),          NULL, this);
     wxTheApp->Connect(XRCID("find_previous"),          wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindPrevious),      NULL, this);
     wxTheApp->Connect(XRCID("find_next_at_caret"),     wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindNextCaret),     NULL, this);
@@ -536,6 +538,34 @@ void QuickFindBar::OnFindPrevious(wxCommandEvent& e)
     DoSearch(false, false);
 }
 
+void QuickFindBar::OnSelectPrevious(wxCommandEvent& e)
+{
+    CHECK_FOCUS_WIN();
+
+    // Highlighted text takes precedence over the current search string
+    wxString selectedText = DoGetSelectedText();
+    if (selectedText.IsEmpty() == false) {
+        m_findWhat->ChangeValue(selectedText);
+        m_findWhat->SelectAll();
+    }
+
+    DoSearch(false, false, true);
+}
+
+void QuickFindBar::OnSelectNext(wxCommandEvent& e)
+{
+    CHECK_FOCUS_WIN();
+
+    // Highlighted text takes precedence over the current search string
+    wxString selectedText = DoGetSelectedText();
+    if (selectedText.IsEmpty() == false) {
+        m_findWhat->ChangeValue( selectedText );
+        m_findWhat->SelectAll();
+    }
+
+    DoSearch(true, false, true);
+}
+
 void QuickFindBar::OnFindNextCaret(wxCommandEvent& e)
 {
     CHECK_FOCUS_WIN();
@@ -718,6 +748,8 @@ QuickFindBar::~QuickFindBar()
     wxTheApp->Disconnect(wxID_COPY,      wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
     wxTheApp->Disconnect(wxID_PASTE,     wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
     wxTheApp->Disconnect(wxID_SELECTALL, wxEVT_UPDATE_UI, wxUpdateUIEventHandler(QuickFindBar::OnEditUI), NULL, this);
+    wxTheApp->Disconnect(XRCID("select_previous"),        wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnSelectPrevious),          NULL, this);
+    wxTheApp->Disconnect(XRCID("select_next"),            wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnSelectNext),          NULL, this);
     wxTheApp->Disconnect(XRCID("find_next"),              wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindNext),          NULL, this);
     wxTheApp->Disconnect(XRCID("find_previous"),          wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindPrevious),      NULL, this);
     wxTheApp->Disconnect(XRCID("find_next_at_caret"),     wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(QuickFindBar::OnFindNextCaret),     NULL, this);
diff --git a/LiteEditor/quickfindbar.h b/LiteEditor/quickfindbar.h
index a8da969..e8bc48e 100644
--- a/LiteEditor/quickfindbar.h
+++ b/LiteEditor/quickfindbar.h
@@ -76,6 +76,8 @@ protected:
     void OnReceivingFocus(wxFocusEvent& event);
     void OnReleaseEditor(wxCommandEvent &e);
 
+    void OnSelectPrevious   (wxCommandEvent &e);
+    void OnSelectNext       (wxCommandEvent &e);
     void OnFindNext         (wxCommandEvent &e);
     void OnFindPrevious     (wxCommandEvent &e);
     void OnFindNextCaret    (wxCommandEvent &e);
diff --git a/Runtime/rc/menu.xrc b/Runtime/rc/menu.xrc
index a672b63..8940e8f 100644
--- a/Runtime/rc/menu.xrc
+++ b/Runtime/rc/menu.xrc
@@ -292,6 +292,12 @@
             <object class="wxMenuItem" name="wxID_REPLACE">
                 <label>&Replace...</label>
             </object>
+            <object class="wxMenuItem" name="select_previous">
+                <label>Select Previous Occu&rrence</label>
+            </object>
+            <object class="wxMenuItem" name="select_next">
+                <label>Select Next &Occurrence</label>
+            </object>
             <object class="wxMenuItem" name="find_next">
                 <label>Find &Next</label>
             </object>
@@ -506,6 +512,47 @@
             <object class="wxMenuItem" name="dbg_stepout">
                 <label>Step &Out</label>
             </object>
+
+            <object class="wxMenu" name="debugger_reverse_debugging">
+                <label>GDB &Reverse Debugging</label>
+                <style>wxMENU_TEAROFF</style>
+                <object class="wxMenuItem" name="dbg_record">
+                    <label>&Begin Recording</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_stoprecord">
+                    <label>&Stop Recording</label>
+                </object>
+                <object class="wxMenuItem" name="wxID_SEPARATOR"/>
+                <object class="wxMenuItem" name="dbg_reverse_stepin">
+                    <label>Reverse Step &Into</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_reverse_next">
+                    <label>Reverse &Next</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_reverse_nexti">
+                    <label>Reverse Next Ins&truction</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_reverse_stepout">
+                    <label>Reverse Step &Out</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_reverse_continue">
+                    <label>Reverse &Continue</label>
+                </object>
+                <object class="wxMenuItem" name="wxID_SEPARATOR"/>
+                <object class="wxMenuItem" name="dbg_set_exec_forward">
+                    <label>Set Exec Direction To &Forward</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_set_exec_reverse">
+                    <label>Set Exec Direction To &Reverse</label>
+                </object>
+                <object class="wxMenuItem" name="wxID_SEPARATOR"/>
+                <object class="wxMenuItem" name="dbg_disable_hardware_breakpoits">
+                    <label>&Disable Hardware Breakpoints</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_enable_hardware_breakpoits">
+                    <label>&Enable Hardware Breakpoints</label>
+                </object>
+            </object>
 			<object class="wxMenuItem" name="wxID_SEPARATOR"/>
             <object class="wxMenuItem" name="show_cursor">
                 <label>Show &Cursor</label>
@@ -529,7 +576,7 @@
 			</object>
             <object class="wxMenuItem" name="wxID_SEPARATOR"/>
             <object class="wxMenu" name="debugger_windows">
-                <label>GDB Windows</label>
+                <label>GDB &Windows</label>
                 <style>wxMENU_TEAROFF</style>
                 <object class="wxMenuItem" name="debugger_win_locals">
                     <label>Locals</label>
accelerators added

Code: Select all

dbg_reverse_stepout|Debugger|Reverse Step Out|Shift-Alt-O
dbg_reverse_stepin|Debugger|Reverse Step Into|Shift-Alt-I
dbg_reverse_next|Debugger|Reverse Next|Shift-Alt-N
dbg_reverse_nexti|Debugger|Reverse Next Instruction|Shift-Alt-T
dbg_reverse_continue|Debugger|Reverse Continue|Shift-Alt-C
dbg_record|Debugger|Begin Record|Shift-Alt-B
dbg_stoprecord|Debugger|Stop Record|Shift-Alt-S
dbg_set_exec_forward|Debugger|Set Exec Direction To Forward|Shift-Alt-F
dbg_set_exec_reverse|Debugger|Set Exec Direction To Reverse|Shift-Alt-R
dbg_disable_hardware_breakpoits|Debugger|Disable Hardware Breakpoints|Shift-Alt-D
dbg_enable_hardware_breakpoits|Debugger|Enable Hardware Breakpoints|Shift-Alt-W

Re: Patch: Reverse Debugging Menu

Posted: Thu Jun 12, 2014 6:52 am
by caibbor
PS, totally didn't mean to include my personal workspace in the diff. I'll try not to do that next time.

Re: Patch: Reverse Debugging Menu

Posted: Thu Jun 12, 2014 1:45 pm
by DavidGH
Hi,
Since I'm a total git newb
There is something of a learning curve... ;) I've been using git for a few years now, but I certainly don't consider myself an expert.

The ideal way, some might say the correct way, is to create a separate local branch for each 'topic'. So, before you start, you'd do:
git checkout -b ReverseDebuggingBranch
Then do the coding. Commit the result (to that local branch) either in a single commit, or as several incremental commits as you make progress.
Finally, you can do:
git checkout master // Back to the main branch
git diff ReverseDebuggingBranch > mypatch.diff

A more newbie-friendly way, for small patches that will affect otherwise-clean files, is to work in 'master'. Write and test the code, then do:
git diff LiteEditor/frame.cpp LiteEditor/frame.h > mypatch.diff // Where you want to diff only changes affecting frame.cpp/h

From your previous thread:
PS, I'm not terribly familiar with git (I'm a svn guy) so I'm not sure how to get the current "revision number" if such a thing exists.
It doesn't in the same sequential way as svn. However each git commit is identified by a unique hash, e.g. 13a5c40ec9c244376ae8a00fedc5352768d66f0c. The first few bits are usually unique-enough, so that would be called 13a5c40.
You can see the current hash of your current HEAD by doing:
git log -1
There are other ways to find it. In fact, with git there are usually multiple ways to do things, which helps make git powerful but complicated.

Regards,

David

Re: Patch: Reverse Debugging Menu

Posted: Thu Jun 19, 2014 8:35 pm
by caibbor
Any chance of getting this into CodeLite? I've been using it and it works. I haven't tried it with watchpoints yet, so still unsure if "disable/enable hardware breakpoints" is necessary.

Re: Patch: Reverse Debugging Menu

Posted: Fri Jun 20, 2014 9:16 am
by eranif
Try re-creating the patch with the latest git head

Eran

Re: Patch: Reverse Debugging Menu

Posted: Sat Jun 21, 2014 8:34 am
by caibbor
Here ya go. There are some aesthetic changes that need to be done, like disabling all the entries when the debugger isn't running. Also making a few of the options as checkboxes, such as start/stop record and set exec direction to forward/reverse. The checkboxes would have to all be reset to unchecked when the debugger isn't running, though, but I'm sure you know that.

The patch is functional as-is, though.

Code: Select all

diff --git a/Debugger/dbgcmd.h b/Debugger/dbgcmd.h
index 624a989..a7a22f2 100644
--- a/Debugger/dbgcmd.h
+++ b/Debugger/dbgcmd.h
@@ -130,11 +130,11 @@ public:
 
 /**
  * this handler, handles the following commands:
- * -exec-run
- * -exec-continue
- * -exec-step
- * -exec-next
- * -exec-finish
+ * -exec-run [--reverse]
+ * -exec-continue [--reverse]
+ * -exec-step [--reverse]
+ * -exec-next [--reverse]
+ * -exec-finish [--reverse]
  */
 class DbgCmdHandlerAsyncCmd : public DbgCmdHandler
 {
diff --git a/Debugger/debuggergdb.cpp b/Debugger/debuggergdb.cpp
index a97f0ed..5112de9 100644
--- a/Debugger/debuggergdb.cpp
+++ b/Debugger/debuggergdb.cpp
@@ -323,6 +323,16 @@ bool DbgGdb::NextInstruction()
     return WriteCommand( wxT( "-exec-next-instruction" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
 }
 
+bool DbgGdb::ReverseNext()
+{
+    return WriteCommand( wxT( "-exec-next --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseNextInstruction()
+{
+    return WriteCommand( wxT( "-exec-next-instruction --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
 void DbgGdb::SetBreakpoints()
 {
     for ( size_t i=0; i< m_bpList.size(); i++ ) {
@@ -509,6 +519,51 @@ bool DbgGdb::StepOut()
     return WriteCommand( wxT( "-exec-finish" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
 }
 
+bool DbgGdb::Record()
+{
+    return WriteCommand( wxT( "record full" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::StopRecord()
+{
+    return WriteCommand( wxT( "record stop" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseContinue()
+{
+    return WriteCommand( wxT( "-exec-continue --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseStepIn()
+{
+    return WriteCommand( wxT( "-exec-step --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::ReverseStepOut()
+{
+    return WriteCommand( wxT( "-exec-finish --reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::SetExecDirectionReverse()
+{
+    return WriteCommand( wxT( "set exec-direction reverse" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::SetExecDirectionForward()
+{
+    return WriteCommand( wxT( "set exec-direction forward" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::DisableHardwareBreakpoints()
+{
+    return WriteCommand( wxT( "set can-use-hw-watchpoints 0" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
+bool DbgGdb::EnableHardwareBreakpoints()
+{
+    return WriteCommand( wxT( "set can-use-hw-watchpoints 1" ), new DbgCmdHandlerAsyncCmd( m_observer, this ) );
+}
+
 bool DbgGdb::IsRunning()
 {
     return m_gdbProcess != NULL;
diff --git a/Debugger/debuggergdb.h b/Debugger/debuggergdb.h
index 6aeb983..1f95761 100644
--- a/Debugger/debuggergdb.h
+++ b/Debugger/debuggergdb.h
@@ -132,6 +132,17 @@ public:
     virtual bool Next();
     virtual bool NextInstruction();
     virtual bool Continue();
+    virtual bool Record();
+    virtual bool StopRecord();
+    virtual bool ReverseStepIn();
+    virtual bool ReverseStepOut();
+    virtual bool ReverseNext();
+    virtual bool ReverseNextInstruction();
+    virtual bool ReverseContinue();
+    virtual bool SetExecDirectionReverse();
+    virtual bool SetExecDirectionForward();
+    virtual bool DisableHardwareBreakpoints();
+    virtual bool EnableHardwareBreakpoints();
     virtual bool QueryFileLine();
     virtual bool Disassemble(const wxString &filename, int lineNumber);
     virtual bool Interrupt();
diff --git a/Interfaces/debugger.h b/Interfaces/debugger.h
index b01a41e..e77c613 100644
--- a/Interfaces/debugger.h
+++ b/Interfaces/debugger.h
@@ -43,6 +43,17 @@ enum DebuggerCommands {
     DBG_STEPOUT,
     DBG_SHOW_CURSOR,
     DBG_NEXTI,
+    DBG_RECORD,
+    DBG_STOP_RECORD,
+    DBG_REVERSE_CONTINUE,
+    DBG_REVERSE_NEXT,
+    DBG_REVERSE_STEPIN,
+    DBG_REVERSE_STEPOUT,
+    DBG_REVERSE_NEXTI,
+    DBG_DISABLE_HARDWARE_BREAKPOINTS,
+    DBG_ENABLE_HARDWARE_BREAKPOINTS,
+    DBG_SET_EXEC_DIRECTION_REVERSE,
+    DBG_SET_EXEC_DIRECTION_FORWARD
 };
 
 // Breakpoint types. If you add more, LEditor::FillBPtoMarkerArray will also need altering
@@ -699,6 +710,55 @@ public:
      * \return true on success, false otherwise
      */
     virtual bool StepOut() = 0;
+     /**
+     * \brief begin recording (for gdb reverse debuggubg)
+     */
+    virtual bool Record() = 0;
+    /**
+     * \brief stop recording (for gdb reverse debuggubg)
+     */
+    virtual bool StopRecord() = 0;
+    /**
+     * \brief step to next line
+     * \return true on success, false otherwise
+     */
+    virtual bool ReverseNext() = 0;
+    /**
+     * @brief perform "reverse next instruction" command
+     * @return true on success, false otherwise
+     */
+    virtual bool ReverseNextInstruction() = 0;
+    /**
+     * \brief reverse continue execution of the debugger, until next breakpoint is hit, or program terminates
+     * \return true on success, false otherwise
+     */
+    virtual bool ReverseContinue() = 0;
+    /**
+     * \brief reverse step into method
+     * \return true on success, false otherwise
+     */
+    virtual bool ReverseStepIn() = 0;
+    /**
+     * \brief reverse step out the current method (gdb's 'reverse-finish' command)
+     * \return true on success, false otherwise
+     */
+    virtual bool ReverseStepOut() = 0;
+    /**
+     * \brief set execution direction to reverse (gdb's '-exec-set exec-direction reverse' command)
+     */
+    virtual bool SetExecDirectionReverse() = 0;
+    /**
+     * \brief set execution direction to forward (gdb's '-exec-set exec-direction forward' command)
+     */
+    virtual bool SetExecDirectionForward() = 0;
+    /**
+     * \brief disable hardware breakpoints. This is necessary if you want to use watchpoints while executing the program in reverse.
+     */
+    virtual bool DisableHardwareBreakpoints() = 0;
+    /**
+     * \brief enable hardware breakpoints.
+     */
+    virtual bool EnableHardwareBreakpoints() = 0;
     /**
      * \brief set break point at given file and line, or function
      */
diff --git a/LiteEditor/frame.cpp b/LiteEditor/frame.cpp
index 89af07c..7be3ecc 100644
--- a/LiteEditor/frame.cpp
+++ b/LiteEditor/frame.cpp
@@ -460,6 +460,17 @@ BEGIN_EVENT_TABLE(clMainFrame, wxFrame)
     EVT_MENU(XRCID("dbg_stepout"),              clMainFrame::OnDebugCmd)
     EVT_MENU(XRCID("dbg_next"),                 clMainFrame::OnDebugCmd)
     EVT_MENU(XRCID("dbg_nexti"),                clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_record"),               clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_stoprecord"),           clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_stepin"),       clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_next"),         clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_nexti"),        clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_stepout"),      clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_reverse_continue"),     clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_set_exec_forward"),     clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_set_exec_reverse"),     clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_disable_hardware_breakpoits"),  clMainFrame::OnDebugCmd)
+    EVT_MENU(XRCID("dbg_enable_hardware_breakpoits"),   clMainFrame::OnDebugCmd)
     EVT_MENU(XRCID("show_cursor"),              clMainFrame::OnDebugCmd)
     EVT_MENU(XRCID("add_breakpoint"),           clMainFrame::DispatchCommandEvent)
     EVT_MENU(XRCID("insert_breakpoint"),        clMainFrame::DispatchCommandEvent) // Toggles
@@ -3299,7 +3310,51 @@ void clMainFrame::OnDebugCmd(wxCommandEvent &e)
     } else if ( e.GetId() == XRCID("dbg_nexti")) {
         cmd = DBG_NEXTI;
         eventId = wxEVT_DBG_UI_NEXT_INST;
-        
+
+    } else if ( e.GetId() == XRCID("dbg_record")) {
+        cmd = DBG_RECORD;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_stoprecord")) {
+        cmd = DBG_STOP_RECORD;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_reverse_next")) {
+        cmd = DBG_REVERSE_NEXT;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_reverse_nexti")) {
+        cmd = DBG_REVERSE_NEXTI;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if (e.GetId() == XRCID("dbg_reverse_stepin")) {
+        cmd = DBG_REVERSE_STEPIN;
+        eventId = wxEVT_DBG_UI_STEP_IN;
+
+    } else if ( e.GetId() == XRCID("dbg_reverse_stepout")) {
+        cmd = DBG_REVERSE_STEPOUT;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_reverse_continue")) {
+        cmd = DBG_REVERSE_CONTINUE;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_set_exec_forward")) {
+        cmd = DBG_SET_EXEC_DIRECTION_FORWARD;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_set_exec_reverse")) {
+        cmd = DBG_SET_EXEC_DIRECTION_REVERSE;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_disable_hardware_breakpoits")) {
+        cmd = DBG_DISABLE_HARDWARE_BREAKPOINTS;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
+    } else if ( e.GetId() == XRCID("dbg_enable_hardware_breakpoits")) {
+        cmd = DBG_ENABLE_HARDWARE_BREAKPOINTS;
+        eventId = wxEVT_DBG_UI_NEXT_INST;
+
     }
     
     // ALlow the plugins to handle this command first
@@ -3325,6 +3380,17 @@ void clMainFrame::OnDebugCmdUI(wxUpdateUIEvent &e)
         e.GetId() == XRCID("dbg_stepout") ||
         e.GetId() == XRCID("dbg_next") ||
         e.GetId() == XRCID("dbg_nexti") ||
+        e.GetId() == XRCID("dbg_record") ||
+        e.GetId() == XRCID("dbg_stoprecord") ||
+        e.GetId() == XRCID("dbg_reverse_stepin") ||
+        e.GetId() == XRCID("dbg_reverse_next") ||
+        e.GetId() == XRCID("dbg_reverse_nexti") ||
+        e.GetId() == XRCID("dbg_reverse_stepout") ||
+        e.GetId() == XRCID("dbg_reverse_continue") ||
+        e.GetId() == XRCID("dbg_set_exec_forward") ||
+        e.GetId() == XRCID("dbg_set_exec_reverse") ||
+        e.GetId() == XRCID("dbg_disable_hardware_breakpoits") ||
+        e.GetId() == XRCID("dbg_enable_hardware_breakpoits") ||
         e.GetId() == XRCID("show_cursor")) {
         IDebugger *dbgr = DebuggerMgr::Get().GetActiveDebugger();
         e.Enable(eventIsRunning.IsAnswer() || (dbgr && dbgr->IsRunning()) );
diff --git a/LiteEditor/manager.cpp b/LiteEditor/manager.cpp
index 2e3ce48..6e4698a 100644
--- a/LiteEditor/manager.cpp
+++ b/LiteEditor/manager.cpp
@@ -2631,6 +2631,47 @@ void Manager::DbgDoSimpleCommand ( int cmd )
             clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
             dbgr->NextInstruction();
             break;
+        case DBG_REVERSE_NEXT:
+            clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+            clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+            dbgr->ReverseNext();
+            break;
+        case DBG_REVERSE_STEPIN:
+            clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+            clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+            dbgr->ReverseStepIn();
+            break;
+        case DBG_REVERSE_STEPOUT:
+            clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+            clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+            dbgr->ReverseStepOut();
+            break;
+        case DBG_REVERSE_NEXTI:
+            clMainFrame::Get()->GetDebuggerPane()->GetLocalsTable()->ResetTableColors();
+            clMainFrame::Get()->GetDebuggerPane()->GetWatchesTable()->ResetTableColors();
+            dbgr->ReverseNextInstruction();
+            break;
+        case DBG_DISABLE_HARDWARE_BREAKPOINTS:
+            dbgr->DisableHardwareBreakpoints();
+            break;
+        case DBG_ENABLE_HARDWARE_BREAKPOINTS:
+            dbgr->EnableHardwareBreakpoints();
+            break;
+        case DBG_SET_EXEC_DIRECTION_REVERSE:
+            dbgr->SetExecDirectionReverse();
+            break;
+        case DBG_SET_EXEC_DIRECTION_FORWARD:
+            dbgr->SetExecDirectionForward();
+            break;
+        case DBG_RECORD:
+            dbgr->Record();
+            break;
+        case DBG_STOP_RECORD:
+            dbgr->StopRecord();
+            break;
+        case DBG_REVERSE_CONTINUE:
+            dbgr->ReverseContinue();
+            break;
         default:
             break;
         }
diff --git a/Runtime/rc/menu.xrc b/Runtime/rc/menu.xrc
index 5bb42bc..1ffdc3f 100644
--- a/Runtime/rc/menu.xrc
+++ b/Runtime/rc/menu.xrc
@@ -520,6 +520,46 @@
             <object class="wxMenuItem" name="dbg_stepout">
                 <label>Step &Out</label>
             </object>
+            <object class="wxMenu" name="debugger_reverse_debugging">
+                <label>GDB &Reverse Debugging</label>
+                <style>wxMENU_TEAROFF</style>
+                <object class="wxMenuItem" name="dbg_record">
+                    <label>&Begin Recording</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_stoprecord">
+                    <label>&Stop Recording</label>
+                </object>
+                <object class="wxMenuItem" name="wxID_SEPARATOR"/>
+                <object class="wxMenuItem" name="dbg_reverse_stepin">
+                    <label>Reverse Step &Into</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_reverse_next">
+                    <label>Reverse &Next</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_reverse_nexti">
+                    <label>Reverse Next Ins&truction</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_reverse_stepout">
+                    <label>Reverse Step &Out</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_reverse_continue">
+                    <label>Reverse &Continue</label>
+                </object>
+                <object class="wxMenuItem" name="wxID_SEPARATOR"/>
+                <object class="wxMenuItem" name="dbg_set_exec_forward">
+                    <label>Set Exec Direction To &Forward</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_set_exec_reverse">
+                    <label>Set Exec Direction To &Reverse</label>
+                </object>
+                <object class="wxMenuItem" name="wxID_SEPARATOR"/>
+                <object class="wxMenuItem" name="dbg_disable_hardware_breakpoits">
+                    <label>&Disable Hardware Breakpoints</label>
+                </object>
+                <object class="wxMenuItem" name="dbg_enable_hardware_breakpoits">
+                    <label>&Enable Hardware Breakpoints</label>
+                </object>
+            </object>
 			<object class="wxMenuItem" name="wxID_SEPARATOR"/>
             <object class="wxMenuItem" name="show_cursor">
                 <label>Show &Cursor</label>
@@ -543,7 +583,7 @@
 			</object>
             <object class="wxMenuItem" name="wxID_SEPARATOR"/>
             <object class="wxMenu" name="debugger_windows">
-                <label>GDB Windows</label>
+                <label>GDB &Windows</label>
                 <style>wxMENU_TEAROFF</style>
                 <object class="wxMenuItem" name="debugger_win_locals">
                     <label>Locals</label>

Re: Patch: Reverse Debugging Menu

Posted: Sat Jun 28, 2014 1:51 am
by eranif
This patch is a bit buggy and it won't work with other debugger plugins (e.g. LLDB)

The logic, atm is like this:

Each command initiated by the user, is first sent to the plugins for processing.
This is done by these 3 lines (frame.cpp, 3316):

Code: Select all

clDebugEvent evnt(eventId);
if ( EventNotifier::Get()->ProcessEvent( evnt ) ) {
    return;
}
In your patch, the eventId is always set to wxEVT_DBG_UI_NEXT_INST
This means that the command 'Next Instruction' is sent to the plugins for all of the new commands you have added and the plugins will perform the wrong action

You need to define a new event type per command (see codelite_events.h for more details)
Also, it will great if you can handle them in LLDBPlugin class (just connect them and add a stub function that prints to the log file)

Eran

Re: Patch: Reverse Debugging Menu

Posted: Wed Aug 13, 2014 7:02 am
by eranif
Hi Caibbor,
Any chance of getting this patch fixed? I would really love to add it to codelite

Thanks,
Eran

Re: Patch: Reverse Debugging Menu

Posted: Sun Aug 17, 2014 10:15 pm
by caibbor
Hey, I can take a look and see. I'm still struggling with figuring out git. It's been a while since I've been able to successfully pull updates and I've got several branches to sort through and figure out which is which.

After I figure that out I'll try to get this patch up to snuff.