mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-25 13:09:48 +00:00
* gdbserver/remote-utils.c (write_ok): Write "OK", not "Ok", to
match stubs and protocol spec. * gdbserver/remote-utils.c (remote_open): Cast to struct sockaddr when passing to function which expects that. The following changes aren't quite enough to make things work with LynxOS (apprently kernel problems). * infrun.c (wait_for_inferior): When resuming new thread, pass pid not -1 for remote case. * thread.c (info_threads_command): Give error if !target_has_stack. * infrun.c (start_remote): Call init_thread_list. * thread.c (info_threads_command): Don't call kill for remote debugging target. * target.c (normal_pid_to_str): Print "thread" not "process" for remote. * remote.c, gdbserver/*: Add 'H', 'S', and 'C' requests, 'X' response, and `thread' part of 'T' response. * gdbserver/*: If program exits, send packet to GDB before exiting. Handle termination with a signal the same as exiting with an exitstatus. * remote.c: Don't try to kill program after getting an 'X' response. * infrun.c (wait_for_inferior): Add comment about kill versus mourn.
This commit is contained in:
parent
4181c9853b
commit
4cc1b3f79d
@ -1,3 +1,29 @@
|
||||
Wed Dec 7 14:50:54 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
|
||||
|
||||
* gdbserver/remote-utils.c (write_ok): Write "OK", not "Ok", to
|
||||
match stubs and protocol spec.
|
||||
* gdbserver/remote-utils.c (remote_open): Cast to struct sockaddr
|
||||
when passing to function which expects that.
|
||||
|
||||
The following changes aren't quite enough to make things work with
|
||||
LynxOS (apprently kernel problems).
|
||||
* infrun.c (wait_for_inferior): When resuming new thread, pass pid
|
||||
not -1 for remote case.
|
||||
* thread.c (info_threads_command): Give error if !target_has_stack.
|
||||
* infrun.c (start_remote): Call init_thread_list.
|
||||
* thread.c (info_threads_command): Don't call kill for remote
|
||||
debugging target.
|
||||
* target.c (normal_pid_to_str): Print "thread" not "process" for
|
||||
remote.
|
||||
* remote.c, gdbserver/*: Add 'H', 'S', and 'C' requests, 'X'
|
||||
response, and `thread' part of 'T' response.
|
||||
* gdbserver/*: If program exits, send packet to GDB before
|
||||
exiting. Handle termination with a signal the same as exiting
|
||||
with an exitstatus.
|
||||
* remote.c: Don't try to kill program after getting an 'X'
|
||||
response.
|
||||
* infrun.c (wait_for_inferior): Add comment about kill versus mourn.
|
||||
|
||||
Thu Dec 8 12:37:38 1994 Rob Savoye <rob@darkstar.cygnus.com>
|
||||
|
||||
* config/pa/tm-pro.h tm-hppap.h, hppapro.mt: Rename tm-hppap.h to
|
||||
|
@ -108,33 +108,57 @@ mywait (status)
|
||||
int pid;
|
||||
union wait w;
|
||||
|
||||
enable_async_io();
|
||||
while (1)
|
||||
{
|
||||
enable_async_io();
|
||||
|
||||
pid = wait (&w);
|
||||
pid = wait (&w);
|
||||
|
||||
disable_async_io();
|
||||
disable_async_io();
|
||||
|
||||
if (pid != PIDGET(inferior_pid))
|
||||
perror_with_name ("wait");
|
||||
if (pid != PIDGET(inferior_pid))
|
||||
perror_with_name ("wait");
|
||||
|
||||
inferior_pid = BUILDPID (inferior_pid, w.w_tid);
|
||||
thread_from_wait = w.w_tid;
|
||||
inferior_pid = BUILDPID (inferior_pid, w.w_tid);
|
||||
printf ("mywait: pid=0x%x, thread=0x%x, inferior_pid=0x%x\n",
|
||||
pid, w.w_tid, inferior_pid);
|
||||
|
||||
if (WIFSTOPPED(w)
|
||||
&& WSTOPSIG(w) == SIGTRAP)
|
||||
{
|
||||
int realsig;
|
||||
|
||||
realsig = ptrace (PTRACE_GETTRACESIG, inferior_pid,
|
||||
(PTRACE_ARG3_TYPE)0, 0);
|
||||
|
||||
if (realsig == SIGNEWTHREAD)
|
||||
{
|
||||
/* Simply ignore new thread notification, as we can't do anything
|
||||
useful with such threads. All ptrace calls at this point just
|
||||
fail for no apparent reason. The thread will eventually get a
|
||||
real signal when it becomes real. */
|
||||
myresume (0, 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (WIFEXITED (w))
|
||||
{
|
||||
fprintf (stderr, "\nChild exited with status %d\n", WEXITSTATUS (w));
|
||||
fprintf (stderr, "GDBserver exiting\n");
|
||||
exit (0);
|
||||
*status = 'W';
|
||||
return ((unsigned char) WEXITSTATUS (w));
|
||||
}
|
||||
else if (!WIFSTOPPED (w))
|
||||
{
|
||||
fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
|
||||
*status = 'T';
|
||||
*status = 'X';
|
||||
return ((unsigned char) WTERMSIG (w));
|
||||
}
|
||||
|
||||
fetch_inferior_registers (0);
|
||||
|
||||
*status = 'S';
|
||||
*status = 'T';
|
||||
return ((unsigned char) WSTOPSIG (w));
|
||||
}
|
||||
|
||||
@ -148,7 +172,9 @@ myresume (step, signal)
|
||||
int signal;
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
|
||||
ptrace (step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT,
|
||||
BUILDPID (inferior_pid, cont_thread == -1 ? 0 : cont_thread),
|
||||
1, signal);
|
||||
if (errno)
|
||||
perror_with_name ("ptrace");
|
||||
}
|
||||
@ -334,7 +360,9 @@ fetch_inferior_registers (regno)
|
||||
int i;
|
||||
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
|
||||
retval = ptrace (PTRACE_GETREGS,
|
||||
BUILDPID (inferior_pid, general_thread),
|
||||
(PTRACE_ARG3_TYPE) &ec,
|
||||
0);
|
||||
if (errno)
|
||||
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||
@ -387,7 +415,7 @@ fetch_inferior_registers (regno)
|
||||
int i;
|
||||
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
|
||||
retval = ptrace (PTRACE_GETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &fc,
|
||||
0);
|
||||
if (errno)
|
||||
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||
@ -446,7 +474,7 @@ store_inferior_registers (regno)
|
||||
8 * REGISTER_RAW_SIZE (O0_REGNUM));
|
||||
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
|
||||
retval = ptrace (PTRACE_SETREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &ec,
|
||||
0);
|
||||
if (errno)
|
||||
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||
@ -493,7 +521,7 @@ store_inferior_registers (regno)
|
||||
|
||||
/* We read fcontext first so that we can get good values for fq_t... */
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
|
||||
retval = ptrace (PTRACE_GETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &fc,
|
||||
0);
|
||||
if (errno)
|
||||
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||
@ -504,7 +532,7 @@ store_inferior_registers (regno)
|
||||
fc.fsr = read_register (FPS_REGNUM);
|
||||
|
||||
errno = 0;
|
||||
retval = ptrace (PTRACE_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
|
||||
retval = ptrace (PTRACE_SETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &fc,
|
||||
0);
|
||||
if (errno)
|
||||
perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
|
||||
@ -526,12 +554,12 @@ lynx_registers_addr()
|
||||
CORE_ADDR ecp;
|
||||
|
||||
errno = 0;
|
||||
stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, inferior_pid,
|
||||
stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, BUILDPID (inferior_pid, general_thread),
|
||||
(PTRACE_ARG3_TYPE)0, 0);
|
||||
if (errno)
|
||||
perror_with_name ("PTRACE_THREADUSER");
|
||||
|
||||
ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, inferior_pid,
|
||||
ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, BUILDPID (inferior_pid, general_thread),
|
||||
(PTRACE_ARG3_TYPE)ecpoff, 0);
|
||||
if (errno)
|
||||
perror_with_name ("lynx_registers_addr(PTRACE_PEEKTHREAD)");
|
||||
@ -562,7 +590,7 @@ fetch_inferior_registers (ignored)
|
||||
#endif
|
||||
|
||||
errno = 0;
|
||||
reg = ptrace (ptrace_fun, inferior_pid,
|
||||
reg = ptrace (ptrace_fun, BUILDPID (inferior_pid, general_thread),
|
||||
(PTRACE_ARG3_TYPE) (ecp + regmap[regno]), 0);
|
||||
if (errno)
|
||||
perror_with_name ("fetch_inferior_registers(PTRACE_PEEKTHREAD)");
|
||||
@ -596,7 +624,7 @@ store_inferior_registers (ignored)
|
||||
reg = *(unsigned long *)®isters[REGISTER_BYTE (regno)];
|
||||
|
||||
errno = 0;
|
||||
ptrace (ptrace_fun, inferior_pid,
|
||||
ptrace (ptrace_fun, BUILDPID (inferior_pid, general_thread),
|
||||
(PTRACE_ARG3_TYPE) (ecp + regmap[regno]), reg);
|
||||
if (errno)
|
||||
perror_with_name ("PTRACE_POKEUSER");
|
||||
@ -632,7 +660,7 @@ read_inferior_memory (memaddr, myaddr, len)
|
||||
/* Read all the longwords */
|
||||
for (i = 0; i < count; i++, addr += sizeof (int))
|
||||
{
|
||||
buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
|
||||
buffer[i] = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread), addr, 0);
|
||||
}
|
||||
|
||||
/* Copy appropriate bytes out of the buffer. */
|
||||
@ -662,12 +690,12 @@ write_inferior_memory (memaddr, myaddr, len)
|
||||
|
||||
/* Fill start and end extra bytes of buffer with existing memory data. */
|
||||
|
||||
buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
|
||||
buffer[0] = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread), addr, 0);
|
||||
|
||||
if (count > 1)
|
||||
{
|
||||
buffer[count - 1]
|
||||
= ptrace (PTRACE_PEEKTEXT, inferior_pid,
|
||||
= ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread),
|
||||
addr + (count - 1) * sizeof (int), 0);
|
||||
}
|
||||
|
||||
@ -682,10 +710,13 @@ write_inferior_memory (memaddr, myaddr, len)
|
||||
while (1)
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (PTRACE_POKETEXT, inferior_pid, addr, buffer[i]);
|
||||
ptrace (PTRACE_POKETEXT, BUILDPID (inferior_pid, general_thread), addr, buffer[i]);
|
||||
if (errno)
|
||||
{
|
||||
fprintf(stderr, "ptrace (PTRACE_POKETEXT): errno=%d, inferior_pid=0x%x, addr=0x%x, buffer[i] = 0x%x\n", errno, inferior_pid, addr, buffer[i]);
|
||||
fprintf(stderr, "\
|
||||
ptrace (PTRACE_POKETEXT): errno=%d, pid=0x%x, addr=0x%x, buffer[i] = 0x%x\n",
|
||||
errno, BUILDPID (inferior_pid, general_thread),
|
||||
addr, buffer[i]);
|
||||
fprintf(stderr, "Sleeping for 1 second\n");
|
||||
sleep(1);
|
||||
}
|
||||
|
@ -114,19 +114,19 @@ mywait (status)
|
||||
if (WIFEXITED (w))
|
||||
{
|
||||
fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
|
||||
*status = 'E';
|
||||
*status = 'W';
|
||||
return ((unsigned char) WEXITSTATUS (w));
|
||||
}
|
||||
else if (!WIFSTOPPED (w))
|
||||
{
|
||||
fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
|
||||
*status = 'T';
|
||||
*status = 'X';
|
||||
return ((unsigned char) WTERMSIG (w));
|
||||
}
|
||||
|
||||
fetch_inferior_registers (0);
|
||||
|
||||
*status = 'S';
|
||||
*status = 'T';
|
||||
return ((unsigned char) WSTOPSIG (w));
|
||||
}
|
||||
|
||||
|
@ -111,19 +111,19 @@ mywait (status)
|
||||
if (WIFEXITED (w))
|
||||
{
|
||||
fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
|
||||
*status = 'E';
|
||||
*status = 'W';
|
||||
return ((unsigned char) WEXITSTATUS (w));
|
||||
}
|
||||
else if (!WIFSTOPPED (w))
|
||||
{
|
||||
fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
|
||||
*status = 'T';
|
||||
*status = 'X';
|
||||
return ((unsigned char) WTERMSIG (w));
|
||||
}
|
||||
|
||||
fetch_inferior_registers (0);
|
||||
|
||||
*status = 'S';
|
||||
*status = 'T';
|
||||
return ((unsigned char) WSTOPSIG (w));
|
||||
}
|
||||
|
||||
|
86
gdb/infrun.c
86
gdb/infrun.c
@ -43,26 +43,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static void
|
||||
signals_info PARAMS ((char *, int));
|
||||
static void signals_info PARAMS ((char *, int));
|
||||
|
||||
static void
|
||||
handle_command PARAMS ((char *, int));
|
||||
static void handle_command PARAMS ((char *, int));
|
||||
|
||||
static void sig_print_info PARAMS ((enum target_signal));
|
||||
|
||||
static void
|
||||
sig_print_header PARAMS ((void));
|
||||
static void sig_print_header PARAMS ((void));
|
||||
|
||||
static void
|
||||
resume_cleanups PARAMS ((int));
|
||||
static void resume_cleanups PARAMS ((int));
|
||||
|
||||
static int
|
||||
hook_stop_stub PARAMS ((char *));
|
||||
static int hook_stop_stub PARAMS ((char *));
|
||||
|
||||
/* GET_LONGJMP_TARGET returns the PC at which longjmp() will resume the
|
||||
program. It needs to examine the jmp_buf argument and extract the PC
|
||||
from it. The return value is non-zero on success, zero otherwise. */
|
||||
|
||||
#ifndef GET_LONGJMP_TARGET
|
||||
#define GET_LONGJMP_TARGET(PC_ADDR) 0
|
||||
#endif
|
||||
@ -71,15 +67,24 @@ hook_stop_stub PARAMS ((char *));
|
||||
/* Some machines have trampoline code that sits between function callers
|
||||
and the actual functions themselves. If this machine doesn't have
|
||||
such things, disable their processing. */
|
||||
|
||||
#ifndef SKIP_TRAMPOLINE_CODE
|
||||
#define SKIP_TRAMPOLINE_CODE(pc) 0
|
||||
#endif
|
||||
|
||||
/* For SVR4 shared libraries, each call goes through a small piece of
|
||||
trampoline code in the ".plt" section. IN_SOLIB_TRAMPOLINE evaluates
|
||||
trampoline code in the ".plt" section. IN_SOLIB_CALL_TRAMPOLINE evaluates
|
||||
to nonzero if we are current stopped in one of these. */
|
||||
#ifndef IN_SOLIB_TRAMPOLINE
|
||||
#define IN_SOLIB_TRAMPOLINE(pc,name) 0
|
||||
|
||||
#ifndef IN_SOLIB_CALL_TRAMPOLINE
|
||||
#define IN_SOLIB_CALL_TRAMPOLINE(pc,name) 0
|
||||
#endif
|
||||
|
||||
/* In some shared library schemes, the return path from a shared library
|
||||
call may need to go through a trampoline too. */
|
||||
|
||||
#ifndef IN_SOLIB_RETURN_TRAMPOLINE
|
||||
#define IN_SOLIB_RETURN_TRAMPOLINE(pc,name) 0
|
||||
#endif
|
||||
|
||||
/* On some systems, the PC may be left pointing at an instruction that won't
|
||||
@ -371,6 +376,7 @@ static char *prev_func_name;
|
||||
void
|
||||
start_remote ()
|
||||
{
|
||||
init_thread_list ();
|
||||
init_wait_for_inferior ();
|
||||
clear_proceed_status ();
|
||||
stop_soon_quietly = 1;
|
||||
@ -522,7 +528,14 @@ wait_for_inferior ()
|
||||
stop_signal = w.value.sig;
|
||||
target_terminal_ours (); /* Must do this before mourn anyway */
|
||||
annotate_signalled ();
|
||||
|
||||
/* This looks pretty bogus to me. Doesn't TARGET_WAITKIND_SIGNALLED
|
||||
mean it is already dead? This has been here since GDB 2.8, so
|
||||
perhaps it means rms didn't understand unix waitstatuses?
|
||||
For the moment I'm just kludging around this in remote.c
|
||||
rather than trying to change it here --kingdon, 5 Dec 1994. */
|
||||
target_kill (); /* kill mourns as well */
|
||||
|
||||
printf_filtered ("\nProgram terminated with signal ");
|
||||
annotate_signal_name ();
|
||||
printf_filtered ("%s", target_signal_to_name (stop_signal));
|
||||
@ -1142,7 +1155,7 @@ wait_for_inferior ()
|
||||
call. I'm not completely sure this is necessary now that we
|
||||
have the above checks with stop_func_start (and now that
|
||||
find_pc_partial_function is pickier). */
|
||||
|| IN_SOLIB_TRAMPOLINE (stop_pc, stop_func_name)
|
||||
|| IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
|
||||
|
||||
/* If none of the above apply, it is a jump within a function,
|
||||
or a return from a subroutine. The other case is longjmp,
|
||||
@ -1280,6 +1293,38 @@ step_into_function:
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we're in the return path from a shared library trampoline,
|
||||
we want to proceed through the trampoline when stepping. */
|
||||
if (IN_SOLIB_RETURN_TRAMPOLINE(stop_pc, stop_func_name))
|
||||
{
|
||||
CORE_ADDR tmp;
|
||||
|
||||
/* Determine where this trampoline returns. */
|
||||
tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
|
||||
|
||||
/* Only proceed through if we know where it's going. */
|
||||
if (tmp)
|
||||
{
|
||||
/* And put the step-breakpoint there and go until there. */
|
||||
struct symtab_and_line sr_sal;
|
||||
|
||||
sr_sal.pc = tmp;
|
||||
sr_sal.symtab = NULL;
|
||||
sr_sal.line = 0;
|
||||
/* Do not specify what the fp should be when we stop
|
||||
since on some machines the prologue
|
||||
is where the new fp value is established. */
|
||||
step_resume_breakpoint =
|
||||
set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
|
||||
if (breakpoints_inserted)
|
||||
insert_breakpoints ();
|
||||
|
||||
/* Restart without fiddling with the step ranges or
|
||||
other state. */
|
||||
goto keep_going;
|
||||
}
|
||||
}
|
||||
|
||||
if (sal.line == 0)
|
||||
{
|
||||
/* We have no line number information. That means to stop
|
||||
@ -1885,7 +1930,7 @@ save_inferior_status (inf_status, restore_stack_info)
|
||||
}
|
||||
|
||||
struct restore_selected_frame_args {
|
||||
FRAME_ADDR frame_address;
|
||||
CORE_ADDR frame_address;
|
||||
int level;
|
||||
};
|
||||
|
||||
@ -1895,27 +1940,28 @@ static int restore_selected_frame PARAMS ((char *));
|
||||
restore_selected_frame_args * (declared as char * for catch_errors)
|
||||
telling us what frame to restore. Returns 1 for success, or 0 for
|
||||
failure. An error message will have been printed on error. */
|
||||
|
||||
static int
|
||||
restore_selected_frame (args)
|
||||
char *args;
|
||||
{
|
||||
struct restore_selected_frame_args *fr =
|
||||
(struct restore_selected_frame_args *) args;
|
||||
FRAME fid;
|
||||
struct frame_info *frame;
|
||||
int level = fr->level;
|
||||
|
||||
fid = find_relative_frame (get_current_frame (), &level);
|
||||
frame = find_relative_frame (get_current_frame (), &level);
|
||||
|
||||
/* If inf_status->selected_frame_address is NULL, there was no
|
||||
previously selected frame. */
|
||||
if (fid == 0 ||
|
||||
FRAME_FP (fid) != fr->frame_address ||
|
||||
if (frame == NULL ||
|
||||
FRAME_FP (frame) != fr->frame_address ||
|
||||
level != 0)
|
||||
{
|
||||
warning ("Unable to restore previously selected frame.\n");
|
||||
return 0;
|
||||
}
|
||||
select_frame (fid, fr->level);
|
||||
select_frame (frame, fr->level);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
238
gdb/remote.c
238
gdb/remote.c
@ -38,10 +38,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
- - if CSUM is incorrect
|
||||
|
||||
<data> is as follows:
|
||||
All values are encoded in ascii hex digits.
|
||||
Most values are encoded in ascii hex digits. Signal numbers are according
|
||||
to the numbering in target.h.
|
||||
|
||||
Request Packet
|
||||
|
||||
set thread Hct... Set thread for subsequent operations.
|
||||
c = 'c' for thread used in step and
|
||||
continue; t... can be -1 for all
|
||||
threads.
|
||||
c = 'g' for thread used in other
|
||||
operations. If zero, pick a thread,
|
||||
any thread.
|
||||
reply OK for success
|
||||
ENN for an error.
|
||||
|
||||
read registers g
|
||||
reply XX....X Each byte of register data
|
||||
is described by two hex digits.
|
||||
@ -78,7 +89,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
where only part of the data was
|
||||
written).
|
||||
|
||||
cont cAA..AA AA..AA is address to resume
|
||||
continue cAA..AA AA..AA is address to resume
|
||||
If AA..AA is omitted,
|
||||
resume at same address.
|
||||
|
||||
@ -86,6 +97,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
If AA..AA is omitted,
|
||||
resume at same address.
|
||||
|
||||
continue with Csig;AA Continue with signal sig (hex signal
|
||||
signal number).
|
||||
|
||||
step with Ssig;AA Like 'C' but step not continue.
|
||||
signal
|
||||
|
||||
last signal ? Reply the current reason for stopping.
|
||||
This is the same reply as is generated
|
||||
for step or cont : SAA where AA is the
|
||||
@ -93,16 +110,31 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
There is no immediate reply to step or cont.
|
||||
The reply comes when the machine stops.
|
||||
It is SAA AA is the "signal number"
|
||||
It is SAA AA is the signal number.
|
||||
|
||||
or... TAAn...:r...;n:r...;n...:r...;
|
||||
or... TAAn...:r...;n...:r...;n...:r...;
|
||||
AA = signal number
|
||||
n... = register number
|
||||
r... = register contents
|
||||
n... = register number (hex)
|
||||
r... = register contents
|
||||
n... = `thread'
|
||||
r... = thread process ID. This is
|
||||
a hex integer.
|
||||
n... = other string not starting
|
||||
with valid hex digit.
|
||||
gdb should ignore this n,r pair
|
||||
and go on to the next. This way
|
||||
we can extend the protocol.
|
||||
or... WAA The process exited, and AA is
|
||||
the exit status. This is only
|
||||
applicable for certains sorts of
|
||||
targets.
|
||||
or... XAA The process terminated with signal
|
||||
AA.
|
||||
or... Otext Send text to stdout. This can happen
|
||||
at any time while the program is
|
||||
running and the debugger should
|
||||
continue to wait for 'W', 'T', etc.
|
||||
|
||||
kill request k
|
||||
|
||||
toggle debug d toggle debug flag (see 386 & 68k stubs)
|
||||
@ -122,8 +154,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
general set QXXXX=yyyy Set value of XXXX to yyyy.
|
||||
query sect offs qOffsets Get section offsets. Reply is
|
||||
Text=xxx;Data=yyy;Bss=zzz
|
||||
console output Otext Send text to stdout. Only comes from
|
||||
remote target.
|
||||
|
||||
Responses can be run-length encoded to save space. A '*' means that
|
||||
the next character is an ASCII encoding giving a repeat count which
|
||||
@ -196,7 +226,7 @@ remote_store_registers PARAMS ((int regno));
|
||||
static void
|
||||
getpkt PARAMS ((char *buf, int forever));
|
||||
|
||||
static void
|
||||
static int
|
||||
putpkt PARAMS ((char *buf));
|
||||
|
||||
static void
|
||||
@ -266,6 +296,39 @@ serial_t remote_desc = NULL;
|
||||
doesn't support 'P', the only consequence is some unnecessary traffic. */
|
||||
static int stub_supports_P = 1;
|
||||
|
||||
|
||||
/* These are the threads which we last sent to the remote system. -1 for all
|
||||
or -2 for not sent yet. */
|
||||
int general_thread;
|
||||
int cont_thread;
|
||||
|
||||
static void
|
||||
set_thread (th, gen)
|
||||
int th;
|
||||
int gen;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
int state = gen ? general_thread : cont_thread;
|
||||
if (state == th)
|
||||
return;
|
||||
buf[0] = 'H';
|
||||
buf[1] = gen ? 'g' : 'c';
|
||||
if (th == 42000)
|
||||
{
|
||||
buf[2] = '0';
|
||||
buf[3] = '\0';
|
||||
}
|
||||
else if (th < 0)
|
||||
sprintf (&buf[2], "-%x", -th);
|
||||
else
|
||||
sprintf (&buf[2], "%x", th);
|
||||
putpkt (buf);
|
||||
getpkt (buf, 0);
|
||||
if (gen)
|
||||
general_thread = th;
|
||||
else
|
||||
cont_thread = th;
|
||||
}
|
||||
|
||||
/* Clean up connection to a remote debugger. */
|
||||
|
||||
@ -348,6 +411,9 @@ remote_start_remote (dummy)
|
||||
|
||||
SERIAL_WRITE (remote_desc, "+", 1);
|
||||
|
||||
/* Let the stub know that we want it to return the thread. */
|
||||
set_thread (-1, 0);
|
||||
|
||||
get_offsets (); /* Get text, data & bss offsets */
|
||||
|
||||
putpkt ("?"); /* initiate a query from remote machine */
|
||||
@ -411,6 +477,9 @@ device is attached to the remote system (e.g. /dev/ttya).");
|
||||
stub to another, we can (if the target is closed and reopened) cope. */
|
||||
stub_supports_P = 1;
|
||||
|
||||
general_thread = -2;
|
||||
cont_thread = -2;
|
||||
|
||||
/* Without this, some commands which require an active target (such as kill)
|
||||
won't work. This variable serves (at least) double duty as both the pid
|
||||
of the target process (if it has such), and as a flag indicating that a
|
||||
@ -477,6 +546,9 @@ tohex (nib)
|
||||
|
||||
/* Tell the remote machine to resume. */
|
||||
|
||||
static enum target_signal last_sent_signal = TARGET_SIGNAL_0;
|
||||
int last_sent_step;
|
||||
|
||||
static void
|
||||
remote_resume (pid, step, siggnal)
|
||||
int pid, step;
|
||||
@ -484,18 +556,25 @@ remote_resume (pid, step, siggnal)
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
|
||||
if (siggnal)
|
||||
{
|
||||
target_terminal_ours_for_output ();
|
||||
printf_filtered
|
||||
("Can't send signals to a remote system. %s not sent.\n",
|
||||
target_signal_to_name (siggnal));
|
||||
target_terminal_inferior ();
|
||||
}
|
||||
if (pid == -1)
|
||||
set_thread (inferior_pid, 0);
|
||||
else
|
||||
set_thread (pid, 0);
|
||||
|
||||
dcache_flush (remote_dcache);
|
||||
|
||||
strcpy (buf, step ? "s": "c");
|
||||
last_sent_signal = siggnal;
|
||||
last_sent_step = step;
|
||||
|
||||
if (siggnal != TARGET_SIGNAL_0)
|
||||
{
|
||||
buf[0] = step ? 'S' : 'C';
|
||||
buf[1] = tohex (((int)siggnal >> 4) & 0xf);
|
||||
buf[2] = tohex ((int)siggnal & 0xf);
|
||||
buf[3] = '\0';
|
||||
}
|
||||
else
|
||||
strcpy (buf, step ? "s": "c");
|
||||
|
||||
putpkt (buf);
|
||||
}
|
||||
@ -547,6 +626,9 @@ Give up (and stop debugging it)? "))
|
||||
target_terminal_inferior ();
|
||||
}
|
||||
|
||||
/* If nonzero, ignore the next kill. */
|
||||
int kill_kludge;
|
||||
|
||||
/* Wait until the remote machine stops, then return,
|
||||
storing status in STATUS just as `wait' would.
|
||||
Returns "pid" (though it's not clear what, if anything, that
|
||||
@ -558,6 +640,7 @@ remote_wait (pid, status)
|
||||
struct target_waitstatus *status;
|
||||
{
|
||||
unsigned char buf[PBUFSIZ];
|
||||
int thread_num = -1;
|
||||
|
||||
status->kind = TARGET_WAITKIND_EXITED;
|
||||
status->value.integer = 0;
|
||||
@ -597,31 +680,44 @@ remote_wait (pid, status)
|
||||
regno = strtol (p, &p1, 16); /* Read the register number */
|
||||
|
||||
if (p1 == p)
|
||||
warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n",
|
||||
p1, buf);
|
||||
|
||||
p = p1;
|
||||
|
||||
if (*p++ != ':')
|
||||
warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n",
|
||||
p, buf);
|
||||
|
||||
if (regno >= NUM_REGS)
|
||||
warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n",
|
||||
regno, p, buf);
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
|
||||
{
|
||||
if (p[0] == 0 || p[1] == 0)
|
||||
warning ("Remote reply is too short: %s", buf);
|
||||
regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
|
||||
p += 2;
|
||||
p1 = (unsigned char *) strchr (p, ':');
|
||||
if (p1 == NULL)
|
||||
warning ("Malformed packet (missing colon): %s\n\
|
||||
Packet: '%s'\n",
|
||||
p, buf);
|
||||
if (strncmp (p, "thread", p1 - p) == 0)
|
||||
{
|
||||
char *p2;
|
||||
thread_num = strtol (++p1, &p, 16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p = p1;
|
||||
|
||||
if (*p++ != ':')
|
||||
warning ("Malformed packet (missing colon): %s\n\
|
||||
Packet: '%s'\n",
|
||||
p, buf);
|
||||
|
||||
if (regno >= NUM_REGS)
|
||||
warning ("Remote sent bad register number %d: %s\n\
|
||||
Packet: '%s'\n",
|
||||
regno, p, buf);
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
|
||||
{
|
||||
if (p[0] == 0 || p[1] == 0)
|
||||
warning ("Remote reply is too short: %s", buf);
|
||||
regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
|
||||
p += 2;
|
||||
}
|
||||
supply_register (regno, regs);
|
||||
}
|
||||
|
||||
if (*p++ != ';')
|
||||
warning ("Remote register badly formatted: %s", buf);
|
||||
|
||||
supply_register (regno, regs);
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
@ -630,22 +726,60 @@ remote_wait (pid, status)
|
||||
status->value.sig = (enum target_signal)
|
||||
(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
|
||||
|
||||
return inferior_pid;
|
||||
goto got_status;
|
||||
case 'W': /* Target exited */
|
||||
{
|
||||
/* The remote process exited. */
|
||||
status->kind = TARGET_WAITKIND_EXITED;
|
||||
status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
|
||||
return inferior_pid;
|
||||
goto got_status;
|
||||
}
|
||||
case 'X':
|
||||
status->kind = TARGET_WAITKIND_SIGNALLED;
|
||||
status->value.sig = (enum target_signal)
|
||||
(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
|
||||
kill_kludge = 1;
|
||||
|
||||
goto got_status;
|
||||
case 'O': /* Console output */
|
||||
fputs_filtered ((char *)(buf + 1), gdb_stdout);
|
||||
continue;
|
||||
case '\0':
|
||||
if (last_sent_signal != TARGET_SIGNAL_0)
|
||||
{
|
||||
/* Zero length reply means that we tried 'S' or 'C' and
|
||||
the remote system doesn't support it. */
|
||||
target_terminal_ours_for_output ();
|
||||
printf_filtered
|
||||
("Can't send signals to this remote system. %s not sent.\n",
|
||||
target_signal_to_name (last_sent_signal));
|
||||
last_sent_signal = TARGET_SIGNAL_0;
|
||||
target_terminal_inferior ();
|
||||
|
||||
strcpy (buf, last_sent_step ? 's' : 'c');
|
||||
putpkt (buf);
|
||||
continue;
|
||||
}
|
||||
/* else fallthrough */
|
||||
default:
|
||||
warning ("Invalid remote reply: %s", buf);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
got_status:
|
||||
if (thread_num != -1)
|
||||
{
|
||||
/* Initial thread value can only be acquired via wait, so deal with
|
||||
this marker which is used before the first thread value is
|
||||
acquired. */
|
||||
if (inferior_pid == 42000)
|
||||
{
|
||||
inferior_pid = thread_num;
|
||||
add_thread (inferior_pid);
|
||||
}
|
||||
return thread_num;
|
||||
}
|
||||
return inferior_pid;
|
||||
}
|
||||
|
||||
/* Number of bytes of registers this stub implements. */
|
||||
@ -663,6 +797,8 @@ remote_fetch_registers (regno)
|
||||
char *p;
|
||||
char regs[REGISTER_BYTES];
|
||||
|
||||
set_thread (inferior_pid, 1);
|
||||
|
||||
sprintf (buf, "g");
|
||||
remote_send (buf);
|
||||
|
||||
@ -736,6 +872,8 @@ remote_store_registers (regno)
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
set_thread (inferior_pid, 1);
|
||||
|
||||
if (regno >= 0 && stub_supports_P)
|
||||
{
|
||||
/* Try storing a single register. */
|
||||
@ -944,6 +1082,8 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target)
|
||||
int bytes_xferred;
|
||||
int total_xferred = 0;
|
||||
|
||||
set_thread (inferior_pid, 1);
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
if (len > MAXBUFBYTES)
|
||||
@ -1096,7 +1236,7 @@ remote_send (buf)
|
||||
/* Send a packet to the remote machine, with error checking.
|
||||
The data of the packet is in BUF. */
|
||||
|
||||
static void
|
||||
static int
|
||||
putpkt (buf)
|
||||
char *buf;
|
||||
{
|
||||
@ -1165,7 +1305,7 @@ putpkt (buf)
|
||||
case '+':
|
||||
if (remote_debug)
|
||||
printf_unfiltered("Ack\n");
|
||||
return;
|
||||
return 1;
|
||||
case SERIAL_TIMEOUT:
|
||||
break; /* Retransmit buffer */
|
||||
case '$':
|
||||
@ -1367,7 +1507,19 @@ retry:
|
||||
static void
|
||||
remote_kill ()
|
||||
{
|
||||
putpkt ("k");
|
||||
/* For some mysterious reason, wait_for_inferior calls kill instead of
|
||||
mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
|
||||
if (kill_kludge)
|
||||
{
|
||||
kill_kludge = 0;
|
||||
target_mourn_inferior ();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Use catch_errors so the user can quit from gdb even when we aren't on
|
||||
speaking terms with the remote system. */
|
||||
catch_errors (putpkt, "k", "", RETURN_MASK_ERROR);
|
||||
|
||||
/* Don't wait for it to die. I'm not really sure it matters whether
|
||||
we do or not. For the existing stubs, kill is a noop. */
|
||||
target_mourn_inferior ();
|
||||
|
10
gdb/thread.c
10
gdb/thread.c
@ -170,9 +170,17 @@ info_threads_command (arg, from_tty)
|
||||
struct thread_info *tp;
|
||||
int current_pid = inferior_pid;
|
||||
|
||||
/* Avoid coredumps which would happen if we tried to access a NULL
|
||||
selected_frame. */
|
||||
if (!target_has_stack) error ("No stack.");
|
||||
|
||||
for (tp = thread_list; tp; tp = tp->next)
|
||||
{
|
||||
if (target_has_execution
|
||||
/* FIXME: need to figure out a way to do this for remote too,
|
||||
or else the print_stack_frame below will fail with a bogus
|
||||
thread ID. */
|
||||
if (!STREQ (current_target.to_shortname, "remote")
|
||||
&& target_has_execution
|
||||
&& kill (tp->pid, 0) == -1)
|
||||
{
|
||||
tp->pid = -1; /* Mark it as dead */
|
||||
|
Loading…
Reference in New Issue
Block a user