From: Grace Sainsbury Date: Fri, 9 Aug 2002 16:41:25 +0000 (+0000) Subject: * remote.c: (remote_wait, remote_async_wait): Add check for awatch X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=3c3bea1c7eb9586fd6d80885c8a972e10401f3f1;p=deliverable%2Fbinutils-gdb.git * remote.c: (remote_wait, remote_async_wait): Add check for awatch T-packets; the 'a' is not taken as a register number. (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: From Mark Salter: * gdb.texinfo (Protocol): Document T packet extension to allow watchpoint address reporting. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 673a6291e3..659e8b041f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,24 @@ +2002-08-09 Grace Sainsbury + + * remote.c: (remote_wait, remote_async_wait): Add check for awatch + T-packets; the 'a' is not taken as a register number. + (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. + 2002-08-09 Corinna Vinschen * cli/cli-dump.c: Change fopen modes to use binary open modes @@ -22,9 +43,10 @@ 2002-08-08 Grace Sainsbury - * remote.c (remote_wait, remote_async_wait): Change thread_num - ULONGEST. - * (unpack_varlen_hex): Change result prameter to ULONGEST *. + * remote.c (remote_wait, remote_async_wait): Change + thread_num from int to ULONGEST. + (unpack_varlen_hex): Change result parameter from + int * to ULONGEST *. 2002-08-08 Andrew Cagney diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 384117a193..b9d82f0976 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,10 @@ +2002-08-08 Grace Sainsbury + + From Mark Salter: + * gdb.texinfo (Protocol): Document T packet extension to + allow watchpoint address reporting. + + 2002-08-03 Andrew Cagney * gdb.texinfo (Dump/Restore Files): Move `[]' to outside of @var. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index bd205626ed..dd5e7aa3c6 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -14751,10 +14751,11 @@ conventions is used. @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 diff --git a/gdb/remote.c b/gdb/remote.c index 6bda0842c8..0c3f23a527 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -250,6 +250,7 @@ struct remote_state long remote_packet_size; }; + /* Handle for retreving the remote protocol data from gdbarch. */ static struct gdbarch_data *remote_gdbarch_data_handle; @@ -340,7 +341,17 @@ packet_reg_from_pnum (struct remote_state *rs, LONGEST pnum) return NULL; } -/* */ +/* FIXME: graces/2002-08-08: These variables should eventually be + bound to an instance of the target object (as in gdbarch-tdep()), + when such a thing exists. */ + +/* 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; @@ -3008,6 +3019,7 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status) struct remote_state *rs = get_remote_state (); unsigned char *buf = alloca (rs->remote_packet_size); ULONGEST thread_num = -1; + ULONGEST addr; status->kind = TARGET_WAITKIND_EXITED; status->value.integer = 0; @@ -3025,6 +3037,8 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status) 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,24 +3062,52 @@ remote_wait (ptid_t ptid, struct target_waitstatus *status) unsigned char *p1; char *p_temp; int fieldsize; + LONGEST pnum = 0; + + /* If the packet contains a register number save it in pnum + and set p1 to point to the character following it. + Otherwise p1 points to p. */ - /* 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 (strncmp (p, "awatch", strlen("awatch")) != 0) + { + /* Read the ``P'' register number. */ + pnum = strtol (p, &p_temp, 16); + p1 = (unsigned char *) p_temp; + } + else + p1 = p; if (p1 == p) /* No register number present here */ { - p1 = (unsigned char *) strchr ((const char *) p, ':'); + p1 = (unsigned char *) strchr (p, ':'); if (p1 == NULL) warning ("Malformed packet(a) (missing colon): %s\n\ Packet: '%s'\n", p, buf); - if (strncmp ((const char *) p, "thread", p1 - p) == 0) + if (strncmp (p, "thread", p1 - p) == 0) { p_temp = unpack_varlen_hex (++p1, &thread_num); record_currthread (thread_num); p = (unsigned char *) p_temp; } + else if ((strncmp (p, "watch", p1 - p) == 0) + || (strncmp (p, "rwatch", p1 - p) == 0) + || (strncmp (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 = strchr (p1 + 1, ';'); + if (p_temp) + p = (unsigned char *) p_temp; + } } else { @@ -3222,10 +3264,13 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status) struct remote_state *rs = get_remote_state (); unsigned char *buf = alloca (rs->remote_packet_size); 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,25 +3313,54 @@ remote_async_wait (ptid_t ptid, struct target_waitstatus *status) 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 the packet contains a register number, save it in pnum + and set p1 to point to the character following it. + Otherwise p1 points to p. */ + + /* If this packet is an awatch packet, don't parse the 'a' + as a register number. */ + + if (!strncmp (p, "awatch", strlen ("awatch")) != 0) + { + /* Read the register number. */ + pnum = strtol (p, &p_temp, 16); + p1 = (unsigned char *) p_temp; + } + else + p1 = p; if (p1 == p) /* No register number present here */ { - p1 = (unsigned char *) strchr ((const char *) p, ':'); + p1 = (unsigned char *) strchr (p, ':'); if (p1 == NULL) warning ("Malformed packet(a) (missing colon): %s\n\ Packet: '%s'\n", p, buf); - if (strncmp ((const char *) p, "thread", p1 - p) == 0) + if (strncmp (p, "thread", p1 - p) == 0) { p_temp = unpack_varlen_hex (++p1, &thread_num); record_currthread (thread_num); p = (unsigned char *) p_temp; } + else if ((strncmp (p, "watch", p1 - p) == 0) + || (strncmp (p, "rwatch", p1 - p) == 0) + || (strncmp (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 (p1 + 1, ';'); + if (p_temp) + p = p_temp; + } } + else { struct packet_reg *reg = packet_reg_from_pnum (rs, pnum); @@ -4794,10 +4868,7 @@ watchpoint_to_Z_packet (int type) } } -/* 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 (); @@ -4831,10 +4902,8 @@ remote_insert_watchpoint (CORE_ADDR addr, int len, int type) "remote_insert_watchpoint: reached end of function"); } -/* 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 +4936,60 @@ remote_remove_watchpoint (CORE_ADDR addr, int len, int type) "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; 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; + /* The length field should be set to soething so that the packet is + well formed. */ + + 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 +5015,19 @@ remote_insert_hw_breakpoint (CORE_ADDR addr, int len) 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 +5053,7 @@ remote_remove_hw_breakpoint (CORE_ADDR addr, int len) 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 +5530,13 @@ 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_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 +5952,14 @@ Specify the serial device it is connected to (e.g. host:2020)."; 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 +6049,13 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; 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;