From patchwork Thu Feb 26 00:17:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 5297 Received: (qmail 13344 invoked by alias); 26 Feb 2015 00:40:36 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 13305 invoked by uid 89); 26 Feb 2015 00:40:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 26 Feb 2015 00:40:33 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t1Q0HcCx001986 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Wed, 25 Feb 2015 19:17:38 -0500 Received: from brno.lan (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t1Q0HXwG000814 for ; Wed, 25 Feb 2015 19:17:37 -0500 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 4/8] remote+docs: software/hardware breakpoint traps Date: Thu, 26 Feb 2015 00:17:28 +0000 Message-Id: <1424909852-25917-5-git-send-email-palves@redhat.com> In-Reply-To: <1424909852-25917-1-git-send-email-palves@redhat.com> References: <1424909852-25917-1-git-send-email-palves@redhat.com> 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-02-25 Pedro Alves * NEWS: Mention the new "swbreak" and "hwbreak" stop reasons. * remote.c (struct remote_state) : Delete field. : 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) : Delete field. : 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-02-25 Pedro Alves * gdb.texinfo (Remote Configuration): Document the "set/show remote swbreak-feature-packet" and "set/show remote hwbreak-feature-packet" commands. (Packets) : 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. --- gdb/NEWS | 10 +++++ gdb/doc/gdb.texinfo | 80 +++++++++++++++++++++++++++++++++++ gdb/remote.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 200 insertions(+), 9 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index b79b162..e70bea0 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -63,6 +63,16 @@ qXfer:btrace-conf:read Qbtrace-conf:bts:size Set the requested ring buffer size for branch tracing in BTS format. +swbreak stop reason + Indicates a memory breakpoint instruction was executed, irrespective + of whether it was GDB that planted the breakpoint or the breakpoint + is hardcoded in the program. This is required for correct non-stop + mode operation. + +hwbreak stop reason + Indicates the target stopped for a hardware breakpoint. This is + required for correct non-stop mode operation. + * The info record command now shows the recording format and the branch tracing configuration for the current thread when using the btrace record target. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index a9a8c66..7aaf6fa 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -19783,6 +19783,15 @@ are: @item @code{conditional-breakpoints-packet} @tab @code{Z0 and Z1} @tab @code{Support for target-side breakpoint condition evaluation} + +@item @code{swbreak-feature} +@tab @code{swbreak stop reason} +@tab @code{break} + +@item @code{hwbreak-feature} +@tab @code{hwbreak stop reason} +@tab @code{hbreak} + @end multitable @node Remote Stub @@ -34985,6 +34994,9 @@ form that should be evaluated on the target's side. These are the conditions that should be taken into consideration when deciding if the breakpoint trigger should be reported back to @var{GDBN}. +See also the @samp{swbreak} stop reason (@pxref{swbreak stop reason}) +for how to best report a memory breakpoint event to @value{GDBN}. + The @var{cond_list} parameter is comprised of a series of expressions, concatenated without separators. Each expression has the following form: @@ -35188,6 +35200,34 @@ logged execution events, because it has reached the end (or the beginning when executing backward) of the log. The value of @var{r} will be either @samp{begin} or @samp{end}. @xref{Reverse Execution}, for more information. + +@item swbreak +@anchor{swbreak stop reason} +The packet indicates a memory breakpoint instruction was executed, +irrespective of whether it was @value{GDBN} that planted the +breakpoint or the breakpoint is hardcoded in the program. The @var{r} +part must be left empty. + +On some architectures, such as x86, at the architecture level, when a +breakpoint instruction executes the program counter points at the +breakpoint address plus an offset. On such targets, the stub is +responsible for adjusting the PC to point back at the breakpoint +address. + +This packet should be not sent by default; older @value{GDBN} versions +did not support it. @value{GDBN} requests it, by supplying an +appropriate @samp{qSupported} feature (@pxref{qSupported}). The +remote stub must also supply the appropriate @samp{qSupported} feature +indicating support. + +This packet is required for correct non-stop mode operation. + +@item hwbreak +The packet indicates the target stopped for a hardware breakpoint. +The @var{r} part must be left empty. + +The same remarks about @samp{qSupported} and non-stop mode above +apply. @end table @item W @var{AA} @@ -35772,6 +35812,14 @@ description. This feature indicates whether @value{GDBN} supports the @samp{qRelocInsn} packet (@pxref{Tracepoint Packets,,Relocate instruction reply packet}). + +@item swbreak +This feature indicates whether @value{GDBN} supports the swbreak stop +reason in stop replies. See @xref{swbreak stop reason}, for details. + +@item hwbreak +This feature indicates whether @value{GDBN} supports the hwbreak stop +reason in stop replies. See @xref{swbreak stop reason}, for details. @end table Stubs should ignore any unknown values for @@ -36000,6 +36048,16 @@ These are the currently defined stub features and their properties: @tab @samp{-} @tab No +@item @samp{swbreak} +@tab No +@tab @samp{-} +@tab No + +@item @samp{hwbreak} +@tab No +@tab @samp{-} +@tab No + @end multitable These are the currently defined stub features, in more detail: @@ -36180,6 +36238,14 @@ The remote stub understands the @samp{Qbtrace:bts} packet. @item Qbtrace-conf:bts:size The remote stub understands the @samp{Qbtrace-conf:bts:size} packet. +@item swbreak +The remote stub reports the @samp{swbreak} stop reason for memory +breakpoints. + +@item hwbreak +The remote stub reports the @samp{hwbreak} stop reason for hardware +breakpoints. + @end table @item qSymbol:: @@ -37565,6 +37631,20 @@ If all threads are running when the target receives the @samp{?} packet, or if the target is not attached to any process, it shall respond @samp{OK}. +If the stub supports non-stop mode, it should also support the +@samp{swbreak} stop reason if software breakpoints are supported, and +the @samp{hwbreak} stop reason if software breakpoints are supported +(@pxref{swbreak stop reason}). This is because given the asynchronous +nature of non-stop mode, between the time a thread hits a breakpoint +and the time the event is finally processed by @value{GDBN}, the +breakpoint may have already been removed from the target. Due to +this, @value{GDBN} needs to be able to tell whether a trap stop was +caused by a delayed breakpoint event, which should be ignored, as +opposed to a random trap signal, which should be reported to the user. +Note the @samp{swbreak} feature implies that the target is responsible +for adjusting the PC when a software breakpoint triggers, if +necessary, such as on the x86 architecture. + @node Packet Acknowledgment @section Packet Acknowledgment diff --git a/gdb/remote.c b/gdb/remote.c index 3479140..ecfa1fb 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; @@ -8418,12 +8467,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 @@ -11614,6 +11705,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 = @@ -12319,6 +12414,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;