+ if (!remote_desc)
+ error (_("command can only be used with remote target"));
+
+ if (!args)
+ error (_("remote-packet command requires packet text as argument"));
+
+ puts_filtered ("sending: ");
+ print_packet (args);
+ puts_filtered ("\n");
+ putpkt (args);
+
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ puts_filtered ("received: ");
+ print_packet (rs->buf);
+ puts_filtered ("\n");
+}
+
+#if 0
+/* --------- UNIT_TEST for THREAD oriented PACKETS ------------------- */
+
+static void display_thread_info (struct gdb_ext_thread_info *info);
+
+static void threadset_test_cmd (char *cmd, int tty);
+
+static void threadalive_test (char *cmd, int tty);
+
+static void threadlist_test_cmd (char *cmd, int tty);
+
+int get_and_display_threadinfo (threadref *ref);
+
+static void threadinfo_test_cmd (char *cmd, int tty);
+
+static int thread_display_step (threadref *ref, void *context);
+
+static void threadlist_update_test_cmd (char *cmd, int tty);
+
+static void init_remote_threadtests (void);
+
+#define SAMPLE_THREAD 0x05060708 /* Truncated 64 bit threadid. */
+
+static void
+threadset_test_cmd (char *cmd, int tty)
+{
+ int sample_thread = SAMPLE_THREAD;
+
+ printf_filtered (_("Remote threadset test\n"));
+ set_thread (sample_thread, 1);
+}
+
+
+static void
+threadalive_test (char *cmd, int tty)
+{
+ int sample_thread = SAMPLE_THREAD;
+
+ if (remote_thread_alive (pid_to_ptid (sample_thread)))
+ printf_filtered ("PASS: Thread alive test\n");
+ else
+ printf_filtered ("FAIL: Thread alive test\n");
+}
+
+void output_threadid (char *title, threadref *ref);
+
+void
+output_threadid (char *title, threadref *ref)
+{
+ char hexid[20];
+
+ pack_threadid (&hexid[0], ref); /* Convert threead id into hex. */
+ hexid[16] = 0;
+ printf_filtered ("%s %s\n", title, (&hexid[0]));
+}
+
+static void
+threadlist_test_cmd (char *cmd, int tty)
+{
+ int startflag = 1;
+ threadref nextthread;
+ int done, result_count;
+ threadref threadlist[3];
+
+ printf_filtered ("Remote Threadlist test\n");
+ if (!remote_get_threadlist (startflag, &nextthread, 3, &done,
+ &result_count, &threadlist[0]))
+ printf_filtered ("FAIL: threadlist test\n");
+ else
+ {
+ threadref *scan = threadlist;
+ threadref *limit = scan + result_count;
+
+ while (scan < limit)
+ output_threadid (" thread ", scan++);
+ }
+}
+
+void
+display_thread_info (struct gdb_ext_thread_info *info)
+{
+ output_threadid ("Threadid: ", &info->threadid);
+ printf_filtered ("Name: %s\n ", info->shortname);
+ printf_filtered ("State: %s\n", info->display);
+ printf_filtered ("other: %s\n\n", info->more_display);
+}
+
+int
+get_and_display_threadinfo (threadref *ref)
+{
+ int result;
+ int set;
+ struct gdb_ext_thread_info threadinfo;
+
+ set = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME
+ | TAG_MOREDISPLAY | TAG_DISPLAY;
+ if (0 != (result = remote_get_threadinfo (ref, set, &threadinfo)))
+ display_thread_info (&threadinfo);
+ return result;
+}
+
+static void
+threadinfo_test_cmd (char *cmd, int tty)
+{
+ int athread = SAMPLE_THREAD;
+ threadref thread;
+ int set;
+
+ int_to_threadref (&thread, athread);
+ printf_filtered ("Remote Threadinfo test\n");
+ if (!get_and_display_threadinfo (&thread))
+ printf_filtered ("FAIL cannot get thread info\n");
+}
+
+static int
+thread_display_step (threadref *ref, void *context)
+{
+ /* output_threadid(" threadstep ",ref); *//* simple test */
+ return get_and_display_threadinfo (ref);
+}
+
+static void
+threadlist_update_test_cmd (char *cmd, int tty)
+{
+ printf_filtered ("Remote Threadlist update test\n");
+ remote_threadlist_iterator (thread_display_step, 0, CRAZY_MAX_THREADS);
+}
+
+static void
+init_remote_threadtests (void)
+{
+ add_com ("tlist", class_obscure, threadlist_test_cmd, _("\
+Fetch and print the remote list of thread identifiers, one pkt only"));
+ add_com ("tinfo", class_obscure, threadinfo_test_cmd,
+ _("Fetch and display info about one thread"));
+ add_com ("tset", class_obscure, threadset_test_cmd,
+ _("Test setting to a different thread"));
+ add_com ("tupd", class_obscure, threadlist_update_test_cmd,
+ _("Iterate through updating all remote thread info"));
+ add_com ("talive", class_obscure, threadalive_test,
+ _(" Remote thread alive test "));
+}
+
+#endif /* 0 */
+
+/* Convert a thread ID to a string. Returns the string in a static
+ buffer. */
+
+static char *
+remote_pid_to_str (ptid_t ptid)
+{
+ static char buf[32];
+
+ xsnprintf (buf, sizeof buf, "Thread %d", ptid_get_pid (ptid));
+ return buf;
+}
+
+/* Get the address of the thread local variable in OBJFILE which is
+ stored at OFFSET within the thread local storage for thread PTID. */
+
+static CORE_ADDR
+remote_get_thread_local_address (ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset)
+{
+ if (remote_protocol_packets[PACKET_qGetTLSAddr].support != PACKET_DISABLE)
+ {
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ enum packet_result result;
+
+ strcpy (p, "qGetTLSAddr:");
+ p += strlen (p);
+ p += hexnumstr (p, PIDGET (ptid));
+ *p++ = ',';
+ p += hexnumstr (p, offset);
+ *p++ = ',';
+ p += hexnumstr (p, lm);
+ *p++ = '\0';
+
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ result = packet_ok (rs->buf, &remote_protocol_packets[PACKET_qGetTLSAddr]);
+ if (result == PACKET_OK)
+ {
+ ULONGEST result;
+
+ unpack_varlen_hex (rs->buf, &result);
+ return result;
+ }
+ else if (result == PACKET_UNKNOWN)
+ throw_error (TLS_GENERIC_ERROR,
+ _("Remote target doesn't support qGetTLSAddr packet"));
+ else
+ throw_error (TLS_GENERIC_ERROR,
+ _("Remote target failed to process qGetTLSAddr request"));
+ }
+ else
+ throw_error (TLS_GENERIC_ERROR,
+ _("TLS not supported or disabled on this target"));
+ /* Not reached. */
+ return 0;
+}
+
+/* Support for inferring a target description based on the current
+ architecture and the size of a 'g' packet. While the 'g' packet
+ can have any size (since optional registers can be left off the
+ end), some sizes are easily recognizable given knowledge of the
+ approximate architecture. */
+
+struct remote_g_packet_guess
+{
+ int bytes;
+ const struct target_desc *tdesc;
+};
+typedef struct remote_g_packet_guess remote_g_packet_guess_s;
+DEF_VEC_O(remote_g_packet_guess_s);
+
+struct remote_g_packet_data
+{
+ VEC(remote_g_packet_guess_s) *guesses;
+};
+
+static struct gdbarch_data *remote_g_packet_data_handle;
+
+static void *
+remote_g_packet_data_init (struct obstack *obstack)
+{
+ return OBSTACK_ZALLOC (obstack, struct remote_g_packet_data);
+}
+
+void
+register_remote_g_packet_guess (struct gdbarch *gdbarch, int bytes,
+ const struct target_desc *tdesc)
+{
+ struct remote_g_packet_data *data
+ = gdbarch_data (gdbarch, remote_g_packet_data_handle);
+ struct remote_g_packet_guess new_guess, *guess;
+ int ix;
+
+ gdb_assert (tdesc != NULL);
+
+ for (ix = 0;
+ VEC_iterate (remote_g_packet_guess_s, data->guesses, ix, guess);
+ ix++)
+ if (guess->bytes == bytes)
+ internal_error (__FILE__, __LINE__,
+ "Duplicate g packet description added for size %d",
+ bytes);
+
+ new_guess.bytes = bytes;
+ new_guess.tdesc = tdesc;
+ VEC_safe_push (remote_g_packet_guess_s, data->guesses, &new_guess);
+}
+
+static const struct target_desc *
+remote_read_description (struct target_ops *target)
+{
+ struct remote_g_packet_data *data
+ = gdbarch_data (current_gdbarch, remote_g_packet_data_handle);
+
+ if (!VEC_empty (remote_g_packet_guess_s, data->guesses))
+ {
+ struct remote_g_packet_guess *guess;
+ int ix;
+ int bytes = send_g_packet ();
+
+ for (ix = 0;
+ VEC_iterate (remote_g_packet_guess_s, data->guesses, ix, guess);
+ ix++)
+ if (guess->bytes == bytes)
+ return guess->tdesc;
+
+ /* We discard the g packet. A minor optimization would be to
+ hold on to it, and fill the register cache once we have selected
+ an architecture, but it's too tricky to do safely. */
+ }
+
+ return NULL;
+}
+
+/* Remote file transfer support. This is host-initiated I/O, not
+ target-initiated; for target-initiated, see remote-fileio.c. */
+
+/* If *LEFT is at least the length of STRING, copy STRING to
+ *BUFFER, update *BUFFER to point to the new end of the buffer, and
+ decrease *LEFT. Otherwise raise an error. */
+
+static void
+remote_buffer_add_string (char **buffer, int *left, char *string)
+{
+ int len = strlen (string);
+
+ if (len > *left)
+ error (_("Packet too long for target."));
+
+ memcpy (*buffer, string, len);
+ *buffer += len;
+ *left -= len;
+
+ /* NUL-terminate the buffer as a convenience, if there is
+ room. */
+ if (*left)
+ **buffer = '\0';
+}
+
+/* If *LEFT is large enough, hex encode LEN bytes from BYTES into
+ *BUFFER, update *BUFFER to point to the new end of the buffer, and
+ decrease *LEFT. Otherwise raise an error. */
+
+static void
+remote_buffer_add_bytes (char **buffer, int *left, const gdb_byte *bytes,
+ int len)
+{
+ if (2 * len > *left)
+ error (_("Packet too long for target."));
+
+ bin2hex (bytes, *buffer, len);
+ *buffer += 2 * len;
+ *left -= 2 * len;
+
+ /* NUL-terminate the buffer as a convenience, if there is
+ room. */
+ if (*left)
+ **buffer = '\0';
+}
+
+/* If *LEFT is large enough, convert VALUE to hex and add it to
+ *BUFFER, update *BUFFER to point to the new end of the buffer, and
+ decrease *LEFT. Otherwise raise an error. */
+
+static void
+remote_buffer_add_int (char **buffer, int *left, ULONGEST value)
+{
+ int len = hexnumlen (value);
+
+ if (len > *left)
+ error (_("Packet too long for target."));
+
+ hexnumstr (*buffer, value);
+ *buffer += len;
+ *left -= len;
+
+ /* NUL-terminate the buffer as a convenience, if there is
+ room. */
+ if (*left)
+ **buffer = '\0';
+}
+
+/* Parse an I/O result packet from BUFFER. Set RETCODE to the return
+ value, *REMOTE_ERRNO to the remote error number or zero if none
+ was included, and *ATTACHMENT to point to the start of the annex
+ if any. The length of the packet isn't needed here; there may
+ be NUL bytes in BUFFER, but they will be after *ATTACHMENT.
+
+ Return 0 if the packet could be parsed, -1 if it could not. If
+ -1 is returned, the other variables may not be initialized. */
+
+static int
+remote_hostio_parse_result (char *buffer, int *retcode,
+ int *remote_errno, char **attachment)
+{
+ char *p, *p2;
+
+ *remote_errno = 0;
+ *attachment = NULL;
+
+ if (buffer[0] != 'F')
+ return -1;
+
+ errno = 0;
+ *retcode = strtol (&buffer[1], &p, 16);
+ if (errno != 0 || p == &buffer[1])
+ return -1;
+
+ /* Check for ",errno". */
+ if (*p == ',')
+ {
+ errno = 0;
+ *remote_errno = strtol (p + 1, &p2, 16);
+ if (errno != 0 || p + 1 == p2)
+ return -1;
+ p = p2;
+ }
+
+ /* Check for ";attachment". If there is no attachment, the
+ packet should end here. */
+ if (*p == ';')
+ {
+ *attachment = p + 1;
+ return 0;
+ }
+ else if (*p == '\0')
+ return 0;
+ else
+ return -1;
+}
+
+/* Send a prepared I/O packet to the target and read its response.
+ The prepared packet is in the global RS->BUF before this function
+ is called, and the answer is there when we return.
+
+ COMMAND_BYTES is the length of the request to send, which may include
+ binary data. WHICH_PACKET is the packet configuration to check
+ before attempting a packet. If an error occurs, *REMOTE_ERRNO
+ is set to the error number and -1 is returned. Otherwise the value
+ returned by the function is returned.
+
+ ATTACHMENT and ATTACHMENT_LEN should be non-NULL if and only if an
+ attachment is expected; an error will be reported if there's a
+ mismatch. If one is found, *ATTACHMENT will be set to point into
+ the packet buffer and *ATTACHMENT_LEN will be set to the
+ attachment's length. */
+
+static int
+remote_hostio_send_command (int command_bytes, int which_packet,
+ int *remote_errno, char **attachment,
+ int *attachment_len)
+{
+ struct remote_state *rs = get_remote_state ();
+ int ret, bytes_read;
+ char *attachment_tmp;
+
+ if (remote_protocol_packets[which_packet].support == PACKET_DISABLE)
+ {
+ *remote_errno = FILEIO_ENOSYS;
+ return -1;
+ }
+
+ putpkt_binary (rs->buf, command_bytes);
+ bytes_read = getpkt_sane (&rs->buf, &rs->buf_size, 0);
+
+ /* If it timed out, something is wrong. Don't try to parse the
+ buffer. */
+ if (bytes_read < 0)
+ {
+ *remote_errno = FILEIO_EINVAL;
+ return -1;
+ }
+
+ switch (packet_ok (rs->buf, &remote_protocol_packets[which_packet]))
+ {
+ case PACKET_ERROR:
+ *remote_errno = FILEIO_EINVAL;
+ return -1;
+ case PACKET_UNKNOWN:
+ *remote_errno = FILEIO_ENOSYS;
+ return -1;
+ case PACKET_OK:
+ break;
+ }
+
+ if (remote_hostio_parse_result (rs->buf, &ret, remote_errno,
+ &attachment_tmp))
+ {
+ *remote_errno = FILEIO_EINVAL;
+ return -1;
+ }
+
+ /* Make sure we saw an attachment if and only if we expected one. */
+ if ((attachment_tmp == NULL && attachment != NULL)
+ || (attachment_tmp != NULL && attachment == NULL))
+ {
+ *remote_errno = FILEIO_EINVAL;
+ return -1;
+ }
+
+ /* If an attachment was found, it must point into the packet buffer;
+ work out how many bytes there were. */
+ if (attachment_tmp != NULL)
+ {
+ *attachment = attachment_tmp;
+ *attachment_len = bytes_read - (*attachment - rs->buf);
+ }
+
+ return ret;
+}
+
+/* Open FILENAME on the remote target, using FLAGS and MODE. Return a
+ remote file descriptor, or -1 if an error occurs (and set
+ *REMOTE_ERRNO). */
+
+static int
+remote_hostio_open (const char *filename, int flags, int mode,
+ int *remote_errno)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ int left = get_remote_packet_size () - 1;
+
+ remote_buffer_add_string (&p, &left, "vFile:open:");
+
+ remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename,
+ strlen (filename));
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, flags);
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, mode);
+
+ return remote_hostio_send_command (p - rs->buf, PACKET_vFile_open,
+ remote_errno, NULL, NULL);
+}
+
+/* Write up to LEN bytes from WRITE_BUF to FD on the remote target.
+ Return the number of bytes written, or -1 if an error occurs (and
+ set *REMOTE_ERRNO). */
+
+static int
+remote_hostio_pwrite (int fd, const gdb_byte *write_buf, int len,
+ ULONGEST offset, int *remote_errno)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ int left = get_remote_packet_size ();
+ int out_len;
+
+ remote_buffer_add_string (&p, &left, "vFile:pwrite:");
+
+ remote_buffer_add_int (&p, &left, fd);
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, offset);
+ remote_buffer_add_string (&p, &left, ",");
+
+ p += remote_escape_output (write_buf, len, p, &out_len,
+ get_remote_packet_size () - (p - rs->buf));
+
+ return remote_hostio_send_command (p - rs->buf, PACKET_vFile_pwrite,
+ remote_errno, NULL, NULL);
+}
+
+/* Read up to LEN bytes FD on the remote target into READ_BUF
+ Return the number of bytes read, or -1 if an error occurs (and
+ set *REMOTE_ERRNO). */
+
+static int
+remote_hostio_pread (int fd, gdb_byte *read_buf, int len,
+ ULONGEST offset, int *remote_errno)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ char *attachment;
+ int left = get_remote_packet_size ();
+ int ret, attachment_len;
+ int read_len;
+
+ remote_buffer_add_string (&p, &left, "vFile:pread:");
+
+ remote_buffer_add_int (&p, &left, fd);
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, len);
+ remote_buffer_add_string (&p, &left, ",");
+
+ remote_buffer_add_int (&p, &left, offset);
+
+ ret = remote_hostio_send_command (p - rs->buf, PACKET_vFile_pread,
+ remote_errno, &attachment,
+ &attachment_len);