diff options
author | Pedro Alves <palves@redhat.com> | 2015-03-04 20:41:16 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2015-03-04 20:41:16 +0000 |
commit | f7e6eed5283bb5c8a3598dd986dc922b9a794f58 (patch) | |
tree | a7343d12474798fc7be6fdc479527d52190bbedc /gdb/remote.c | |
parent | 9e8915c6cee5c37637521b424d723e990e06d597 (diff) | |
download | gdb-f7e6eed5283bb5c8a3598dd986dc922b9a794f58.zip gdb-f7e6eed5283bb5c8a3598dd986dc922b9a794f58.tar.gz gdb-f7e6eed5283bb5c8a3598dd986dc922b9a794f58.tar.bz2 |
remote+docs: software/hardware breakpoint traps
This adjusts target remote to tell the core whether a trap was caused
by a breakpoint.
To that end, the patch teaches GDB about new RSP stop reasons "T05
swbreak" and "T05 hwbreak", that remote targets report back to GDB,
similarly to how "T05 watch" indicates a stop caused by a watchpoint.
Because targets that can report these events are expected to
themselves adjust the PC after a software breakpoint, these new stop
reasons must only be reported if the stub is talking to a GDB that
understands them. Because of that, the use of the new stop reasons
needs to be handshaked on initial connection, using the qSupported
mechanism. GDB simply sends "swbreak+" in its qSupports query, and
the stub reports back "swbreak+" too.
Because these new stop reasons are required to fix a fundamental
non-stop mode problem, this commit extends the remote non-stop intro
section in the manual, documenting the events as required.
To be clear, GDB will still cope with remote targets that don't
support these new stop reasons; it will behave just like today.
Tested on x86-64 Fedora 20, native and gdbserver.
gdb/ChangeLog:
2015-03-04 Pedro Alves <palves@redhat.com>
* NEWS: Mention the new "swbreak" and "hwbreak" stop reasons.
* remote.c (struct remote_state) <remote_stopped_by_watchpoint_p>:
Delete field.
<stop_reason>: New field.
(PACKET_swbreak_feature, PACKET_hwbreak_feature): New enum values.
(packet_set_cmd_state): New function.
(remote_protocol_features): Register the "swbreak" and "hwbreak"
features.
(remote_query_supported): If not disabled with the corresponding
"set remote foo-packet" command, report support for the swbreak
and hwbreak features.
(struct stop_reply) <remote_stopped_by_watchpoint_p>: Delete
field.
<stop_reason>: New field.
(remote_parse_stop_reply): Handle "swbreak" and "hwbreak".
(remote_wait_as): Adjust.
(remote_stopped_by_sw_breakpoint)
(remote_supports_stopped_by_sw_breakpoint)
(remote_stopped_by_hw_breakpoint)
(remote_supports_stopped_by_hw_breakpoint): New functions.
(remote_stopped_by_watchpoint): New function.
(init_remote_ops): Install them.
(_initialize_remote): Register new "set/show remote
swbreak-feature-packet" and "set/show remote
swbreak-feature-packet" commands.
gdb/doc/ChangeLog:
2015-03-04 Pedro Alves <palves@redhat.com>
* gdb.texinfo (Remote Configuration): Document the "set/show
remote swbreak-feature-packet" and "set/show remote
hwbreak-feature-packet" commands.
(Packets) <Z0>: Add cross link to the "swbreak" stop reason's
decription.
(Stop Reply Packets): Document the swbreak and hwbreak stop
reasons.
(General Query Packets): Document the swbreak and hwbreak
qSupported features.
(Remote Non-Stop): Explain that swbreak and hwbreak are required.
Diffstat (limited to 'gdb/remote.c')
-rw-r--r-- | gdb/remote.c | 119 |
1 files changed, 110 insertions, 9 deletions
diff --git a/gdb/remote.c b/gdb/remote.c index 2a823eb..8f783a4 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -364,8 +364,8 @@ struct remote_state to stop for a watchpoint. */ CORE_ADDR remote_watch_data_address; - /* This is non-zero if target stopped for a watchpoint. */ - int remote_stopped_by_watchpoint_p; + /* Whether the target stopped for a breakpoint/watchpoint. */ + enum target_stop_reason stop_reason; threadref echo_nextthread; threadref nextthread; @@ -1338,11 +1338,26 @@ enum { /* Support for the Qbtrace-conf:bts:size packet. */ PACKET_Qbtrace_conf_bts_size, + /* Support for swbreak+ feature. */ + PACKET_swbreak_feature, + + /* Support for hwbreak+ feature. */ + PACKET_hwbreak_feature, + PACKET_MAX }; static struct packet_config remote_protocol_packets[PACKET_MAX]; +/* Returns the packet's corresponding "set remote foo-packet" command + state. See struct packet_config for more details. */ + +static enum auto_boolean +packet_set_cmd_state (int packet) +{ + return remote_protocol_packets[packet].detect; +} + /* Returns whether a given packet or feature is supported. This takes into account the state of the corresponding "set remote foo-packet" command, which may be used to bypass auto-detection. */ @@ -4025,7 +4040,9 @@ static const struct protocol_feature remote_protocol_features[] = { { "qXfer:btrace-conf:read", PACKET_DISABLE, remote_supported_packet, PACKET_qXfer_btrace_conf }, { "Qbtrace-conf:bts:size", PACKET_DISABLE, remote_supported_packet, - PACKET_Qbtrace_conf_bts_size } + PACKET_Qbtrace_conf_bts_size }, + { "swbreak", PACKET_DISABLE, remote_supported_packet, PACKET_swbreak_feature }, + { "hwbreak", PACKET_DISABLE, remote_supported_packet, PACKET_hwbreak_feature } }; static char *remote_support_xml; @@ -4094,6 +4111,11 @@ remote_query_supported (void) q = remote_query_supported_append (q, "multiprocess+"); + if (packet_set_cmd_state (PACKET_swbreak_feature) != AUTO_BOOLEAN_FALSE) + q = remote_query_supported_append (q, "swbreak+"); + if (packet_set_cmd_state (PACKET_hwbreak_feature) != AUTO_BOOLEAN_FALSE) + q = remote_query_supported_append (q, "hwbreak+"); + if (remote_support_xml) q = remote_query_supported_append (q, remote_support_xml); @@ -5202,7 +5224,8 @@ typedef struct stop_reply fetch them is avoided). */ VEC(cached_reg_t) *regcache; - int stopped_by_watchpoint_p; + enum target_stop_reason stop_reason; + CORE_ADDR watch_data_address; int core; @@ -5513,7 +5536,7 @@ remote_parse_stop_reply (char *buf, struct stop_reply *event) event->rs = get_remote_state (); event->ws.kind = TARGET_WAITKIND_IGNORE; event->ws.value.integer = 0; - event->stopped_by_watchpoint_p = 0; + event->stop_reason = TARGET_STOPPED_BY_NO_REASON; event->regcache = NULL; event->core = -1; @@ -5556,10 +5579,36 @@ Packet: '%s'\n"), || (strncmp (p, "rwatch", p1 - p) == 0) || (strncmp (p, "awatch", p1 - p) == 0)) { - event->stopped_by_watchpoint_p = 1; + event->stop_reason = TARGET_STOPPED_BY_WATCHPOINT; p = unpack_varlen_hex (++p1, &addr); event->watch_data_address = (CORE_ADDR) addr; } + else if (strncmp (p, "swbreak", p1 - p) == 0) + { + event->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; + + /* Make sure the stub doesn't forget to indicate support + with qSupported. */ + if (packet_support (PACKET_swbreak_feature) != PACKET_ENABLE) + error (_("Unexpected swbreak stop reason")); + + /* The value part is documented as "must be empty", + though we ignore it, in case we ever decide to make + use of it in a backward compatible way. */ + p = skip_to_semicolon (p1 + 1); + } + else if (strncmp (p, "hwbreak", p1 - p) == 0) + { + event->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; + + /* Make sure the stub doesn't forget to indicate support + with qSupported. */ + if (packet_support (PACKET_hwbreak_feature) != PACKET_ENABLE) + error (_("Unexpected hwbreak stop reason")); + + /* See above. */ + p = skip_to_semicolon (p1 + 1); + } else if (strncmp (p, "library", p1 - p) == 0) { event->ws.kind = TARGET_WAITKIND_LOADED; @@ -5817,7 +5866,7 @@ process_stop_reply (struct stop_reply *stop_reply, VEC_free (cached_reg_t, stop_reply->regcache); } - rs->remote_stopped_by_watchpoint_p = stop_reply->stopped_by_watchpoint_p; + rs->stop_reason = stop_reply->stop_reason; rs->remote_watch_data_address = stop_reply->watch_data_address; remote_notice_new_inferior (ptid, 0); @@ -5944,7 +5993,7 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options) buf = rs->buf; - rs->remote_stopped_by_watchpoint_p = 0; + rs->stop_reason = TARGET_STOPPED_BY_NO_REASON; /* We got something. */ rs->waiting_for_stop_reply = 0; @@ -8421,12 +8470,54 @@ remote_check_watch_resources (struct target_ops *self, return -1; } +/* The to_stopped_by_sw_breakpoint method of target remote. */ + +static int +remote_stopped_by_sw_breakpoint (struct target_ops *ops) +{ + struct remote_state *rs = get_remote_state (); + + return rs->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT; +} + +/* The to_supports_stopped_by_sw_breakpoint method of target + remote. */ + +static int +remote_supports_stopped_by_sw_breakpoint (struct target_ops *ops) +{ + struct remote_state *rs = get_remote_state (); + + return (packet_support (PACKET_swbreak_feature) == PACKET_ENABLE); +} + +/* The to_stopped_by_hw_breakpoint method of target remote. */ + +static int +remote_stopped_by_hw_breakpoint (struct target_ops *ops) +{ + struct remote_state *rs = get_remote_state (); + + return rs->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT; +} + +/* The to_supports_stopped_by_hw_breakpoint method of target + remote. */ + +static int +remote_supports_stopped_by_hw_breakpoint (struct target_ops *ops) +{ + struct remote_state *rs = get_remote_state (); + + return (packet_support (PACKET_hwbreak_feature) == PACKET_ENABLE); +} + static int remote_stopped_by_watchpoint (struct target_ops *ops) { struct remote_state *rs = get_remote_state (); - return rs->remote_stopped_by_watchpoint_p; + return rs->stop_reason == TARGET_STOPPED_BY_WATCHPOINT; } static int @@ -11617,6 +11708,10 @@ Specify the serial device it is connected to\n\ remote_ops.to_files_info = remote_files_info; remote_ops.to_insert_breakpoint = remote_insert_breakpoint; remote_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_ops.to_stopped_by_sw_breakpoint = remote_stopped_by_sw_breakpoint; + remote_ops.to_supports_stopped_by_sw_breakpoint = remote_supports_stopped_by_sw_breakpoint; + remote_ops.to_stopped_by_hw_breakpoint = remote_stopped_by_hw_breakpoint; + remote_ops.to_supports_stopped_by_hw_breakpoint = remote_supports_stopped_by_hw_breakpoint; remote_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint; remote_ops.to_stopped_data_address = remote_stopped_data_address; remote_ops.to_watchpoint_addr_within_range = @@ -12322,6 +12417,12 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_conf_bts_size], "Qbtrace-conf:bts:size", "btrace-conf-bts-size", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_swbreak_feature], + "swbreak-feature", "swbreak-feature", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_hwbreak_feature], + "hwbreak-feature", "hwbreak-feature", 0); + /* Assert that we've registered commands for all packet configs. */ { int i; |