mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-03-01 13:26:47 +08:00
* i386-linux-nat.c (ORIG_EAX): Define to -1 if not already
defined. (regmap): Extend to cover all registers. (PT_READ_U, PT_WRITE_U, PTRACE_XFER_TYPE, OLD_CANNOT_FETCH_REGISTERS, OLD_CANNOT_STORE_REGISTERS): Remove definitions. (fetch_register, sore_register): Simplify. (old_fetch_inferior_registers, old_store_inferior_registers): Remove functions. (cannot_fetch_register, cannot_store_register): Change implementation to use regmap array to decide which registers cannot be fetched/stored. This removes $orig_eax from the registers that cannot be fetched/stored. (fetch_inferior_registers): Call fetch_register directly instead of calling old_fetch_inferior_registers. (store_inferior_registers): Call store_register directly instead of calling old_store_inferior_registers. (i386_linux_dr_get): Replace PT_READ_U with PTRACE_PEEKUSER. (i386_linux_dr_set): Replace PT_WRITE_U with PTRACE_POKEUSER. * config/i386/nm-linux.h (U_REGS_OFFSET): Remove definition.
This commit is contained in:
parent
932bb5249e
commit
ce556f8539
@ -1,3 +1,26 @@
|
||||
2002-11-09 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
* i386-linux-nat.c (ORIG_EAX): Define to -1 if not already
|
||||
defined.
|
||||
(regmap): Extend to cover all registers.
|
||||
(PT_READ_U, PT_WRITE_U, PTRACE_XFER_TYPE,
|
||||
OLD_CANNOT_FETCH_REGISTERS, OLD_CANNOT_STORE_REGISTERS): Remove
|
||||
definitions.
|
||||
(fetch_register, sore_register): Simplify.
|
||||
(old_fetch_inferior_registers, old_store_inferior_registers):
|
||||
Remove functions.
|
||||
(cannot_fetch_register, cannot_store_register): Change
|
||||
implementation to use regmap array to decide which registers
|
||||
cannot be fetched/stored. This removes $orig_eax from the
|
||||
registers that cannot be fetched/stored.
|
||||
(fetch_inferior_registers): Call fetch_register directly instead
|
||||
of calling old_fetch_inferior_registers.
|
||||
(store_inferior_registers): Call store_register directly instead
|
||||
of calling old_store_inferior_registers.
|
||||
(i386_linux_dr_get): Replace PT_READ_U with PTRACE_PEEKUSER.
|
||||
(i386_linux_dr_set): Replace PT_WRITE_U with PTRACE_POKEUSER.
|
||||
* config/i386/nm-linux.h (U_REGS_OFFSET): Remove definition.
|
||||
|
||||
2002-11-09 Klee Dienes <kdienes@apple.com>
|
||||
|
||||
* i387-tdep.c (i387_supply_register): When called with NULL as a
|
||||
|
@ -39,9 +39,6 @@ extern int kernel_u_size (void);
|
||||
the core file of the register values. */
|
||||
#define KERNEL_U_ADDR 0
|
||||
|
||||
/* Offset of the registers within the user area. */
|
||||
#define U_REGS_OFFSET 0
|
||||
|
||||
extern CORE_ADDR register_u_addr (CORE_ADDR blockend, int regnum);
|
||||
#define REGISTER_U_ADDR(addr, blockend, regnum) \
|
||||
(addr) = register_u_addr (blockend, regnum)
|
||||
|
@ -34,6 +34,10 @@
|
||||
#include <sys/reg.h>
|
||||
#endif
|
||||
|
||||
#ifndef ORIG_EAX
|
||||
#define ORIG_EAX -1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_DEBUGREG_H
|
||||
#include <sys/debugreg.h>
|
||||
#endif
|
||||
@ -90,7 +94,15 @@ static int regmap[] =
|
||||
EAX, ECX, EDX, EBX,
|
||||
UESP, EBP, ESI, EDI,
|
||||
EIP, EFL, CS, SS,
|
||||
DS, ES, FS, GS
|
||||
DS, ES, FS, GS,
|
||||
-1, -1, -1, -1, /* st0, st1, st2, st3 */
|
||||
-1, -1, -1, -1, /* st4, st5, st6, st7 */
|
||||
-1, -1, -1, -1, /* fctrl, fstat, ftag, fiseg */
|
||||
-1, -1, -1, -1, /* fioff, foseg, fooff, fop */
|
||||
-1, -1, -1, -1, /* xmm0, xmm1, xmm2, xmm3 */
|
||||
-1, -1, -1, -1, /* xmm4, xmm5, xmm6, xmm6 */
|
||||
-1, /* mxcsr */
|
||||
ORIG_EAX
|
||||
};
|
||||
|
||||
/* Which ptrace request retrieves which registers?
|
||||
@ -148,155 +160,58 @@ kernel_u_size (void)
|
||||
}
|
||||
|
||||
|
||||
/* Fetching registers directly from the U area, one at a time. */
|
||||
|
||||
/* 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. */
|
||||
|
||||
#ifndef PT_READ_U
|
||||
#define PT_READ_U PTRACE_PEEKUSR
|
||||
#endif
|
||||
#ifndef PT_WRITE_U
|
||||
#define PT_WRITE_U PTRACE_POKEUSR
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
#define OLD_CANNOT_FETCH_REGISTER(regno) ((regno) >= I386_NUM_GREGS)
|
||||
/* Accessing registers through the U area, one at a time. */
|
||||
|
||||
/* Fetch one register. */
|
||||
|
||||
static void
|
||||
fetch_register (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;
|
||||
int val;
|
||||
|
||||
if (OLD_CANNOT_FETCH_REGISTER (regno))
|
||||
gdb_assert (!have_ptrace_getregs);
|
||||
if (cannot_fetch_register (regno))
|
||||
{
|
||||
memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
|
||||
supply_register (regno, buf);
|
||||
supply_register (regno, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Overload thread id onto process id */
|
||||
/* GNU/Linux LWP ID's are process ID's. */
|
||||
if ((tid = TIDGET (inferior_ptid)) == 0)
|
||||
tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
|
||||
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
|
||||
|
||||
offset = U_REGS_OFFSET;
|
||||
errno = 0;
|
||||
val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0);
|
||||
if (errno != 0)
|
||||
error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno),
|
||||
regno, safe_strerror (errno));
|
||||
|
||||
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);
|
||||
supply_register (regno, &val);
|
||||
}
|
||||
|
||||
/* 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 (int regno)
|
||||
{
|
||||
if (regno >= 0)
|
||||
{
|
||||
fetch_register (regno);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
{
|
||||
fetch_register (regno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Registers we shouldn't try to store. */
|
||||
#define OLD_CANNOT_STORE_REGISTER(regno) ((regno) >= I386_NUM_GREGS)
|
||||
|
||||
/* Store one register. */
|
||||
|
||||
static void
|
||||
store_register (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;
|
||||
int val;
|
||||
|
||||
if (OLD_CANNOT_STORE_REGISTER (regno))
|
||||
{
|
||||
return;
|
||||
}
|
||||
gdb_assert (!have_ptrace_getregs);
|
||||
if (cannot_store_register (regno))
|
||||
return;
|
||||
|
||||
/* Overload thread id onto process id */
|
||||
/* GNU/Linux LWP ID's are process ID's. */
|
||||
if ((tid = TIDGET (inferior_ptid)) == 0)
|
||||
tid = PIDGET (inferior_ptid); /* no thread id, just use process id */
|
||||
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
|
||||
|
||||
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 (int regno)
|
||||
{
|
||||
if (regno >= 0)
|
||||
{
|
||||
store_register (regno);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
{
|
||||
store_register (regno);
|
||||
}
|
||||
}
|
||||
errno = 0;
|
||||
regcache_collect (regno, &val);
|
||||
ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val);
|
||||
if (errno != 0)
|
||||
error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno),
|
||||
regno, safe_strerror (errno));
|
||||
}
|
||||
|
||||
|
||||
@ -573,16 +488,15 @@ static void dummy_sse_values (void) {}
|
||||
int
|
||||
cannot_fetch_register (int regno)
|
||||
{
|
||||
if (! have_ptrace_getregs)
|
||||
return OLD_CANNOT_FETCH_REGISTER (regno);
|
||||
return 0;
|
||||
gdb_assert (regno >= 0 && regno < NUM_REGS);
|
||||
return (!have_ptrace_getregs && regmap[regno] == -1);
|
||||
}
|
||||
|
||||
int
|
||||
cannot_store_register (int regno)
|
||||
{
|
||||
if (! have_ptrace_getregs)
|
||||
return OLD_CANNOT_STORE_REGISTER (regno);
|
||||
return 0;
|
||||
gdb_assert (regno >= 0 && regno < NUM_REGS);
|
||||
return (!have_ptrace_getregs && regmap[regno] == -1);
|
||||
}
|
||||
|
||||
/* Fetch register REGNO from the child process. If REGNO is -1, do
|
||||
@ -596,9 +510,14 @@ fetch_inferior_registers (int regno)
|
||||
|
||||
/* Use the old method of peeking around in `struct user' if the
|
||||
GETREGS request isn't available. */
|
||||
if (! have_ptrace_getregs)
|
||||
if (!have_ptrace_getregs)
|
||||
{
|
||||
old_fetch_inferior_registers (regno);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_REGS; i++)
|
||||
if (regno == -1 || regno == i)
|
||||
fetch_register (i);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -615,9 +534,9 @@ fetch_inferior_registers (int regno)
|
||||
fetch_regs (tid);
|
||||
|
||||
/* The call above might reset `have_ptrace_getregs'. */
|
||||
if (! have_ptrace_getregs)
|
||||
if (!have_ptrace_getregs)
|
||||
{
|
||||
old_fetch_inferior_registers (-1);
|
||||
fetch_inferior_registers (regno);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -662,9 +581,14 @@ store_inferior_registers (int regno)
|
||||
|
||||
/* Use the old method of poking around in `struct user' if the
|
||||
SETREGS request isn't available. */
|
||||
if (! have_ptrace_getregs)
|
||||
if (!have_ptrace_getregs)
|
||||
{
|
||||
old_store_inferior_registers (regno);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_REGS; i++)
|
||||
if (regno == -1 || regno == i)
|
||||
store_register (i);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -724,7 +648,7 @@ i386_linux_dr_get (int regnum)
|
||||
stuff to the target vectore. For now, just return zero if the
|
||||
ptrace call fails. */
|
||||
errno = 0;
|
||||
value = ptrace (PT_READ_U, tid,
|
||||
value = ptrace (PTRACE_PEEKUSER, tid,
|
||||
offsetof (struct user, u_debugreg[regnum]), 0);
|
||||
if (errno != 0)
|
||||
#if 0
|
||||
@ -747,7 +671,7 @@ i386_linux_dr_set (int regnum, unsigned long value)
|
||||
tid = PIDGET (inferior_ptid);
|
||||
|
||||
errno = 0;
|
||||
ptrace (PT_WRITE_U, tid,
|
||||
ptrace (PTRACE_POKEUSER, tid,
|
||||
offsetof (struct user, u_debugreg[regnum]), value);
|
||||
if (errno != 0)
|
||||
perror_with_name ("Couldn't write debug register");
|
||||
|
Loading…
Reference in New Issue
Block a user