[PATCH] 670464 - Make breakpoint ignore count persistent



When you set the ignore count of a breakpoint B to an integer number
N, that ignore count gets decremented each time the breakpoint is hit.
When the inferior program finally stops at said breakpoint, its ignore
count is zero.

Then, when you restart the debugger, the inferior re-runs with a
breakpoint that has an ignore count of zero.

I use ignore counts a lot, to debug a code base that has lots of
loops, and I happen to have several breakpoints with several different
ignore counts set on them.  Of course, I need to frequently re-start
the inferior to try to figure out things I missed during the previous
run.  With all those ignore counts to set again, each time I need to
restart, C'est la catastrophe!

I just ended up cooking up this patch so that the inferior restarts
with an ignore count of B set to N (instead of zero) even after the
current ignore count reached zero.

And initial ignore counts are persisted on disk as well, so that when
you do "nemiver --last", your last debugging session is resumed along
with your breakpoints and their initial ignore counts.

Tested and applied to master.


	* src/dbgengine/nmv-i-debugger.h
	(IDebugger::Breakpoint::initial_ignore_count): New accessor for
	the initial ignore count that got set by the user.
	(IDebugger::Breakpoint::clear): Zero the new
	m_initial_ignore_count member.
	* src/dbgengine/nmv-gdbmi-parser.cc
	(GDBMIParser::parse_breakpoint): Set initial ignore count when
	we are on the edge of an ignore count change.
	* src/dbgengine/nmv-gdb-engine.h
	(GDBEngine::append_breakpoints_to_cache): Remove const from
	breakpoint(s) parameter.
	* src/dbgengine/nmv-gdb-engine.cc
	(GDBEngine::set_breakpoint_ignore_count): Set the initial ignore
	count on the locally cached breakpoint, when we have one.  This is
	how we 'remember' the initial ignore count, even though GDB
	decrements the ignore count at each hit.  That way, we can have a
	chance to set the proper ignore count back to the instance of
	Breakpoint we receive from GDB, if necessary.
	(GDBEngine::append_breakpoint_to_cache): Remove the const from the
	breakpoint parameter.  Update that argument with the cached
	initial ignore count if necessary.
	(GDBEngine::append_breakpoints_to_cache): Remove const from the
	breakpoints parameter.
	* src/persp/dbgperspective/nmv-dbg-perspective.cc
	(DBGPerspective::re_initialize_set_breakpoints): New.
	(DBGPerspective::on_going_to_run_target_signal): Use here.
	(DBGPerspective::record_and_save_session): Save the initial ignore
	count ...
	(DBGPerspective::execute_session): ... and restore it.
	(DBGPerspective::set_breakpoint): Set the breakpoint ignore count
	to the initial ignore count.
---
 src/dbgengine/nmv-gdb-engine.cc                 |   39 ++++++++++++++++++++--
 src/dbgengine/nmv-gdb-engine.h                  |    4 +-
 src/dbgengine/nmv-gdbmi-parser.cc               |    7 ++++
 src/dbgengine/nmv-i-debugger.h                  |   13 +++++++
 src/persp/dbgperspective/nmv-dbg-perspective.cc |   34 +++++++++++++++++---
 5 files changed, 86 insertions(+), 11 deletions(-)

diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index 8bc780a..b304843 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -4576,6 +4576,14 @@ GDBEngine::set_breakpoint_ignore_count (gint a_break_num,
                      a_cookie);
     queue_command (command);
     list_breakpoints (a_cookie);
+
+    typedef map<int, IDebugger::Breakpoint> BPMap;
+    BPMap &bp_cache =
+        get_cached_breakpoints ();
+    BPMap::iterator b_it;
+    if ((b_it = bp_cache.find (a_break_num)) == bp_cache.end ())
+        return;
+    b_it->second.initial_ignore_count (a_ignore_count);
 }
 
 void
@@ -4729,8 +4737,14 @@ GDBEngine::get_breakpoint_from_cache (int a_num,
     return true;
 }
 
+/// Append a breakpoint to the internal cache.
+///
+/// This function can also update the breakpoint given in parameter,
+/// for things like initial ignore count, that we simulate over GDB.
+///
+/// \param a_break the break point to append to the cache.
 void
-GDBEngine::append_breakpoint_to_cache (const IDebugger::Breakpoint &a_break)
+GDBEngine::append_breakpoint_to_cache (IDebugger::Breakpoint &a_break)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
@@ -4751,7 +4765,10 @@ GDBEngine::append_breakpoint_to_cache (const IDebugger::Breakpoint &a_break)
                 << a_break.number ()
                 << " is not a count point");
     }
