[nemiver/varobjs-support] Initial backend support for setting watchpoints
- From: Dodji Seketeli <dodji src gnome org>
- To: svn-commits-list gnome org
- Subject: [nemiver/varobjs-support] Initial backend support for setting watchpoints
- Date: Sun, 17 May 2009 14:44:06 -0400 (EDT)
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]