[nemiver/varobjs-support] Initial backend support for setting watchpoints



commit 5045cb0155f4b6051c1d3cdaf9dc9ffbb6a26161
Author: Dodji Seketeli <dodji redhat com>
Date:   Sun May 17 18:43:44 2009 +0200

    Initial backend support for setting watchpoints
    
    	* src/dbgengine/nmv-i-debugger.h (class IDebugger::BreakPoint):
    	New IDebugge::BreakPoint::Type enum to discriminate different types
    	of breakpoints e.g. watchpoint and standard breakpoints.
    	(IDebugger::BreakPoint::expression): New accessors for the
    	expression that triggered the watchpoint.
    	(IDebugger::BreakPoint::type): New accessors for the type of
    	Breakpoint.
    	(IDebugger::set_watchpoint): Declare new abstract entry point.
    	* src/dbgengine/nmv-gdb-engine.h (DGBEngine::set_watchpoint):
    	Declare new concrete entry point.
    	* src/dbgengine/nmv-gdb-engine.cc (OnStoppedHandler::do_handle):
    	Consider IDebugger::WATCHPOINT_SCOPE types of breakpoints when
    	notifying the user.
    	(GDBEngine::set_watchpoint): New implementation of
    	IDebugger::set_watchpoint.
    	* src/dbgengine/nmv-gdbmi-parser.cc (GDBMIParser::parse_attribute):
    	Add a new overload that represents an attribute using the
    	GDBMIResult type. Make the old overload use this new one.
    	(GDBMIParser::parse_stopped_async_output): use the
    	new GDBMIParser::parse_attribute overload. Do some style cleanup.
    	(GDBMIParser::parse_out_of_band_record): Recognize the wpnum
    	attribute that is present when the inferior stopped because a
    	watchpoint triggered.
    	Use the IDebugger::BreakPoint::expression accessor to store the
    	expression that triggered the watchpoint.
    	Set the new IDebugger::BreakPoint::type property so that we can
    	tell the difference between a standard breakpoint and a watchpoint.
---
 src/dbgengine/nmv-gdb-engine.cc   |   27 ++++++++++++++-
 src/dbgengine/nmv-gdb-engine.h    |    4 ++
 src/dbgengine/nmv-gdbmi-parser.cc |   70 ++++++++++++++++++++++++++++++------
 src/dbgengine/nmv-i-debugger.h    |   27 +++++++++++++-
 4 files changed, 113 insertions(+), 15 deletions(-)