-        
+    LOG_DD ("initial_ignore_count on bp "
+            << (int)  a_break.number ()
+            << ": " << a_break.initial_ignore_count ());
+
     // First, let's see if a_break is already in our cache.
     cur = bp_cache.find (a_break.number ());
     if (cur != nil) {
@@ -4762,6 +4779,20 @@ GDBEngine::append_breakpoint_to_cache (const IDebugger::Breakpoint &a_break)
         // the content of a_break.
         if (cur->second.type () == IDebugger::Breakpoint::COUNTPOINT_TYPE)
             preserve_count_point = true;
+        
+        // Let's preserve the initial ignore count property.
+        if (cur->second.initial_ignore_count () != a_break.initial_ignore_count ()) {
+            a_break.initial_ignore_count (cur->second.initial_ignore_count ());
+            LOG_DD ("initial_ignore_count propagated on bp "
+                    << (int)  a_break.number ()
+                    << ": " << a_break.initial_ignore_count ());
+        }
+    } else {
+        // The breakpoint doesn't exist in the cache, so it's the
+        // first time we are seeing it.  In this case, the GDBMI
+        // parser should have properly set the initial ignore count
+        // property.  So there is nothing to do regarding ignore
+        // counts here.
     }
 
     // So now is the cache updating time.
@@ -4800,11 +4831,11 @@ GDBEngine::append_breakpoint_to_cache (const IDebugger::Breakpoint &a_break)
 /// \param a_breaks the set of breakpoints to append to the cache.
 void
 GDBEngine::append_breakpoints_to_cache
-                            (const map<int, IDebugger::Breakpoint> &a_breaks)
+                            (map<int, IDebugger::Breakpoint> &a_breaks)
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
 
-    map<int, IDebugger::Breakpoint>::const_iterator iter;
+    map<int, IDebugger::Breakpoint>::iterator iter;
     for (iter = a_breaks.begin (); iter != a_breaks.end (); ++iter)
         append_breakpoint_to_cache (iter->second);
 }
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index f6b5651..88a5816 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -321,9 +321,9 @@ public:
 
     void init_output_handlers ();
 
-    void append_breakpoint_to_cache (const IDebugger::Breakpoint &a_break);
+    void append_breakpoint_to_cache (IDebugger::Breakpoint &a_break);
 
-    void append_breakpoints_to_cache (const map<int, IDebugger::Breakpoint>&);
+    void append_breakpoints_to_cache (map<int, IDebugger::Breakpoint>&);
 
     void do_continue (const UString &a_cookie);
 
diff --git a/src/dbgengine/nmv-gdbmi-parser.cc b/src/dbgengine/nmv-gdbmi-parser.cc
index 2d4d602..6fc604e 100644
--- a/src/dbgengine/nmv-gdbmi-parser.cc
+++ b/src/dbgengine/nmv-gdbmi-parser.cc
@@ -2270,6 +2270,7 @@ GDBMIParser::parse_breakpoint (Glib::ustring::size_type a_from,
         }
     }
 
+    bool ignore_count_present = false;
     map<UString, UString>::iterator iter, null_iter = attrs.end ();
     // we use to require that the "fullname" property be present as
     // well, but it seems that a lot debug info set got shipped without
@@ -2333,6 +2334,7 @@ GDBMIParser::parse_breakpoint (Glib::ustring::size_type a_from,
     }
     a_bkpt.nb_times_hit (atoi (attrs["times"].c_str ()));
     if ((iter = attrs.find ("ignore")) != null_iter) {
+        ignore_count_present = true;
         a_bkpt.ignore_count (atoi (iter->second.c_str ()));
     }
 
