From 5b1c542ea1c4ff247db390bd24a9e0665d0c2e48 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 1 Apr 2009 22:31:45 +0000 Subject: [PATCH] Decouple target code from remote protocol. * target.h (enum target_waitkind): New. (struct target_waitstatus): New. (struct target_ops) : 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. --- gdb/gdbserver/ChangeLog | 39 +++++++++ gdb/gdbserver/linux-low.c | 38 +++++--- gdb/gdbserver/remote-utils.c | 151 +++++++++++++++++--------------- gdb/gdbserver/server.c | 164 ++++++++++++++++++++--------------- gdb/gdbserver/server.h | 6 +- gdb/gdbserver/spu-low.c | 26 +++--- gdb/gdbserver/target.c | 8 +- gdb/gdbserver/target.h | 60 +++++++++++-- gdb/gdbserver/win32-low.c | 69 +++------------ 9 files changed, 329 insertions(+), 232 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index ed70d446d3f..208cdf46c53 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,42 @@ +2009-04-01 Pedro Alves + + Decouple target code from remote protocol. + + * target.h (enum target_waitkind): New. + (struct target_waitstatus): New. + (struct target_ops) : 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 * target.h (struct thread_resume): Delete leave_stopped member. diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index c1f533f60a2..c0b1e538df8 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -929,11 +929,12 @@ linux_wait_for_event (struct thread_info *child) /* 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 @@ -966,6 +967,8 @@ retry: 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, @@ -980,25 +983,34 @@ retry: 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 @@ -1007,8 +1019,10 @@ retry: 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 diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index 61312207a03..d0967e3c12d 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -20,6 +20,7 @@ #include "server.h" #include "terminal.h" +#include "target.h" #include #include #if HAVE_SYS_IOCTL_H @@ -933,88 +934,98 @@ dead_thread_notify (int id) } 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 diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 2be5e0e4ba7..1f61c0edc57 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -35,8 +35,7 @@ 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; @@ -87,6 +86,10 @@ int disable_packet_Tthread; 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) { @@ -94,7 +97,7 @@ target_running (void) } static int -start_inferior (char **argv, char *statusptr) +start_inferior (char **argv) { char **new_argv = argv; attached = 0; @@ -141,36 +144,38 @@ start_inferior (char **argv, char *statusptr) 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. */ @@ -188,13 +193,14 @@ attach_inferior (int pid, char *statusptr, int *sigptr) 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; } @@ -917,8 +923,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) && 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); @@ -942,7 +949,10 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) 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; } @@ -950,12 +960,12 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) 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); } @@ -1051,7 +1061,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) /* 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; @@ -1146,8 +1156,8 @@ handle_v_cont (char *own_buf, char *status, int *signal) 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; @@ -1159,19 +1169,19 @@ err: /* 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 @@ -1183,7 +1193,7 @@ handle_v_attach (char *own_buf, char *status, int *signal) /* 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; @@ -1250,10 +1260,10 @@ handle_v_run (char *own_buf, char *status, int *signal) 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 @@ -1265,15 +1275,14 @@ handle_v_run (char *own_buf, char *status, int *signal) /* 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; } @@ -1296,7 +1305,7 @@ handle_v_requests (char *own_buf, char *status, int *signal, write_enn (own_buf); return; } - handle_v_attach (own_buf, status, signal); + handle_v_attach (own_buf); return; } @@ -1308,7 +1317,7 @@ handle_v_requests (char *own_buf, char *status, int *signal, write_enn (own_buf); return; } - handle_v_run (own_buf, status, signal); + handle_v_run (own_buf); return; } @@ -1319,11 +1328,10 @@ handle_v_requests (char *own_buf, char *status, int *signal, } 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); @@ -1349,11 +1357,23 @@ myresume (char *own_buf, int step, int *signalp, char *statusp) 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) { @@ -1406,7 +1426,7 @@ gdbserver_show_disableable (FILE *stream) int main (int argc, char *argv[]) { - char ch, status, *own_buf; + char ch, *own_buf; unsigned char *mem_buf; int i = 0; int signal; @@ -1563,7 +1583,7 @@ main (int argc, char *argv[]) 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 @@ -1571,15 +1591,16 @@ main (int argc, char *argv[]) } 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, @@ -1594,7 +1615,8 @@ main (int argc, char *argv[]) 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; @@ -1656,8 +1678,9 @@ main (int argc, char *argv[]) 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 { @@ -1679,7 +1702,7 @@ main (int argc, char *argv[]) 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') @@ -1762,7 +1785,7 @@ main (int argc, char *argv[]) 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); @@ -1771,17 +1794,17 @@ main (int argc, char *argv[]) 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': { @@ -1860,8 +1883,8 @@ main (int argc, char *argv[]) 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; } @@ -1902,11 +1925,11 @@ main (int argc, char *argv[]) /* 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; } @@ -1920,8 +1943,7 @@ main (int argc, char *argv[]) } 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: @@ -1939,17 +1961,20 @@ main (int argc, char *argv[]) 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; @@ -1961,7 +1986,8 @@ main (int argc, char *argv[]) } } - if (status != 'W' && status != 'X') + if (last_status.kind != TARGET_WAITKIND_EXITED + && last_status.kind != TARGET_WAITKIND_SIGNALLED) was_running = 1; } diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h index db750bdd206..7727e5553fb 100644 --- a/gdb/gdbserver/server.h +++ b/gdb/gdbserver/server.h @@ -160,8 +160,7 @@ void unloaded_dll (const char *name, CORE_ADDR base_addr); 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[]; @@ -201,7 +200,8 @@ void convert_ascii_to_int (char *from, unsigned char *to, int n); 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); diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c index 792241cd8ab..d0ff22ca7cf 100644 --- a/gdb/gdbserver/spu-low.c +++ b/gdb/gdbserver/spu-low.c @@ -371,8 +371,8 @@ spu_resume (struct thread_resume *resume_info, size_t n) } /* 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; @@ -407,31 +407,37 @@ spu_wait (char *status) } } + 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. */ diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c index b49bdb5bd8c..3bdc469e789 100644 --- a/gdb/gdbserver/target.c +++ b/gdb/gdbserver/target.c @@ -88,15 +88,15 @@ write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr, 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; diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index 5bd589654c6..27f57eafcf3 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -38,6 +38,53 @@ struct thread_resume 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. @@ -82,15 +129,10 @@ struct target_ops 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. @@ -225,7 +267,7 @@ void set_target_ops (struct target_ops *); #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); diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c index 7c63ff44e8e..2fed73cba48 100644 --- a/gdb/gdbserver/win32-low.c +++ b/gdb/gdbserver/win32-low.c @@ -241,45 +241,6 @@ child_xfer_memory (CORE_ADDR memaddr, char *our, 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 @@ -1514,37 +1475,30 @@ get_child_debug_event (struct target_waitstatus *ourstatus) /* 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 @@ -1553,9 +1507,14 @@ win32_wait (char *status) 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: -- 2.30.2