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.
This commit is contained in:
parent
2bd7c093f6
commit
5b1c542ea1
|
@ -1,3 +1,42 @@
|
|||
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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "server.h"
|
||||
#include "terminal.h"
|
||||
#include "target.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
if (debug_threads)
|
||||
fprintf (stderr, "Writing resume reply for %lu:%d\n\n",
|
||||
ptid, status->kind);
|
||||
|
||||
*buf++ = status;
|
||||
|
||||
nib = ((sig & 0xf0) >> 4);
|
||||
*buf++ = tohex (nib);
|
||||
nib = sig & 0x0f;
|
||||
*buf++ = tohex (nib);
|
||||
|
||||
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--)
|
||||
{
|
||||
current_inferior = gdb_id_to_thread (ptid);
|
||||
|
||||
if (the_target->stopped_by_watchpoint != NULL
|
||||
&& (*the_target->stopped_by_watchpoint) ())
|
||||
{
|
||||
CORE_ADDR addr;
|
||||
int i;
|
||||
|
||||
strncpy (buf, "watch:", 6);
|
||||
buf += 6;
|
||||
|
||||
addr = (*the_target->stopped_data_address) ();
|
||||
|
||||
/* 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++ = ';';
|
||||
}
|
||||
*buf++ = ';';
|
||||
}
|
||||
|
||||
while (*regp)
|
||||
{
|
||||
buf = outreg (find_regno (*regp), buf);
|
||||
regp ++;
|
||||
}
|
||||
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. */
|
||||
/* 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)
|
||||
{
|
||||
unsigned int gdb_id_from_wait;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 (dlls_changed)
|
||||
{
|
||||
strcpy (buf, "library:;");
|
||||
buf += strlen (buf);
|
||||
dlls_changed = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
/* Wait for the inferior process or thread to change state. Store
|
||||
status through argument pointer STATUS. */
|
||||
|
||||
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'. */
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue