/* Main code for remote server for GDB.
Copyright (C) 1989, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GDB.
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
unsigned long cont_thread;
unsigned long general_thread;
/* TERMINAL_FD's original foreground group. */
pid_t old_foreground_pgrp;
-/* Set if you want to disable optional thread related packets support
- in gdbserver, for the sake of testing GDB against stubs that don't
- support them. */
-int disable_packet_vCont;
-int disable_packet_Tthread;
-int disable_packet_qC;
-int disable_packet_qfThreadInfo;
-
/* Hand back terminal ownership to the original foreground group. */
static void
}
#endif
+/* Set if you want to disable optional thread related packets support
+ in gdbserver, for the sake of testing GDB against stubs that don't
+ support them. */
+int disable_packet_vCont;
+int disable_packet_Tthread;
+int disable_packet_qC;
+int disable_packet_qfThreadInfo;
+
static int
target_running (void)
{
return;
}
+ if (strcmp (own_buf, "QStartNoAckMode") == 0)
+ {
+ if (remote_debug)
+ {
+ fprintf (stderr, "[noack mode enabled]\n");
+ fflush (stderr);
+ }
+
+ noack_mode = 1;
+ write_ok (own_buf);
+ return;
+ }
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
if (len > PBUFSIZ - 2)
len = PBUFSIZ - 2;
data = malloc (len + 1);
+ if (data == NULL)
+ {
+ write_enn (own_buf);
+ return;
+ }
n = (*the_target->read_auxv) (ofs, data, len + 1);
if (n < 0)
write_enn (own_buf);
total_len += 128 + 6 * strlen (((struct dll_info *) dll_ptr)->name);
document = malloc (total_len);
+ if (document == NULL)
+ {
+ write_enn (own_buf);
+ return;
+ }
strcpy (document, "<library-list>\n");
p = document + strlen (document);
return;
}
+ if (the_target->qxfer_osdata != NULL
+ && strncmp ("qXfer:osdata:read:", own_buf, 18) == 0)
+ {
+ char *annex;
+ int n;
+ unsigned int len;
+ CORE_ADDR ofs;
+ unsigned char *workbuf;
+
+ strcpy (own_buf, "E00");
+ if (decode_xfer_read (own_buf + 18, &annex, &ofs, &len) < 0)
+ return;
+ if (len > PBUFSIZ - 2)
+ len = PBUFSIZ - 2;
+ workbuf = malloc (len + 1);
+ if (!workbuf)
+ return;
+
+ n = (*the_target->qxfer_osdata) (annex, workbuf, NULL, ofs, len + 1);
+ if (n < 0)
+ write_enn (own_buf);
+ else if (n > len)
+ *new_packet_len_p = write_qxfer_response
+ (own_buf, workbuf, len, 1);
+ else
+ *new_packet_len_p = write_qxfer_response
+ (own_buf, workbuf, n, 0);
+
+ free (workbuf);
+ return;
+ }
+
+ if (the_target->qxfer_siginfo != NULL
+ && strncmp ("qXfer:siginfo:read:", own_buf, 19) == 0)
+ {
+ unsigned char *data;
+ int n;
+ CORE_ADDR ofs;
+ unsigned int len;
+ char *annex;
+
+ require_running (own_buf);
+
+ /* Reject any annex; grab the offset and length. */
+ if (decode_xfer_read (own_buf + 19, &annex, &ofs, &len) < 0
+ || annex[0] != '\0')
+ {
+ strcpy (own_buf, "E00");
+ return;
+ }
+
+ /* Read one extra byte, as an indicator of whether there is
+ more. */
+ if (len > PBUFSIZ - 2)
+ len = PBUFSIZ - 2;
+ data = malloc (len + 1);
+ if (!data)
+ return;
+ n = (*the_target->qxfer_siginfo) (annex, data, NULL, ofs, len + 1);
+ if (n < 0)
+ write_enn (own_buf);
+ else if (n > len)
+ *new_packet_len_p = write_qxfer_response (own_buf, data, len, 1);
+ else
+ *new_packet_len_p = write_qxfer_response (own_buf, data, n, 0);
+
+ free (data);
+ return;
+ }
+
+ if (the_target->qxfer_siginfo != NULL
+ && strncmp ("qXfer:siginfo:write:", own_buf, 20) == 0)
+ {
+ char *annex;
+ int n;
+ unsigned int len;
+ CORE_ADDR ofs;
+ unsigned char *data;
+
+ require_running (own_buf);
+
+ strcpy (own_buf, "E00");
+ data = malloc (packet_len - 19);
+ if (!data)
+ return;
+ if (decode_xfer_write (own_buf + 20, packet_len - 20, &annex,
+ &ofs, &len, data) < 0)
+ {
+ free (data);
+ return;
+ }
+
+ n = (*the_target->qxfer_siginfo)
+ (annex, NULL, (unsigned const char *)data, ofs, len);
+ if (n < 0)
+ write_enn (own_buf);
+ else
+ sprintf (own_buf, "%x", n);
+
+ free (data);
+ return;
+ }
+
/* Protocol features query. */
if (strncmp ("qSupported", own_buf, 10) == 0
&& (own_buf[10] == ':' || own_buf[10] == '\0'))
if (the_target->qxfer_spu != NULL)
strcat (own_buf, ";qXfer:spu:read+;qXfer:spu:write+");
+ if (the_target->qxfer_siginfo != NULL)
+ strcat (own_buf, ";qXfer:siginfo:read+;qXfer:siginfo:write+");
+
/* We always report qXfer:features:read, as targets may
install XML files on a subsequent call to arch_setup.
If we reported to GDB on startup that we don't support
qXfer:feature:read at all, we will never be re-queried. */
strcat (own_buf, ";qXfer:features:read+");
+ if (transport_is_reliable)
+ strcat (own_buf, ";QStartNoAckMode+");
+
+ if (the_target->qxfer_osdata != NULL)
+ strcat (own_buf, ";qXfer:osdata:read+");
+
return;
}
char *mon = malloc (PBUFSIZ);
int len = strlen (own_buf + 6);
+ if (mon == NULL)
+ {
+ write_enn (own_buf);
+ return;
+ }
+
if ((len % 2) != 0 || unhexify (mon, own_buf + 6, len / 2) != len / 2)
{
write_enn (own_buf);
behavior; if no default action is in the list, we'll need the extra
slot. */
resume_info = malloc ((n + 1) * sizeof (resume_info[0]));
+ if (resume_info == NULL)
+ goto err;
default_action.thread = -1;
default_action.leave_stopped = 1;
static int
handle_v_run (char *own_buf, char *status, int *signal)
{
- char *p, **pp, *next_p, **new_argv;
+ char *p, *next_p, **new_argv;
int i, new_argc;
new_argc = 0;
new_argc++;
}
- new_argv = malloc ((new_argc + 2) * sizeof (char *));
+ new_argv = calloc (new_argc + 2, sizeof (char *));
+ if (new_argv == NULL)
+ {
+ write_enn (own_buf);
+ return 0;
+ }
+
i = 0;
for (p = own_buf + strlen ("vRun;"); *p; p = next_p)
{
new_argv[i] = NULL;
else
{
- new_argv[i] = malloc (1 + (next_p - p) / 2);
+ /* FIXME: Fail request if out of memory instead of dying. */
+ new_argv[i] = xmalloc (1 + (next_p - p) / 2);
unhexify (new_argv[i], p, (next_p - p) / 2);
new_argv[i][(next_p - p) / 2] = '\0';
}
if (new_argv[0] == NULL)
{
+ /* GDB didn't specify a program to run. Use the program from the
+ last run with the new argument list. */
+
if (program_argv == NULL)
{
+ /* FIXME: new_argv memory leak */
write_enn (own_buf);
return 0;
}
new_argv[0] = strdup (program_argv[0]);
+ if (new_argv[0] == NULL)
+ {
+ /* FIXME: new_argv memory leak */
+ write_enn (own_buf);
+ return 0;
+ }
}
- /* Free the old argv. */
- if (program_argv)
- {
- for (pp = program_argv; *pp != NULL; pp++)
- free (*pp);
- free (program_argv);
- }
+ /* Free the old argv and install the new one. */
+ freeargv (program_argv);
program_argv = new_argv;
*signal = start_inferior (program_argv, status);
gdbserver_version (void)
{
printf ("GNU gdbserver %s%s\n"
- "Copyright (C) 2007 Free Software Foundation, Inc.\n"
+ "Copyright (C) 2009 Free Software Foundation, Inc.\n"
"gdbserver is free software, covered by the GNU General Public License.\n"
"This gdbserver was configured as \"%s\"\n",
PKGVERSION, version, host_name);
"HOST:PORT to listen for a TCP connection.\n"
"\n"
"Options:\n"
- " --debug\t\tEnable debugging output.\n"
- " --version\t\tDisplay version information and exit.\n"
- " --wrapper WRAPPER --\tRun WRAPPER to start new programs.\n");
+ " --debug Enable general debugging output.\n"
+ " --remote-debug Enable remote protocol debugging output.\n"
+ " --version Display version information and exit.\n"
+ " --wrapper WRAPPER -- Run WRAPPER to start new programs.\n");
if (REPORT_BUGS_TO[0] && stream == stdout)
fprintf (stream, "Report bugs to \"%s\".\n", REPORT_BUGS_TO);
}
}
else if (strcmp (*next_arg, "--debug") == 0)
debug_threads = 1;
+ else if (strcmp (*next_arg, "--remote-debug") == 0)
+ remote_debug = 1;
else if (strcmp (*next_arg, "--disable-packet") == 0)
{
gdbserver_show_disableable (stdout);
initialize_async_io ();
initialize_low ();
- own_buf = malloc (PBUFSIZ + 1);
- mem_buf = malloc (PBUFSIZ);
+ own_buf = xmalloc (PBUFSIZ + 1);
+ mem_buf = xmalloc (PBUFSIZ);
if (pid == 0 && *next_arg != NULL)
{
int i, n;
n = argc - (next_arg - argv);
- program_argv = malloc (sizeof (char *) * (n + 1));
+ program_argv = xmalloc (sizeof (char *) * (n + 1));
for (i = 0; i < n; i++)
- program_argv[i] = strdup (next_arg[i]);
+ program_argv[i] = xstrdup (next_arg[i]);
program_argv[i] = NULL;
/* Wait till we are at first instruction in program. */
while (1)
{
+ noack_mode = 0;
remote_open (port);
restart: