mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-22 11:00:01 +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:
@ -117,6 +117,9 @@
|
|||||||
/* Set to true if the save_state_t structure has the ss_wide member */
|
/* Set to true if the save_state_t structure has the ss_wide member */
|
||||||
#undef HAVE_STRUCT_MEMBER_SS_WIDE
|
#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. */
|
/* Define if <sys/ptrace.h> defines the PTRACE_GETXFPREGS request. */
|
||||||
#undef HAVE_PTRACE_GETXFPREGS
|
#undef HAVE_PTRACE_GETXFPREGS
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Native support for GNU/Linux, for GDB, the GNU debugger.
|
/* 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.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GDB.
|
This file is part of GDB.
|
||||||
@ -62,9 +62,16 @@ extern int kernel_u_size PARAMS ((void));
|
|||||||
#include "solib.h" /* Support for shared libraries. */
|
#include "solib.h" /* Support for shared libraries. */
|
||||||
#endif
|
#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
|
#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
|
extern CORE_ADDR
|
||||||
i386_stopped_by_watchpoint PARAMS ((int));
|
i386_stopped_by_watchpoint PARAMS ((int));
|
||||||
extern int
|
extern int
|
||||||
|
@ -101,6 +101,18 @@ AC_C_CONST
|
|||||||
AC_CHECK_FUNCS(setpgid sbrk sigaction isascii bzero bcopy btowc poll sigprocmask)
|
AC_CHECK_FUNCS(setpgid sbrk sigaction isascii bzero bcopy btowc poll sigprocmask)
|
||||||
AC_FUNC_ALLOCA
|
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 See if ptrace.h provides the PTRACE_GETXFPREGS request.
|
||||||
dnl PTRACE_GETXFPREGS is a Cygnus invention, since we wrote our own
|
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
|
dnl Linux kernel patch for SSE support. That patch may or may not
|
||||||
|
@ -79,6 +79,15 @@ static int regmap[] =
|
|||||||
#define GETXFPREGS_SUPPLIES(regno) \
|
#define GETXFPREGS_SUPPLIES(regno) \
|
||||||
(FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
|
(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
|
/* Does the current host support the GETXFPREGS request? The header
|
||||||
file may or may not define it, and even if it is defined, the
|
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.
|
kernel will return EIO if it's running on a pre-SSE processor.
|
||||||
@ -102,6 +111,157 @@ int have_ptrace_getxfpregs =
|
|||||||
#endif
|
#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
|
/* Transfering the general-purpose registers between GDB, inferiors
|
||||||
and core files. */
|
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
|
/* Fetch all general-purpose registers from process/thread TID and
|
||||||
store their values in GDB's register array. */
|
store their values in GDB's register array. */
|
||||||
|
|
||||||
@ -170,6 +332,14 @@ fetch_regs (int tid)
|
|||||||
ret = ptrace (PTRACE_GETREGS, tid, 0, (int) ®s);
|
ret = ptrace (PTRACE_GETREGS, tid, 0, (int) ®s);
|
||||||
if (ret < 0)
|
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.");
|
warning ("Couldn't get registers.");
|
||||||
return;
|
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. */
|
/* 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
|
/* Fetch all floating-point registers from process/thread TID and store
|
||||||
thier values in GDB's register array. */
|
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. */
|
/* Transfering floating-point and SSE registers to and from GDB. */
|
||||||
|
|
||||||
@ -561,6 +747,14 @@ fetch_inferior_registers (int regno)
|
|||||||
{
|
{
|
||||||
int tid;
|
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. */
|
/* Linux LWP ID's are process ID's. */
|
||||||
if ((tid = TIDGET (inferior_pid)) == 0)
|
if ((tid = TIDGET (inferior_pid)) == 0)
|
||||||
tid = inferior_pid; /* Not a threaded program. */
|
tid = inferior_pid; /* Not a threaded program. */
|
||||||
@ -572,6 +766,14 @@ fetch_inferior_registers (int regno)
|
|||||||
if (regno == -1)
|
if (regno == -1)
|
||||||
{
|
{
|
||||||
fetch_regs (tid);
|
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))
|
if (fetch_xfpregs (tid))
|
||||||
return;
|
return;
|
||||||
fetch_fpregs (tid);
|
fetch_fpregs (tid);
|
||||||
@ -612,6 +814,14 @@ store_inferior_registers (int regno)
|
|||||||
{
|
{
|
||||||
int tid;
|
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. */
|
/* Linux LWP ID's are process ID's. */
|
||||||
if ((tid = TIDGET (inferior_pid)) == 0)
|
if ((tid = TIDGET (inferior_pid)) == 0)
|
||||||
tid = inferior_pid; /* Not a threaded program. */
|
tid = inferior_pid; /* Not a threaded program. */
|
||||||
|
Reference in New Issue
Block a user