/* Remote utility routines for the remote server for GDB.
- Copyright (C) 1986, 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1986-2014 Free Software Foundation, Inc.
This file is part of GDB.
#include "server.h"
#include "terminal.h"
#include "target.h"
+#include "gdbthread.h"
+#include "tdesc.h"
+#include "dll.h"
+#include "rsp-low.h"
+
#include <stdio.h>
#include <string.h>
#if HAVE_SYS_IOCTL_H
#include <fcntl.h>
#endif
#include <sys/time.h>
-#if HAVE_UNISTD_H
#include <unistd.h>
-#endif
#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
int remote_debug = 0;
struct ui_file *gdb_stdlog;
+static int remote_is_stdio = 0;
+
static gdb_fildes_t remote_desc = INVALID_DESCRIPTOR;
static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
return remote_desc != INVALID_DESCRIPTOR;
}
+/* Return true if the remote connection is over stdio. */
+
+int
+remote_connection_is_stdio (void)
+{
+ return remote_is_stdio;
+}
+
static void
enable_async_notification (int fd)
{
socklen_t tmp;
if (debug_threads)
- fprintf (stderr, "handling possible accept event\n");
+ debug_printf ("handling possible accept event\n");
tmp = sizeof (sockaddr);
remote_desc = accept (listen_desc, (struct sockaddr *) &sockaddr, &tmp);
socklen_t tmp;
char *port_end;
+ remote_is_stdio = 0;
+ if (strcmp (name, STDIO_CONNECTION_NAME) == 0)
+ {
+ /* We need to record fact that we're using stdio sooner than the
+ call to remote_open so start_inferior knows the connection is
+ via stdio. */
+ remote_is_stdio = 1;
+ transport_is_reliable = 1;
+ return;
+ }
+
port_str = strchr (name, ':');
if (port_str == NULL)
{
char *port_str;
port_str = strchr (name, ':');
+#ifdef USE_WIN32API
if (port_str == NULL)
+ error ("Only <host>:<port> is supported on this platform.");
+#endif
+
+ if (strcmp (name, STDIO_CONNECTION_NAME) == 0)
+ {
+ fprintf (stderr, "Remote debugging using stdio\n");
+
+ /* Use stdin as the handle of the connection.
+ We only select on reads, for example. */
+ remote_desc = fileno (stdin);
+
+ enable_async_notification (remote_desc);
+
+ /* Register the event loop handler. */
+ add_file_handler (remote_desc, handle_serial_event, NULL);
+ }
+#ifndef USE_WIN32API
+ else if (port_str == NULL)
{
-#ifdef USE_WIN32API
- error ("Only <host>:<port> is supported on this platform.");
-#else
struct stat statbuf;
if (stat (name, &statbuf) == 0
/* Register the event loop handler. */
add_file_handler (remote_desc, handle_serial_event, NULL);
-#endif /* USE_WIN32API */
}
+#endif /* USE_WIN32API */
else
{
int port;
#ifdef USE_WIN32API
closesocket (remote_desc);
#else
- close (remote_desc);
+ if (! remote_connection_is_stdio ())
+ close (remote_desc);
#endif
remote_desc = INVALID_DESCRIPTOR;
reset_readchar ();
}
-/* Convert hex digit A to a number. */
-
-static int
-fromhex (int a)
-{
- if (a >= '0' && a <= '9')
- return a - '0';
- else if (a >= 'a' && a <= 'f')
- return a - 'a' + 10;
- else
- error ("Reply contains invalid hex digit");
- return 0;
-}
-
#endif
-static const char hexchars[] = "0123456789abcdef";
-
-static int
-ishex (int ch, int *val)
-{
- if ((ch >= 'a') && (ch <= 'f'))
- {
- *val = ch - 'a' + 10;
- return 1;
- }
- if ((ch >= 'A') && (ch <= 'F'))
- {
- *val = ch - 'A' + 10;
- return 1;
- }
- if ((ch >= '0') && (ch <= '9'))
- {
- *val = ch - '0';
- return 1;
- }
- return 0;
-}
-
#ifndef IN_PROCESS_AGENT
-int
-unhexify (char *bin, const char *hex, int count)
-{
- int i;
-
- for (i = 0; i < count; i++)
- {
- if (hex[0] == 0 || hex[1] == 0)
- {
- /* Hex string is short, or of uneven length.
- Return the count that has been converted so far. */
- return i;
- }
- *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]);
- hex += 2;
- }
- return i;
-}
-
void
decode_address (CORE_ADDR *addrp, const char *start, int len)
{
#endif
-/* Convert number NIB to a hex digit. */
-
-static int
-tohex (int nib)
-{
- if (nib < 10)
- return '0' + nib;
- else
- return 'a' + nib - 10;
-}
-
#ifndef IN_PROCESS_AGENT
-int
-hexify (char *hex, const char *bin, int count)
-{
- int i;
-
- /* May use a length, or a nul-terminated string as input. */
- if (count == 0)
- count = strlen (bin);
-
- for (i = 0; i < count; i++)
- {
- *hex++ = tohex ((*bin >> 4) & 0xf);
- *hex++ = tohex (*bin++ & 0xf);
- }
- *hex = 0;
- return i;
-}
-
-/* Convert BUFFER, binary data at least LEN bytes long, into escaped
- binary data in OUT_BUF. Set *OUT_LEN to the length of the data
- encoded in OUT_BUF, and return the number of bytes in OUT_BUF
- (which may be more than *OUT_LEN due to escape characters). The
- total number of bytes in the output buffer will be at most
- OUT_MAXLEN. */
-
-int
-remote_escape_output (const gdb_byte *buffer, int len,
- gdb_byte *out_buf, int *out_len,
- int out_maxlen)
-{
- int input_index, output_index;
-
- output_index = 0;
- for (input_index = 0; input_index < len; input_index++)
- {
- gdb_byte b = buffer[input_index];
-
- if (b == '$' || b == '#' || b == '}' || b == '*')
- {
- /* These must be escaped. */
- if (output_index + 2 > out_maxlen)
- break;
- out_buf[output_index++] = '}';
- out_buf[output_index++] = b ^ 0x20;
- }
- else
- {
- if (output_index + 1 > out_maxlen)
- break;
- out_buf[output_index++] = b;
- }
- }
-
- *out_len = input_index;
- return output_index;
-}
-
-/* Convert BUFFER, escaped data LEN bytes long, into binary data
- in OUT_BUF. Return the number of bytes written to OUT_BUF.
- Raise an error if the total number of bytes exceeds OUT_MAXLEN.
-
- This function reverses remote_escape_output. It allows more
- escaped characters than that function does, in particular because
- '*' must be escaped to avoid the run-length encoding processing
- in reading packets. */
-
-static int
-remote_unescape_input (const gdb_byte *buffer, int len,
- gdb_byte *out_buf, int out_maxlen)
-{
- int input_index, output_index;
- int escaped;
-
- output_index = 0;
- escaped = 0;
- for (input_index = 0; input_index < len; input_index++)
- {
- gdb_byte b = buffer[input_index];
-
- if (output_index + 1 > out_maxlen)
- error ("Received too much data from the target.");
-
- if (escaped)
- {
- out_buf[output_index++] = b ^ 0x20;
- escaped = 0;
- }
- else if (b == '}')
- escaped = 1;
- else
- out_buf[output_index++] = b;
- }
-
- if (escaped)
- error ("Unmatched escape character in target response.");
-
- return output_index;
-}
-
/* Look for a sequence of characters which can be run-length encoded.
If there are any, update *CSUM and *P. Otherwise, output the
single character. Return the number of characters consumed. */
#endif
-char *
-unpack_varlen_hex (char *buff, /* packet to parse */
- ULONGEST *result)
-{
- int nibble;
- ULONGEST retval = 0;
-
- while (ishex (*buff, &nibble))
- {
- buff++;
- retval = retval << 4;
- retval |= nibble & 0x0f;
- }
- *result = retval;
- return buff;
-}
-
#ifndef IN_PROCESS_AGENT
/* Write a PTID to BUF. Returns BUF+CHARACTERS_WRITTEN. */
/* Since the stub is not sending a process id, then default to
what's in the current inferior. */
- pid = ptid_get_pid (((struct inferior_list_entry *) current_inferior)->id);
+ pid = ptid_get_pid (current_ptid);
if (obuf)
*obuf = pp;
return ptid_build (pid, tid, 0);
}
+/* Write COUNT bytes in BUF to the client.
+ The result is the number of bytes written or -1 if error.
+ This may return less than COUNT. */
+
+static int
+write_prim (const void *buf, int count)
+{
+ if (remote_connection_is_stdio ())
+ return write (fileno (stdout), buf, count);
+ else
+ return write (remote_desc, buf, count);
+}
+
+/* Read COUNT bytes from the client and store in BUF.
+ The result is the number of bytes read or -1 if error.
+ This may return less than COUNT. */
+
+static int
+read_prim (void *buf, int count)
+{
+ if (remote_connection_is_stdio ())
+ return read (fileno (stdin), buf, count);
+ else
+ return read (remote_desc, buf, count);
+}
+
/* Send a packet to the remote machine, with error checking.
The data of the packet is in BUF, and the length of the
packet is in CNT. Returns >= 0 on success, -1 otherwise. */
do
{
- if (write (remote_desc, buf2, p - buf2) != p - buf2)
+ if (write_prim (buf2, p - buf2) != p - buf2)
{
perror ("putpkt(write)");
free (buf2);
int cc;
char c = 0;
- cc = read (remote_desc, &c, 1);
+ cc = read_prim (&c, 1);
if (cc != 1 || c != '\003' || current_inferior == NULL)
{
if (readchar_bufcnt == 0)
{
- readchar_bufcnt = read (remote_desc, readchar_buf,
- sizeof (readchar_buf));
+ readchar_bufcnt = read_prim (readchar_buf, sizeof (readchar_buf));
if (readchar_bufcnt <= 0)
{
fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
(c1 << 4) + c2, csum, buf);
- if (write (remote_desc, "-", 1) != 1)
+ if (write_prim ("-", 1) != 1)
return -1;
}
fflush (stderr);
}
- if (write (remote_desc, "+", 1) != 1)
+ if (write_prim ("+", 1) != 1)
return -1;
if (remote_debug)
#endif
-void
-convert_int_to_ascii (const unsigned char *from, char *to, int n)
-{
- int nib;
- int ch;
- while (n--)
- {
- ch = *from++;
- nib = ((ch & 0xf0) >> 4) & 0x0f;
- *to++ = tohex (nib);
- nib = ch & 0x0f;
- *to++ = tohex (nib);
- }
- *to++ = 0;
-}
-
#ifndef IN_PROCESS_AGENT
-void
-convert_ascii_to_int (const char *from, unsigned char *to, int n)
-{
- int nib1, nib2;
- while (n--)
- {
- nib1 = fromhex (*from++);
- nib2 = fromhex (*from++);
- *to++ = (((nib1 & 0x0f) << 4) & 0xf0) | (nib2 & 0x0f);
- }
-}
-
static char *
outreg (struct regcache *regcache, int regno, char *buf)
{
*buf++ = tohex (regno & 0xf);
*buf++ = ':';
collect_register_as_string (regcache, regno, buf);
- buf += 2 * register_size (regno);
+ buf += 2 * register_size (regcache->tdesc, regno);
*buf++ = ';';
return buf;
struct target_waitstatus *status)
{
if (debug_threads)
- fprintf (stderr, "Writing resume reply for %s:%d\n\n",
- target_pid_to_str (ptid), status->kind);
+ debug_printf ("Writing resume reply for %s:%d\n",
+ target_pid_to_str (ptid), status->kind);
switch (status->kind)
{
sprintf (buf, "T%02x", status->value.sig);
buf += strlen (buf);
- regp = gdbserver_expedite_regs;
-
saved_inferior = current_inferior;
current_inferior = find_thread_ptid (ptid);
+ regp = current_target_desc ()->expedite_regs;
+
regcache = get_thread_regcache (current_inferior, 1);
if (the_target->stopped_by_watchpoint != NULL
while (*regp)
{
- buf = outreg (regcache, find_regno (*regp), buf);
+ buf = outreg (regcache, find_regno (regcache->tdesc, *regp), buf);
regp ++;
}
*buf = '\0';
strcat (buf, ";");
buf += strlen (buf);
- if (the_target->core_of_thread)
- core = (*the_target->core_of_thread) (ptid);
+ core = target_core_of_thread (ptid);
+
if (core != -1)
{
sprintf (buf, "core:");
/* Send the request. */
strcpy (own_buf, "qSymbol:");
- hexify (own_buf + strlen ("qSymbol:"), name, strlen (name));
+ bin2hex ((const gdb_byte *) name, own_buf + strlen ("qSymbol:"),
+ strlen (name));
if (putpkt (own_buf) < 0)
return -1;
decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
mem_buf = xmalloc (mem_len);
if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
- convert_int_to_ascii (mem_buf, own_buf, mem_len);
+ bin2hex (mem_buf, own_buf, mem_len);
else
write_enn (own_buf);
free (mem_buf);
decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
mem_buf = xmalloc (mem_len);
if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
- convert_int_to_ascii (mem_buf, own_buf, mem_len);
+ bin2hex (mem_buf, own_buf, mem_len);
else
write_enn (own_buf);
}
void
monitor_output (const char *msg)
{
- char *buf = xmalloc (strlen (msg) * 2 + 2);
+ int len = strlen (msg);
+ char *buf = xmalloc (len * 2 + 2);
buf[0] = 'O';
- hexify (buf + 1, msg, 0);
+ bin2hex ((const gdb_byte *) msg, buf + 1, len);
putpkt (buf);
free (buf);