1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-05 09:14:03 +00:00

bring in the necessary changes to make gdbserver compile and work (at

least on i386)...  fbsd-* changes started out as s/linux/fbsd/g and then
additional changes to handle different ptrace defines among other things..
(use vfork to eliminate a race for progress group creation)

reg-i386.c is generated by regdat.sh..
This commit is contained in:
John-Mark Gurney 2006-04-06 22:24:01 +00:00
parent 2f05465cd1
commit c7f87cc77f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=157574
5 changed files with 212 additions and 318 deletions

View File

@ -0,0 +1,22 @@
# $FreeBSD$
# Not elf specific so don't install in /usr/libexec/elf
BINDIR=/usr/bin
GDBDIR= ${.CURDIR}/../../../../contrib/gdb
.PATH: ${GDBDIR}/gdb/signals
.PATH: ${GDBDIR}/gdb/gdbserver
.PATH: ${GDBDIR}/gdb
PROG= gdbserver
SRCS= i387-fp.c inferiors.c mem-break.c regcache.c remote-utils.c \
server.c signals.c target.c reg-i386.c utils.c
SRCS+= fbsd-low.c fbsd-i386-low.c
#CFLAGS+= -I${.CURDIR}/../arch/${MACHINE_ARCH}
CFLAGS+= -I${GDBDIR}/gdb/gdbserver
CFLAGS+= -I${GDBDIR}/gdb/regformats
CFLAGS+= -DNO_MMALLOC -DGDBSERVER
.include <bsd.prog.mk>

View File

