* target.h (enum target_waitkind): New.
(struct target_waitstatus): New.
(struct target_ops) <wait>: Return an unsigned long. Take a
target_waitstatus pointer instead of a char pointer.
(mywait): Likewise.
* target.c (mywait): Change prototype to return an unsigned long.
Take a target_waitstatus pointer instead of a char pointer. Adjust.
* server.h (thread_from_wait, old_thread_from_wait): Delete
declarations.
(prepare_resume_reply): Change prototype to take a
target_waitstatus.
* server.c (thread_from_wait, old_thread_from_wait): Delete.
(last_status, last_ptid): New.
(start_inferior): Remove "statusptr" argument. Adjust. Return a
pid instead of a signal.
(attach_inferior): Remove "status" and "signal" parameters.
Adjust.
(handle_query): For qGetTLSAddr, parse the thread id with strtol,
not as an address.
(handle_v_cont, handle_v_attach, handle_v_run, handle_v_kill)
(handle_v_requests, myresume): Remove "status" and "signal"
parameters. Adjust.
(handle_status): New.
(main): Delete local `status'. Adjust.
* remote-utils.c: Include target.h.
(prepare_resume_reply): Change prototype to take a
target_waitstatus. Adjust.
* linux-low.c (linux_wait): Adjust to new target_ops->wait
interface.
* spu-low.c (spu_wait): Adjust.
* win32-low.c (enum target_waitkind, struct target_waitstatus):
Delete.
(win32_wait): Adjust.
+2009-04-01 Pedro Alves <pedro@codesourcery.com>
+
+ Decouple target code from remote protocol.
+
+ * target.h (enum target_waitkind): New.
+ (struct target_waitstatus): New.
+ (struct target_ops) <wait>: Return an unsigned long. Take a
+ target_waitstatus pointer instead of a char pointer.
+ (mywait): Likewise.
+ * target.c (mywait): Change prototype to return an unsigned long.
+ Take a target_waitstatus pointer instead of a char pointer. Adjust.
+ * server.h (thread_from_wait, old_thread_from_wait): Delete
+ declarations.
+ (prepare_resume_reply): Change prototype to take a
+ target_waitstatus.
+ * server.c (thread_from_wait, old_thread_from_wait): Delete.
+ (last_status, last_ptid): New.
+ (start_inferior): Remove "statusptr" argument. Adjust. Return a
+ pid instead of a signal.
+ (attach_inferior): Remove "status" and "signal" parameters.
+ Adjust.
+ (handle_query): For qGetTLSAddr, parse the thread id with strtol,
+ not as an address.
+ (handle_v_cont, handle_v_attach, handle_v_run, handle_v_kill)
+ (handle_v_requests, myresume): Remove "status" and "signal"
+ parameters. Adjust.
+ (handle_status): New.
+ (main): Delete local `status'. Adjust.
+ * remote-utils.c: Include target.h.
+ (prepare_resume_reply): Change prototype to take a
+ target_waitstatus. Adjust.
+
+ * linux-low.c (linux_wait): Adjust to new target_ops->wait
+ interface.
+ * spu-low.c (spu_wait): Adjust.
+ * win32-low.c (enum target_waitkind, struct target_waitstatus):
+ Delete.
+ (win32_wait): Adjust.
+
2009-04-01 Pedro Alves <pedro@codesourcery.com>
* target.h (struct thread_resume): Delete leave_stopped member.
/* Wait for process, returns status. */
-static unsigned char
-linux_wait (char *status)
+static unsigned long
+linux_wait (struct target_waitstatus *ourstatus)
{
int w;
struct thread_info *child = NULL;
+ struct lwp_info *lwp;
retry:
/* If we were only supposed to resume one thread, only wait for
must_set_ptrace_flags = 0;
}
+ lwp = get_thread_lwp (current_inferior);
+
/* If we are waiting for a particular child, and it exited,
linux_wait_for_event will return its exit status. Similarly if
the last child exited. If this is not the last child, however,
if (all_threads.head == all_threads.tail)
{
+ int pid = pid_of (lwp);
if (WIFEXITED (w))
{
- fprintf (stderr, "\nChild exited with retcode = %x \n",
- WEXITSTATUS (w));
- *status = 'W';
+ if (debug_threads)
+ fprintf (stderr, "\nChild exited with retcode = %x \n",
+ WEXITSTATUS (w));
+
+ ourstatus->kind = TARGET_WAITKIND_EXITED;
+ ourstatus->value.integer = WEXITSTATUS (w);
clear_inferiors ();
free (all_lwps.head);
all_lwps.head = all_lwps.tail = NULL;
- return WEXITSTATUS (w);
+
+ return pid;
}
else if (!WIFSTOPPED (w))
{
- fprintf (stderr, "\nChild terminated with signal = %x \n",
- WTERMSIG (w));
- *status = 'X';
+ if (debug_threads)
+ fprintf (stderr, "\nChild terminated with signal = %x \n",
+ WTERMSIG (w));
+
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = target_signal_from_host (WTERMSIG (w));
clear_inferiors ();
free (all_lwps.head);
all_lwps.head = all_lwps.tail = NULL;
- return target_signal_from_host (WTERMSIG (w));
+
+ return pid;
}
}
else
goto retry;
}
- *status = 'T';
- return target_signal_from_host (WSTOPSIG (w));
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig = target_signal_from_host (WSTOPSIG (w));
+
+ return lwp->lwpid;
}
/* Send a signal to an LWP. For LinuxThreads, kill is enough; however, if
#include "server.h"
#include "terminal.h"
+#include "target.h"
#include <stdio.h>
#include <string.h>
#if HAVE_SYS_IOCTL_H
}
void
-prepare_resume_reply (char *buf, char status, unsigned char sig)
+prepare_resume_reply (char *buf, unsigned long ptid,
+ struct target_waitstatus *status)
{
- int nib;
-
- *buf++ = status;
-
- nib = ((sig & 0xf0) >> 4);
- *buf++ = tohex (nib);
- nib = sig & 0x0f;
- *buf++ = tohex (nib);
+ if (debug_threads)
+ fprintf (stderr, "Writing resume reply for %lu:%d\n\n",
+ ptid, status->kind);
- if (status == 'T')
+ switch (status->kind)
{
- const char **regp = gdbserver_expedite_regs;
+ case TARGET_WAITKIND_STOPPED:
+ {
+ struct thread_info *saved_inferior;
+ const char **regp;
- if (the_target->stopped_by_watchpoint != NULL
- && (*the_target->stopped_by_watchpoint) ())
- {
- CORE_ADDR addr;
- int i;
+ sprintf (buf, "T%02x", status->value.sig);
+ buf += strlen (buf);
- strncpy (buf, "watch:", 6);
- buf += 6;
+ regp = gdbserver_expedite_regs;
- addr = (*the_target->stopped_data_address) ();
+ saved_inferior = current_inferior;
- /* Convert each byte of the address into two hexadecimal chars.
- Note that we take sizeof (void *) instead of sizeof (addr);
- this is to avoid sending a 64-bit address to a 32-bit GDB. */
- for (i = sizeof (void *) * 2; i > 0; i--)
- {
- *buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
- }
- *buf++ = ';';
- }
+ current_inferior = gdb_id_to_thread (ptid);
- while (*regp)
- {
- buf = outreg (find_regno (*regp), buf);
- regp ++;
- }
+ if (the_target->stopped_by_watchpoint != NULL
+ && (*the_target->stopped_by_watchpoint) ())
+ {
+ CORE_ADDR addr;
+ int i;
- /* Formerly, if the debugger had not used any thread features we would not
- burden it with a thread status response. This was for the benefit of
- GDB 4.13 and older. However, in recent GDB versions the check
- (``if (cont_thread != 0)'') does not have the desired effect because of
- sillyness in the way that the remote protocol handles specifying a thread.
- Since thread support relies on qSymbol support anyway, assume GDB can handle
- threads. */
+ strncpy (buf, "watch:", 6);
+ buf += 6;
- if (using_threads && !disable_packet_Tthread)
- {
- unsigned int gdb_id_from_wait;
-
- /* FIXME right place to set this? */
- thread_from_wait = ((struct inferior_list_entry *)current_inferior)->id;
- gdb_id_from_wait = thread_to_gdb_id (current_inferior);
-
- if (debug_threads)
- fprintf (stderr, "Writing resume reply for %ld\n\n", thread_from_wait);
- /* This if (1) ought to be unnecessary. But remote_wait in GDB
- will claim this event belongs to inferior_ptid if we do not
- specify a thread, and there's no way for gdbserver to know
- what inferior_ptid is. */
- if (1 || old_thread_from_wait != thread_from_wait)
- {
- general_thread = thread_from_wait;
- sprintf (buf, "thread:%x;", gdb_id_from_wait);
- buf += strlen (buf);
- old_thread_from_wait = thread_from_wait;
- }
- }
+ addr = (*the_target->stopped_data_address) ();
- if (dlls_changed)
- {
- strcpy (buf, "library:;");
- buf += strlen (buf);
- dlls_changed = 0;
- }
+ /* Convert each byte of the address into two hexadecimal
+ chars. Note that we take sizeof (void *) instead of
+ sizeof (addr); this is to avoid sending a 64-bit
+ address to a 32-bit GDB. */
+ for (i = sizeof (void *) * 2; i > 0; i--)
+ *buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
+ *buf++ = ';';
+ }
+
+ while (*regp)
+ {
+ buf = outreg (find_regno (*regp), buf);
+ regp ++;
+ }
+
+ /* Formerly, if the debugger had not used any thread features
+ we would not burden it with a thread status response. This
+ was for the benefit of GDB 4.13 and older. However, in
+ recent GDB versions the check (``if (cont_thread != 0)'')
+ does not have the desired effect because of sillyness in
+ the way that the remote protocol handles specifying a
+ thread. Since thread support relies on qSymbol support
+ anyway, assume GDB can handle threads. */
+
+ if (using_threads && !disable_packet_Tthread)
+ {
+ /* This if (1) ought to be unnecessary. But remote_wait
+ in GDB will claim this event belongs to inferior_ptid
+ if we do not specify a thread, and there's no way for
+ gdbserver to know what inferior_ptid is. */
+ if (1 || general_thread != ptid)
+ {
+ general_thread = ptid;
+ sprintf (buf, "thread:%lx;", ptid);
+ buf += strlen (buf);
+ }
+ }
+
+ if (dlls_changed)
+ {
+ strcpy (buf, "library:;");
+ buf += strlen (buf);
+ dlls_changed = 0;
+ }
+
+ current_inferior = saved_inferior;
+ }
+ break;
+ case TARGET_WAITKIND_EXITED:
+ sprintf (buf, "W%02x", status->value.integer);
+ break;
+ case TARGET_WAITKIND_SIGNALLED:
+ sprintf (buf, "X%02x", status->value.sig);
+ break;
+ default:
+ error ("unhandled waitkind");
+ break;
}
- /* For W and X, we're done. */
- *buf++ = 0;
}
void
unsigned long cont_thread;
unsigned long general_thread;
unsigned long step_thread;
-unsigned long thread_from_wait;
-unsigned long old_thread_from_wait;
+
int server_waiting;
static int extended_protocol;
int disable_packet_qC;
int disable_packet_qfThreadInfo;
+/* Last status reported to GDB. */
+static struct target_waitstatus last_status;
+static unsigned long last_ptid;
+
static int
target_running (void)
{
}
static int
-start_inferior (char **argv, char *statusptr)
+start_inferior (char **argv)
{
char **new_argv = argv;
attached = 0;
if (wrapper_argv != NULL)
{
struct thread_resume resume_info;
- int sig;
+ unsigned long ptid;
resume_info.thread = -1;
resume_info.step = 0;
resume_info.sig = 0;
- sig = mywait (statusptr, 0);
- if (*statusptr != 'T')
- return sig;
+ ptid = mywait (&last_status, 0);
+ if (last_status.kind != TARGET_WAITKIND_STOPPED)
+ return signal_pid;
do
{
(*the_target->resume) (&resume_info, 1);
- sig = mywait (statusptr, 0);
- if (*statusptr != 'T')
- return sig;
+ mywait (&last_status, 0);
+ if (last_status.kind != TARGET_WAITKIND_STOPPED)
+ return signal_pid;
}
- while (sig != TARGET_SIGNAL_TRAP);
+ while (last_status.value.sig != TARGET_SIGNAL_TRAP);
- return sig;
+ return signal_pid;
}
- /* Wait till we are at 1st instruction in program, return signal
- number (assuming success). */
- return mywait (statusptr, 0);
+ /* Wait till we are at 1st instruction in program, return new pid
+ (assuming success). */
+ last_ptid = mywait (&last_status, 0);
+
+ return signal_pid;
}
static int
-attach_inferior (int pid, char *statusptr, int *sigptr)
+attach_inferior (int pid)
{
/* myattach should return -1 if attaching is unsupported,
0 if it succeeded, and call error() otherwise. */
whichever we were told to attach to. */
signal_pid = pid;
- *sigptr = mywait (statusptr, 0);
+ last_ptid = mywait (&last_status, 0);
/* GDB knows to ignore the first SIGSTOP after attaching to a running
process using the "attach" command, but this is different; it's
just using "target remote". Pretend it's just starting up. */
- if (*statusptr == 'T' && *sigptr == TARGET_SIGNAL_STOP)
- *sigptr = TARGET_SIGNAL_TRAP;
+ if (last_status.kind == TARGET_WAITKIND_STOPPED
+ && last_status.value.sig == TARGET_SIGNAL_STOP)
+ last_status.value.sig = TARGET_SIGNAL_TRAP;
return 0;
}
&& strncmp ("qGetTLSAddr:", own_buf, 12) == 0)
{
char *p = own_buf + 12;
- CORE_ADDR parts[3], address = 0;
+ CORE_ADDR parts[2], address = 0;
int i, err;
+ unsigned long ptid;
require_running (own_buf);
p2 = NULL;
}
- decode_address (&parts[i], p, len);
+ if (i == 0)
+ ptid = strtoul (p, NULL, 16);
+ else
+ decode_address (&parts[i - 1], p, len);
p = p2;
}
err = 1;
else
{
- struct thread_info *thread = gdb_id_to_thread (parts[0]);
+ struct thread_info *thread = gdb_id_to_thread (ptid);
if (thread == NULL)
err = 2;
else
- err = the_target->get_tls_address (thread, parts[1], parts[2],
+ err = the_target->get_tls_address (thread, parts[0], parts[1],
&address);
}
/* Parse vCont packets. */
void
-handle_v_cont (char *own_buf, char *status, int *signal)
+handle_v_cont (char *own_buf)
{
char *p, *q;
int n = 0, i = 0;
free (resume_info);
- *signal = mywait (status, 1);
- prepare_resume_reply (own_buf, *status, *signal);
+ last_ptid = mywait (&last_status, 1);
+ prepare_resume_reply (own_buf, last_ptid, &last_status);
disable_async_io ();
return;
/* Attach to a new program. Return 1 if successful, 0 if failure. */
int
-handle_v_attach (char *own_buf, char *status, int *signal)
+handle_v_attach (char *own_buf)
{
int pid;
pid = strtol (own_buf + 8, NULL, 16);
- if (pid != 0 && attach_inferior (pid, status, signal) == 0)
+ if (pid != 0 && attach_inferior (pid) == 0)
{
/* Don't report shared library events after attaching, even if
some libraries are preloaded. GDB will always poll the
library list. Avoids the "stopped by shared library event"
notice on the GDB side. */
dlls_changed = 0;
- prepare_resume_reply (own_buf, *status, *signal);
+ prepare_resume_reply (own_buf, last_ptid, &last_status);
return 1;
}
else
/* Run a new program. Return 1 if successful, 0 if failure. */
static int
-handle_v_run (char *own_buf, char *status, int *signal)
+handle_v_run (char *own_buf)
{
char *p, *next_p, **new_argv;
int i, new_argc;
freeargv (program_argv);
program_argv = new_argv;
- *signal = start_inferior (program_argv, status);
- if (*status == 'T')
+ start_inferior (program_argv);
+ if (last_status.kind == TARGET_WAITKIND_STOPPED)
{
- prepare_resume_reply (own_buf, *status, *signal);
+ prepare_resume_reply (own_buf, last_ptid, &last_status);
return 1;
}
else
/* Handle all of the extended 'v' packets. */
void
-handle_v_requests (char *own_buf, char *status, int *signal,
- int packet_len, int *new_packet_len)
+handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
{
if (!disable_packet_vCont)
{
if (strncmp (own_buf, "vCont;", 6) == 0)
{
require_running (own_buf);
- handle_v_cont (own_buf, status, signal);
+ handle_v_cont (own_buf);
return;
}
write_enn (own_buf);
return;
}
- handle_v_attach (own_buf, status, signal);
+ handle_v_attach (own_buf);
return;
}
write_enn (own_buf);
return;
}
- handle_v_run (own_buf, status, signal);
+ handle_v_run (own_buf);
return;
}
}
void
-myresume (char *own_buf, int step, int *signalp, char *statusp)
+myresume (char *own_buf, int step, int sig)
{
struct thread_resume resume_info[2];
int n = 0;
- int sig = *signalp;
int valid_cont_thread;
set_desired_inferior (0);
enable_async_io ();
(*the_target->resume) (resume_info, n);
- *signalp = mywait (statusp, 1);
- prepare_resume_reply (own_buf, *statusp, *signalp);
+ last_ptid = mywait (&last_status, 1);
+ prepare_resume_reply (own_buf, last_ptid, &last_status);
disable_async_io ();
}
+/* Status handler for the '?' packet. */
+
+static void
+handle_status (char *own_buf)
+{
+ if (all_threads.head)
+ prepare_resume_reply (own_buf,
+ all_threads.head->id, &last_status);
+ else
+ strcpy (own_buf, "W00");
+}
+
static void
gdbserver_version (void)
{
int
main (int argc, char *argv[])
{
- char ch, status, *own_buf;
+ char ch, *own_buf;
unsigned char *mem_buf;
int i = 0;
int signal;
program_argv[i] = NULL;
/* Wait till we are at first instruction in program. */
- signal = start_inferior (program_argv, &status);
+ start_inferior (program_argv);
/* We are now (hopefully) stopped at the first instruction of
the target process. This assumes that the target process was
}
else if (pid != 0)
{
- if (attach_inferior (pid, &status, &signal) == -1)
+ if (attach_inferior (pid) == -1)
error ("Attaching not supported on this target");
/* Otherwise succeeded. */
}
else
{
- status = 'W';
- signal = 0;
+ last_status.kind = TARGET_WAITKIND_EXITED;
+ last_status.value.integer = 0;
+ last_ptid = -1;
}
/* Don't report shared library events on the initial connection,
exit (1);
}
- if (status == 'W' || status == 'X')
+ if (last_status.kind == TARGET_WAITKIND_EXITED
+ || last_status.kind == TARGET_WAITKIND_SIGNALLED)
was_running = 0;
else
was_running = 1;
if (extended_protocol)
{
/* Treat this like a normal program exit. */
- signal = 0;
- status = 'W';
+ last_status.kind = TARGET_WAITKIND_EXITED;
+ last_status.value.integer = 0;
+ last_ptid = signal_pid;
}
else
{
write_ok (own_buf);
break;
case '?':
- prepare_resume_reply (own_buf, status, signal);
+ handle_status (own_buf);
break;
case 'H':
if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
signal = target_signal_to_host (sig);
else
signal = 0;
- myresume (own_buf, 0, &signal, &status);
+ myresume (own_buf, 0, signal);
break;
case 'S':
require_running (own_buf);
signal = target_signal_to_host (sig);
else
signal = 0;
- myresume (own_buf, 1, &signal, &status);
+ myresume (own_buf, 1, signal);
break;
case 'c':
require_running (own_buf);
signal = 0;
- myresume (own_buf, 0, &signal, &status);
+ myresume (own_buf, 0, signal);
break;
case 's':
require_running (own_buf);
signal = 0;
- myresume (own_buf, 1, &signal, &status);
+ myresume (own_buf, 1, signal);
break;
case 'Z':
{
instead. */
if (extended_protocol)
{
- status = 'X';
- signal = TARGET_SIGNAL_KILL;
+ last_status.kind = TARGET_WAITKIND_EXITED;
+ last_status.value.sig = TARGET_SIGNAL_KILL;
was_running = 0;
goto restart;
}
/* Wait till we are at 1st instruction in prog. */
if (program_argv != NULL)
- signal = start_inferior (program_argv, &status);
+ start_inferior (program_argv);
else
{
- status = 'X';
- signal = TARGET_SIGNAL_KILL;
+ last_status.kind = TARGET_WAITKIND_EXITED;
+ last_status.value.sig = TARGET_SIGNAL_KILL;
}
goto restart;
}
}
case 'v':
/* Extended (long) request. */
- handle_v_requests (own_buf, &status, &signal,
- packet_len, &new_packet_len);
+ handle_v_requests (own_buf, packet_len, &new_packet_len);
break;
default:
response_needed = 0;
- if (was_running && (status == 'W' || status == 'X'))
+ if (was_running
+ && (last_status.kind == TARGET_WAITKIND_EXITED
+ || last_status.kind == TARGET_WAITKIND_SIGNALLED))
{
was_running = 0;
- if (status == 'W')
+ if (last_status.kind == TARGET_WAITKIND_EXITED)
fprintf (stderr,
- "\nChild exited with status %d\n", signal);
- if (status == 'X')
+ "\nChild exited with status %d\n",
+ last_status.value.integer);
+ else if (last_status.kind == TARGET_WAITKIND_SIGNALLED)
fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
- target_signal_to_host (signal),
- target_signal_to_name (signal));
+ target_signal_to_host (last_status.value.sig),
+ target_signal_to_name (last_status.value.sig));
if (extended_protocol)
goto restart;
}
}
- if (status != 'W' && status != 'X')
+ if (last_status.kind != TARGET_WAITKIND_EXITED
+ && last_status.kind != TARGET_WAITKIND_SIGNALLED)
was_running = 1;
}
extern unsigned long cont_thread;
extern unsigned long general_thread;
extern unsigned long step_thread;
-extern unsigned long thread_from_wait;
-extern unsigned long old_thread_from_wait;
+
extern int server_waiting;
extern int debug_threads;
extern int pass_signals[];
void convert_int_to_ascii (unsigned char *from, char *to, int n);
void new_thread_notify (int id);
void dead_thread_notify (int id);
-void prepare_resume_reply (char *buf, char status, unsigned char sig);
+void prepare_resume_reply (char *buf, unsigned long thread_id,
+ struct target_waitstatus *status);
const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start);
void decode_address (CORE_ADDR *addrp, const char *start, int len);
}
/* Wait for process, returns status. */
-static unsigned char
-spu_wait (char *status)
+static unsigned long
+spu_wait (struct target_waitstatus *ourstatus)
{
int tid = current_tid;
int w;
}
}
+ ret = current_tid;
+
if (WIFEXITED (w))
{
fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
- *status = 'W';
+ ourstatus->kind = TARGET_WAITKIND_EXITED;
+ ourstatus->value.integer = WEXITSTATUS (w);
clear_inferiors ();
- return ((unsigned char) WEXITSTATUS (w));
+ return ret;
}
else if (!WIFSTOPPED (w))
{
fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
- *status = 'X';
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = target_signal_from_host (WTERMSIG (w));
clear_inferiors ();
- return ((unsigned char) WTERMSIG (w));
+ return ret;
}
/* After attach, we may have received a SIGSTOP. Do not return this
as signal to GDB, or else it will try to continue with SIGSTOP ... */
if (!server_waiting)
{
- *status = 'T';
- return 0;
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig = TARGET_SIGNAL_0;
+ return ret;
}
- *status = 'T';
- return ((unsigned char) WSTOPSIG (w));
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig = target_signal_from_host (WSTOPSIG (w));
+ return ret;
}
/* Fetch inferior registers. */
return res;
}
-unsigned char
-mywait (char *statusp, int connected_wait)
+unsigned long
+mywait (struct target_waitstatus *ourstatus, int connected_wait)
{
- unsigned char ret;
+ unsigned long ret;
if (connected_wait)
server_waiting = 1;
- ret = (*the_target->wait) (statusp);
+ ret = (*the_target->wait) (ourstatus);
if (connected_wait)
server_waiting = 0;
int sig;
};
+/* Generally, what has the program done? */
+enum target_waitkind
+ {
+ /* The program has exited. The exit status is in
+ value.integer. */
+ TARGET_WAITKIND_EXITED,
+
+ /* The program has stopped with a signal. Which signal is in
+ value.sig. */
+ TARGET_WAITKIND_STOPPED,
+
+ /* The program has terminated with a signal. Which signal is in
+ value.sig. */
+ TARGET_WAITKIND_SIGNALLED,
+
+ /* The program is letting us know that it dynamically loaded
+ something. */
+ TARGET_WAITKIND_LOADED,
+
+ /* The program has exec'ed a new executable file. The new file's
+ pathname is pointed to by value.execd_pathname. */
+ TARGET_WAITKIND_EXECD,
+
+ /* Nothing of interest to GDB happened, but we stopped anyway. */
+ TARGET_WAITKIND_SPURIOUS,
+
+ /* An event has occurred, but we should wait again. In this case,
+ we want to go back to the event loop and wait there for another
+ event from the inferior. */
+ TARGET_WAITKIND_IGNORE
+ };
+
+struct target_waitstatus
+ {
+ enum target_waitkind kind;
+
+ /* Forked child pid, execd pathname, exit status or signal number. */
+ union
+ {
+ int integer;
+ enum target_signal sig;
+ unsigned long related_pid;
+ char *execd_pathname;
+ }
+ value;
+ };
+
struct target_ops
{
/* Start a new process.
void (*resume) (struct thread_resume *resume_info, size_t n);
- /* Wait for the inferior process to change state.
-
- STATUS will be filled in with a response code to send to GDB.
-
- Returns the signal which caused the process to stop, in the
- remote protocol numbering (e.g. TARGET_SIGNAL_STOP), or the
- exit code as an integer if *STATUS is 'W'. */
+ /* Wait for the inferior process or thread to change state. Store
+ status through argument pointer STATUS. */
- unsigned char (*wait) (char *status);
+ unsigned long (*wait) (struct target_waitstatus *status);
/* Fetch registers from the inferior process.
#define join_inferior() \
(*the_target->join) ()
-unsigned char mywait (char *statusp, int connected_wait);
+unsigned long mywait (struct target_waitstatus *ourstatus, int connected_wait);
int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len);
return done;
}
-/* Generally, what has the program done? */
-enum target_waitkind
-{
- /* The program has exited. The exit status is in value.integer. */
- TARGET_WAITKIND_EXITED,
-
- /* The program has stopped with a signal. Which signal is in
- value.sig. */
- TARGET_WAITKIND_STOPPED,
-
- /* The program is letting us know that it dynamically loaded
- or unloaded something. */
- TARGET_WAITKIND_LOADED,
-
- /* The program has exec'ed a new executable file. The new file's
- pathname is pointed to by value.execd_pathname. */
- TARGET_WAITKIND_EXECD,
-
- /* Nothing interesting happened, but we stopped anyway. We take the
- chance to check if GDB requested an interrupt. */
- TARGET_WAITKIND_SPURIOUS,
-};
-
-struct target_waitstatus
-{
- enum target_waitkind kind;
-
- /* Forked child pid, execd pathname, exit status or signal number. */
- union
- {
- int integer;
- enum target_signal sig;
- int related_pid;
- char *execd_pathname;
- int syscall_id;
- }
- value;
-};
-
/* Clear out any old thread list and reinitialize it to a pristine
state. */
static void
/* Wait for the inferior process to change state.
STATUS will be filled in with a response code to send to GDB.
Returns the signal which caused the process to stop. */
-static unsigned char
-win32_wait (char *status)
+static unsigned long
+win32_wait (struct target_waitstatus *ourstatus)
{
- struct target_waitstatus our_status;
-
- *status = 'T';
-
while (1)
{
- if (!get_child_debug_event (&our_status))
+ if (!get_child_debug_event (ourstatus))
continue;
- switch (our_status.kind)
+ switch (ourstatus->kind)
{
case TARGET_WAITKIND_EXITED:
OUTMSG2 (("Child exited with retcode = %x\n",
- our_status.value.integer));
+ ourstatus->value.integer));
- *status = 'W';
win32_clear_inferiors ();
- return our_status.value.integer;
+ return current_event.dwProcessId;
case TARGET_WAITKIND_STOPPED:
case TARGET_WAITKIND_LOADED:
OUTMSG2 (("Child Stopped with signal = %d \n",
our_status.value.sig));
- *status = 'T';
-
child_fetch_inferior_registers (-1);
- if (our_status.kind == TARGET_WAITKIND_LOADED
+ if (ourstatus->kind == TARGET_WAITKIND_LOADED
&& !server_waiting)
{
/* When gdb connects, we want to be stopped at the
break;
}
- return our_status.value.sig;
+ /* We don't expose _LOADED events to gdbserver core. See
+ the `dlls_changed' global. */
+ if (ourstatus->kind == TARGET_WAITKIND_LOADED)
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+
+ return current_event.dwThreadId;
default:
- OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
+ OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
/* fall-through */
case TARGET_WAITKIND_SPURIOUS:
case TARGET_WAITKIND_EXECD: