aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2008-01-30 00:51:50 +0000
committerDaniel Jacobowitz <drow@false.org>2008-01-30 00:51:50 +0000
commit2d717e4f8a548fbfc4fabe506fd1d53f6b81994d (patch)
tree28e3eacb77be01a42135a0df907a10fd57917d85 /gdb/gdbserver
parent9dc513fc0e920994bd8f7cad33c6920c1285ce29 (diff)
downloadgdb-2d717e4f8a548fbfc4fabe506fd1d53f6b81994d.zip
gdb-2d717e4f8a548fbfc4fabe506fd1d53f6b81994d.tar.gz
gdb-2d717e4f8a548fbfc4fabe506fd1d53f6b81994d.tar.bz2
* linux-low.c (linux_attach_lwp): Do not _exit after errors.
(linux_kill, linux_detach): Clean up the process list. * remote-utils.c (remote_open): Improve port number parsing. (putpkt_binary, input_interrupt): Only send interrupts if the target is running. * server.c (extended_protocol): Make static. (attached): Define earlier. (exit_requested, response_needed, program_argv): New variables. (target_running): New. (start_inferior): Clear attached here. (attach_inferior): Set attached here. (require_running): Define. (handle_query): Use require_running and target_running. Implement "monitor exit". (handle_v_attach, handle_v_run): New. (handle_v_requests): Use require_running. Handle vAttach and vRun. (gdbserver_usage): Update. (main): Redo argument parsing. Handle --debug and --multi. Handle --attach along with other options or after the port. Save program_argv. Support no initial program. Resynchronize communication with GDB after an error. Handle "monitor exit". Use require_running and target_running. Always allow the extended protocol. Do not error out for Hc0 or Hc-1. Do not automatically restart in extended mode. * README: Refer to the GDB manual. Update --attach usage. * remote.c (struct remote_state): Add cached_wait_status. (remote_exec_file): New variable. (PACKET_vAttach, PACKET_vRun): New constants. (extended_remote_restart): Do not query for status. (struct start_remote_args): New. (remote_start_remote): Take it as a second argument. Check whether the target is running. Issue an error for non-running non-extended targets. Cache the wait status. Set inferior_ptid here. (remote_open_1): Prompt to disconnect non-running targets. Make sure the target is marked running. Do not set inferior_ptid here. Update call to remote_start_remote. Do not call remote_check_symbols if the target is not running. (remote_detach_1): Rename from remote_detach. Take an EXTENDED argument. Handle a non-running target. (remote_detach): Use it. (extended_remote_detach): New. (remote_disconnect): Fix typo. Use remoute_mourn_1. (extended_remote_attach_1, extended_remote_attach) (extended_async_remote_attach): New. (remote_vcont_resume): Remove unused variable. (remote_wait, remote_async_wait): Use any cached wait status. (putpkt_binary, getpkt): Clear any cached wait status. (extended_remoute_mourn_1): New. (extended_remote_mourn): Use it. (extended_async_remote_mourn, extended_remote_run): New. (extended_remote_create_inferior_1): New. (extended_remote_create_inferior): Use it. (extended_remote_async_create_inferior): Likewise. (remote_xfer_partial): Skip for non-executing targets. (init_extended_remote_ops): Set to_detach and to_attach. (init_extended_async_remote_ops): Likewise. Use extended_async_remote_mourn. (_initialize_remote): Register vAttach, vRun, and set remote exec-file. * NEWS: Mention vAttach, vRun, and gdbserver extended-remote support. * gdb.server/ext-attach.c, gdb.server/ext-attach.exp, gdb.server/ext-run.exp: New files. * lib/gdbserver-support.exp (gdbserver_download): New. (gdbserver_start): New. Update gdbserver expected output. (gdbserver_spawn): Use them. (gdbserver_start_extended): New. * gdb.texinfo (Using the `gdbserver' Program): Add security warning. Rearrange into subsections and subsubsections. Document --multi and --debug. Correct --with-sysroot typo. Update --attach usage. Make load reference clearer. Document monitor exit. (Remote Configuration): Document set remote exec-file, attach-packet, and run-packet. (Packets): Document vAttach and vRun.
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r--gdb/gdbserver/ChangeLog28
-rw-r--r--gdb/gdbserver/README4
-rw-r--r--gdb/gdbserver/linux-low.c24
-rw-r--r--gdb/gdbserver/remote-utils.c12
-rw-r--r--gdb/gdbserver/server.c468
5 files changed, 410 insertions, 126 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index ced28cd..5a6e7b9 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,31 @@
+2008-01-29 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * linux-low.c (linux_attach_lwp): Do not _exit after errors.
+ (linux_kill, linux_detach): Clean up the process list.
+ * remote-utils.c (remote_open): Improve port number parsing.
+ (putpkt_binary, input_interrupt): Only send interrupts if the target
+ is running.
+ * server.c (extended_protocol): Make static.
+ (attached): Define earlier.
+ (exit_requested, response_needed, program_argv): New variables.
+ (target_running): New.
+ (start_inferior): Clear attached here.
+ (attach_inferior): Set attached here.
+ (require_running): Define.
+ (handle_query): Use require_running and target_running. Implement
+ "monitor exit".
+ (handle_v_attach, handle_v_run): New.
+ (handle_v_requests): Use require_running. Handle vAttach and vRun.
+ (gdbserver_usage): Update.
+ (main): Redo argument parsing. Handle --debug and --multi. Handle
+ --attach along with other options or after the port. Save
+ program_argv. Support no initial program. Resynchronize
+ communication with GDB after an error. Handle "monitor exit".
+ Use require_running and target_running. Always allow the extended
+ protocol. Do not error out for Hc0 or Hc-1. Do not automatically
+ restart in extended mode.
+ * README: Refer to the GDB manual. Update --attach usage.
+
2007-12-20 Andreas Schwab <schwab@suse.de>
* linux-low.c (STACK_SIZE): Define.
diff --git a/gdb/gdbserver/README b/gdb/gdbserver/README
index eda00ba..9394198 100644
--- a/gdb/gdbserver/README
+++ b/gdb/gdbserver/README
@@ -9,6 +9,8 @@ host. GDB and GDBserver communicate using the standard remote serial protocol
implemented in remote.c, and various *-stub.c files. They communicate via
either a serial line or a TCP connection.
+For more information about GDBserver, see the GDB manual.
+
Usage (server (target) side):
First, you need to have a copy of the program you want to debug put onto
@@ -47,7 +49,7 @@ print an error message and exit.
On some targets, gdbserver can also attach to running programs. This is
accomplished via the --attach argument. The syntax is:
- target> gdbserver COMM --attach PID
+ target> gdbserver --attach COMM PID
PID is the process ID of a currently running process. It isn't necessary
to point gdbserver at a binary for the running process.
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index e5cb528..f5bf5dc 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -304,14 +304,18 @@ linux_attach_lwp (unsigned long pid)
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
{
- fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
+ if (all_threads.head != NULL)
+ {
+ /* If we fail to attach to an LWP, just warn. */
+ fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
+ strerror (errno), errno);
+ fflush (stderr);
+ return;
+ }
+ else
+ /* If we fail to attach to a process, report an error. */
+ error ("Cannot attach to process %ld: %s (%d)\n", pid,
strerror (errno), errno);
- fflush (stderr);
-
- /* If we fail to attach to an LWP, just return. */
- if (all_threads.head == NULL)
- _exit (0177);
- return;
}
ptrace (PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACECLONE);
@@ -396,6 +400,10 @@ linux_kill (void)
/* Make sure it died. The loop is most likely unnecessary. */
wstat = linux_wait_for_event (thread);
} while (WIFSTOPPED (wstat));
+
+ clear_inferiors ();
+ free (all_processes.head);
+ all_processes.head = all_processes.tail = NULL;
}
static void
@@ -434,6 +442,8 @@ linux_detach (void)
delete_all_breakpoints ();
for_each_inferior (&all_threads, linux_detach_one_process);
clear_inferiors ();
+ free (all_processes.head);
+ all_processes.head = all_processes.tail = NULL;
return 0;
}
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 68ed939..2e049ee 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -187,15 +187,15 @@ remote_open (char *name)
#ifdef USE_WIN32API
static int winsock_initialized;
#endif
- char *port_str;
int port;
struct sockaddr_in sockaddr;
socklen_t tmp;
int tmp_desc;
+ char *port_end;
- port_str = strchr (name, ':');
-
- port = atoi (port_str + 1);
+ 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)
@@ -575,7 +575,7 @@ putpkt_binary (char *buf, int cnt)
}
/* Check for an input interrupt while we're here. */
- if (buf3[0] == '\003')
+ if (buf3[0] == '\003' && current_inferior != NULL)
(*the_target->request_interrupt) ();
}
while (buf3[0] != '+');
@@ -617,7 +617,7 @@ input_interrupt (int unused)
cc = read (remote_desc, &c, 1);
- if (cc != 1 || c != '\003')
+ if (cc != 1 || c != '\003' || current_inferior == NULL)
{
fprintf (stderr, "input_interrupt, count = %d c = %d ('%c')\n",
cc, c, c);
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index a6cb125..51dfbcc 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -34,9 +34,15 @@ unsigned long general_thread;
unsigned long step_thread;
unsigned long thread_from_wait;
unsigned long old_thread_from_wait;
-int extended_protocol;
int server_waiting;
+static int extended_protocol;
+static int attached;
+static int response_needed;
+static int exit_requested;
+
+static char **program_argv;
+
/* Enable miscellaneous debugging output. The name is historical - it
was originally used to debug LinuxThreads support. */
int debug_threads;
@@ -69,8 +75,16 @@ restore_old_foreground_pgrp (void)
#endif
static int
+target_running (void)
+{
+ return all_threads.head != NULL;
+}
+
+static int
start_inferior (char *argv[], char *statusptr)
{
+ attached = 0;
+
#ifdef SIGTTOU
signal (SIGTTOU, SIG_DFL);
signal (SIGTTIN, SIG_DFL);
@@ -107,6 +121,8 @@ attach_inferior (int pid, char *statusptr, int *sigptr)
if (myattach (pid) != 0)
return -1;
+ attached = 1;
+
fprintf (stderr, "Attached; pid = %d\n", pid);
fflush (stderr);
@@ -254,6 +270,13 @@ monitor_show_help (void)
monitor_output (" Enable remote protocol debugging messages\n");
}
+#define require_running(BUF) \
+ if (!target_running ()) \
+ { \
+ write_enn (BUF); \
+ return; \
+ }
+
/* Handle all of the extended 'q' packets. */
void
handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
@@ -263,6 +286,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
/* Reply the current thread id. */
if (strcmp ("qC", own_buf) == 0)
{
+ require_running (own_buf);
thread_ptr = all_threads.head;
sprintf (own_buf, "QC%x",
thread_to_gdb_id ((struct thread_info *)thread_ptr));
@@ -271,7 +295,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (strcmp ("qSymbol::", own_buf) == 0)
{
- if (the_target->look_up_symbols != NULL)
+ if (target_running () && the_target->look_up_symbols != NULL)
(*the_target->look_up_symbols) ();
strcpy (own_buf, "OK");
@@ -280,6 +304,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (strcmp ("qfThreadInfo", own_buf) == 0)
{
+ require_running (own_buf);
thread_ptr = all_threads.head;
sprintf (own_buf, "m%x", thread_to_gdb_id ((struct thread_info *)thread_ptr));
thread_ptr = thread_ptr->next;
@@ -288,6 +313,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (strcmp ("qsThreadInfo", own_buf) == 0)
{
+ require_running (own_buf);
if (thread_ptr != NULL)
{
sprintf (own_buf, "m%x", thread_to_gdb_id ((struct thread_info *)thread_ptr));
@@ -305,7 +331,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
&& strcmp ("qOffsets", own_buf) == 0)
{
CORE_ADDR text, data;
-
+
+ require_running (own_buf);
if (the_target->read_offsets (&text, &data))
sprintf (own_buf, "Text=%lX;Data=%lX;Bss=%lX",
(long)text, (long)data, (long)data);
@@ -324,6 +351,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
CORE_ADDR ofs;
unsigned char *spu_buf;
+ require_running (own_buf);
strcpy (own_buf, "E00");
if (decode_xfer_read (own_buf + 15, &annex, &ofs, &len) < 0)
return;
@@ -356,6 +384,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
CORE_ADDR ofs;
unsigned char *spu_buf;
+ require_running (own_buf);
strcpy (own_buf, "E00");
spu_buf = malloc (packet_len - 15);
if (!spu_buf)
@@ -387,6 +416,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
unsigned int len;
char *annex;
+ require_running (own_buf);
+
/* Reject any annex; grab the offset and length. */
if (decode_xfer_read (own_buf + 16, &annex, &ofs, &len) < 0
|| annex[0] != '\0')
@@ -420,6 +451,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
const char *document;
char *annex;
+ require_running (own_buf);
+
/* Check for support. */
document = get_features_xml ("target.xml");
if (document == NULL)
@@ -467,6 +500,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
struct inferior_list_entry *dll_ptr;
char *annex;
+ require_running (own_buf);
+
/* Reject any annex; grab the offset and length. */
if (decode_xfer_read (own_buf + 21, &annex, &ofs, &len) < 0
|| annex[0] != '\0')
@@ -535,7 +570,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (the_target->read_auxv != NULL)
strcat (own_buf, ";qXfer:auxv:read+");
-
+
if (the_target->qxfer_spu != NULL)
strcat (own_buf, ";qXfer:spu:read+;qXfer:spu:write+");
@@ -553,6 +588,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
CORE_ADDR parts[3], address = 0;
int i, err;
+ require_running (own_buf);
+
for (i = 0; i < 3; i++)
{
char *p2;
@@ -642,6 +679,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
}
else if (strcmp (mon, "help") == 0)
monitor_show_help ();
+ else if (strcmp (mon, "exit") == 0)
+ exit_requested = 1;
else
{
monitor_output ("Unknown monitor command.\n\n");
@@ -772,6 +811,95 @@ err:
return;
}
+/* Attach to a new program. Return 1 if successful, 0 if failure. */
+int
+handle_v_attach (char *own_buf, char *status, int *signal)
+{
+ int pid;
+
+ pid = strtol (own_buf + 8, NULL, 16);
+ if (pid != 0 && attach_inferior (pid, status, signal) == 0)
+ {
+ prepare_resume_reply (own_buf, *status, *signal);
+ return 1;
+ }
+ else
+ {
+ write_enn (own_buf);
+ return 0;
+ }
+}
+
+/* Run a new program. Return 1 if successful, 0 if failure. */
+static int
+handle_v_run (char *own_buf, char *status, int *signal)
+{
+ char *p, **pp, *next_p, **new_argv;
+ int i, new_argc;
+
+ new_argc = 0;
+ for (p = own_buf + strlen ("vRun;"); p && *p; p = strchr (p, ';'))
+ {
+ p++;
+ new_argc++;
+ }
+
+ new_argv = malloc ((new_argc + 2) * sizeof (char *));
+ i = 0;
+ for (p = own_buf + strlen ("vRun;"); *p; p = next_p)
+ {
+ next_p = strchr (p, ';');
+ if (next_p == NULL)
+ next_p = p + strlen (p);
+
+ if (i == 0 && p == next_p)
+ new_argv[i] = NULL;
+ else
+ {
+ new_argv[i] = malloc (1 + (next_p - p) / 2);
+ unhexify (new_argv[i], p, (next_p - p) / 2);
+ new_argv[i][(next_p - p) / 2] = '\0';
+ }
+
+ if (*next_p)
+ next_p++;
+ i++;
+ }
+ new_argv[i] = NULL;
+
+ if (new_argv[0] == NULL)
+ {
+ if (program_argv == NULL)
+ {
+ write_enn (own_buf);
+ return 0;
+ }
+
+ new_argv[0] = strdup (program_argv[0]);
+ }
+
+ /* Free the old argv. */
+ if (program_argv)
+ {
+ for (pp = program_argv; *pp != NULL; pp++)
+ free (*pp);
+ free (program_argv);
+ }
+ program_argv = new_argv;
+
+ *signal = start_inferior (program_argv, status);
+ if (*status == 'T')
+ {
+ prepare_resume_reply (own_buf, *status, *signal);
+ return 1;
+ }
+ else
+ {
+ write_enn (own_buf);
+ return 0;
+ }
+}
+
/* Handle all of the extended 'v' packets. */
void
handle_v_requests (char *own_buf, char *status, int *signal,
@@ -779,6 +907,7 @@ handle_v_requests (char *own_buf, char *status, int *signal,
{
if (strncmp (own_buf, "vCont;", 6) == 0)
{
+ require_running (own_buf);
handle_v_cont (own_buf, status, signal);
return;
}
@@ -793,6 +922,28 @@ handle_v_requests (char *own_buf, char *status, int *signal,
&& handle_vFile (own_buf, packet_len, new_packet_len))
return;
+ if (strncmp (own_buf, "vAttach;", 8) == 0)
+ {
+ if (target_running ())
+ {
+ fprintf (stderr, "Killing inferior\n");
+ kill_inferior ();
+ }
+ handle_v_attach (own_buf, status, signal);
+ return;
+ }
+
+ if (strncmp (own_buf, "vRun;", 5) == 0)
+ {
+ if (target_running ())
+ {
+ fprintf (stderr, "Killing inferior\n");
+ kill_inferior ();
+ }
+ handle_v_run (own_buf, status, signal);
+ return;
+ }
+
/* Otherwise we didn't know what packet it was. Say we didn't
understand it. */
own_buf[0] = 0;
@@ -829,8 +980,6 @@ myresume (char *own_buf, int step, int *signalp, char *statusp)
disable_async_io ();
}
-static int attached;
-
static void
gdbserver_version (void)
{
@@ -844,13 +993,25 @@ gdbserver_version (void)
static void
gdbserver_usage (void)
{
- printf ("Usage:\tgdbserver COMM PROG [ARGS ...]\n"
- "\tgdbserver COMM --attach PID\n"
+ printf ("Usage:\tgdbserver [OPTIONS] COMM PROG [ARGS ...]\n"
+ "\tgdbserver [OPTIONS] --attach COMM PID\n"
+ "\tgdbserver [OPTIONS] --multi COMM\n"
"\n"
"COMM may either be a tty device (for serial debugging), or \n"
- "HOST:PORT to listen for a TCP connection.\n");
+ "HOST:PORT to listen for a TCP connection.\n"
+ "\n"
+ "Options:\n"
+ " --debug\t\tEnable debugging output.\n");
}
+#undef require_running
+#define require_running(BUF) \
+ if (!target_running ()) \
+ { \
+ write_enn (BUF); \
+ break; \
+ }
+
int
main (int argc, char *argv[])
{
@@ -862,18 +1023,38 @@ main (int argc, char *argv[])
CORE_ADDR mem_addr;
int bad_attach;
int pid;
- char *arg_end;
+ char *arg_end, *port;
+ char **next_arg = &argv[1];
+ int multi_mode = 0;
+ int attach = 0;
+ int was_running;
- if (argc >= 2 && strcmp (argv[1], "--version") == 0)
+ while (*next_arg != NULL && **next_arg == '-')
{
- gdbserver_version ();
- exit (0);
- }
+ if (strcmp (*next_arg, "--version") == 0)
+ {
+ gdbserver_version ();
+ exit (0);
+ }
+ else if (strcmp (*next_arg, "--help") == 0)
+ {
+ gdbserver_usage ();
+ exit (0);
+ }
+ else if (strcmp (*next_arg, "--attach") == 0)
+ attach = 1;
+ else if (strcmp (*next_arg, "--multi") == 0)
+ multi_mode = 1;
+ else if (strcmp (*next_arg, "--debug") == 0)
+ debug_threads = 1;
+ else
+ {
+ fprintf (stderr, "Unknown argument: %s\n", *next_arg);
+ exit (1);
+ }
- if (argc >= 2 && strcmp (argv[1], "--help") == 0)
- {
- gdbserver_usage ();
- exit (0);
+ next_arg++;
+ continue;
}
if (setjmp (toplevel))
@@ -882,23 +1063,34 @@ main (int argc, char *argv[])
exit (1);
}
+ port = *next_arg;
+ next_arg++;
+ if (port == NULL || (!attach && !multi_mode && *next_arg == NULL))
+ {
+ gdbserver_usage ();
+ exit (1);
+ }
+
bad_attach = 0;
pid = 0;
- attached = 0;
- if (argc >= 3 && strcmp (argv[2], "--attach") == 0)
+
+ /* --attach used to come after PORT, so allow it there for
+ compatibility. */
+ if (*next_arg != NULL && strcmp (*next_arg, "--attach") == 0)
{
- if (argc == 4
- && argv[3][0] != '\0'
- && (pid = strtoul (argv[3], &arg_end, 0)) != 0
- && *arg_end == '\0')
- {
- ;
- }
- else
- bad_attach = 1;
+ attach = 1;
+ next_arg++;
}
- if (argc < 3 || bad_attach)
+ if (attach
+ && (*next_arg == NULL
+ || (*next_arg)[0] == '\0'
+ || (pid = strtoul (*next_arg, &arg_end, 0)) == 0
+ || *arg_end != '\0'
+ || next_arg[1] != NULL))
+ bad_attach = 1;
+
+ if (bad_attach)
{
gdbserver_usage ();
exit (1);
@@ -910,26 +1102,34 @@ main (int argc, char *argv[])
own_buf = malloc (PBUFSIZ + 1);
mem_buf = malloc (PBUFSIZ);
- if (pid == 0)
+ if (pid == 0 && *next_arg != NULL)
{
+ int i, n;
+
+ n = argc - (next_arg - argv);
+ program_argv = malloc (sizeof (char *) * (n + 1));
+ for (i = 0; i < n; i++)
+ program_argv[i] = strdup (next_arg[i]);
+ program_argv[i] = NULL;
+
/* Wait till we are at first instruction in program. */
- signal = start_inferior (&argv[2], &status);
+ signal = start_inferior (program_argv, &status);
/* We are now (hopefully) stopped at the first instruction of
the target process. This assumes that the target process was
successfully created. */
}
+ else if (pid != 0)
+ {
+ if (attach_inferior (pid, &status, &signal) == -1)
+ error ("Attaching not supported on this target");
+
+ /* Otherwise succeeded. */
+ }
else
{
- switch (attach_inferior (pid, &status, &signal))
- {
- case -1:
- error ("Attaching not supported on this target");
- break;
- default:
- attached = 1;
- break;
- }
+ status = 'W';
+ signal = 0;
}
/* Don't report shared library events on the initial connection,
@@ -945,27 +1145,43 @@ main (int argc, char *argv[])
}
if (status == 'W' || status == 'X')
+ was_running = 0;
+ else
+ was_running = 1;
+
+ if (!was_running && !multi_mode)
{
- fprintf (stderr, "No inferior, GDBserver exiting.\n");
+ fprintf (stderr, "No program to debug. GDBserver exiting.\n");
exit (1);
}
while (1)
{
- remote_open (argv[1]);
+ remote_open (port);
restart:
- setjmp (toplevel);
+ if (setjmp (toplevel) != 0)
+ {
+ /* An error occurred. */
+ if (response_needed)
+ {
+ write_enn (own_buf);
+ putpkt (own_buf);
+ }
+ }
+
disable_async_io ();
- while (1)
+ while (!exit_requested)
{
unsigned char sig;
int packet_len;
int new_packet_len = -1;
+ response_needed = 0;
packet_len = getpkt (own_buf);
if (packet_len <= 0)
break;
+ response_needed = 1;
i = 0;
ch = own_buf[i++];
@@ -978,39 +1194,38 @@ main (int argc, char *argv[])
handle_general_set (own_buf);
break;
case 'D':
+ require_running (own_buf);
fprintf (stderr, "Detaching from inferior\n");
if (detach_inferior () != 0)
- {
- write_enn (own_buf);
- putpkt (own_buf);
- }
+ write_enn (own_buf);
else
{
write_ok (own_buf);
- putpkt (own_buf);
- remote_close ();
- /* If we are attached, then we can exit. Otherwise, we
- need to hang around doing nothing, until the child
- is gone. */
- if (!attached)
- join_inferior ();
+ if (extended_protocol)
+ {
+ /* Treat this like a normal program exit. */
+ signal = 0;
+ status = 'W';
+ }
+ else
+ {
+ putpkt (own_buf);
+ remote_close ();
- exit (0);
+ /* If we are attached, then we can exit. Otherwise, we
+ need to hang around doing nothing, until the child
+ is gone. */
+ if (!attached)
+ join_inferior ();
+
+ exit (0);
+ }
}
+ break;
case '!':
- if (attached == 0)
- {
- extended_protocol = 1;
- prepare_resume_reply (own_buf, status, signal);
- }
- else
- {
- /* We can not use the extended protocol if we are
- attached, because we can not restart the running
- program. So return unrecognized. */
- own_buf[0] = '\0';
- }
+ extended_protocol = 1;
+ write_ok (own_buf);
break;
case '?':
prepare_resume_reply (own_buf, status, signal);
@@ -1020,12 +1235,18 @@ main (int argc, char *argv[])
{
unsigned long gdb_id, thread_id;
+ require_running (own_buf);
gdb_id = strtoul (&own_buf[2], NULL, 16);
- thread_id = gdb_id_to_thread_id (gdb_id);
- if (thread_id == 0)
+ if (gdb_id == 0 || gdb_id == -1)
+ thread_id = gdb_id;
+ else
{
- write_enn (own_buf);
- break;
+ thread_id = gdb_id_to_thread_id (gdb_id);
+ if (thread_id == 0)
+ {
+ write_enn (own_buf);
+ break;
+ }
}
if (own_buf[1] == 'g')
@@ -1048,15 +1269,18 @@ main (int argc, char *argv[])
}
break;
case 'g':
+ require_running (own_buf);
set_desired_inferior (1);
registers_to_string (own_buf);
break;
case 'G':
+ require_running (own_buf);
set_desired_inferior (1);
registers_from_string (&own_buf[1]);
write_ok (own_buf);
break;
case 'm':
+ require_running (own_buf);
decode_m_packet (&own_buf[1], &mem_addr, &len);
if (read_inferior_memory (mem_addr, mem_buf, len) == 0)
convert_int_to_ascii (mem_buf, own_buf, len);
@@ -1064,6 +1288,7 @@ main (int argc, char *argv[])
write_enn (own_buf);
break;
case 'M':
+ require_running (own_buf);
decode_M_packet (&own_buf[1], &mem_addr, &len, mem_buf);
if (write_inferior_memory (mem_addr, mem_buf, len) == 0)
write_ok (own_buf);
@@ -1071,6 +1296,7 @@ main (int argc, char *argv[])
write_enn (own_buf);
break;
case 'X':
+ require_running (own_buf);
if (decode_X_packet (&own_buf[1], packet_len - 1,
&mem_addr, &len, mem_buf) < 0
|| write_inferior_memory (mem_addr, mem_buf, len) != 0)
@@ -1079,6 +1305,7 @@ main (int argc, char *argv[])
write_ok (own_buf);
break;
case 'C':
+ require_running (own_buf);
convert_ascii_to_int (own_buf + 1, &sig, 1);
if (target_signal_to_host_p (sig))
signal = target_signal_to_host (sig);
@@ -1087,6 +1314,7 @@ main (int argc, char *argv[])
myresume (own_buf, 0, &signal, &status);
break;
case 'S':
+ require_running (own_buf);
convert_ascii_to_int (own_buf + 1, &sig, 1);
if (target_signal_to_host_p (sig))
signal = target_signal_to_host (sig);
@@ -1095,10 +1323,12 @@ main (int argc, char *argv[])
myresume (own_buf, 1, &signal, &status);
break;
case 'c':
+ require_running (own_buf);
signal = 0;
myresume (own_buf, 0, &signal, &status);
break;
case 's':
+ require_running (own_buf);
signal = 0;
myresume (own_buf, 1, &signal, &status);
break;
@@ -1121,6 +1351,7 @@ main (int argc, char *argv[])
{
int res;
+ require_running (own_buf);
res = (*the_target->insert_watchpoint) (type, addr, len);
if (res == 0)
write_ok (own_buf);
@@ -1151,6 +1382,7 @@ main (int argc, char *argv[])
{
int res;
+ require_running (own_buf);
res = (*the_target->remove_watchpoint) (type, addr, len);
if (res == 0)
write_ok (own_buf);
@@ -1163,20 +1395,24 @@ main (int argc, char *argv[])
break;
}
case 'k':
+ response_needed = 0;
+ if (!target_running ())
+ /* The packet we received doesn't make sense - but we
+ can't reply to it, either. */
+ goto restart;
+
fprintf (stderr, "Killing inferior\n");
kill_inferior ();
- /* When using the extended protocol, we start up a new
- debugging session. The traditional protocol will
- exit instead. */
+
+ /* When using the extended protocol, we wait with no
+ program running. The traditional protocol will exit
+ instead. */
if (extended_protocol)
{
- write_ok (own_buf);
- fprintf (stderr, "GDBserver restarting\n");
-
- /* Wait till we are at 1st instruction in prog. */
- signal = start_inferior (&argv[2], &status);
+ status = 'X';
+ signal = TARGET_SIGNAL_KILL;
+ was_running = 0;
goto restart;
- break;
}
else
{
@@ -1187,6 +1423,7 @@ main (int argc, char *argv[])
{
unsigned long gdb_id, thread_id;
+ require_running (own_buf);
gdb_id = strtoul (&own_buf[1], NULL, 16);
thread_id = gdb_id_to_thread_id (gdb_id);
if (thread_id == 0)
@@ -1202,18 +1439,25 @@ main (int argc, char *argv[])
}
break;
case 'R':
+ response_needed = 0;
+
/* Restarting the inferior is only supported in the
extended protocol. */
if (extended_protocol)
{
- kill_inferior ();
- write_ok (own_buf);
+ if (target_running ())
+ kill_inferior ();
fprintf (stderr, "GDBserver restarting\n");
/* Wait till we are at 1st instruction in prog. */
- signal = start_inferior (&argv[2], &status);
+ if (program_argv != NULL)
+ signal = start_inferior (program_argv, &status);
+ else
+ {
+ status = 'X';
+ signal = TARGET_SIGNAL_KILL;
+ }
goto restart;
- break;
}
else
{
@@ -1242,45 +1486,45 @@ main (int argc, char *argv[])
else
putpkt (own_buf);
- if (status == 'W')
- fprintf (stderr,
- "\nChild exited with status %d\n", signal);
- if (status == 'X')
- fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
- target_signal_to_host (signal),
- target_signal_to_name (signal));
- if (status == 'W' || status == 'X')
+ response_needed = 0;
+
+ if (was_running && (status == 'W' || status == 'X'))
{
- if (extended_protocol)
- {
- fprintf (stderr, "Killing inferior\n");
- kill_inferior ();
- write_ok (own_buf);
- fprintf (stderr, "GDBserver restarting\n");
+ was_running = 0;
- /* Wait till we are at 1st instruction in prog. */
- signal = start_inferior (&argv[2], &status);
- goto restart;
- break;
- }
+ if (status == 'W')
+ fprintf (stderr,
+ "\nChild exited with status %d\n", signal);
+ if (status == 'X')
+ fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
+ target_signal_to_host (signal),
+ target_signal_to_name (signal));
+
+ if (extended_protocol)
+ goto restart;
else
{
fprintf (stderr, "GDBserver exiting\n");
exit (0);
}
}
- }
- /* We come here when getpkt fails.
+ if (status != 'W' && status != 'X')
+ was_running = 1;
+ }
- For the extended remote protocol we exit (and this is the only
- way we gracefully exit!).
+ /* If an exit was requested (using the "monitor exit" command),
+ terminate now. The only other way to get here is for
+ getpkt to fail; close the connection and reopen it at the
+ top of the loop. */
- For the traditional remote protocol close the connection,
- and re-open it at the top of the loop. */
- if (extended_protocol)
+ if (exit_requested)
{
remote_close ();
+ if (attached && target_running ())
+ detach_inferior ();
+ else if (target_running ())
+ kill_inferior ();
exit (0);
}
else