mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-16 12:24:19 +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:
@ -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. */
|
||||
|
Reference in New Issue
Block a user