/* 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
- Free Software Foundation, Inc.
+ Copyright (C) 1986-2015 Free Software Foundation, Inc.
This file is part of GDB.
#include "server.h"
#include "terminal.h"
#include "target.h"
-#include <stdio.h>
-#include <string.h>
+#include "gdbthread.h"
+#include "tdesc.h"
+#include "dll.h"
+#include "rsp-low.h"
+#include <ctype.h>
#if HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#include <sys/time.h>
-#if HAVE_UNISTD_H
+#include "gdb_sys_time.h"
#include <unistd.h>
-#endif
#if HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <sys/stat.h>
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
#if USE_WIN32API
#include <winsock2.h>
int remote_debug = 0;
struct ui_file *gdb_stdlog;
-static int remote_desc = INVALID_DESCRIPTOR;
-static int listen_desc = INVALID_DESCRIPTOR;
+static int remote_is_stdio = 0;
+
+static gdb_fildes_t remote_desc = INVALID_DESCRIPTOR;
+static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
/* FIXME headerize? */
extern int using_threads;
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);
(char *) &tmp, sizeof (tmp));
#ifndef USE_WIN32API
- close (listen_desc); /* No longer need this */
-
signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply
exits when the remote side dies. */
+#endif
+
+ if (run_once)
+ {
+#ifndef USE_WIN32API
+ close (listen_desc); /* No longer need this */
#else
- closesocket (listen_desc); /* No longer need this */
+ closesocket (listen_desc); /* No longer need this */
#endif
+ }
+ /* Even if !RUN_ONCE no longer notice new connections. Still keep the
+ descriptor open for add_file_handler to wait for a new connection. */
delete_file_handler (listen_desc);
/* Convert IP address to string. */
return 0;
}
+/* Prepare for a later connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+void
+remote_prepare (char *name)
+{
+ char *port_str;
+#ifdef USE_WIN32API
+ static int winsock_initialized;
+#endif
+ int port;
+ struct sockaddr_in sockaddr;
+ 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)
+ {
+ transport_is_reliable = 0;
+ return;
+ }
+
+ port = strtoul (port_str + 1, &port_end, 10);
+ if (port_str[1] == '\0' || *port_end != '\0')
+ error ("Bad port argument: %s", name);
+
+#ifdef USE_WIN32API
+ if (!winsock_initialized)
+ {
+ WSADATA wsad;
+
+ WSAStartup (MAKEWORD (1, 0), &wsad);
+ winsock_initialized = 1;
+ }
+#endif
+
+ listen_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (listen_desc == -1)
+ perror_with_name ("Can't open socket");
+
+ /* Allow rapid reuse of this port. */
+ tmp = 1;
+ setsockopt (listen_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
+ sizeof (tmp));
+
+ sockaddr.sin_family = PF_INET;
+ sockaddr.sin_port = htons (port);
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind (listen_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
+ || listen (listen_desc, 1))
+ perror_with_name ("Can't bind address");
+
+ transport_is_reliable = 1;
+}
+
/* Open a connection to a remote debugger.
NAME is the filename used for communication. */
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
fprintf (stderr, "Remote debugging using %s\n", name);
- transport_is_reliable = 0;
-
enable_async_notification (remote_desc);
/* Register the event loop handler. */
add_file_handler (remote_desc, handle_serial_event, NULL);
-#endif /* USE_WIN32API */
}
+#endif /* USE_WIN32API */
else
{
-#ifdef USE_WIN32API
- static int winsock_initialized;
-#endif
int port;
+ socklen_t len;
struct sockaddr_in sockaddr;
- socklen_t tmp;
- char *port_end;
- port = strtoul (port_str + 1, &port_end, 10);
- if (port_str[1] == '\0' || *port_end != '\0')
- fatal ("Bad port argument: %s", name);
-
-#ifdef USE_WIN32API
- if (!winsock_initialized)
- {
- WSADATA wsad;
-
- WSAStartup (MAKEWORD (1, 0), &wsad);
- winsock_initialized = 1;
- }
-#endif
-
- listen_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (listen_desc == -1)
- perror_with_name ("Can't open socket");
-
- /* Allow rapid reuse of this port. */
- tmp = 1;
- setsockopt (listen_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
- sizeof (tmp));
-
- sockaddr.sin_family = PF_INET;
- sockaddr.sin_port = htons (port);
- sockaddr.sin_addr.s_addr = INADDR_ANY;
-
- if (bind (listen_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
- || listen (listen_desc, 1))
- perror_with_name ("Can't bind address");
-
- /* If port is zero, a random port will be selected, and the
- fprintf below needs to know what port was selected. */
- if (port == 0)
- {
- socklen_t len = sizeof (sockaddr);
- if (getsockname (listen_desc, (struct sockaddr *) &sockaddr, &len) < 0
- || len < sizeof (sockaddr))
- perror_with_name ("Can't determine port");
- port = ntohs (sockaddr.sin_port);
- }
+ len = sizeof (sockaddr);
+ if (getsockname (listen_desc,
+ (struct sockaddr *) &sockaddr, &len) < 0
+ || len < sizeof (sockaddr))
+ perror_with_name ("Can't determine port");
+ port = ntohs (sockaddr.sin_port);
fprintf (stderr, "Listening on port %d\n", port);
fflush (stderr);
/* Register the event loop handler. */
add_file_handler (listen_desc, handle_accept_event, NULL);
-
- transport_is_reliable = 1;
}
}
#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. */
{
ULONGEST ret;
- if (strncmp (buf, "-1", 2) == 0)
+ if (startswith (buf, "-1"))
{
ret = (ULONGEST) -1;
buf += 2;
/* No multi-process. Just a tid. */
tid = hex_or_minus_one (p, &pp);
- /* 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);
+ /* Since GDB is not sending a process id (multi-process extensions
+ are off), then there's only one process. Default to the first in
+ the list. */
+ pid = pid_of (get_first_process ());
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. */
char *p;
int cc;
- buf2 = xmalloc (PBUFSIZ);
+ buf2 = (char *) xmalloc (strlen ("$") + cnt + strlen ("#nn") + 1);
/* Copy the packet into buffer BUF2, encapsulating it
and giving it a checksum. */
do
{
- if (write (remote_desc, buf2, p - buf2) != p - buf2)
+ if (write_prim (buf2, p - buf2) != p - buf2)
{
perror ("putpkt(write)");
free (buf2);
}
/* Check for an input interrupt while we're here. */
- if (cc == '\003' && current_inferior != NULL)
+ if (cc == '\003' && current_thread != NULL)
(*the_target->request_interrupt) ();
}
while (cc != '+');
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 (cc == 0)
{
- fprintf (stderr, "input_interrupt, count = %d c = %d ('%c')\n",
- cc, c, c);
+ fprintf (stderr, "client connection closed\n");
+ return;
+ }
+ else if (cc != 1 || c != '\003')
+ {
+ fprintf (stderr, "input_interrupt, count = %d c = %d ", cc, c);
+ if (isprint (c))
+ fprintf (stderr, "('%c')\n", c);
+ else
+ fprintf (stderr, "('\\x%02x')\n", c & 0xff);
return;
}
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)
{
if (noack_mode)
{
- fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s [no-ack-mode, Bad medium?]\n",
+ fprintf (stderr,
+ "Bad checksum, sentsum=0x%x, csum=0x%x, "
+ "buf=%s [no-ack-mode, Bad medium?]\n",
(c1 << 4) + c2, csum, buf);
/* Not much we can do, GDB wasn't expecting an ack/nac. */
break;
fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
(c1 << 4) + c2, csum, buf);
- write (remote_desc, "-", 1);
+ if (write_prim ("-", 1) != 1)
+ return -1;
}
if (!noack_mode)
fflush (stderr);
}
- write (remote_desc, "+", 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)
{
case TARGET_WAITKIND_STOPPED:
+ case TARGET_WAITKIND_FORKED:
+ case TARGET_WAITKIND_VFORKED:
+ case TARGET_WAITKIND_VFORK_DONE:
+ case TARGET_WAITKIND_EXECD:
{
- struct thread_info *saved_inferior;
+ struct thread_info *saved_thread;
const char **regp;
struct regcache *regcache;
- sprintf (buf, "T%02x", status->value.sig);
+ if ((status->kind == TARGET_WAITKIND_FORKED && report_fork_events)
+ || (status->kind == TARGET_WAITKIND_VFORKED && report_vfork_events))
+ {
+ enum gdb_signal signal = GDB_SIGNAL_TRAP;
+ const char *event = (status->kind == TARGET_WAITKIND_FORKED
+ ? "fork" : "vfork");
+
+ sprintf (buf, "T%02x%s:", signal, event);
+ buf += strlen (buf);
+ buf = write_ptid (buf, status->value.related_pid);
+ strcat (buf, ";");
+ }
+ else if (status->kind == TARGET_WAITKIND_VFORK_DONE && report_vfork_events)
+ {
+ enum gdb_signal signal = GDB_SIGNAL_TRAP;
+
+ sprintf (buf, "T%02xvforkdone:;", signal);
+ }
+ else if (status->kind == TARGET_WAITKIND_EXECD && report_exec_events)
+ {
+ enum gdb_signal signal = GDB_SIGNAL_TRAP;
+ const char *event = "exec";
+ char hexified_pathname[PATH_MAX * 2];
+
+ sprintf (buf, "T%02x%s:", signal, event);
+ buf += strlen (buf);
+
+ /* Encode pathname to hexified format. */
+ bin2hex ((const gdb_byte *) status->value.execd_pathname,
+ hexified_pathname,
+ strlen (status->value.execd_pathname));
+
+ sprintf (buf, "%s;", hexified_pathname);
+ xfree (status->value.execd_pathname);
+ status->value.execd_pathname = NULL;
+ buf += strlen (buf);
+ }
+ else
+ sprintf (buf, "T%02x", status->value.sig);
+
buf += strlen (buf);
- regp = gdbserver_expedite_regs;
+ saved_thread = current_thread;
- saved_inferior = current_inferior;
+ current_thread = find_thread_ptid (ptid);
- current_inferior = find_thread_ptid (ptid);
+ regp = current_target_desc ()->expedite_regs;
- regcache = get_thread_regcache (current_inferior, 1);
+ regcache = get_thread_regcache (current_thread, 1);
if (the_target->stopped_by_watchpoint != NULL
&& (*the_target->stopped_by_watchpoint) ())
*buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
*buf++ = ';';
}
+ else if (swbreak_feature && target_stopped_by_sw_breakpoint ())
+ {
+ sprintf (buf, "swbreak:;");
+ buf += strlen (buf);
+ }
+ else if (hwbreak_feature && target_stopped_by_hw_breakpoint ())
+ {
+ sprintf (buf, "hwbreak:;");
+ buf += strlen (buf);
+ }
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:");
dlls_changed = 0;
}
- current_inferior = saved_inferior;
+ current_thread = saved_thread;
}
break;
case TARGET_WAITKIND_EXITED:
}
if (*to_p == NULL)
- *to_p = xmalloc (*len_ptr);
+ *to_p = (unsigned char *) xmalloc (*len_ptr);
- convert_ascii_to_int (&from[i++], *to_p, *len_ptr);
+ hex2bin (&from[i++], *to_p, *len_ptr);
}
int
}
if (*to_p == NULL)
- *to_p = xmalloc (*len_ptr);
+ *to_p = (unsigned char *) xmalloc (*len_ptr);
if (remote_unescape_input ((const gdb_byte *) &from[i], packet_len - i,
*to_p, *len_ptr) != *len_ptr)
}
/* Decode a qXfer write request. */
+
int
-decode_xfer_write (char *buf, int packet_len, char **annex, CORE_ADDR *offset,
+decode_xfer_write (char *buf, int packet_len, CORE_ADDR *offset,
unsigned int *len, unsigned char *data)
{
char ch;
-
- /* Extract and NUL-terminate the annex. */
- *annex = buf;
- while (*buf && *buf != ':')
- buf++;
- if (*buf == '\0')
- return -1;
- *buf++ = 0;
+ char *b = buf;
/* Extract the offset. */
*offset = 0;
}
/* Get encoded data. */
- packet_len -= buf - *annex;
+ packet_len -= buf - b;
*len = remote_unescape_input ((const gdb_byte *) buf, packet_len,
data, packet_len);
return 0;
/* 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;
unsigned int mem_len;
decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
- mem_buf = xmalloc (mem_len);
+ mem_buf = (unsigned char *) 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);
return -1;
}
- if (strncmp (own_buf, "qSymbol:", strlen ("qSymbol:")) != 0)
+ if (!startswith (own_buf, "qSymbol:"))
{
warning ("Malformed response to qSymbol, ignoring: %s\n", own_buf);
return -1;
decode_address (addrp, p, q - p);
/* Save the symbol in our cache. */
- sym = xmalloc (sizeof (*sym));
+ sym = XNEW (struct sym_cache);
sym->name = xstrdup (name);
sym->addr = *addrp;
sym->next = proc->symbol_cache;
where we want the instruction to be copied (and possibly adjusted)
to. On output, it points to one past the end of the resulting
instruction(s). The effect of executing the instruction at TO
- shall be the same as if executing it at FROM. For example, call
+ shall be the same as if executing it at OLDLOC. For example, call
instructions that implicitly push the return address on the stack
should be adjusted to return to the instruction after OLDLOC;
relative branches, and other PC-relative instructions need the
if (own_buf[0] == 'm')
{
decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
- mem_buf = xmalloc (mem_len);
+ mem_buf = (unsigned char *) 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);
}
return -1;
}
- if (strncmp (own_buf, "qRelocInsn:", strlen ("qRelocInsn:")) != 0)
+ if (!startswith (own_buf, "qRelocInsn:"))
{
warning ("Malformed response to qRelocInsn, ignoring: %s\n",
own_buf);
void
monitor_output (const char *msg)
{
- char *buf = xmalloc (strlen (msg) * 2 + 2);
+ int len = strlen (msg);
+ char *buf = (char *) xmalloc (len * 2 + 2);
buf[0] = 'O';
- hexify (buf + 1, msg, 0);
+ bin2hex ((const gdb_byte *) msg, buf + 1, len);
putpkt (buf);
free (buf);
}
-/* Return a malloc allocated string with special characters from TEXT
- replaced by entity references. */
-
-char *
-xml_escape_text (const char *text)
-{
- char *result;
- int i, special;
-
- /* Compute the length of the result. */
- for (i = 0, special = 0; text[i] != '\0'; i++)
- switch (text[i])
- {
- case '\'':
- case '\"':
- special += 5;
- break;
- case '&':
- special += 4;
- break;
- case '<':
- case '>':
- special += 3;
- break;
- default:
- break;
- }
-
- /* Expand the result. */
- result = xmalloc (i + special + 1);
- for (i = 0, special = 0; text[i] != '\0'; i++)
- switch (text[i])
- {
- case '\'':
- strcpy (result + i + special, "'");
- special += 5;
- break;
- case '\"':
- strcpy (result + i + special, """);
- special += 5;
- break;
- case '&':
- strcpy (result + i + special, "&");
- special += 4;
- break;
- case '<':
- strcpy (result + i + special, "<");
- special += 3;
- break;
- case '>':
- strcpy (result + i + special, ">");
- special += 3;
- break;
- default:
- result[i + special] = text[i];
- break;
- }
- result[i + special] = '\0';
-
- return result;
-}
-
-void
-buffer_grow (struct buffer *buffer, const char *data, size_t size)
-{
- char *new_buffer;
- size_t new_buffer_size;
-
- if (size == 0)
- return;
-
- new_buffer_size = buffer->buffer_size;
-
- if (new_buffer_size == 0)
- new_buffer_size = 1;
-
- while (buffer->used_size + size > new_buffer_size)
- new_buffer_size *= 2;
- new_buffer = realloc (buffer->buffer, new_buffer_size);
- if (!new_buffer)
- abort ();
- memcpy (new_buffer + buffer->used_size, data, size);
- buffer->buffer = new_buffer;
- buffer->buffer_size = new_buffer_size;
- buffer->used_size += size;
-}
-
-void
-buffer_free (struct buffer *buffer)
-{
- if (!buffer)
- return;
-
- free (buffer->buffer);
- buffer->buffer = NULL;
- buffer->buffer_size = 0;
- buffer->used_size = 0;
-}
-
-void
-buffer_init (struct buffer *buffer)
-{
- memset (buffer, 0, sizeof (*buffer));
-}
-
-char*
-buffer_finish (struct buffer *buffer)
-{
- char *ret = buffer->buffer;
- buffer->buffer = NULL;
- buffer->buffer_size = 0;
- buffer->used_size = 0;
- return ret;
-}
-
-void
-buffer_xml_printf (struct buffer *buffer, const char *format, ...)
-{
- va_list ap;
- const char *f;
- const char *prev;
- int percent = 0;
-
- va_start (ap, format);
-
- prev = format;
- for (f = format; *f; f++)
- {
- if (percent)
- {
- switch (*f)
- {
- case 's':
- {
- char *p;
- char *a = va_arg (ap, char *);
- buffer_grow (buffer, prev, f - prev - 1);
- p = xml_escape_text (a);
- buffer_grow_str (buffer, p);
- free (p);
- prev = f + 1;
- }
- break;
- case 'd':
- {
- int i = va_arg (ap, int);
- char b[sizeof ("4294967295")];
-
- buffer_grow (buffer, prev, f - prev - 1);
- sprintf (b, "%d", i);
- buffer_grow_str (buffer, b);
- prev = f + 1;
- }
- }
- percent = 0;
- }
- else if (*f == '%')
- percent = 1;
- }
-
- buffer_grow_str (buffer, prev);
- va_end (ap);
-}
-
#endif