+ return remote_write_bytes_aux (packet_format,
+ memaddr, myaddr, len, packet_format[0], 1);
+}
+
+/* Read memory data directly from the remote machine.
+ This does not use the data cache; the data cache uses this.
+ MEMADDR is the address in the remote memory space.
+ MYADDR is the address of the buffer in our space.
+ LEN is the number of bytes.
+
+ Returns number of bytes transferred, or 0 for error. */
+
+static int
+remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+{
+ struct remote_state *rs = get_remote_state ();
+ int max_buf_size; /* Max size of packet output buffer. */
+ char *p;
+ int todo;
+ int i;
+
+ if (len <= 0)
+ return 0;
+
+ max_buf_size = get_memory_read_packet_size ();
+ /* The packet buffer will be large enough for the payload;
+ get_memory_packet_size ensures this. */
+
+ /* Number if bytes that will fit. */
+ todo = min (len, max_buf_size / 2);
+
+ /* Construct "m"<memaddr>","<len>". */
+ memaddr = remote_address_masked (memaddr);
+ p = rs->buf;
+ *p++ = 'm';
+ p += hexnumstr (p, (ULONGEST) memaddr);
+ *p++ = ',';
+ p += hexnumstr (p, (ULONGEST) todo);
+ *p = '\0';
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ if (rs->buf[0] == 'E'
+ && isxdigit (rs->buf[1]) && isxdigit (rs->buf[2])
+ && rs->buf[3] == '\0')
+ {
+ /* There is no correspondance between what the remote protocol
+ uses for errors and errno codes. We would like a cleaner way
+ of representing errors (big enough to include errno codes,
+ bfd_error codes, and others). But for now just return
+ EIO. */
+ errno = EIO;
+ return 0;
+ }
+ /* Reply describes memory byte by byte, each byte encoded as two hex
+ characters. */
+ p = rs->buf;
+ i = hex2bin (p, myaddr, todo);
+ /* Return what we have. Let higher layers handle partial reads. */
+ return i;
+}
+\f
+
+/* Remote notification handler. */
+
+static void
+handle_notification (char *buf, size_t length)
+{
+ if (strncmp (buf, "Stop:", 5) == 0)
+ {
+ if (pending_stop_reply)
+ {
+ /* We've already parsed the in-flight stop-reply, but the
+ stub for some reason thought we didn't, possibly due to
+ timeout on its side. Just ignore it. */
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stdlog, "ignoring resent notification\n");
+ }
+ else
+ {
+ struct cleanup *old_chain;
+ struct stop_reply *reply = stop_reply_xmalloc ();
+
+ old_chain = make_cleanup (do_stop_reply_xfree, reply);
+
+ remote_parse_stop_reply (buf + 5, reply);
+
+ discard_cleanups (old_chain);
+
+ /* Be careful to only set it after parsing, since an error
+ may be thrown then. */
+ pending_stop_reply = reply;
+
+ /* Notify the event loop there's a stop reply to acknowledge
+ and that there may be more events to fetch. */
+ mark_async_event_handler (remote_async_get_pending_events_token);
+
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stdlog, "stop notification captured\n");
+ }
+ }
+ else
+ /* We ignore notifications we don't recognize, for compatibility
+ with newer stubs. */
+ ;
+}
+
+\f
+/* Read or write LEN bytes from inferior memory at MEMADDR,
+ transferring to or from debugger address BUFFER. Write to inferior
+ if SHOULD_WRITE is nonzero. Returns length of data written or
+ read; 0 for error. TARGET is unused. */
+
+static int
+remote_xfer_memory (CORE_ADDR mem_addr, gdb_byte *buffer, int mem_len,
+ int should_write, struct mem_attrib *attrib,
+ struct target_ops *target)
+{
+ int res;
+
+ set_remote_traceframe ();
+ set_general_thread (inferior_ptid);
+
+ if (should_write)
+ res = remote_write_bytes (mem_addr, buffer, mem_len);
+ else
+ res = remote_read_bytes (mem_addr, buffer, mem_len);
+
+ return res;
+}
+
+/* Sends a packet with content determined by the printf format string
+ FORMAT and the remaining arguments, then gets the reply. Returns
+ whether the packet was a success, a failure, or unknown. */
+
+static enum packet_result
+remote_send_printf (const char *format, ...)
+{
+ struct remote_state *rs = get_remote_state ();
+ int max_size = get_remote_packet_size ();
+ va_list ap;
+
+ va_start (ap, format);
+
+ rs->buf[0] = '\0';
+ if (vsnprintf (rs->buf, max_size, format, ap) >= max_size)
+ internal_error (__FILE__, __LINE__, _("Too long remote packet."));
+
+ if (putpkt (rs->buf) < 0)
+ error (_("Communication problem with target."));
+
+ rs->buf[0] = '\0';
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ return packet_check_result (rs->buf);
+}
+
+static void
+restore_remote_timeout (void *p)
+{
+ int value = *(int *)p;
+
+ remote_timeout = value;
+}
+
+/* Flash writing can take quite some time. We'll set
+ effectively infinite timeout for flash operations.
+ In future, we'll need to decide on a better approach. */
+static const int remote_flash_timeout = 1000;
+
+static void
+remote_flash_erase (struct target_ops *ops,
+ ULONGEST address, LONGEST length)
+{
+ int addr_size = gdbarch_addr_bit (target_gdbarch) / 8;
+ int saved_remote_timeout = remote_timeout;
+ enum packet_result ret;
+ struct cleanup *back_to = make_cleanup (restore_remote_timeout,
+ &saved_remote_timeout);
+
+ remote_timeout = remote_flash_timeout;
+
+ ret = remote_send_printf ("vFlashErase:%s,%s",
+ phex (address, addr_size),
+ phex (length, 4));
+ switch (ret)
+ {
+ case PACKET_UNKNOWN:
+ error (_("Remote target does not support flash erase"));
+ case PACKET_ERROR:
+ error (_("Error erasing flash with vFlashErase packet"));
+ default:
+ break;
+ }
+
+ do_cleanups (back_to);
+}
+
+static LONGEST
+remote_flash_write (struct target_ops *ops,
+ ULONGEST address, LONGEST length,
+ const gdb_byte *data)
+{
+ int saved_remote_timeout = remote_timeout;
+ int ret;
+ struct cleanup *back_to = make_cleanup (restore_remote_timeout,
+ &saved_remote_timeout);
+
+ remote_timeout = remote_flash_timeout;
+ ret = remote_write_bytes_aux ("vFlashWrite:", address, data, length, 'X', 0);
+ do_cleanups (back_to);
+
+ return ret;
+}
+
+static void
+remote_flash_done (struct target_ops *ops)
+{
+ int saved_remote_timeout = remote_timeout;
+ int ret;
+ struct cleanup *back_to = make_cleanup (restore_remote_timeout,
+ &saved_remote_timeout);
+
+ remote_timeout = remote_flash_timeout;
+ ret = remote_send_printf ("vFlashDone");
+ do_cleanups (back_to);
+
+ switch (ret)
+ {
+ case PACKET_UNKNOWN:
+ error (_("Remote target does not support vFlashDone"));
+ case PACKET_ERROR:
+ error (_("Error finishing flash operation"));
+ default:
+ break;
+ }
+}
+
+static void
+remote_files_info (struct target_ops *ignore)
+{
+ puts_filtered ("Debugging a target over a serial line.\n");
+}
+\f
+/* Stuff for dealing with the packets which are part of this protocol.
+ See comment at top of file for details. */
+
+/* Read a single character from the remote end. */
+
+static int
+readchar (int timeout)
+{
+ int ch;
+
+ ch = serial_readchar (remote_desc, timeout);
+
+ if (ch >= 0)
+ return ch;
+
+ switch ((enum serial_rc) ch)
+ {
+ case SERIAL_EOF:
+ pop_target ();
+ error (_("Remote connection closed"));
+ /* no return */
+ case SERIAL_ERROR:
+ pop_target ();
+ perror_with_name (_("Remote communication error. "
+ "Target disconnected."));
+ /* no return */
+ case SERIAL_TIMEOUT:
+ break;
+ }
+ return ch;
+}
+
+/* Send the command in *BUF to the remote machine, and read the reply
+ into *BUF. Report an error if we get an error reply. Resize
+ *BUF using xrealloc if necessary to hold the result, and update
+ *SIZEOF_BUF. */
+
+static void
+remote_send (char **buf,
+ long *sizeof_buf)
+{
+ putpkt (*buf);
+ getpkt (buf, sizeof_buf, 0);
+
+ if ((*buf)[0] == 'E')
+ error (_("Remote failure reply: %s"), *buf);
+}
+
+/* Return a pointer to an xmalloc'ed string representing an escaped
+ version of BUF, of len N. E.g. \n is converted to \\n, \t to \\t,
+ etc. The caller is responsible for releasing the returned
+ memory. */
+
+static char *
+escape_buffer (const char *buf, int n)
+{
+ struct cleanup *old_chain;
+ struct ui_file *stb;
+ char *str;
+
+ stb = mem_fileopen ();
+ old_chain = make_cleanup_ui_file_delete (stb);
+
+ fputstrn_unfiltered (buf, n, 0, stb);
+ str = ui_file_xstrdup (stb, NULL);
+ do_cleanups (old_chain);
+ return str;
+}
+
+/* Display a null-terminated packet on stdout, for debugging, using C
+ string notation. */
+
+static void
+print_packet (char *buf)
+{
+ puts_filtered ("\"");
+ fputstr_filtered (buf, '"', gdb_stdout);
+ puts_filtered ("\"");
+}
+
+int
+putpkt (char *buf)
+{
+ return putpkt_binary (buf, strlen (buf));
+}
+
+/* Send a packet to the remote machine, with error checking. The data
+ of the packet is in BUF. The string in BUF can be at most
+ get_remote_packet_size () - 5 to account for the $, # and checksum,
+ and for a possible /0 if we are debugging (remote_debug) and want
+ to print the sent packet as a string. */
+
+static int
+putpkt_binary (char *buf, int cnt)
+{
+ struct remote_state *rs = get_remote_state ();
+ int i;
+ unsigned char csum = 0;
+ char *buf2 = alloca (cnt + 6);
+
+ int ch;
+ int tcount = 0;
+ char *p;
+
+ /* Catch cases like trying to read memory or listing threads while
+ we're waiting for a stop reply. The remote server wouldn't be
+ ready to handle this request, so we'd hang and timeout. We don't
+ have to worry about this in synchronous mode, because in that
+ case it's not possible to issue a command while the target is
+ running. This is not a problem in non-stop mode, because in that
+ case, the stub is always ready to process serial input. */
+ if (!non_stop && target_can_async_p () && rs->waiting_for_stop_reply)
+ error (_("Cannot execute this command while the target is running."));
+
+ /* We're sending out a new packet. Make sure we don't look at a
+ stale cached response. */
+ rs->cached_wait_status = 0;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ p = buf2;
+ *p++ = '$';
+
+ for (i = 0; i < cnt; i++)
+ {
+ csum += buf[i];
+ *p++ = buf[i];
+ }
+ *p++ = '#';
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+
+ /* Send it over and over until we get a positive ack. */
+
+ while (1)
+ {
+ int started_error_output = 0;
+
+ if (remote_debug)
+ {
+ struct cleanup *old_chain;
+ char *str;
+
+ *p = '\0';
+ str = escape_buffer (buf2, p - buf2);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog, "Sending packet: %s...", str);
+ gdb_flush (gdb_stdlog);
+ do_cleanups (old_chain);
+ }
+ if (serial_write (remote_desc, buf2, p - buf2))
+ perror_with_name (_("putpkt: write failed"));
+
+ /* If this is a no acks version of the remote protocol, send the
+ packet and move on. */
+ if (rs->noack_mode)
+ break;
+
+ /* Read until either a timeout occurs (-2) or '+' is read.
+ Handle any notification that arrives in the mean time. */
+ while (1)
+ {
+ ch = readchar (remote_timeout);
+
+ if (remote_debug)
+ {
+ switch (ch)
+ {
+ case '+':
+ case '-':
+ case SERIAL_TIMEOUT:
+ case '$':
+ case '%':
+ if (started_error_output)
+ {
+ putchar_unfiltered ('\n');
+ started_error_output = 0;
+ }
+ }
+ }
+
+ switch (ch)
+ {
+ case '+':
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stdlog, "Ack\n");
+ return 1;
+ case '-':
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stdlog, "Nak\n");
+ /* FALLTHROUGH */
+ case SERIAL_TIMEOUT:
+ tcount++;
+ if (tcount > 3)
+ return 0;
+ break; /* Retransmit buffer. */
+ case '$':
+ {
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "Packet instead of Ack, ignoring it\n");
+ /* It's probably an old response sent because an ACK
+ was lost. Gobble up the packet and ack it so it
+ doesn't get retransmitted when we resend this
+ packet. */
+ skip_frame ();
+ serial_write (remote_desc, "+", 1);
+ continue; /* Now, go look for +. */
+ }
+
+ case '%':
+ {
+ int val;
+
+ /* If we got a notification, handle it, and go back to looking
+ for an ack. */
+ /* We've found the start of a notification. Now
+ collect the data. */
+ val = read_frame (&rs->buf, &rs->buf_size);
+ if (val >= 0)
+ {
+ if (remote_debug)
+ {
+ struct cleanup *old_chain;
+ char *str;
+
+ str = escape_buffer (rs->buf, val);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog,
+ " Notification received: %s\n",
+ str);
+ do_cleanups (old_chain);
+ }
+ handle_notification (rs->buf, val);
+ /* We're in sync now, rewait for the ack. */
+ tcount = 0;
+ }
+ else
+ {
+ if (remote_debug)
+ {
+ if (!started_error_output)
+ {
+ started_error_output = 1;
+ fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: ");
+ }
+ fputc_unfiltered (ch & 0177, gdb_stdlog);
+ fprintf_unfiltered (gdb_stdlog, "%s", rs->buf);
+ }
+ }
+ continue;
+ }
+ /* fall-through */
+ default:
+ if (remote_debug)
+ {
+ if (!started_error_output)
+ {
+ started_error_output = 1;
+ fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: ");
+ }
+ fputc_unfiltered (ch & 0177, gdb_stdlog);
+ }
+ continue;
+ }
+ break; /* Here to retransmit. */
+ }
+
+#if 0
+ /* This is wrong. If doing a long backtrace, the user should be
+ able to get out next time we call QUIT, without anything as
+ violent as interrupt_query. If we want to provide a way out of
+ here without getting to the next QUIT, it should be based on
+ hitting ^C twice as in remote_wait. */
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ interrupt_query ();
+ }
+#endif
+ }
+ return 0;
+}
+
+/* Come here after finding the start of a frame when we expected an
+ ack. Do our best to discard the rest of this packet. */
+
+static void
+skip_frame (void)
+{
+ int c;
+
+ while (1)
+ {
+ c = readchar (remote_timeout);
+ switch (c)
+ {
+ case SERIAL_TIMEOUT:
+ /* Nothing we can do. */
+ return;
+ case '#':
+ /* Discard the two bytes of checksum and stop. */
+ c = readchar (remote_timeout);
+ if (c >= 0)
+ c = readchar (remote_timeout);
+
+ return;
+ case '*': /* Run length encoding. */
+ /* Discard the repeat count. */
+ c = readchar (remote_timeout);
+ if (c < 0)
+ return;
+ break;
+ default:
+ /* A regular character. */
+ break;
+ }
+ }
+}
+
+/* Come here after finding the start of the frame. Collect the rest
+ into *BUF, verifying the checksum, length, and handling run-length
+ compression. NUL terminate the buffer. If there is not enough room,
+ expand *BUF using xrealloc.
+
+ Returns -1 on error, number of characters in buffer (ignoring the
+ trailing NULL) on success. (could be extended to return one of the
+ SERIAL status indications). */
+
+static long
+read_frame (char **buf_p,
+ long *sizeof_buf)
+{
+ unsigned char csum;
+ long bc;
+ int c;
+ char *buf = *buf_p;
+ struct remote_state *rs = get_remote_state ();
+
+ csum = 0;
+ bc = 0;
+
+ while (1)
+ {
+ c = readchar (remote_timeout);
+ switch (c)
+ {
+ case SERIAL_TIMEOUT:
+ if (remote_debug)
+ fputs_filtered ("Timeout in mid-packet, retrying\n", gdb_stdlog);
+ return -1;
+ case '$':
+ if (remote_debug)
+ fputs_filtered ("Saw new packet start in middle of old one\n",
+ gdb_stdlog);
+ return -1; /* Start a new packet, count retries. */
+ case '#':
+ {
+ unsigned char pktcsum;
+ int check_0 = 0;
+ int check_1 = 0;
+
+ buf[bc] = '\0';
+
+ check_0 = readchar (remote_timeout);
+ if (check_0 >= 0)
+ check_1 = readchar (remote_timeout);
+
+ if (check_0 == SERIAL_TIMEOUT || check_1 == SERIAL_TIMEOUT)
+ {
+ if (remote_debug)
+ fputs_filtered ("Timeout in checksum, retrying\n",
+ gdb_stdlog);
+ return -1;
+ }
+ else if (check_0 < 0 || check_1 < 0)
+ {
+ if (remote_debug)
+ fputs_filtered ("Communication error in checksum\n",
+ gdb_stdlog);
+ return -1;
+ }
+
+ /* Don't recompute the checksum; with no ack packets we
+ don't have any way to indicate a packet retransmission
+ is necessary. */
+ if (rs->noack_mode)
+ return bc;
+
+ pktcsum = (fromhex (check_0) << 4) | fromhex (check_1);
+ if (csum == pktcsum)
+ return bc;
+
+ if (remote_debug)
+ {
+ struct cleanup *old_chain;
+ char *str;
+
+ str = escape_buffer (buf, bc);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog,
+ "Bad checksum, sentsum=0x%x, "
+ "csum=0x%x, buf=%s\n",
+ pktcsum, csum, str);
+ do_cleanups (old_chain);
+ }
+ /* Number of characters in buffer ignoring trailing
+ NULL. */
+ return -1;
+ }
+ case '*': /* Run length encoding. */
+ {
+ int repeat;
+
+ csum += c;
+ c = readchar (remote_timeout);
+ csum += c;
+ repeat = c - ' ' + 3; /* Compute repeat count. */
+
+ /* The character before ``*'' is repeated. */
+
+ if (repeat > 0 && repeat <= 255 && bc > 0)
+ {
+ if (bc + repeat - 1 >= *sizeof_buf - 1)
+ {
+ /* Make some more room in the buffer. */
+ *sizeof_buf += repeat;
+ *buf_p = xrealloc (*buf_p, *sizeof_buf);
+ buf = *buf_p;
+ }
+
+ memset (&buf[bc], buf[bc - 1], repeat);
+ bc += repeat;
+ continue;
+ }
+
+ buf[bc] = '\0';
+ printf_filtered (_("Invalid run length encoding: %s\n"), buf);
+ return -1;
+ }
+ default:
+ if (bc >= *sizeof_buf - 1)
+ {
+ /* Make some more room in the buffer. */
+ *sizeof_buf *= 2;
+ *buf_p = xrealloc (*buf_p, *sizeof_buf);
+ buf = *buf_p;
+ }
+
+ buf[bc++] = c;
+ csum += c;
+ continue;
+ }
+ }
+}
+
+/* Read a packet from the remote machine, with error checking, and
+ store it in *BUF. Resize *BUF using xrealloc if necessary to hold
+ the result, and update *SIZEOF_BUF. If FOREVER, wait forever
+ rather than timing out; this is used (in synchronous mode) to wait
+ for a target that is is executing user code to stop. */
+/* FIXME: ezannoni 2000-02-01 this wrapper is necessary so that we
+ don't have to change all the calls to getpkt to deal with the
+ return value, because at the moment I don't know what the right
+ thing to do it for those. */
+void
+getpkt (char **buf,
+ long *sizeof_buf,
+ int forever)
+{
+ int timed_out;
+
+ timed_out = getpkt_sane (buf, sizeof_buf, forever);
+}
+
+
+/* Read a packet from the remote machine, with error checking, and
+ store it in *BUF. Resize *BUF using xrealloc if necessary to hold
+ the result, and update *SIZEOF_BUF. If FOREVER, wait forever
+ rather than timing out; this is used (in synchronous mode) to wait
+ for a target that is is executing user code to stop. If FOREVER ==
+ 0, this function is allowed to time out gracefully and return an
+ indication of this to the caller. Otherwise return the number of
+ bytes read. If EXPECTING_NOTIF, consider receiving a notification
+ enough reason to return to the caller. */
+
+static int
+getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever,
+ int expecting_notif)
+{
+ struct remote_state *rs = get_remote_state ();
+ int c;
+ int tries;
+ int timeout;
+ int val = -1;
+
+ /* We're reading a new response. Make sure we don't look at a
+ previously cached response. */
+ rs->cached_wait_status = 0;
+
+ strcpy (*buf, "timeout");
+
+ if (forever)
+ timeout = watchdog > 0 ? watchdog : -1;
+ else if (expecting_notif)
+ timeout = 0; /* There should already be a char in the buffer. If
+ not, bail out. */
+ else
+ timeout = remote_timeout;
+
+#define MAX_TRIES 3
+
+ /* Process any number of notifications, and then return when
+ we get a packet. */
+ for (;;)
+ {
+ /* If we get a timeout or bad checksm, retry up to MAX_TRIES
+ times. */
+ for (tries = 1; tries <= MAX_TRIES; tries++)
+ {
+ /* This can loop forever if the remote side sends us
+ characters continuously, but if it pauses, we'll get
+ SERIAL_TIMEOUT from readchar because of timeout. Then
+ we'll count that as a retry.
+
+ Note that even when forever is set, we will only wait
+ forever prior to the start of a packet. After that, we
+ expect characters to arrive at a brisk pace. They should
+ show up within remote_timeout intervals. */
+ do
+ c = readchar (timeout);
+ while (c != SERIAL_TIMEOUT && c != '$' && c != '%');
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (expecting_notif)
+ return -1; /* Don't complain, it's normal to not get
+ anything in this case. */
+
+ if (forever) /* Watchdog went off? Kill the target. */
+ {
+ QUIT;
+ pop_target ();
+ error (_("Watchdog timeout has expired. Target detached."));
+ }
+ if (remote_debug)
+ fputs_filtered ("Timed out.\n", gdb_stdlog);
+ }
+ else
+ {
+ /* We've found the start of a packet or notification.
+ Now collect the data. */
+ val = read_frame (buf, sizeof_buf);
+ if (val >= 0)
+ break;
+ }
+
+ serial_write (remote_desc, "-", 1);
+ }
+
+ if (tries > MAX_TRIES)
+ {
+ /* We have tried hard enough, and just can't receive the
+ packet/notification. Give up. */
+ printf_unfiltered (_("Ignoring packet error, continuing...\n"));
+
+ /* Skip the ack char if we're in no-ack mode. */
+ if (!rs->noack_mode)
+ serial_write (remote_desc, "+", 1);
+ return -1;
+ }
+
+ /* If we got an ordinary packet, return that to our caller. */
+ if (c == '$')
+ {
+ if (remote_debug)
+ {
+ struct cleanup *old_chain;
+ char *str;
+
+ str = escape_buffer (*buf, val);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog, "Packet received: %s\n", str);
+ do_cleanups (old_chain);
+ }
+
+ /* Skip the ack char if we're in no-ack mode. */
+ if (!rs->noack_mode)
+ serial_write (remote_desc, "+", 1);
+ return val;
+ }
+
+ /* If we got a notification, handle it, and go back to looking
+ for a packet. */
+ else
+ {
+ gdb_assert (c == '%');
+
+ if (remote_debug)
+ {
+ struct cleanup *old_chain;
+ char *str;
+
+ str = escape_buffer (*buf, val);
+ old_chain = make_cleanup (xfree, str);
+ fprintf_unfiltered (gdb_stdlog,
+ " Notification received: %s\n",
+ str);
+ do_cleanups (old_chain);
+ }
+
+ handle_notification (*buf, val);
+
+ /* Notifications require no acknowledgement. */
+
+ if (expecting_notif)
+ return -1;
+ }
+ }
+}
+
+static int
+getpkt_sane (char **buf, long *sizeof_buf, int forever)
+{
+ return getpkt_or_notif_sane_1 (buf, sizeof_buf, forever, 0);
+}
+
+static int
+getpkt_or_notif_sane (char **buf, long *sizeof_buf, int forever)
+{
+ return getpkt_or_notif_sane_1 (buf, sizeof_buf, forever, 1);
+}
+
+\f
+static void
+remote_kill (struct target_ops *ops)
+{
+ /* Use catch_errors so the user can quit from gdb even when we
+ aren't on speaking terms with the remote system. */
+ catch_errors ((catch_errors_ftype *) putpkt, "k", "", RETURN_MASK_ERROR);
+
+ /* Don't wait for it to die. I'm not really sure it matters whether
+ we do or not. For the existing stubs, kill is a noop. */
+ target_mourn_inferior ();
+}
+
+static int
+remote_vkill (int pid, struct remote_state *rs)
+{
+ if (remote_protocol_packets[PACKET_vKill].support == PACKET_DISABLE)
+ return -1;
+
+ /* Tell the remote target to detach. */
+ sprintf (rs->buf, "vKill;%x", pid);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf,
+ &remote_protocol_packets[PACKET_vKill]) == PACKET_OK)
+ return 0;
+ else if (remote_protocol_packets[PACKET_vKill].support == PACKET_DISABLE)
+ return -1;
+ else
+ return 1;
+}
+
+static void
+extended_remote_kill (struct target_ops *ops)
+{
+ int res;
+ int pid = ptid_get_pid (inferior_ptid);
+ struct remote_state *rs = get_remote_state ();
+
+ res = remote_vkill (pid, rs);
+ if (res == -1 && !remote_multi_process_p (rs))
+ {
+ /* Don't try 'k' on a multi-process aware stub -- it has no way
+ to specify the pid. */
+
+ putpkt ("k");
+#if 0
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ if (rs->buf[0] != 'O' || rs->buf[0] != 'K')
+ res = 1;
+#else
+ /* Don't wait for it to die. I'm not really sure it matters whether
+ we do or not. For the existing stubs, kill is a noop. */
+ res = 0;
+#endif
+ }
+
+ if (res != 0)
+ error (_("Can't kill process"));
+
+ target_mourn_inferior ();
+}
+
+static void
+remote_mourn (struct target_ops *ops)
+{
+ remote_mourn_1 (ops);
+}
+
+/* Worker function for remote_mourn. */
+static void
+remote_mourn_1 (struct target_ops *target)
+{
+ unpush_target (target);
+
+ /* remote_close takes care of doing most of the clean up. */
+ generic_mourn_inferior ();
+}
+
+static void
+extended_remote_mourn_1 (struct target_ops *target)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ /* In case we got here due to an error, but we're going to stay
+ connected. */
+ rs->waiting_for_stop_reply = 0;
+
+ /* We're no longer interested in these events. */
+ discard_pending_stop_replies (ptid_get_pid (inferior_ptid));
+
+ /* If the current general thread belonged to the process we just
+ detached from or has exited, the remote side current general
+ thread becomes undefined. Considering a case like this:
+
+ - We just got here due to a detach.
+ - The process that we're detaching from happens to immediately
+ report a global breakpoint being hit in non-stop mode, in the
+ same thread we had selected before.
+ - GDB attaches to this process again.
+ - This event happens to be the next event we handle.
+
+ GDB would consider that the current general thread didn't need to
+ be set on the stub side (with Hg), since for all it knew,
+ GENERAL_THREAD hadn't changed.
+
+ Notice that although in all-stop mode, the remote server always
+ sets the current thread to the thread reporting the stop event,
+ that doesn't happen in non-stop mode; in non-stop, the stub *must
+ not* change the current thread when reporting a breakpoint hit,
+ due to the decoupling of event reporting and event handling.
+
+ To keep things simple, we always invalidate our notion of the
+ current thread. */
+ record_currthread (minus_one_ptid);
+
+ /* Unlike "target remote", we do not want to unpush the target; then
+ the next time the user says "run", we won't be connected. */
+
+ /* Call common code to mark the inferior as not running. */
+ generic_mourn_inferior ();
+
+ if (!have_inferiors ())
+ {
+ if (!remote_multi_process_p (rs))
+ {
+ /* Check whether the target is running now - some remote stubs
+ automatically restart after kill. */
+ putpkt ("?");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (rs->buf[0] == 'S' || rs->buf[0] == 'T')
+ {
+ /* Assume that the target has been restarted. Set
+ inferior_ptid so that bits of core GDB realizes
+ there's something here, e.g., so that the user can
+ say "kill" again. */
+ inferior_ptid = magic_null_ptid;
+ }
+ }
+ }
+}
+
+static void
+extended_remote_mourn (struct target_ops *ops)
+{
+ extended_remote_mourn_1 (ops);
+}
+
+static int
+extended_remote_run (char *args)
+{
+ struct remote_state *rs = get_remote_state ();
+ int len;
+
+ /* If the user has disabled vRun support, or we have detected that
+ support is not available, do not try it. */
+ if (remote_protocol_packets[PACKET_vRun].support == PACKET_DISABLE)
+ return -1;
+
+ strcpy (rs->buf, "vRun;");
+ len = strlen (rs->buf);
+
+ if (strlen (remote_exec_file) * 2 + len >= get_remote_packet_size ())
+ error (_("Remote file name too long for run packet"));
+ len += 2 * bin2hex ((gdb_byte *) remote_exec_file, rs->buf + len, 0);
+
+ gdb_assert (args != NULL);
+ if (*args)
+ {
+ struct cleanup *back_to;
+ int i;
+ char **argv;
+
+ argv = gdb_buildargv (args);
+ back_to = make_cleanup ((void (*) (void *)) freeargv, argv);
+ for (i = 0; argv[i] != NULL; i++)
+ {
+ if (strlen (argv[i]) * 2 + 1 + len >= get_remote_packet_size ())
+ error (_("Argument list too long for run packet"));
+ rs->buf[len++] = ';';
+ len += 2 * bin2hex ((gdb_byte *) argv[i], rs->buf + len, 0);
+ }
+ do_cleanups (back_to);
+ }
+
+ rs->buf[len++] = '\0';
+
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_vRun]) == PACKET_OK)
+ {
+ /* We have a wait response; we don't need it, though. All is well. */
+ return 0;
+ }
+ else if (remote_protocol_packets[PACKET_vRun].support == PACKET_DISABLE)
+ /* It wasn't disabled before, but it is now. */
+ return -1;
+ else
+ {
+ if (remote_exec_file[0] == '\0')
+ error (_("Running the default executable on the remote target failed; "
+ "try \"set remote exec-file\"?"));
+ else
+ error (_("Running \"%s\" on the remote target failed"),
+ remote_exec_file);
+ }
+}
+
+/* In the extended protocol we want to be able to do things like
+ "run" and have them basically work as expected. So we need
+ a special create_inferior function. We support changing the
+ executable file and the command line arguments, but not the
+ environment. */
+
+static void
+extended_remote_create_inferior_1 (char *exec_file, char *args,
+ char **env, int from_tty)
+{
+ /* If running asynchronously, register the target file descriptor
+ with the event loop. */
+ if (target_can_async_p ())
+ target_async (inferior_event_handler, 0);
+
+ /* Now restart the remote server. */
+ if (extended_remote_run (args) == -1)
+ {
+ /* vRun was not supported. Fail if we need it to do what the
+ user requested. */
+ if (remote_exec_file[0])
+ error (_("Remote target does not support \"set remote exec-file\""));
+ if (args[0])
+ error (_("Remote target does not support \"set args\" or run <ARGS>"));
+
+ /* Fall back to "R". */
+ extended_remote_restart ();
+ }
+
+ if (!have_inferiors ())
+ {
+ /* Clean up from the last time we ran, before we mark the target
+ running again. This will mark breakpoints uninserted, and
+ get_offsets may insert breakpoints. */
+ init_thread_list ();
+ init_wait_for_inferior ();
+ }
+
+ /* Now mark the inferior as running before we do anything else. */
+ inferior_ptid = magic_null_ptid;
+
+ /* Now, if we have thread information, update inferior_ptid. */
+ inferior_ptid = remote_current_thread (inferior_ptid);
+
+ remote_add_inferior (ptid_get_pid (inferior_ptid), 0);
+ add_thread_silent (inferior_ptid);
+
+ /* Get updated offsets, if the stub uses qOffsets. */
+ get_offsets ();
+}
+
+static void
+extended_remote_create_inferior (struct target_ops *ops,
+ char *exec_file, char *args,
+ char **env, int from_tty)
+{
+ extended_remote_create_inferior_1 (exec_file, args, env, from_tty);
+}
+\f
+
+/* Insert a breakpoint. On targets that have software breakpoint
+ support, we ask the remote target to do the work; on targets
+ which don't, we insert a traditional memory breakpoint. */
+
+static int
+remote_insert_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
+{
+ /* Try the "Z" s/w breakpoint packet if it is not already disabled.
+ If it succeeds, then set the support to PACKET_ENABLE. If it
+ fails, and the user has explicitly requested the Z support then
+ report an error, otherwise, mark it disabled and go on. */
+
+ if (remote_protocol_packets[PACKET_Z0].support != PACKET_DISABLE)
+ {
+ CORE_ADDR addr = bp_tgt->placed_address;
+ struct remote_state *rs;
+ char *p;
+ int bpsize;
+
+ gdbarch_remote_breakpoint_from_pc (gdbarch, &addr, &bpsize);
+
+ rs = get_remote_state ();
+ p = rs->buf;
+
+ *(p++) = 'Z';
+ *(p++) = '0';
+ *(p++) = ',';
+ addr = (ULONGEST) remote_address_masked (addr);
+ p += hexnumstr (p, addr);
+ sprintf (p, ",%d", bpsize);
+
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_Z0]))
+ {
+ case PACKET_ERROR:
+ return -1;
+ case PACKET_OK:
+ bp_tgt->placed_address = addr;
+ bp_tgt->placed_size = bpsize;
+ return 0;
+ case PACKET_UNKNOWN:
+ break;
+ }
+ }
+
+ return memory_insert_breakpoint (gdbarch, bp_tgt);
+}
+
+static int
+remote_remove_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
+{
+ CORE_ADDR addr = bp_tgt->placed_address;
+ struct remote_state *rs = get_remote_state ();
+
+ if (remote_protocol_packets[PACKET_Z0].support != PACKET_DISABLE)
+ {
+ char *p = rs->buf;
+
+ *(p++) = 'z';
+ *(p++) = '0';
+ *(p++) = ',';
+
+ addr = (ULONGEST) remote_address_masked (bp_tgt->placed_address);
+ p += hexnumstr (p, addr);
+ sprintf (p, ",%d", bp_tgt->placed_size);
+
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ return (rs->buf[0] == 'E');
+ }
+
+ return memory_remove_breakpoint (gdbarch, bp_tgt);
+}
+
+static int
+watchpoint_to_Z_packet (int type)
+{
+ switch (type)
+ {
+ case hw_write:
+ return Z_PACKET_WRITE_WP;
+ break;
+ case hw_read:
+ return Z_PACKET_READ_WP;
+ break;
+ case hw_access:
+ return Z_PACKET_ACCESS_WP;
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("hw_bp_to_z: bad watchpoint type %d"), type);
+ }
+}
+
+static int
+remote_insert_watchpoint (CORE_ADDR addr, int len, int type,
+ struct expression *cond)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p;
+ enum Z_packet_type packet = watchpoint_to_Z_packet (type);
+
+ if (remote_protocol_packets[PACKET_Z0 + packet].support == PACKET_DISABLE)
+ return 1;
+
+ sprintf (rs->buf, "Z%x,", packet);
+ p = strchr (rs->buf, '\0');
+ addr = remote_address_masked (addr);
+ p += hexnumstr (p, (ULONGEST) addr);
+ sprintf (p, ",%x", len);
+
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_Z0 + packet]))
+ {
+ case PACKET_ERROR:
+ return -1;
+ case PACKET_UNKNOWN:
+ return 1;
+ case PACKET_OK:
+ return 0;
+ }
+ internal_error (__FILE__, __LINE__,
+ _("remote_insert_watchpoint: reached end of function"));
+}
+
+
+static int
+remote_remove_watchpoint (CORE_ADDR addr, int len, int type,
+ struct expression *cond)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p;
+ enum Z_packet_type packet = watchpoint_to_Z_packet (type);
+
+ if (remote_protocol_packets[PACKET_Z0 + packet].support == PACKET_DISABLE)
+ return -1;
+
+ sprintf (rs->buf, "z%x,", packet);
+ p = strchr (rs->buf, '\0');
+ addr = remote_address_masked (addr);
+ p += hexnumstr (p, (ULONGEST) addr);
+ sprintf (p, ",%x", len);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_Z0 + packet]))
+ {
+ case PACKET_ERROR:
+ case PACKET_UNKNOWN:
+ return -1;
+ case PACKET_OK:
+ return 0;
+ }
+ internal_error (__FILE__, __LINE__,
+ _("remote_remove_watchpoint: reached end of function"));
+}
+
+
+int remote_hw_watchpoint_limit = -1;
+int remote_hw_breakpoint_limit = -1;
+
+static int
+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 (remote_hw_breakpoint_limit < 0)
+ return 1;
+ else if (cnt <= remote_hw_breakpoint_limit)
+ return 1;
+ }
+ else
+ {
+ if (remote_hw_watchpoint_limit == 0)
+ return 0;
+ else if (remote_hw_watchpoint_limit < 0)
+ return 1;
+ else if (ot)
+ return -1;
+ else if (cnt <= remote_hw_watchpoint_limit)
+ return 1;
+ }
+ return -1;
+}
+
+static int
+remote_stopped_by_watchpoint (void)
+{
+ return remote_stopped_by_watchpoint_p;
+}
+
+static int
+remote_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
+{
+ int rc = 0;
+
+ if (remote_stopped_by_watchpoint ())
+ {
+ *addr_p = remote_watch_data_address;
+ rc = 1;