@@ -2342,6 +2344,11 @@ GDBMIParser::parse_breakpoint (Glib::ustring::size_type a_from,
     else if (type.find ("watchpoint") != type.npos)
         a_bkpt.type (IDebugger::Breakpoint::WATCHPOINT_TYPE);
 
+    // Set the initial ignore count
+    if (ignore_count_present)
+        a_bkpt.initial_ignore_count (a_bkpt.ignore_count ()
+                                     + a_bkpt.nb_times_hit ());
+
     //TODO: get the 'at' attribute that is present on targets that
     //are not compiled with -g.
     a_to = cur;
diff --git a/src/dbgengine/nmv-i-debugger.h b/src/dbgengine/nmv-i-debugger.h
index 2191e1a..29480d9 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -108,6 +108,10 @@ public:
         Type m_type;
         int m_line;
         int m_nb_times_hit;
+        // The ignore count set by the user.
+        int m_initial_ignore_count;
+        // The current ignore count.  This one is decremented each
+        // time the breakpoint is hit.
         int m_ignore_count;
         bool m_is_read_watchpoint;
         bool m_is_write_watchpoint;
@@ -151,6 +155,14 @@ public:
         int nb_times_hit () const {return m_nb_times_hit;}
         void nb_times_hit (int a_nb) {m_nb_times_hit = a_nb;}
 
+        ///  This is the ignore count as set by the user through the
+        ///  user interface.
+        int initial_ignore_count () const {return m_initial_ignore_count;}
+        void initial_ignore_count (int a) {m_initial_ignore_count = a;}
+
+        /// This is the current ignore count present on the
+        /// breakpoint.  It gets decremented each time the breakpoint
+        /// is hit.
         int ignore_count () const {return m_ignore_count;}
         void ignore_count (int a) {m_ignore_count = a;}
 
@@ -186,6 +198,7 @@ public:
             m_line = 0;
             m_condition.clear ();
             m_nb_times_hit = 0;
+            m_initial_ignore_count = 0;
             m_ignore_count = 0;
             m_is_read_watchpoint = false;
             m_is_write_watchpoint = false;
diff --git a/src/persp/dbgperspective/nmv-dbg-perspective.cc b/src/persp/dbgperspective/nmv-dbg-perspective.cc
index 48cf7bb..347b1ef 100644
--- a/src/persp/dbgperspective/nmv-dbg-perspective.cc
+++ b/src/persp/dbgperspective/nmv-dbg-perspective.cc
@@ -635,6 +635,7 @@ public:
     void set_breakpoint (const Address &a_address,
                          bool a_is_count_point);
     void set_breakpoint (const IDebugger::Breakpoint &a_breakpoint);
+    void re_initialize_set_breakpoints ();
     void append_breakpoint (const IDebugger::Breakpoint &a_breakpoint);
     void append_breakpoints
                     (const map<int, IDebugger::Breakpoint> &a_breaks);
@@ -1825,7 +1826,10 @@ void
 DBGPerspective::on_going_to_run_target_signal ()
 {
     LOG_FUNCTION_SCOPE_NORMAL_DD;
-    NEMIVER_TRY
+
+    NEMIVER_TRY;
+
+    re_initialize_set_breakpoints ();
     clear_session_data ();
     get_local_vars_inspector ().re_init_widget ();
     get_breakpoints_view ().re_init ();
@@ -1834,7 +1838,8 @@ DBGPerspective::on_going_to_run_target_signal ()
     get_memory_view ().clear ();
 #endif
     get_registers_view ().clear ();
-    NEMIVER_CATCH
+
+    NEMIVER_CATCH;
 }
 
 void
@@ -5026,7 +5031,7 @@ DBGPerspective::record_and_save_session (ISessMgr::Session &a_session)
                                      break_iter->second.line (),
                                      break_iter->second.enabled (),
                                      break_iter->second.condition (),
-                                     break_iter->second.ignore_count (),
+                                     break_iter->second.initial_ignore_count (),
                                      debugger ()->is_countpoint
                                      (break_iter->second));
             a_session.breakpoints ().push_back (bp);
@@ -5705,7 +5710,7 @@ DBGPerspective::execute_session (ISessMgr::Session &a_session)
         breakpoint.file_full_name (it->file_full_name ());
         breakpoint.enabled (it->enabled ());
         breakpoint.condition (it->condition ());
-        breakpoint.ignore_count (it->ignore_count ());
+        breakpoint.initial_ignore_count (it->ignore_count ());
         if (it->is_countpoint ()) {
             breakpoint.type (IDebugger::Breakpoint::COUNTPOINT_TYPE);
             LOG_DD ("breakpoint "
@@ -6655,7 +6660,7 @@ DBGPerspective::set_breakpoint (const IDebugger::Breakpoint &a_breakpoint)
         int ignore_count =
             debugger ()->is_countpoint (a_breakpoint)
             ? -1
-            : a_breakpoint.ignore_count ();
+            : a_breakpoint.initial_ignore_count ();
 
         if (!file_name.empty ())
             debugger ()->set_breakpoint (file_name,
@@ -6676,6 +6681,25 @@ DBGPerspective::set_breakpoint (const IDebugger::Breakpoint &a_breakpoint)
     }
 }
 
+/// Re-set ignore count on breakpoints that are already set.
+void
+DBGPerspective::re_initialize_set_breakpoints ()
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    typedef map<int, IDebugger::Breakpoint> BPMap;
+    BPMap &bps = m_priv->breakpoints;
+
+    // Re-set ignore count on set breakpoints.
+    for (BPMap::const_iterator i = bps.begin ();
+         i != bps.end ();
+         ++i) {
+        debugger ()->set_breakpoint_ignore_count
+            (i->second.number (),
+             i->second.initial_ignore_count ());
+    }
+}
+
 void
 DBGPerspective::append_breakpoint (const IDebugger::Breakpoint &a_breakpoint)
 {
-- 
1.7.6.5


-- 
		Dodji


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]