/* Native-dependent code for GNU/Linux i386.
- Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "inferior.h"
;
\f
-/* Support for the user struct. */
-
-/* Return the address of register REGNUM. BLOCKEND is the value of
- u.u_ar0, which should point to the registers. */
-
-CORE_ADDR
-register_u_addr (CORE_ADDR blockend, int regnum)
-{
- return (blockend + 4 * regmap[regnum]);
-}
-
-/* Return the size of the user struct. */
-
-int
-kernel_u_size (void)
-{
- return (sizeof (struct user));
-}
-\f
-
/* Accessing registers through the U area, one at a time. */
/* Fetch one register. */
static void
-fetch_register (int regno)
+fetch_register (struct regcache *regcache, int regno)
{
int tid;
int val;
gdb_assert (!have_ptrace_getregs);
- if (cannot_fetch_register (regno))
+ if (regmap[regno] == -1)
{
- regcache_raw_supply (current_regcache, regno, NULL);
+ regcache_raw_supply (regcache, regno, NULL);
return;
}
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
errno = 0;
- val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0);
+ val = ptrace (PTRACE_PEEKUSER, tid, 4 * regmap[regno], 0);
if (errno != 0)
error (_("Couldn't read register %s (#%d): %s."), REGISTER_NAME (regno),
regno, safe_strerror (errno));
- regcache_raw_supply (current_regcache, regno, &val);
+ regcache_raw_supply (regcache, regno, &val);
}
/* Store one register. */
static void
-store_register (int regno)
+store_register (const struct regcache *regcache, int regno)
{
int tid;
int val;
gdb_assert (!have_ptrace_getregs);
- if (cannot_store_register (regno))
+ if (regmap[regno] == -1)
return;
/* GNU/Linux LWP ID's are process ID's. */
tid = PIDGET (inferior_ptid); /* Not a threaded program. */
errno = 0;
- regcache_raw_collect (current_regcache, regno, &val);
- ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val);
+ regcache_raw_collect (regcache, regno, &val);
+ ptrace (PTRACE_POKEUSER, tid, 4 * regmap[regno], val);
if (errno != 0)
error (_("Couldn't write register %s (#%d): %s."), REGISTER_NAME (regno),
regno, safe_strerror (errno));
in *GREGSETP. */
void
-supply_gregset (elf_gregset_t *gregsetp)
+supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
{
- elf_greg_t *regp = (elf_greg_t *) gregsetp;
+ const elf_greg_t *regp = (const elf_greg_t *) gregsetp;
int i;
for (i = 0; i < I386_NUM_GREGS; i++)
- regcache_raw_supply (current_regcache, i, regp + regmap[i]);
+ regcache_raw_supply (regcache, i, regp + regmap[i]);
if (I386_LINUX_ORIG_EAX_REGNUM < NUM_REGS)
- regcache_raw_supply (current_regcache, I386_LINUX_ORIG_EAX_REGNUM,
+ regcache_raw_supply (regcache, I386_LINUX_ORIG_EAX_REGNUM,
regp + ORIG_EAX);
}
do this for all registers. */
void
-fill_gregset (elf_gregset_t *gregsetp, int regno)
+fill_gregset (const struct regcache *regcache,
+ elf_gregset_t *gregsetp, int regno)
{
elf_greg_t *regp = (elf_greg_t *) gregsetp;
int i;
for (i = 0; i < I386_NUM_GREGS; i++)
if (regno == -1 || regno == i)
- regcache_raw_collect (current_regcache, i, regp + regmap[i]);
+ regcache_raw_collect (regcache, i, regp + regmap[i]);
if ((regno == -1 || regno == I386_LINUX_ORIG_EAX_REGNUM)
&& I386_LINUX_ORIG_EAX_REGNUM < NUM_REGS)
- regcache_raw_collect (current_regcache, I386_LINUX_ORIG_EAX_REGNUM,
+ regcache_raw_collect (regcache, I386_LINUX_ORIG_EAX_REGNUM,
regp + ORIG_EAX);
}
store their values in GDB's register array. */
static void
-fetch_regs (int tid)
+fetch_regs (struct regcache *regcache, int tid)
{
elf_gregset_t regs;
perror_with_name (_("Couldn't get registers"));
}
- supply_gregset (®s);
+ supply_gregset (regcache, (const elf_gregset_t *) ®s);
}
/* Store all valid general-purpose registers in GDB's register array
into the process/thread specified by TID. */
static void
-store_regs (int tid, int regno)
+store_regs (const struct regcache *regcache, int tid, int regno)
{
elf_gregset_t regs;
if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0)
perror_with_name (_("Couldn't get registers"));
- fill_gregset (®s, regno);
+ fill_gregset (regcache, ®s, regno);
if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0)
perror_with_name (_("Couldn't write registers"));
#else
-static void fetch_regs (int tid) {}
-static void store_regs (int tid, int regno) {}
+static void fetch_regs (struct regcache *regcache, int tid) {}
+static void store_regs (const struct regcache *regcache, int tid, int regno) {}
#endif
\f
*FPREGSETP. */
void
-supply_fpregset (elf_fpregset_t *fpregsetp)
+supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
{
- i387_supply_fsave (current_regcache, -1, fpregsetp);
+ i387_supply_fsave (regcache, -1, fpregsetp);
}
/* Fill register REGNO (if it is a floating-point register) in
do this for all registers. */
void
-fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
+fill_fpregset (const struct regcache *regcache,
+ elf_fpregset_t *fpregsetp, int regno)
{
- i387_fill_fsave ((char *) fpregsetp, regno);
+ i387_collect_fsave (regcache, regno, fpregsetp);
}
#ifdef HAVE_PTRACE_GETREGS
thier values in GDB's register array. */
static void
-fetch_fpregs (int tid)
+fetch_fpregs (struct regcache *regcache, int tid)
{
elf_fpregset_t fpregs;
if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
perror_with_name (_("Couldn't get floating point status"));
- supply_fpregset (&fpregs);
+ supply_fpregset (regcache, (const elf_fpregset_t *) &fpregs);
}
/* Store all valid floating-point registers in GDB's register array
into the process/thread specified by TID. */
static void
-store_fpregs (int tid, int regno)
+store_fpregs (const struct regcache *regcache, int tid, int regno)
{
elf_fpregset_t fpregs;
if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0)
perror_with_name (_("Couldn't get floating point status"));
- fill_fpregset (&fpregs, regno);
+ fill_fpregset (regcache, &fpregs, regno);
if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0)
perror_with_name (_("Couldn't write floating point status"));
#else
-static void fetch_fpregs (int tid) {}
-static void store_fpregs (int tid, int regno) {}
+static void fetch_fpregs (struct regcache *regcache, int tid) {}
+static void store_fpregs (const struct regcache *regcache, int tid, int regno) {}
#endif
\f
values in *FPXREGSETP. */
void
-supply_fpxregset (elf_fpxregset_t *fpxregsetp)
+supply_fpxregset (struct regcache *regcache,
+ const elf_fpxregset_t *fpxregsetp)
{
- i387_supply_fxsave (current_regcache, -1, fpxregsetp);
+ i387_supply_fxsave (regcache, -1, fpxregsetp);
}
/* Fill register REGNO (if it is a floating-point or SSE register) in
-1, do this for all registers. */
void
-fill_fpxregset (elf_fpxregset_t *fpxregsetp, int regno)
+fill_fpxregset (const struct regcache *regcache,
+ elf_fpxregset_t *fpxregsetp, int regno)
{
- i387_fill_fxsave ((char *) fpxregsetp, regno);
+ i387_collect_fxsave (regcache, regno, fpxregsetp);
}
/* Fetch all registers covered by the PTRACE_GETFPXREGS request from
Return non-zero if successful, zero otherwise. */
static int
-fetch_fpxregs (int tid)
+fetch_fpxregs (struct regcache *regcache, int tid)
{
elf_fpxregset_t fpxregs;
perror_with_name (_("Couldn't read floating-point and SSE registers"));
}
- supply_fpxregset (&fpxregs);
+ supply_fpxregset (regcache, (const elf_fpxregset_t *) &fpxregs);
return 1;
}
Return non-zero if successful, zero otherwise. */
static int
-store_fpxregs (int tid, int regno)
+store_fpxregs (const struct regcache *regcache, int tid, int regno)
{
elf_fpxregset_t fpxregs;
perror_with_name (_("Couldn't read floating-point and SSE registers"));
}
- fill_fpxregset (&fpxregs, regno);
+ fill_fpxregset (regcache, &fpxregs, regno);
if (ptrace (PTRACE_SETFPXREGS, tid, 0, &fpxregs) == -1)
perror_with_name (_("Couldn't write floating-point and SSE registers"));
#else
-static int fetch_fpxregs (int tid) { return 0; }
-static int store_fpxregs (int tid, int regno) { return 0; }
+static int fetch_fpxregs (struct regcache *regcache, int tid) { return 0; }
+static int store_fpxregs (const struct regcache *regcache, int tid, int regno) { return 0; }
#endif /* HAVE_PTRACE_GETFPXREGS */
\f
/* Transferring arbitrary registers between GDB and inferior. */
-/* Check if register REGNO in the child process is accessible.
- If we are accessing registers directly via the U area, only the
- general-purpose registers are available.
- All registers should be accessible if we have GETREGS support. */
-
-int
-cannot_fetch_register (int regno)
-{
- gdb_assert (regno >= 0 && regno < NUM_REGS);
- return (!have_ptrace_getregs && regmap[regno] == -1);
-}
-
-int
-cannot_store_register (int regno)
-{
- 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
this for all registers (including the floating point and SSE
registers). */
static void
-i386_linux_fetch_inferior_registers (int regno)
+i386_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
{
int tid;
for (i = 0; i < NUM_REGS; i++)
if (regno == -1 || regno == i)
- fetch_register (i);
+ fetch_register (regcache, i);
return;
}
zero. */
if (regno == -1)
{
- fetch_regs (tid);
+ fetch_regs (regcache, tid);
/* The call above might reset `have_ptrace_getregs'. */
if (!have_ptrace_getregs)
{
- i386_linux_fetch_inferior_registers (regno);
+ i386_linux_fetch_inferior_registers (regcache, regno);
return;
}
- if (fetch_fpxregs (tid))
+ if (fetch_fpxregs (regcache, tid))
return;
- fetch_fpregs (tid);
+ fetch_fpregs (regcache, tid);
return;
}
if (GETREGS_SUPPLIES (regno))
{
- fetch_regs (tid);
+ fetch_regs (regcache, tid);
return;
}
if (GETFPXREGS_SUPPLIES (regno))
{
- if (fetch_fpxregs (tid))
+ if (fetch_fpxregs (regcache, tid))
return;
/* Either our processor or our kernel doesn't support the SSE
more graceful to handle differences in the register set using
gdbarch. Until then, this will at least make things work
plausibly. */
- fetch_fpregs (tid);
+ fetch_fpregs (regcache, tid);
return;
}
do this for all registers (including the floating point and SSE
registers). */
static void
-i386_linux_store_inferior_registers (int regno)
+i386_linux_store_inferior_registers (struct regcache *regcache, int regno)
{
int tid;
for (i = 0; i < NUM_REGS; i++)
if (regno == -1 || regno == i)
- store_register (i);
+ store_register (regcache, i);
return;
}
store_fpxregs can fail, and return zero. */
if (regno == -1)
{
- store_regs (tid, regno);
- if (store_fpxregs (tid, regno))
+ store_regs (regcache, tid, regno);
+ if (store_fpxregs (regcache, tid, regno))
return;
- store_fpregs (tid, regno);
+ store_fpregs (regcache, tid, regno);
return;
}
if (GETREGS_SUPPLIES (regno))
{
- store_regs (tid, regno);
+ store_regs (regcache, tid, regno);
return;
}
if (GETFPXREGS_SUPPLIES (regno))
{
- if (store_fpxregs (tid, regno))
+ if (store_fpxregs (regcache, tid, regno))
return;
/* Either our processor or our kernel doesn't support the SSE
registers, so just write the FP registers in the traditional
way. */
- store_fpregs (tid, regno);
+ store_fpregs (regcache, tid, regno);
return;
}
that's about to be restored, and set the trace flag there. */
/* First check if PC is at a system call. */
- if (deprecated_read_memory_nobpt (pc, buf, LINUX_SYSCALL_LEN) == 0
+ if (read_memory_nobpt (pc, buf, LINUX_SYSCALL_LEN) == 0
&& memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0)
{
int syscall = read_register_pid (LINUX_SYSCALL_REGNUM,
t->to_store_registers = i386_linux_store_inferior_registers;
/* Register the target. */
- add_target (t);
+ linux_nat_add_target (t);
}