diff --git a/src/dbgengine/nmv-gdb-engine.cc b/src/dbgengine/nmv-gdb-engine.cc
index 96c1aff..1524066 100644
--- a/src/dbgengine/nmv-gdb-engine.cc
+++ b/src/dbgengine/nmv-gdb-engine.cc
@@ -1134,7 +1134,8 @@ struct OnStoppedHandler: OutputHandler {
         int thread_id = m_out_of_band_record.thread_id ();
         int breakpoint_number = -1;
         IDebugger::StopReason reason = m_out_of_band_record.stop_reason ();
-        if (reason == IDebugger::BREAKPOINT_HIT)
+        if (reason == IDebugger::BREAKPOINT_HIT
+            || reason == IDebugger::WATCHPOINT_SCOPE)
             breakpoint_number = m_out_of_band_record.breakpoint_number ();
 
         if (m_out_of_band_record.has_frame ()) {
@@ -3274,6 +3275,30 @@ GDBEngine::set_breakpoint (const UString &a_path,
 }
 
 void
+GDBEngine::set_watchpoint (const UString &a_expression,
+                           bool a_write, bool a_read,
+                           const UString &a_cookie)
+{
+    LOG_FUNCTION_SCOPE_NORMAL_DD;
+
+    if (a_expression.empty ())
+        return;
+
+    string cmd_str = "-break-watch";
+
+    if (a_write && a_read)
+        cmd_str += " -a";
+    else if (a_read == true)
+        cmd_str += " -r";
+
+    cmd_str += " " + a_expression;
+
+    Command command ("set-watchpoint", cmd_str, a_cookie);
+    queue_command (command);
+    list_breakpoints (a_cookie);
+}
+
+void
 GDBEngine::set_breakpoint (const UString &a_func_name,
                            const UString &a_condition,
                            const UString &a_cookie)
diff --git a/src/dbgengine/nmv-gdb-engine.h b/src/dbgengine/nmv-gdb-engine.h
index d91ac6e..e02d2b0 100644
--- a/src/dbgengine/nmv-gdb-engine.h
+++ b/src/dbgengine/nmv-gdb-engine.h
@@ -310,6 +310,10 @@ public:
                          const UString &a_condition,
                          const UString &a_cookie)  ;
 
+    void set_watchpoint (const UString &a_expression,
+                         bool a_write, bool a_read,
+                         const UString &a_cookie);
+
     void list_breakpoints (const UString &a_cookie) ;
 
     map<int, IDebugger::BreakPoint>& get_cached_breakpoints () ;
diff --git a/src/dbgengine/nmv-gdbmi-parser.cc b/src/dbgengine/nmv-gdbmi-parser.cc
index 7450623..71848fc 100644
--- a/src/dbgengine/nmv-gdbmi-parser.cc
+++ b/src/dbgengine/nmv-gdbmi-parser.cc
@@ -1231,20 +1231,30 @@ GDBMIParser::parse_stopped_async_output (UString::size_type a_from,
     if (m_priv->index_passed_end (cur)) {return false;}
 
     map<UString, UString> attrs;
-    UString name, value;
+    UString name;
+    GDBMIResultSafePtr result;
     bool got_frame (false);
     IDebugger::Frame frame;
     while (true) {
-        if (!m_priv->input.raw ().compare (cur, strlen (PREFIX_FRAME), PREFIX_FRAME)) {
+        if (!m_priv->input.raw ().compare (cur,
+                                           strlen (PREFIX_FRAME),
+                                           PREFIX_FRAME)) {
             if (!parse_frame (cur, cur, frame)) {
                 LOG_PARSING_ERROR2 (cur);
                 return false;
             }
             got_frame = true;
         } else {
-            if (!parse_attribute (cur, cur, name, value)) {break;}
-            attrs[name] = value;
-            name.clear (); value.clear ();
+            if (!parse_attribute (cur, cur, name, result)) {break;}
+            if (result
+                && result->value ()
+                && result->value ()->content_type ()
+                      == GDBMIValue::STRING_TYPE) {
+                attrs[name] = result->value ()->get_string_content ();
+                LOG_D ("got " << name << ":" << attrs[name],
+                       GDBMI_PARSING_DOMAIN);
+            }
+            name.clear (); result.reset ();
         }
 
         if (m_priv->index_passed_end (cur)) {break;}
@@ -1252,7 +1262,12 @@ GDBMIParser::parse_stopped_async_output (UString::size_type a_from,
         if (m_priv->index_passed_end (cur)) {break;}
     }
 
-    for (; !m_priv->index_passed_end (cur) && RAW_CHAR_AT (cur) != '\n'; ++cur) {}
+    for (;
+         !m_priv->index_passed_end (cur)
+         && RAW_CHAR_AT (cur) != '\n';
+         ++cur)
+    {
+    }
 
     if (RAW_CHAR_AT (cur) != '\n') {
         LOG_PARSING_ERROR2 (cur);
@@ -1310,7 +1325,7 @@ bool
 GDBMIParser::parse_attribute (UString::size_type a_from,
                               UString::size_type &a_to,
                               UString &a_name,
-                              UString &a_value)
+                              GDBMIResultSafePtr &a_value)
 {
     UString::size_type cur = a_from;
 
@@ -1327,7 +1342,23 @@ GDBMIParser::parse_attribute (UString::size_type a_from,
     }
 
     a_name = result->variable ();
-    return gdbmi_value_to_string (result->value (), a_value);
+    a_value = result;
+    return true;
+}
+
+bool
+GDBMIParser::parse_attribute (UString::size_type a_from,
+                              UString::size_type &a_to,
+                              UString &a_name,
+                              UString &a_value)
+{
+
+    GDBMIResultSafePtr result;
+    bool is_ok = parse_attribute (a_from, a_to, a_name, result);
+    if (!is_ok)
+        return false;
+    gdbmi_value_to_string (result->value (), a_value);
+    return true;
 }
 
 bool
@@ -1559,6 +1590,10 @@ GDBMIParser::parse_out_of_band_record (UString::size_type a_from,
         if (attrs.find ("bkptno") != attrs.end ()) {
             record.breakpoint_number (atoi (attrs["bkptno"].c_str ()));
         }
+        if (attrs.find ("wpnum") != attrs.end ()) {
+            record.breakpoint_number (atoi (attrs["wpnum"].c_str ()));
+            LOG_D ("wpnum:" << attrs["wpnum"], GDBMI_PARSING_DOMAIN);
+        }
         record.thread_id (atoi (attrs["thread-id"].c_str ()));
         record.signal_type (attrs["signal-name"]);
         record.signal_meaning (attrs["signal-meaning"]);
@@ -1991,10 +2026,14 @@ GDBMIParser::parse_breakpoint (Glib::ustring::size_type a_from,
     a_bkpt.address (attrs["addr"]);
     if (!attrs["func"].empty ()) {
         a_bkpt.function (attrs["func"]);
-    } else if (!attrs["what"].empty ()) {
-        // catchpoints don't have a 'func' field, but they have a 'what' field
-        // that says something like "Exception throw"
-        a_bkpt.function (attrs["what"]);
+    }
+    if (!attrs["what"].empty ()) {
+        // catchpoints or watchpoints
+        // don't have a 'func' field, but they have a 'what' field
+        // that describes the expression that was being watched.
+        // something like "Exception throw" for catchpoint, or "varname"
+        // for a watchpoint.
+        a_bkpt.expression (attrs["what"]);
     }
     a_bkpt.file_name (attrs["file"]); //may be nil
     a_bkpt.file_full_name (attrs["fullname"]); //may be nil
@@ -2003,6 +2042,13 @@ GDBMIParser::parse_breakpoint (Glib::ustring::size_type a_from,
         a_bkpt.condition (iter->second);
     }
     a_bkpt.nb_times_hit (atoi (attrs["times"].c_str ()));
+
+    string type = attrs["type"];
+    if (type.find ("breakpoint") != type.npos)
+        a_bkpt.type (IDebugger::BreakPoint::STANDARD_BREAKPOINT_TYPE);
+    else if (type.find ("watchpoint") != type.npos)
+        a_bkpt.type (IDebugger::BreakPoint::WATCHPOINT_TYPE);
+
     //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 74d4832..1ae1ed5 100644
--- a/src/dbgengine/nmv-i-debugger.h
+++ b/src/dbgengine/nmv-i-debugger.h
@@ -78,18 +78,28 @@ public:
 
     /// \brief a breakpoint descriptor
     class BreakPoint {
+    public:
+
+        enum Type {
+            UNDEFINED_TYPE = 0,
+            STANDARD_BREAKPOINT_TYPE,
+            WATCHPOINT_TYPE
+        };
+
+    private:
         int m_number;
         bool m_enabled;
         UString m_address;
         UString m_function;
+        UString m_expression;
         UString m_file_name;
         UString m_file_full_name;
-        int m_line;
         UString m_condition;
+        Type m_type;
+        int m_line;
         int m_nb_times_hit;
 
     public:
-
         BreakPoint () {clear ();}
 
         /// \name accessors
@@ -107,6 +117,9 @@ public:
         const UString& function () const {return m_function;}
         void function (const UString &a_in) {m_function = a_in;}
 
+        const UString& expression () const {return m_expression;}
+        void expression (const UString &a_expr) {m_expression = a_expr;}
+
         const UString& file_name () const {return m_file_name;}
         void file_name (const UString &a_in) {m_file_name = a_in;}
 
@@ -131,6 +144,10 @@ public:
             }
             return false;
         }
+
+        Type type () const {return m_type;}
+        void type (Type a_type) {m_type = a_type;}
+
         /// @}
 
         /// \brief clear this instance of breakpoint
@@ -991,6 +1008,12 @@ public:
     virtual void set_breakpoint (const UString &a_func_name,
                                  const UString &a_condition="",
                                  const UString &a_cookie="") = 0;
+
+    virtual void set_watchpoint (const UString &a_expression,
+                                 bool a_write = true,
+                                 bool a_read = false,
+                                 const UString &a_cookie = "") = 0;
+
     virtual void set_catch (const UString &a_event,
                             const UString &a_cookie="") = 0;
 



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