From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2316 invoked by alias); 8 Aug 2002 17:06:51 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 2304 invoked from network); 8 Aug 2002 17:06:49 -0000 Received: from unknown (HELO tomago.toronto.redhat.com) (216.138.202.10) by sources.redhat.com with SMTP; 8 Aug 2002 17:06:49 -0000 Received: (from graces@localhost) by tomago.toronto.redhat.com (8.11.6/8.11.6) id g78H6mS28248 for gdb-patches@sources.redhat.com; Thu, 8 Aug 2002 13:06:48 -0400 Date: Thu, 08 Aug 2002 10:06:00 -0000 From: Grace Sainsbury To: gdb-patches@sources.redhat.com Subject: Re: [rfa] hardware breakpoints -- remote targets Message-ID: <20020808130648.A27850@tomago.toronto.redhat.com> References: <20020806121916.A24815@tomago.toronto.redhat.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="OXfL5xGRrasGEqWY" Content-Disposition: inline User-Agent: Mutt/1.2.5.1i In-Reply-To: <20020806121916.A24815@tomago.toronto.redhat.com>; from graces@redhat.com on Tue, Aug 06, 2002 at 12:19:16PM -0400 X-SW-Source: 2002-08/txt/msg00186.txt.bz2 --OXfL5xGRrasGEqWY Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 1369 I revised the patch to include Mark Salter's earlier patch, as well as his documentation changes. ok to commit? grace Changelog: 2002-08-08 Grace Sainsbury * remote.c: (remote_wait, remote_async_wait): Add check for awatch T-packets; the 'a' is not taken as a register number. (set_hardware_watchpoint_limit, show_hardware_watchpoint_limit) (set_hardware_breakpoint_limit, show_hardware_breakpoint_limit): New functions. Add commands to call them. (remote_check_watch_resources, remote_stopped_by_watchpoint) (remote_stopped_data_address): New functions; add to target vector. (remote_insert_hw_breakpoint, remote_remove_hw_breakpoint): Change prototypes to match other implementations of this function. replace integer argument with pointer -- the length field in the Z-packet is the length of what is pointed to or 1 if pointer is null. Add to target vector. (remote_insert_watchpoint, remote_remove_watchpoint): Add to target vector. From Mark Salter: * remote.c (remote_wait): Add support to extract optional watchpoint information from T-packet. Ignore unrecognized optional info in T-packet. (remote_async_wait): Ditto. doc/Changelog: 2002-08-08 Grace Sainsbury From Mark Salter: * gdb.texinfo (Protocol): Document T packet extension to allow watchpoint address reporting. --OXfL5xGRrasGEqWY Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="watch2.patch" Content-length: 13842 Index: remote.c =================================================================== RCS file: /cvs/src/src/gdb/remote.c,v retrieving revision 1.89 diff -u -r1.89 remote.c --- remote.c 23 Jul 2002 18:55:06 -0000 1.89 +++ remote.c 8 Aug 2002 17:02:27 -0000 @@ -250,6 +250,7 @@ long remote_packet_size; }; + /* Handle for retreving the remote protocol data from gdbarch. */ static struct gdbarch_data *remote_gdbarch_data_handle; @@ -342,6 +343,14 @@ /* */ +/* This is set to the data address of the access causing the target + * to stop for a watchpoint. */ +static CORE_ADDR remote_watch_data_address; + +/* This is non-zero if taregt stopped for a watchpoint. */ +static int remote_stopped_by_watchpoint_p; + + static struct target_ops remote_ops; static struct target_ops extended_remote_ops; @@ -1107,7 +1116,7 @@ #define BUF_THREAD_ID_SIZE (OPAQUETHREADBYTES*2) -char *unpack_varlen_hex (char *buff, int *result); +char *unpack_varlen_hex (char *buff, ULONGEST *result); static char *unpack_nibble (char *buf, int *val); @@ -1228,7 +1237,7 @@ char * unpack_varlen_hex (char *buff, /* packet to parse */ - int *result) + ULONGEST *result) { int nibble; int retval = 0; @@ -3007,7 +3016,8 @@ { struct remote_state *rs = get_remote_state (); unsigned char *buf = alloca (rs->remote_packet_size); - int thread_num = -1; + ULONGEST thread_num = -1; + ULONGEST addr; status->kind = TARGET_WAITKIND_EXITED; status->value.integer = 0; @@ -3025,6 +3035,8 @@ if (target_wait_loop_hook) (*target_wait_loop_hook) (); + remote_stopped_by_watchpoint_p = 0; + switch (buf[0]) { case 'E': /* Error of some sort */ @@ -3048,10 +3060,19 @@ unsigned char *p1; char *p_temp; int fieldsize; + LONGEST pnum = 0; - /* Read the ``P'' register number. */ - LONGEST pnum = strtol ((const char *) p, &p_temp, 16); - p1 = (unsigned char *) p_temp; + /* If this packet is an awatch packet, don't parse the 'a' + as a register number. */ + + if (!strstr ((const char *) p, "awatch")) + { + /* Read the ``P'' register number. */ + pnum = strtol ((const char *) p, &p_temp, 16); + p1 = (unsigned char *) p_temp; + } + else + p1=p; if (p1 == p) /* No register number present here */ { @@ -3066,6 +3087,21 @@ record_currthread (thread_num); p = (unsigned char *) p_temp; } + else if ((strncmp ((const char *) p, "watch", p1 - p) == 0) + || (strncmp ((const char *) p, "rwatch", p1 - p) == 0) + || (strncmp ((const char *) p, "awatch", p1 - p) == 0)) + { + remote_stopped_by_watchpoint_p = 1; + p = unpack_varlen_hex (++p1, &addr); + remote_watch_data_address = (CORE_ADDR)addr; + } + else + { + /* silently skip unknown optional info */ + p_temp = (unsigned char *) strchr ((const char *) p1+1, ';'); + if (p_temp) + p = p_temp; + } } else { @@ -3221,11 +3257,14 @@ { struct remote_state *rs = get_remote_state (); unsigned char *buf = alloca (rs->remote_packet_size); - int thread_num = -1; + ULONGEST thread_num = -1; + ULONGEST addr; status->kind = TARGET_WAITKIND_EXITED; status->value.integer = 0; + remote_stopped_by_watchpoint_p = 0; + while (1) { unsigned char *p; @@ -3268,10 +3307,19 @@ unsigned char *p1; char *p_temp; int fieldsize; + long pnum = 0; - /* Read the register number */ - long pnum = strtol ((const char *) p, &p_temp, 16); - p1 = (unsigned char *) p_temp; + /* If this packet is an awatch packet, don't parse the 'a' + as a register number. */ + + if (!strstr ((const char *) p, "awatch")) + { + /* Read the register number. */ + pnum = strtol ((const char *) p, &p_temp, 16); + p1 = (unsigned char *) p_temp; + } + else + p1=p; if (p1 == p) /* No register number present here */ { @@ -3286,7 +3334,23 @@ record_currthread (thread_num); p = (unsigned char *) p_temp; } + else if ((strncmp ((const char *) p, "watch", p1 - p) == 0) + || (strncmp ((const char *) p, "rwatch", p1 - p) == 0) + || (strncmp ((const char *) p, "awatch", p1 - p) == 0)) + { + remote_stopped_by_watchpoint_p = 1; + p = unpack_varlen_hex (++p1, &addr); + remote_watch_data_address = (CORE_ADDR)addr; + } + else + { + /* silently skip unknown optional info */ + p_temp = (unsigned char *) strchr ((const char *) p1+1, ';'); + if (p_temp) + p = p_temp; + } } + else { struct packet_reg *reg = packet_reg_from_pnum (rs, pnum); @@ -4797,7 +4861,7 @@ /* FIXME: This function should be static and a member of the remote target vector. */ -int +static int remote_insert_watchpoint (CORE_ADDR addr, int len, int type) { struct remote_state *rs = get_remote_state (); @@ -4834,7 +4898,7 @@ /* FIXME: This function should be static and a member of the remote target vector. */ -int +static int remote_remove_watchpoint (CORE_ADDR addr, int len, int type) { struct remote_state *rs = get_remote_state (); @@ -4867,16 +4931,109 @@ "remote_remove_watchpoint: reached end of function"); } -/* FIXME: This function should be static and a member of the remote - target vector. */ + +int remote_hw_watchpoint_limit = 0; +int remote_hw_breakpoint_limit = 0; + + +static void +set_hardware_watchpoint_limit (char *args, int from_tty) +{ + if (args) + { + char *arg_end; + int val = strtoul (args, &arg_end, 10); + if (*args && *arg_end == '\0') + { + remote_hw_watchpoint_limit = val; + return; + } + } + error ("Illegal argument for \"set remote hardware-watchpoint-limit\" command"); +} + +static void +show_hardware_watchpoint_limit (char *args, int from_tty) +{ + if (args) + error ("Garbage after \"show remote hardware-watchpoint-limit\" command: `%s'", args); + printf_unfiltered ("Remote target supports %d hardware watchpoints.\n", + remote_hw_watchpoint_limit); +} + +static void +set_hardware_breakpoint_limit (char *args, int from_tty) +{ + if (args) + { + char *arg_end; + int val = strtoul (args, &arg_end, 10); + if (*args && *arg_end == '\0') + { + remote_hw_breakpoint_limit = val; + return; + } + } + error ("Illegal argument for \"set remote hardware-breakpoint-limit\" command"); +} + +static void +show_hardware_breakpoint_limit (char *args, int from_tty) +{ + if (args) + error ("Garbage after \"show remote hardware-breakpoint-limit\" command: `%s'", args); + printf_unfiltered ("Remote target supports %d hardware breakpoints.\n", + remote_hw_breakpoint_limit); +} + int -remote_insert_hw_breakpoint (CORE_ADDR addr, int len) +remote_check_watch_resources (int type, int cnt, int ot) { + if (type == bp_hardware_breakpoint) + { + if (remote_hw_breakpoint_limit == 0) + return 0; + else if (cnt <= remote_hw_breakpoint_limit) + return 1; + } + else + { + if (remote_hw_watchpoint_limit == 0) + return 0; + else if (ot) + return -1; + else if (cnt <= remote_hw_watchpoint_limit) + return 1; + } + return -1; +} + +int +remote_stopped_by_watchpoint (void) +{ + return remote_stopped_by_watchpoint_p; +} + +CORE_ADDR +remote_stopped_data_address (void) +{ + if (remote_stopped_by_watchpoint ()) + return remote_watch_data_address; + return (CORE_ADDR)0; +} + + +static int +remote_insert_hw_breakpoint (CORE_ADDR addr, char *shadow) +{ + int len=0; struct remote_state *rs = get_remote_state (); char *buf = alloca (rs->remote_packet_size); char *p = buf; + len = strlen (shadow); + len = len ? len : 1; if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE) error ("Can't set hardware breakpoint without the '%s' (%s) packet\n", remote_protocol_Z[Z_PACKET_HARDWARE_BP].name, @@ -4902,19 +5059,19 @@ return 0; } internal_error (__FILE__, __LINE__, - "remote_remove_watchpoint: reached end of function"); + "remote_insert_hw_breakpoint: reached end of function"); } -/* FIXME: This function should be static and a member of the remote - target vector. */ -int -remote_remove_hw_breakpoint (CORE_ADDR addr, int len) +static int +remote_remove_hw_breakpoint (CORE_ADDR addr, char * shadow) { + int len; struct remote_state *rs = get_remote_state (); char *buf = alloca (rs->remote_packet_size); char *p = buf; + len = sizeof (shadow); if (remote_protocol_Z[Z_PACKET_HARDWARE_BP].support == PACKET_DISABLE) error ("Can't clear hardware breakpoint without the '%s' (%s) packet\n", remote_protocol_Z[Z_PACKET_HARDWARE_BP].name, @@ -4940,7 +5097,7 @@ return 0; } internal_error (__FILE__, __LINE__, - "remote_remove_watchpoint: reached end of function"); + "remote_remove_hw_breakpoint: reached end of function"); } /* Some targets are only capable of doing downloads, and afterwards @@ -5417,6 +5574,13 @@ 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_watchpoint = remote_stopped_by_watchpoint; + remote_ops.to_stopped_data_address = remote_stopped_data_address; + remote_ops.to_can_use_hw_breakpoint = remote_check_watch_resources; + remote_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint; + remote_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint; + remote_ops.to_insert_watchpoint = remote_insert_watchpoint; + remote_ops.to_remove_watchpoint = remote_remove_watchpoint; remote_ops.to_kill = remote_kill; remote_ops.to_load = generic_load; remote_ops.to_mourn_inferior = remote_mourn; @@ -5832,7 +5996,14 @@ remote_cisco_ops.to_xfer_memory = remote_xfer_memory; remote_cisco_ops.to_files_info = remote_files_info; remote_cisco_ops.to_insert_breakpoint = remote_insert_breakpoint; - remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_cisco_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_cisco_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint; + remote_cisco_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint; + remote_cisco_ops.to_insert_watchpoint = remote_insert_watchpoint; + remote_cisco_ops.to_remove_watchpoint = remote_remove_watchpoint; + remote_cisco_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint; + remote_cisco_ops.to_stopped_data_address = remote_stopped_data_address; + remote_cisco_ops.to_can_use_hw_breakpoint = remote_check_watch_resources; remote_cisco_ops.to_kill = remote_kill; remote_cisco_ops.to_load = generic_load; remote_cisco_ops.to_mourn_inferior = remote_cisco_mourn; @@ -5922,6 +6093,13 @@ remote_async_ops.to_files_info = remote_files_info; remote_async_ops.to_insert_breakpoint = remote_insert_breakpoint; remote_async_ops.to_remove_breakpoint = remote_remove_breakpoint; + remote_async_ops.to_can_use_hw_breakpoint = remote_check_watch_resources; + remote_async_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint; + remote_async_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint; + remote_async_ops.to_insert_watchpoint = remote_insert_watchpoint; + remote_async_ops.to_remove_watchpoint = remote_remove_watchpoint; + remote_async_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint; + remote_async_ops.to_stopped_data_address = remote_stopped_data_address; remote_async_ops.to_terminal_inferior = remote_async_terminal_inferior; remote_async_ops.to_terminal_ours = remote_async_terminal_ours; remote_async_ops.to_kill = remote_async_kill; @@ -6114,6 +6292,22 @@ add_cmd ("memory-read-packet-size", no_class, show_memory_read_packet_size, "Show the maximum number of bytes per memory-read packet.\n", + &remote_show_cmdlist); + add_cmd ("hardware-watchpoint-limit", no_class, + set_hardware_watchpoint_limit, + "Set the maximum number of target hardware watchpoints.\n", + &remote_set_cmdlist); + add_cmd ("hardware-watchpoint-limit", no_class, + show_hardware_watchpoint_limit, + "Show the maximum number of target hardware watchpoints.\n", + &remote_show_cmdlist); + add_cmd ("hardware-breakpoint-limit", no_class, + set_hardware_breakpoint_limit, + "Set the maximum number of target hardware breakpoints.\n", + &remote_set_cmdlist); + add_cmd ("hardware-breakpoint-limit", no_class, + show_hardware_breakpoint_limit, + "Show the maximum number of target hardware breakpoints.\n", &remote_show_cmdlist); add_show_from_set Index: doc/gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.107 diff -u -r1.107 gdb.texinfo --- doc/gdb.texinfo 3 Aug 2002 23:37:07 -0000 1.107 +++ doc/gdb.texinfo 8 Aug 2002 17:02:33 -0000 @@ -14751,10 +14751,11 @@ @var{AA} = two hex digit signal number; @var{n...} = register number (hex), @var{r...} = target byte ordered register contents, size defined by @code{REGISTER_RAW_SIZE}; @var{n...} = @samp{thread}, @var{r...} = -thread process ID, this is a hex integer; @var{n...} = other string not -starting with valid hex digit. @value{GDBN} should ignore this -@var{n...}, @var{r...} pair and go on to the next. This way we can -extend the protocol. +thread process ID, this is a hex integer; @var{n...} = (@samp{watch} | +@samp{rwatch} | @samp{awatch}, @var{r...} = data address, this is a hex +integer; @var{n...} = other string not starting with valid hex digit. +@value{GDBN} should ignore this @var{n...}, @var{r...} pair and go on +to the next. This way we can extend the protocol. @item @code{W}@var{AA} @tab --OXfL5xGRrasGEqWY--