@ -19,28 +19,33 @@
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "server.h"
#include "linux-low.h"
#include "fbsd-low.h"
#include "i387-fp.h"
#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
#else
#include <machine/reg.h>
#endif
/* This module only supports access to the general purpose registers. */
#define i386_num_regs 16
/* This stuff comes from i386-linux-nat.c. */
/* This stuff comes from i386-fbsd-nat.c. */
/* Mapping between the general-purpose registers in `struct user'
format and GDB's register array layout. */
static int i386_regmap[] =
{
EAX * 4, ECX * 4, EDX * 4, EBX * 4,
UESP * 4, EBP * 4, ESI * 4, EDI * 4,
EIP * 4, EFL * 4, CS * 4, SS * 4,
DS * 4, ES * 4, FS * 4, GS * 4
tEAX * 4, tECX * 4, tEDX * 4, tEBX * 4,
tESP * 4, tEBP * 4, tESI * 4, tEDI * 4,
tEIP * 4, tEFLAGS * 4, tCS * 4, tSS * 4,
tDS * 4, tES * 4, tFS * 4, tGS * 4
};
static int
@ -56,7 +61,6 @@ i386_cannot_fetch_register (int regno)
}
#ifdef HAVE_LINUX_REGSETS
#include <sys/procfs.h>
#include <sys/ptrace.h>
@ -68,7 +72,6 @@ i386_fill_gregset (void *buf)
for (i = 0; i < i386_num_regs; i++)
collect_register (i, ((char *) buf) + i386_regmap[i]);
collect_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4);
}
static void
@ -79,7 +82,6 @@ i386_store_gregset (const void *buf)
for (i = 0; i < i386_num_regs; i++)
supply_register (i, ((char *) buf) + i386_regmap[i]);
supply_register_by_name ("orig_eax", ((char *) buf) + ORIG_EAX * 4);
}
static void
@ -108,7 +110,7 @@ i386_store_fpxregset (const void *buf)
struct regset_info target_regsets[] = {
{ PTRACE_GETREGS, PTRACE_SETREGS, sizeof (elf_gregset_t),
{ PT_GETREGS, PT_SETREGS, sizeof (struct reg),
GENERAL_REGS,
i386_fill_gregset, i386_store_gregset },
#ifdef HAVE_PTRACE_GETFPXREGS
@ -116,14 +118,12 @@ struct regset_info target_regsets[] = {
EXTENDED_REGS,
i386_fill_fpxregset, i386_store_fpxregset },
#endif
{ PTRACE_GETFPREGS, PTRACE_SETFPREGS, sizeof (elf_fpregset_t),
{ PT_GETFPREGS, PT_SETFPREGS, sizeof (struct fpreg),
FP_REGS,
i386_fill_fpregset, i386_store_fpregset },
{ 0, 0, -1, -1, NULL, NULL }
};
#endif /* HAVE_LINUX_REGSETS */
static const char i386_breakpoint[] = { 0xCC };
#define i386_breakpoint_len 1
@ -161,7 +161,7 @@ i386_breakpoint_at (CORE_ADDR pc)
return 0;
}
struct linux_target_ops the_low_target = {
struct fbsd_target_ops the_low_target = {
i386_num_regs,
i386_regmap,
i386_cannot_fetch_register,

View File

@ -19,22 +19,25 @@
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "server.h"
#include "linux-low.h"
#include "fbsd-low.h"
#include <sys/wait.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* ``all_threads'' is keyed by the LWP ID - it should be the thread ID instead,
however. This requires changing the ID in place when we go from !using_threads
@ -51,11 +54,11 @@ int stopping_threads;
/* FIXME make into a target method? */
int using_threads;
static void linux_resume_one_process (struct inferior_list_entry *entry,
static void fbsd_resume_one_process (struct inferior_list_entry *entry,
int step, int signal);
static void linux_resume (struct thread_resume *resume_info);
static void fbsd_resume (struct thread_resume *resume_info);
static void stop_all_processes (void);
static int linux_wait_for_event (struct thread_info *child);
static int fbsd_wait_for_event (struct thread_info *child);
struct pending_signals
{
@ -63,12 +66,8 @@ struct pending_signals
struct pending_signals *prev;
};
#define PTRACE_ARG3_TYPE long
#define PTRACE_XFER_TYPE long
#ifdef HAVE_LINUX_REGSETS
static int use_regsets_p = 1;
#endif
#define PTRACE_ARG3_TYPE caddr_t
#define PTRACE_XFER_TYPE int
int debug_threads = 0;
@ -81,7 +80,7 @@ int debug_threads = 0;
The SIGTRAP could mean several things.
On i386, where decr_pc_after_break is non-zero:
If we were single-stepping this process using PTRACE_SINGLESTEP,
If we were single-stepping this process using PT_STEP,
we will get only the one SIGTRAP (even if the instruction we
stepped over was a breakpoint). The value of $eip will be the
next instruction.
@ -133,20 +132,18 @@ add_process (int pid)
ALLARGS is a vector of program-name and args. */
static int
linux_create_inferior (char *program, char **allargs)
fbsd_create_inferior (char *program, char **allargs)
{
void *new_process;
int pid;
pid = fork ();
pid = vfork ();
if (pid < 0)
perror_with_name ("fork");
perror_with_name ("vfork");
if (pid == 0)
{
ptrace (PTRACE_TRACEME, 0, 0, 0);
signal (__SIGRTMIN + 1, SIG_DFL);
ptrace (PT_TRACE_ME, 0, 0, 0);
setpgid (0, 0);
@ -167,11 +164,11 @@ linux_create_inferior (char *program, char **allargs)
/* Attach to an inferior process. */
void
linux_attach_lwp (int pid, int tid)
fbsd_attach_lwp (int pid, int tid)
{
struct process_info *new_process;
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
if (ptrace (PT_ATTACH, pid, 0, 0) != 0)
{
fprintf (stderr, "Cannot attach to process %d: %s (%d)\n", pid,
strerror (errno), errno);
@ -189,7 +186,7 @@ linux_attach_lwp (int pid, int tid)
/* The next time we wait for this LWP we'll see a SIGSTOP as PTRACE_ATTACH
brings it to a halt. We should ignore that SIGSTOP and resume the process
(unless this is the first process, in which case the flag will be cleared
in linux_attach).
in fbsd_attach).
On the other hand, if we are currently trying to stop all threads, we
should treat the new thread as if we had sent it a SIGSTOP. This works
@ -201,11 +198,11 @@ linux_attach_lwp (int pid, int tid)
}
int
linux_attach (int pid)
fbsd_attach (int pid)
{
struct process_info *process;
linux_attach_lwp (pid, pid);
fbsd_attach_lwp (pid, pid);
/* Don't ignore the initial SIGSTOP if we just attached to this process. */
process = (struct process_info *) find_inferior_id (&all_processes, pid);
@ -217,7 +214,7 @@ linux_attach (int pid)
/* Kill the inferior process. Make us have no inferior. */
static void
linux_kill_one_process (struct inferior_list_entry *entry)
fbsd_kill_one_process (struct inferior_list_entry *entry)
{
struct thread_info *thread = (struct thread_info *) entry;
struct process_info *process = get_thread_process (thread);
@ -225,37 +222,37 @@ linux_kill_one_process (struct inferior_list_entry *entry)
do
{
ptrace (PTRACE_KILL, pid_of (process), 0, 0);
ptrace (PT_KILL, pid_of (process), 0, 0);
/* Make sure it died. The loop is most likely unnecessary. */
wstat = linux_wait_for_event (thread);
wstat = fbsd_wait_for_event (thread);
} while (WIFSTOPPED (wstat));
}
static void
linux_kill (void)
fbsd_kill (void)
{
for_each_inferior (&all_threads, linux_kill_one_process);
for_each_inferior (&all_threads, fbsd_kill_one_process);
}
static void
linux_detach_one_process (struct inferior_list_entry *entry)
fbsd_detach_one_process (struct inferior_list_entry *entry)
{
struct thread_info *thread = (struct thread_info *) entry;
struct process_info *process = get_thread_process (thread);
ptrace (PTRACE_DETACH, pid_of (process), 0, 0);
ptrace (PT_DETACH, pid_of (process), 0, 0);
}
static void
linux_detach (void)
fbsd_detach (void)
{
for_each_inferior (&all_threads, linux_detach_one_process);
for_each_inferior (&all_threads, fbsd_detach_one_process);
}
/* Return nonzero if the given thread is still alive. */
static int
linux_thread_alive (int tid)
fbsd_thread_alive (int tid)
{
if (find_inferior_id (&all_threads, tid) != NULL)
return 1;
@ -339,7 +336,7 @@ status_pending_p (struct inferior_list_entry *entry, void *dummy)
So instead of reporting the old SIGTRAP, pretend we got to
the breakpoint just after it was removed instead of just
before; resume the process. */
linux_resume_one_process (&process->head, 0, 0);
fbsd_resume_one_process (&process->head, 0, 0);
return 0;
}
@ -347,7 +344,7 @@ status_pending_p (struct inferior_list_entry *entry, void *dummy)
}
static void
linux_wait_for_process (struct process_info **childp, int *wstatp)
fbsd_wait_for_process (struct process_info **childp, int *wstatp)
{
int ret;
int to_wait_for = -1;
@ -367,16 +364,6 @@ linux_wait_for_process (struct process_info **childp, int *wstatp)
else if (ret > 0)
break;
ret = waitpid (to_wait_for, wstatp, WNOHANG | __WCLONE);
if (ret == -1)
{
if (errno != ECHILD)
perror_with_name ("waitpid (WCLONE)");
}
else if (ret > 0)
break;
usleep (1000);
}
@ -404,7 +391,7 @@ linux_wait_for_process (struct process_info **childp, int *wstatp)
}
static int
linux_wait_for_event (struct thread_info *child)
fbsd_wait_for_event (struct thread_info *child)
{
CORE_ADDR stop_pc;
struct process_info *event_child;
@ -455,7 +442,7 @@ linux_wait_for_event (struct thread_info *child)
else
event_child = get_thread_process (child);
linux_wait_for_process (&event_child, &wstat);
fbsd_wait_for_process (&event_child, &wstat);
if (event_child == NULL)
error ("event from unknown child");
@ -499,22 +486,20 @@ linux_wait_for_event (struct thread_info *child)
if (debug_threads)
fprintf (stderr, "Expected stop.\n");
event_child->stop_expected = 0;
linux_resume_one_process (&event_child->head,
fbsd_resume_one_process (&event_child->head,
event_child->stepping, 0);
continue;
}
/* FIXME drow/2002-06-09: Get signal numbers from the inferior's
thread library? */
if (WIFSTOPPED (wstat)
&& (WSTOPSIG (wstat) == __SIGRTMIN
|| WSTOPSIG (wstat) == __SIGRTMIN + 1))
if (WIFSTOPPED (wstat))
{
if (debug_threads)
fprintf (stderr, "Ignored signal %d for %d (LWP %d).\n",
WSTOPSIG (wstat), event_child->tid,
event_child->head.id);
linux_resume_one_process (&event_child->head,
fbsd_resume_one_process (&event_child->head,
event_child->stepping,
WSTOPSIG (wstat));
continue;
@ -545,7 +530,7 @@ linux_wait_for_event (struct thread_info *child)
event_child->bp_reinsert = 0;
/* Clear the single-stepping flag and SIGTRAP as we resume. */
linux_resume_one_process (&event_child->head, 0, 0);
fbsd_resume_one_process (&event_child->head, 0, 0);
continue;
}
@ -572,7 +557,7 @@ linux_wait_for_event (struct thread_info *child)
be avoided where possible.
If breakpoint_reinsert_addr is NULL, that means that we can
use PTRACE_SINGLESTEP on this platform. Uninsert the breakpoint,
use PT_STEP on this platform. Uninsert the breakpoint,
mark it for reinsertion, and single-step.
Otherwise, call the target function to figure out where we need
@ -582,13 +567,13 @@ linux_wait_for_event (struct thread_info *child)
{
event_child->bp_reinsert = stop_pc;
uninsert_breakpoint (stop_pc);
linux_resume_one_process (&event_child->head, 1, 0);
fbsd_resume_one_process (&event_child->head, 1, 0);
}
else
{
reinsert_breakpoint_by_bp
(stop_pc, (*the_low_target.breakpoint_reinsert_addr) ());
linux_resume_one_process (&event_child->head, 0, 0);
fbsd_resume_one_process (&event_child->head, 0, 0);
}
continue;
@ -633,7 +618,7 @@ linux_wait_for_event (struct thread_info *child)
/* Wait for process, returns status. */
static unsigned char
linux_wait (char *status)
fbsd_wait (char *status)
{
int w;
struct thread_info *child = NULL;
@ -656,18 +641,18 @@ linux_wait (char *status)
struct thread_resume resume_info;
resume_info.thread = -1;
resume_info.step = resume_info.sig = resume_info.leave_stopped = 0;
linux_resume (&resume_info);
fbsd_resume (&resume_info);
}
}
enable_async_io ();
unblock_async_io ();
w = linux_wait_for_event (child);
w = fbsd_wait_for_event (child);
stop_all_processes ();
disable_async_io ();
/* If we are waiting for a particular child, and it exited,
linux_wait_for_event will return its exit status. Similarly if
fbsd_wait_for_event will return its exit status. Similarly if
the last child exited. If this is not the last child, however,
do not report it as exited until there is a 'thread exited' response
available in the remote protocol. Instead, just wait for another event.
@ -746,7 +731,7 @@ wait_for_sigstop (struct inferior_list_entry *entry)
saved_tid = ((struct inferior_list_entry *) saved_inferior)->id;
thread = (struct thread_info *) find_inferior_id (&all_threads,
process->tid);
wstat = linux_wait_for_event (thread);
wstat = fbsd_wait_for_event (thread);
/* If we stopped with a non-SIGSTOP signal, save it for later
and record the pending SIGSTOP. If the process exited, just
@ -761,7 +746,7 @@ wait_for_sigstop (struct inferior_list_entry *entry)
process->stop_expected = 1;
}
if (linux_thread_alive (saved_tid))
if (fbsd_thread_alive (saved_tid))
current_inferior = saved_inferior;
else
{
@ -787,7 +772,7 @@ stop_all_processes (void)
If SIGNAL is nonzero, give it that signal. */
static void
linux_resume_one_process (struct inferior_list_entry *entry,
fbsd_resume_one_process (struct inferior_list_entry *entry,
int step, int signal)
{
struct process_info *process = (struct process_info *) entry;
@ -828,7 +813,7 @@ linux_resume_one_process (struct inferior_list_entry *entry,
the reinsert happened right away and not lose any signals.
Making this stack would also shrink the window in which breakpoints are
uninserted (see comment in linux_wait_for_process) but not enough for
uninserted (see comment in fbsd_wait_for_process) but not enough for
complete correctness, so it won't solve that problem. It may be
worthwhile just to solve this one, however. */
if (process->bp_reinsert != 0)
@ -871,7 +856,7 @@ linux_resume_one_process (struct inferior_list_entry *entry,
errno = 0;
process->stopped = 0;
process->stepping = step;
ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, process->lwpid, 0, signal);
ptrace (step ? PT_STEP : PT_CONTINUE, process->lwpid, (PTRACE_ARG3_TYPE) 1, signal);
current_inferior = saved_inferior;
if (errno)
@ -888,7 +873,7 @@ static struct thread_resume *resume_ptr;
is small (and will remain small at least until GDB supports thread
suspension). */
static void
linux_set_resume_request (struct inferior_list_entry *entry)
fbsd_set_resume_request (struct inferior_list_entry *entry)
{
struct process_info *process;
struct thread_info *thread;
@ -911,7 +896,7 @@ linux_set_resume_request (struct inferior_list_entry *entry)
is used for stepping over gdbserver-placed breakpoints. */
static void
linux_continue_one_thread (struct inferior_list_entry *entry)
fbsd_continue_one_thread (struct inferior_list_entry *entry)
{
struct process_info *process;
struct thread_info *thread;
@ -928,7 +913,7 @@ linux_continue_one_thread (struct inferior_list_entry *entry)
else
step = process->resume->step;
linux_resume_one_process (&process->head, step, process->resume->sig);
fbsd_resume_one_process (&process->head, step, process->resume->sig);
process->resume = NULL;
}
@ -941,7 +926,7 @@ linux_continue_one_thread (struct inferior_list_entry *entry)
be re-issued if necessary. */
static void
linux_queue_one_thread (struct inferior_list_entry *entry)
fbsd_queue_one_thread (struct inferior_list_entry *entry)
{
struct process_info *process;
struct thread_info *thread;
@ -972,7 +957,7 @@ resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
struct process_info *process = (struct process_info *) entry;
/* Processes which will not be resumed are not interesting, because
we might not wait for them next time through linux_wait. */
we might not wait for them next time through fbsd_wait. */
if (process->resume->leave_stopped)
return 0;
@ -994,14 +979,14 @@ resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
}
static void
linux_resume (struct thread_resume *resume_info)
fbsd_resume (struct thread_resume *resume_info)
{
int pending_flag;
/* Yes, the use of a global here is rather ugly. */
resume_ptr = resume_info;
for_each_inferior (&all_threads, linux_set_resume_request);
for_each_inferior (&all_threads, fbsd_set_resume_request);
/* If there is a thread which would otherwise be resumed, which
has a pending status, then don't resume any threads - we can just
@ -1019,133 +1004,15 @@ linux_resume (struct thread_resume *resume_info)
}
if (pending_flag)
for_each_inferior (&all_threads, linux_queue_one_thread);
for_each_inferior (&all_threads, fbsd_queue_one_thread);
else
{
block_async_io ();
enable_async_io ();
for_each_inferior (&all_threads, linux_continue_one_thread);
for_each_inferior (&all_threads, fbsd_continue_one_thread);
}
}
#ifdef HAVE_LINUX_USRREGS
int
register_addr (int regnum)
{
int addr;
if (regnum < 0 || regnum >= the_low_target.num_regs)
error ("Invalid register number %d.", regnum);
addr = the_low_target.regmap[regnum];
return addr;
}
/* Fetch one register. */
static void
fetch_register (int regno)
{
CORE_ADDR regaddr;
register int i;
char *buf;
if (regno >= the_low_target.num_regs)
return;
if ((*the_low_target.cannot_fetch_register) (regno))
return;
regaddr = register_addr (regno);
if (regaddr == -1)
return;
buf = alloca (register_size (regno));
for (i = 0; i < register_size (regno); i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
*(PTRACE_XFER_TYPE *) (buf + i) =
ptrace (PTRACE_PEEKUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, 0);
regaddr += sizeof (PTRACE_XFER_TYPE);
if (errno != 0)
{
/* Warning, not error, in case we are attached; sometimes the
kernel doesn't let us at the registers. */
char *err = strerror (errno);
char *msg = alloca (strlen (err) + 128);
sprintf (msg, "reading register %d: %s", regno, err);
error (msg);
goto error_exit;
}
}
supply_register (regno, buf);
error_exit:;
}
/* Fetch all registers, or just one, from the child process. */
static void
usr_fetch_inferior_registers (int regno)
{
if (regno == -1 || regno == 0)
for (regno = 0; regno < the_low_target.num_regs; regno++)
fetch_register (regno);
else
fetch_register (regno);
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
static void
usr_store_inferior_registers (int regno)
{
CORE_ADDR regaddr;
int i;
char *buf;
if (regno >= 0)
{
if (regno >= the_low_target.num_regs)
return;
if ((*the_low_target.cannot_store_register) (regno) == 1)
return;
regaddr = register_addr (regno);
if (regaddr == -1)
return;
errno = 0;
buf = alloca (register_size (regno));
collect_register (regno, buf);
for (i = 0; i < register_size (regno); i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
*(PTRACE_XFER_TYPE *) (buf + i));
if (errno != 0)
{
if ((*the_low_target.cannot_store_register) (regno) == 0)
{
char *err = strerror (errno);
char *msg = alloca (strlen (err) + 128);
sprintf (msg, "writing register %d: %s",
regno, err);
error (msg);
return;
}
}
regaddr += sizeof (PTRACE_XFER_TYPE);
}
}
else
for (regno = 0; regno < the_low_target.num_regs; regno++)
usr_store_inferior_registers (regno);
}
#endif /* HAVE_LINUX_USRREGS */
#ifdef HAVE_LINUX_REGSETS
static int
regsets_fetch_inferior_registers ()
@ -1166,31 +1033,13 @@ regsets_fetch_inferior_registers ()
}
buf = malloc (regset->size);
res = ptrace (regset->get_request, inferior_pid, 0, buf);
res = ptrace (regset->get_request, inferior_pid, (PTRACE_ARG3_TYPE) buf, 0);
if (res < 0)
{
if (errno == EIO)
{
/* If we get EIO on the first regset, do not try regsets again.
If we get EIO on a later regset, disable that regset. */
if (regset == target_regsets)
{
use_regsets_p = 0;
return -1;
}
else
{
regset->size = 0;
continue;
}
}
else
{
char s[256];
sprintf (s, "ptrace(regsets_fetch_inferior_registers) PID=%d",
inferior_pid);
perror (s);
}
char s[256];
sprintf (s, "ptrace(regsets_fetch_inferior_registers) PID=%d",
inferior_pid);
perror (s);
}
regset->store_function (buf);
regset ++;
@ -1218,28 +1067,10 @@ regsets_store_inferior_registers ()
buf = malloc (regset->size);
regset->fill_function (buf);
res = ptrace (regset->set_request, inferior_pid, 0, buf);
res = ptrace (regset->set_request, inferior_pid, (PTRACE_ARG3_TYPE) buf, 0);
if (res < 0)
{
if (errno == EIO)
{
/* If we get EIO on the first regset, do not try regsets again.
If we get EIO on a later regset, disable that regset. */
if (regset == target_regsets)
{
use_regsets_p = 0;
return -1;
}
else
{
regset->size = 0;
continue;
}
}
else
{
perror ("Warning: ptrace(regsets_store_inferior_registers)");
}
perror ("Warning: ptrace(regsets_store_inferior_registers)");
}
regset ++;
free (buf);
@ -1247,37 +1078,16 @@ regsets_store_inferior_registers ()
return 0;
}
#endif /* HAVE_LINUX_REGSETS */
void
linux_fetch_registers (int regno)
fbsd_fetch_registers (int regno)
{
#ifdef HAVE_LINUX_REGSETS
if (use_regsets_p)
{
if (regsets_fetch_inferior_registers () == 0)
return;
}
#endif
#ifdef HAVE_LINUX_USRREGS
usr_fetch_inferior_registers (regno);
#endif
regsets_fetch_inferior_registers ();
}
void
linux_store_registers (int regno)
fbsd_store_registers (int regno)
{
#ifdef HAVE_LINUX_REGSETS
if (use_regsets_p)
{
if (regsets_store_inferior_registers () == 0)
return;
}
#endif
#ifdef HAVE_LINUX_USRREGS
usr_store_inferior_registers (regno);
#endif
regsets_store_inferior_registers ();
}
@ -1285,7 +1095,7 @@ linux_store_registers (int regno)
to debugger memory starting at MYADDR. */
static int
linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
fbsd_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
register int i;
/* Round starting address down to longword boundary. */
@ -1302,7 +1112,7 @@ linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
buffer[i] = ptrace (PT_READ_D, inferior_pid, (PTRACE_ARG3_TYPE) (intptr_t)addr, 0);
if (errno)
return errno;
}
@ -1319,7 +1129,7 @@ linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
returns the value of errno. */
static int
linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
fbsd_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
{
register int i;
/* Round starting address down to longword boundary. */
@ -1338,14 +1148,14 @@ linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
/* Fill start and end extra bytes of buffer with existing memory data. */
buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid,
(PTRACE_ARG3_TYPE) addr, 0);
buffer[0] = ptrace (PT_READ_D, inferior_pid,
(PTRACE_ARG3_TYPE) (intptr_t)addr, 0);
if (count > 1)
{
buffer[count - 1]
= ptrace (PTRACE_PEEKTEXT, inferior_pid,
(PTRACE_ARG3_TYPE) (addr + (count - 1)
= ptrace (PT_READ_D, inferior_pid,
(PTRACE_ARG3_TYPE) (intptr_t) (addr + (count - 1)
* sizeof (PTRACE_XFER_TYPE)),
0);
}
@ -1359,7 +1169,7 @@ linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
ptrace (PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
ptrace (PT_WRITE_D, inferior_pid, (PTRACE_ARG3_TYPE) (intptr_t)addr, buffer[i]);
if (errno)
return errno;
}
@ -1368,7 +1178,7 @@ linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
}
static void
linux_look_up_symbols (void)
fbsd_look_up_symbols (void)
{
#ifdef USE_THREAD_DB
if (using_threads)
@ -1379,7 +1189,7 @@ linux_look_up_symbols (void)
}
static void
linux_send_signal (int signum)
fbsd_send_signal (int signum)
{
extern int signal_pid;
@ -1398,7 +1208,7 @@ linux_send_signal (int signum)
to debugger memory starting at MYADDR. */
static int
linux_read_auxv (CORE_ADDR offset, char *myaddr, unsigned int len)
fbsd_read_auxv (CORE_ADDR offset, char *myaddr, unsigned int len)
{
char filename[PATH_MAX];
int fd, n;
@ -1421,38 +1231,35 @@ linux_read_auxv (CORE_ADDR offset, char *myaddr, unsigned int len)
}
static struct target_ops linux_target_ops = {
linux_create_inferior,
linux_attach,
linux_kill,
linux_detach,
linux_thread_alive,
linux_resume,
linux_wait,
linux_fetch_registers,
linux_store_registers,
linux_read_memory,
linux_write_memory,
linux_look_up_symbols,
linux_send_signal,
linux_read_auxv,
static struct target_ops fbsd_target_ops = {
fbsd_create_inferior,
fbsd_attach,
fbsd_kill,
fbsd_detach,
fbsd_thread_alive,
fbsd_resume,
fbsd_wait,
fbsd_fetch_registers,
fbsd_store_registers,
fbsd_read_memory,
fbsd_write_memory,
fbsd_look_up_symbols,
fbsd_send_signal,
fbsd_read_auxv,
};
static void
linux_init_signals ()
fbsd_init_signals ()
{
/* FIXME drow/2002-06-09: As above, we should check with LinuxThreads
to find what the cancel signal actually is. */
signal (__SIGRTMIN+1, SIG_IGN);
}
void
initialize_low (void)
{
using_threads = 0;
set_target_ops (&linux_target_ops);
set_target_ops (&fbsd_target_ops);
set_breakpoint_data (the_low_target.breakpoint,
the_low_target.breakpoint_len);
init_registers ();
linux_init_signals ();
fbsd_init_signals ();
}

View File

@ -18,7 +18,10 @@
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifdef HAVE_LINUX_REGSETS
/*
* $FreeBSD$
*/
typedef void (*regset_fill_func) (void *);
typedef void (*regset_store_func) (const void *);
enum regset_type {
@ -36,9 +39,8 @@ struct regset_info
regset_store_func store_function;
};
extern struct regset_info target_regsets[];
#endif
struct linux_target_ops
struct fbsd_target_ops
{
int num_regs;
int *regmap;
@ -59,7 +61,7 @@ struct linux_target_ops
int (*breakpoint_at) (CORE_ADDR pc);
};
extern struct linux_target_ops the_low_target;
extern struct fbsd_target_ops the_low_target;
#define get_process(inf) ((struct process_info *)(inf))
#define get_thread_process(thr) (get_process (inferior_target_data (thr)))
@ -108,13 +110,13 @@ struct process_info
struct pending_signals *pending_signals;
/* A link used when resuming. It is initialized from the resume request,
and then processed and cleared in linux_resume_one_process. */
and then processed and cleared in fbsd_resume_one_process. */
struct thread_resume *resume;
};
extern struct inferior_list all_processes;
void linux_attach_lwp (int pid, int tid);
void fbsd_attach_lwp (int pid, int tid);
int thread_db_init (void);

View File

@ -0,0 +1,63 @@
/* *INDENT-OFF* */ /* THIS FILE IS GENERATED */
/* This file was created with the aid of ``regdat.sh'' and ``../../../../contrib/gdb/gdb/regformats/reg-i386.dat''. */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "regdef.h"
#include "regcache.h"
struct reg regs_i386[] = {
{ "eax", 0, 32 },
{ "ecx", 32, 32 },
{ "edx", 64, 32 },
{ "ebx", 96, 32 },
{ "esp", 128, 32 },
{ "ebp", 160, 32 },
{ "esi", 192, 32 },
{ "edi", 224, 32 },
{ "eip", 256, 32 },
{ "eflags", 288, 32 },
{ "cs", 320, 32 },
{ "ss", 352, 32 },
{ "ds", 384, 32 },
{ "es", 416, 32 },
{ "fs", 448, 32 },
{ "gs", 480, 32 },
{ "st0", 512, 80 },
{ "st1", 592, 80 },
{ "st2", 672, 80 },
{ "st3", 752, 80 },
{ "st4", 832, 80 },
{ "st5", 912, 80 },
{ "st6", 992, 80 },
{ "st7", 1072, 80 },
{ "fctrl", 1152, 32 },
{ "fstat", 1184, 32 },
{ "ftag", 1216, 32 },
{ "fiseg", 1248, 32 },
{ "fioff", 1280, 32 },
{ "foseg", 1312, 32 },
{ "fooff", 1344, 32 },
{ "fop", 1376, 32 },
{ "xmm0", 1408, 128 },
{ "xmm1", 1536, 128 },
{ "xmm2", 1664, 128 },
{ "xmm3", 1792, 128 },
{ "xmm4", 1920, 128 },
{ "xmm5", 2048, 128 },
{ "xmm6", 2176, 128 },
{ "xmm7", 2304, 128 },
{ "mxcsr", 2432, 32 },
};
const char *expedite_regs_i386[] = { "ebp", "esp", "eip", 0 };
void
init_registers ()
{
set_register_cache (regs_i386,
sizeof (regs_i386) / sizeof (regs_i386[0]));
gdbserver_expedite_regs = expedite_regs_i386;
}