mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-28 12:33:36 +08:00
2000-03-05 Mark Kettenis <kettenis@gnu.org>
Allow GDB to run on Linux 2.0 again. * config.in: Add HAVE_PTRACE_GETREGS. * configure.in: Check if <sys/ptrace.h> defines PTRACE_GETREGS. * configure: Regenerated. * config/i386/nm-linux.h (CANNOT_FETCH_REGISTER, CANNOT_STORE_REGISTER): New defines. * i386-linux-nat.c (have_ptrace_getregs): New variable. (PTRACE_XFER_TYPE, CANNOT_FETCH_REGISTER, fetch_register, old_fetch_inferior_registers, CANNOT_STORE_REGISTER, store_register, old_store_inferior_registers): Copied over from `inptrace.c' as a temporary measure. (fetch_regs, store_regs, fetch_fpregs, store_fpregs): Conditionalize on HAVE_PTRACE_GETREGS. Define stubs if HAVE_PTRACE_GETREGS isn't defined. (fetch_regs): Reset `have_ptrace_getregs' if ptrace call fails with EIO. (fetch_inferior_registers, store_inferior_registers): Fall back on the method use in `infptrace.c' (by calling old_fetch_inferior_registers and old_store_inferior_registers) if `have_ptrace_getregs' isn't set.
This commit is contained in:
parent
04cd15b61d
commit
f60300e72c
@ -117,6 +117,9 @@
|
||||
/* Set to true if the save_state_t structure has the ss_wide member */
|
||||
#undef HAVE_STRUCT_MEMBER_SS_WIDE
|
||||
|
||||
/* Define if <sys/ptrace.h> defines the PTRACE_GETREGS request. */
|
||||
#undef HAVE_PTRACE_GETREGS
|
||||
|
||||
/* Define if <sys/ptrace.h> defines the PTRACE_GETXFPREGS request. */
|
||||
#undef HAVE_PTRACE_GETXFPREGS
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Native support for GNU/Linux, for GDB, the GNU debugger.
|
||||
Copyright (C) 1986, 1987, 1989, 1992, 1996, 1998
|
||||
Copyright (C) 1986, 1987, 1989, 1992, 1996, 1998, 2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
@ -62,9 +62,16 @@ extern int kernel_u_size PARAMS ((void));
|
||||
#include "solib.h" /* Support for shared libraries. */
|
||||
#endif
|
||||
|
||||
/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
|
||||
/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'. */
|
||||
#define FETCH_INFERIOR_REGISTERS
|
||||
|
||||
/* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we fall
|
||||
back on the code `infptrace.c' (well a copy of that code in
|
||||
`i386-linux-nat.c' for now) and we can access only the
|
||||
general-purpose registers in that way. */
|
||||
#define CANNOT_FETCH_REGISTER(regno) ((regno) >= NUM_GREGS)
|
||||
#define CANNOT_STORE_REGISTER(regno) CANNOT_FETCH_REGISTER (regno)
|
||||
|
||||
extern CORE_ADDR
|
||||
i386_stopped_by_watchpoint PARAMS ((int));
|
||||
extern int
|
||||
|
@ -101,6 +101,18 @@ AC_C_CONST
|
||||
AC_CHECK_FUNCS(setpgid sbrk sigaction isascii bzero bcopy btowc poll sigprocmask)
|
||||
AC_FUNC_ALLOCA
|
||||
|
||||
dnl See if ptrace.h provides the PTRACE_GETREGS request.
|
||||
AC_MSG_CHECKING(for PTRACE_GETREGS)
|
||||
AC_CACHE_VAL(gdb_cv_have_ptrace_getregs,
|
||||
[AC_TRY_COMPILE([#include <sys/ptrace.h>],
|
||||
[PTRACE_GETREGS;],
|
||||
[gdb_cv_have_ptrace_getregs=yes],
|
||||
[gdb_cv_have_ptrace_getregs=no])])
|
||||
AC_MSG_RESULT($gdb_cv_have_ptrace_getregs)
|
||||
if test $gdb_cv_have_ptrace_getregs = yes; then
|
||||
AC_DEFINE(HAVE_PTRACE_GETREGS)
|
||||
fi
|
||||
|
||||
dnl See if ptrace.h provides the PTRACE_GETXFPREGS request.
|
||||
dnl PTRACE_GETXFPREGS is a Cygnus invention, since we wrote our own
|
||||
dnl Linux kernel patch for SSE support. That patch may or may not
|
||||
|
@ -79,6 +79,15 @@ static int regmap[] =
|
||||
#define GETXFPREGS_SUPPLIES(regno) \
|
||||
(FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
|
||||
|
||||
/* Does the current host support the GETREGS request? */
|
||||
int have_ptrace_getregs =
|
||||
#ifdef HAVE_PTRACE_GETREGS
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
;
|
||||
|
||||
/* Does the current host support the GETXFPREGS request? The header
|
||||
file may or may not define it, and even if it is defined, the
|
||||
kernel will return EIO if it's running on a pre-SSE processor.
|
||||
@ -102,6 +111,157 @@ int have_ptrace_getxfpregs =
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
/* FIXME: kettenis/2000-03-05: This duplicates code from `inptrace.c'.
|
||||
The problem is that we define FETCH_INFERIOR_REGISTERS since we
|
||||
want to use our own versions of {fetch,store}_inferior_registers
|
||||
that use the GETREGS request. This means that the code in
|
||||
`infptrace.c' is #ifdef'd out. But we need to fall back on that
|
||||
code when GDB is running on top of a kernel that doesn't support
|
||||
the GETREGS request. I want to avoid changing `infptrace.c' right
|
||||
now. */
|
||||
|
||||
/* Default the type of the ptrace transfer to int. */
|
||||
#ifndef PTRACE_XFER_TYPE
|
||||
#define PTRACE_XFER_TYPE int
|
||||
#endif
|
||||
|
||||
/* Registers we shouldn't try to fetch. */
|
||||
#if !defined (CANNOT_FETCH_REGISTER)
|
||||
#define CANNOT_FETCH_REGISTER(regno) 0
|
||||
#endif
|
||||
|
||||
/* Fetch one register. */
|
||||
|
||||
static void
|
||||
fetch_register (regno)
|
||||
int regno;
|
||||
{
|
||||
/* This isn't really an address. But ptrace thinks of it as one. */
|
||||
CORE_ADDR regaddr;
|
||||
char mess[128]; /* For messages */
|
||||
register int i;
|
||||
unsigned int offset; /* Offset of registers within the u area. */
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
int tid;
|
||||
|
||||
if (CANNOT_FETCH_REGISTER (regno))
|
||||
{
|
||||
memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
|
||||
supply_register (regno, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Overload thread id onto process id */
|
||||
if ((tid = TIDGET (inferior_pid)) == 0)
|
||||
tid = inferior_pid; /* no thread id, just use process id */
|
||||
|
||||
offset = U_REGS_OFFSET;
|
||||
|
||||
regaddr = register_addr (regno, offset);
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
|
||||
{
|
||||
errno = 0;
|
||||
*(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
|
||||
(PTRACE_ARG3_TYPE) regaddr, 0);
|
||||
regaddr += sizeof (PTRACE_XFER_TYPE);
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (mess, "reading register %s (#%d)",
|
||||
REGISTER_NAME (regno), regno);
|
||||
perror_with_name (mess);
|
||||
}
|
||||
}
|
||||
supply_register (regno, buf);
|
||||
}
|
||||
|
||||
/* Fetch register values from the inferior.
|
||||
If REGNO is negative, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
old_fetch_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
if (regno >= 0)
|
||||
{
|
||||
fetch_register (regno);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regno = 0; regno < ARCH_NUM_REGS; regno++)
|
||||
{
|
||||
fetch_register (regno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Registers we shouldn't try to store. */
|
||||
#if !defined (CANNOT_STORE_REGISTER)
|
||||
#define CANNOT_STORE_REGISTER(regno) 0
|
||||
#endif
|
||||
|
||||
/* Store one register. */
|
||||
|
||||
static void
|
||||
store_register (regno)
|
||||
int regno;
|
||||
{
|
||||
/* This isn't really an address. But ptrace thinks of it as one. */
|
||||
CORE_ADDR regaddr;
|
||||
char mess[128]; /* For messages */
|
||||
register int i;
|
||||
unsigned int offset; /* Offset of registers within the u area. */
|
||||
int tid;
|
||||
|
||||
if (CANNOT_STORE_REGISTER (regno))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Overload thread id onto process id */
|
||||
if ((tid = TIDGET (inferior_pid)) == 0)
|
||||
tid = inferior_pid; /* no thread id, just use process id */
|
||||
|
||||
offset = U_REGS_OFFSET;
|
||||
|
||||
regaddr = register_addr (regno, offset);
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
|
||||
{
|
||||
errno = 0;
|
||||
ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
|
||||
*(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i]);
|
||||
regaddr += sizeof (PTRACE_XFER_TYPE);
|
||||
if (errno != 0)
|
||||
{
|
||||
sprintf (mess, "writing register %s (#%d)",
|
||||
REGISTER_NAME (regno), regno);
|
||||
perror_with_name (mess);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store our register values back into the inferior.
|
||||
If REGNO is negative, do this for all registers.
|
||||
Otherwise, REGNO specifies which register (so we can save time). */
|
||||
|
||||
void
|
||||
old_store_inferior_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
if (regno >= 0)
|
||||
{
|
||||
store_register (regno);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regno = 0; regno < ARCH_NUM_REGS; regno++)
|
||||
{
|
||||
store_register (regno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Transfering the general-purpose registers between GDB, inferiors
|
||||
and core files. */
|
||||
@ -158,6 +318,8 @@ fill_gregset (elf_gregset_t *gregsetp, int regno)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_PTRACE_GETREGS
|
||||
|
||||
/* Fetch all general-purpose registers from process/thread TID and
|
||||
store their values in GDB's register array. */
|
||||
|
||||
@ -170,6 +332,14 @@ fetch_regs (int tid)
|
||||
ret = ptrace (PTRACE_GETREGS, tid, 0, (int) ®s);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno == EIO)
|
||||
{
|
||||
/* The kernel we're running on doesn't support the GETREGS
|
||||
request. Reset `have_ptrace_getregs'. */
|
||||
have_ptrace_getregs = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
warning ("Couldn't get registers.");
|
||||
return;
|
||||
}
|
||||
@ -203,6 +373,13 @@ store_regs (int tid)
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void fetch_regs (int tid) {}
|
||||
static void store_regs (int tid) {}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Transfering floating-point registers between GDB, inferiors and cores. */
|
||||
|
||||
@ -307,6 +484,8 @@ fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_PTRACE_GETREGS
|
||||
|
||||
/* Fetch all floating-point registers from process/thread TID and store
|
||||
thier values in GDB's register array. */
|
||||
|
||||
@ -352,6 +531,13 @@ store_fpregs (int tid)
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void fetch_fpregs (int tid) {}
|
||||
static void store_fpregs (int tid) {}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Transfering floating-point and SSE registers to and from GDB. */
|
||||
|
||||
@ -561,6 +747,14 @@ fetch_inferior_registers (int regno)
|
||||
{
|
||||
int tid;
|
||||
|
||||
/* Use the old method of peeking around in `struct user' if the
|
||||
GETREGS request isn't available. */
|
||||
if (! have_ptrace_getregs)
|
||||
{
|
||||
old_fetch_inferior_registers (regno);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Linux LWP ID's are process ID's. */
|
||||
if ((tid = TIDGET (inferior_pid)) == 0)
|
||||
tid = inferior_pid; /* Not a threaded program. */
|
||||
@ -572,6 +766,14 @@ fetch_inferior_registers (int regno)
|
||||
if (regno == -1)
|
||||
{
|
||||
fetch_regs (tid);
|
||||
|
||||
/* The call above might reset `have_ptrace_getregs'. */
|
||||
if (! have_ptrace_getregs)
|
||||
{
|
||||
old_fetch_inferior_registers (-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fetch_xfpregs (tid))
|
||||
return;
|
||||
fetch_fpregs (tid);
|
||||
@ -612,6 +814,14 @@ store_inferior_registers (int regno)
|
||||
{
|
||||
int tid;
|
||||
|
||||
/* Use the old method of poking around in `struct user' if the
|
||||
SETREGS request isn't available. */
|
||||
if (! have_ptrace_getregs)
|
||||
{
|
||||
old_store_inferior_registers (regno);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Linux LWP ID's are process ID's. */
|
||||
if ((tid = TIDGET (inferior_pid)) == 0)
|
||||
tid = inferior_pid; /* Not a threaded program. */
|
||||
|
Loading…
Reference in New Issue
Block a user