X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Fi386-linux-nat.c;h=a08b9b85cf49ed980a4cdd9bd78f98bfeffd7242;hb=012d8ebc4bd1a1afb95d902604007b04762207f0;hp=16436615883c36806fe19a0f11f2d764fe2b0927;hpb=4ffc84662b5166a2bc18ffdd933f482f933efddc;p=platform%2Fupstream%2Fbinutils.git
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index 1643661..a08b9b8 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -1,12 +1,12 @@
-/* Native-dependent code for GNU/Linux x86.
+/* Native-dependent code for GNU/Linux i386.
- Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999-2014 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -15,68 +15,25 @@
GNU General Public License for more details.
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. */
+ along with this program. If not, see . */
#include "defs.h"
#include "inferior.h"
#include "gdbcore.h"
#include "regcache.h"
-#include "linux-nat.h"
-
-#include "gdb_assert.h"
-#include "gdb_string.h"
+#include "elf/common.h"
#include
-#include
-#include
-
-#ifdef HAVE_SYS_REG_H
-#include
-#endif
-
-#ifndef ORIG_EAX
-#define ORIG_EAX -1
-#endif
-
-#ifdef HAVE_SYS_DEBUGREG_H
-#include
-#endif
-
-#ifndef DR_FIRSTADDR
-#define DR_FIRSTADDR 0
-#endif
-
-#ifndef DR_LASTADDR
-#define DR_LASTADDR 3
-#endif
-
-#ifndef DR_STATUS
-#define DR_STATUS 6
-#endif
-
-#ifndef DR_CONTROL
-#define DR_CONTROL 7
-#endif
-
-/* Prototypes for supply_gregset etc. */
+#include
#include "gregset.h"
+#include "gdb_proc_service.h"
-/* Prototypes for i387_supply_fsave etc. */
+#include "i386-linux-nat.h"
#include "i387-tdep.h"
-
-/* Defines for XMM0_REGNUM etc. */
#include "i386-tdep.h"
-
-/* Defines I386_LINUX_ORIG_EAX_REGNUM. */
#include "i386-linux-tdep.h"
+#include "x86-xstate.h"
-/* Defines ps_err_e, struct ps_prochandle. */
-#include "gdb_proc_service.h"
-
-/* Prototypes for local functions. */
-static void dummy_sse_values (void);
-
+#include "x86-linux-nat.h"
/* The register sets used in GNU/Linux ELF core-dumps are identical to
the register sets in `struct user' that is used for a.out
@@ -90,35 +47,17 @@ static void dummy_sse_values (void);
those names are now used for the register sets used in the
`mcontext_t' type, and have a different size and layout. */
-/* Mapping between the general-purpose registers in `struct user'
- format and GDB's register array layout. */
-static int regmap[] =
-{
- EAX, ECX, EDX, EBX,
- UESP, EBP, ESI, EDI,
- EIP, EFL, CS, SS,
- 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?
These apply to the corresponding SET requests as well. */
#define GETREGS_SUPPLIES(regno) \
((0 <= (regno) && (regno) <= 15) || (regno) == I386_LINUX_ORIG_EAX_REGNUM)
-#define GETFPREGS_SUPPLIES(regno) \
- (FP0_REGNUM <= (regno) && (regno) <= LAST_FPU_CTRL_REGNUM)
-
#define GETFPXREGS_SUPPLIES(regno) \
- (FP0_REGNUM <= (regno) && (regno) <= MXCSR_REGNUM)
+ (I386_ST0_REGNUM <= (regno) && (regno) < I386_SSE_NUM_REGS)
+
+#define GETXSTATEREGS_SUPPLIES(regno) \
+ (I386_ST0_REGNUM <= (regno) && (regno) < I386_AVX512_NUM_REGS)
/* Does the current host support the GETREGS request? */
int have_ptrace_getregs =
@@ -139,86 +78,70 @@ int have_ptrace_getregs =
for this to be a simple variable. */
int have_ptrace_getfpxregs =
#ifdef HAVE_PTRACE_GETFPXREGS
- 1
+ -1
#else
0
#endif
;
-/* 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));
-}
-
-
/* 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 (i386_linux_gregset_reg_offset[regno] == -1)
{
- supply_register (regno, NULL);
+ regcache_raw_supply (regcache, regno, NULL);
return;
}
/* GNU/Linux LWP ID's are process ID's. */
- tid = TIDGET (inferior_ptid);
+ tid = ptid_get_lwp (inferior_ptid);
if (tid == 0)
- tid = PIDGET (inferior_ptid); /* Not a threaded program. */
+ tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
errno = 0;
- val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0);
+ val = ptrace (PTRACE_PEEKUSER, tid,
+ i386_linux_gregset_reg_offset[regno], 0);
if (errno != 0)
- error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno),
+ error (_("Couldn't read register %s (#%d): %s."),
+ gdbarch_register_name (get_regcache_arch (regcache), regno),
regno, safe_strerror (errno));
- supply_register (regno, &val);
+ regcache_raw_supply (regcache, regno, &val);
}
-/* Store one register. */
+/* 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 (i386_linux_gregset_reg_offset[regno] == -1)
return;
/* GNU/Linux LWP ID's are process ID's. */
- tid = TIDGET (inferior_ptid);
+ tid = ptid_get_lwp (inferior_ptid);
if (tid == 0)
- tid = PIDGET (inferior_ptid); /* Not a threaded program. */
+ tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
errno = 0;
- regcache_collect (regno, &val);
- ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val);
+ regcache_raw_collect (regcache, regno, &val);
+ ptrace (PTRACE_POKEUSER, tid,
+ i386_linux_gregset_reg_offset[regno], val);
if (errno != 0)
- error ("Couldn't write register %s (#%d): %s.", REGISTER_NAME (regno),
+ error (_("Couldn't write register %s (#%d): %s."),
+ gdbarch_register_name (get_regcache_arch (regcache), regno),
regno, safe_strerror (errno));
}
@@ -230,16 +153,19 @@ store_register (int regno)
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 gdb_byte *regp = (const gdb_byte *) gregsetp;
int i;
for (i = 0; i < I386_NUM_GREGS; i++)
- supply_register (i, regp + regmap[i]);
+ regcache_raw_supply (regcache, i,
+ regp + i386_linux_gregset_reg_offset[i]);
- if (I386_LINUX_ORIG_EAX_REGNUM < NUM_REGS)
- supply_register (I386_LINUX_ORIG_EAX_REGNUM, regp + ORIG_EAX);
+ if (I386_LINUX_ORIG_EAX_REGNUM
+ < gdbarch_num_regs (get_regcache_arch (regcache)))
+ regcache_raw_supply (regcache, I386_LINUX_ORIG_EAX_REGNUM, regp
+ + i386_linux_gregset_reg_offset[I386_LINUX_ORIG_EAX_REGNUM]);
}
/* Fill register REGNO (if it is a general-purpose register) in
@@ -247,18 +173,22 @@ supply_gregset (elf_gregset_t *gregsetp)
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;
+ gdb_byte *regp = (gdb_byte *) gregsetp;
int i;
for (i = 0; i < I386_NUM_GREGS; i++)
if (regno == -1 || regno == i)
- regcache_collect (i, regp + regmap[i]);
+ regcache_raw_collect (regcache, i,
+ regp + i386_linux_gregset_reg_offset[i]);
if ((regno == -1 || regno == I386_LINUX_ORIG_EAX_REGNUM)
- && I386_LINUX_ORIG_EAX_REGNUM < NUM_REGS)
- regcache_collect (I386_LINUX_ORIG_EAX_REGNUM, regp + ORIG_EAX);
+ && I386_LINUX_ORIG_EAX_REGNUM
+ < gdbarch_num_regs (get_regcache_arch (regcache)))
+ regcache_raw_collect (regcache, I386_LINUX_ORIG_EAX_REGNUM, regp
+ + i386_linux_gregset_reg_offset[I386_LINUX_ORIG_EAX_REGNUM]);
}
#ifdef HAVE_PTRACE_GETREGS
@@ -267,9 +197,10 @@ fill_gregset (elf_gregset_t *gregsetp, int regno)
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;
+ elf_gregset_t *regs_p = ®s;
if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0)
{
@@ -281,33 +212,33 @@ fetch_regs (int tid)
return;
}
- perror_with_name ("Couldn't get registers");
+ perror_with_name (_("Couldn't get registers"));
}
- supply_gregset (®s);
+ supply_gregset (regcache, (const elf_gregset_t *) regs_p);
}
/* 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");
+ 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");
+ 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
@@ -318,10 +249,9 @@ static void store_regs (int tid, int regno) {}
*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);
- dummy_sse_values ();
+ i387_supply_fsave (regcache, -1, fpregsetp);
}
/* Fill register REGNO (if it is a floating-point register) in
@@ -329,9 +259,10 @@ supply_fpregset (elf_fpregset_t *fpregsetp)
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
@@ -340,70 +271,109 @@ fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
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");
+ 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");
+ 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");
+ 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
/* Transfering floating-point and SSE registers to and from GDB. */
-#ifdef HAVE_PTRACE_GETFPXREGS
-
-/* Fill GDB's register array with the floating-point and SSE register
- values in *FPXREGSETP. */
+/* Fetch all registers covered by the PTRACE_GETREGSET request from
+ process/thread TID and store their values in GDB's register array.
+ Return non-zero if successful, zero otherwise. */
-void
-supply_fpxregset (elf_fpxregset_t *fpxregsetp)
+static int
+fetch_xstateregs (struct regcache *regcache, int tid)
{
- i387_supply_fxsave (current_regcache, -1, fpxregsetp);
+ char xstateregs[X86_XSTATE_MAX_SIZE];
+ struct iovec iov;
+
+ if (!have_ptrace_getregset)
+ return 0;
+
+ iov.iov_base = xstateregs;
+ iov.iov_len = sizeof(xstateregs);
+ if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE,
+ &iov) < 0)
+ perror_with_name (_("Couldn't read extended state status"));
+
+ i387_supply_xsave (regcache, -1, xstateregs);
+ return 1;
}
-/* Fill register REGNO (if it is a floating-point or SSE register) in
- *FPXREGSETP with the value in GDB's register array. If REGNO is
- -1, do this for all registers. */
+/* Store all valid registers in GDB's register array covered by the
+ PTRACE_SETREGSET request into the process/thread specified by TID.
+ Return non-zero if successful, zero otherwise. */
-void
-fill_fpxregset (elf_fpxregset_t *fpxregsetp, int regno)
+static int
+store_xstateregs (const struct regcache *regcache, int tid, int regno)
{
- i387_fill_fxsave ((char *) fpxregsetp, regno);
+ char xstateregs[X86_XSTATE_MAX_SIZE];
+ struct iovec iov;
+
+ if (!have_ptrace_getregset)
+ return 0;
+
+ iov.iov_base = xstateregs;
+ iov.iov_len = sizeof(xstateregs);
+ if (ptrace (PTRACE_GETREGSET, tid, (unsigned int) NT_X86_XSTATE,
+ &iov) < 0)
+ perror_with_name (_("Couldn't read extended state status"));
+
+ i387_collect_xsave (regcache, regno, xstateregs, 0);
+
+ if (ptrace (PTRACE_SETREGSET, tid, (unsigned int) NT_X86_XSTATE,
+ (int) &iov) < 0)
+ perror_with_name (_("Couldn't write extended state status"));
+
+ return 1;
}
+#ifdef HAVE_PTRACE_GETFPXREGS
+
/* Fetch all registers covered by the PTRACE_GETFPXREGS request from
process/thread TID and store their values in GDB's register array.
Return non-zero if successful, zero otherwise. */
static int
-fetch_fpxregs (int tid)
+fetch_fpxregs (struct regcache *regcache, int tid)
{
elf_fpxregset_t fpxregs;
@@ -418,10 +388,10 @@ fetch_fpxregs (int tid)
return 0;
}
- perror_with_name ("Couldn't read floating-point and SSE registers");
+ perror_with_name (_("Couldn't read floating-point and SSE registers"));
}
- supply_fpxregset (&fpxregs);
+ i387_supply_fxsave (regcache, -1, (const elf_fpxregset_t *) &fpxregs);
return 1;
}
@@ -430,7 +400,7 @@ fetch_fpxregs (int tid)
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;
@@ -445,74 +415,43 @@ store_fpxregs (int tid, int regno)
return 0;
}
- perror_with_name ("Couldn't read floating-point and SSE registers");
+ perror_with_name (_("Couldn't read floating-point and SSE registers"));
}
- fill_fpxregset (&fpxregs, regno);
+ i387_collect_fxsave (regcache, regno, &fpxregs);
if (ptrace (PTRACE_SETFPXREGS, tid, 0, &fpxregs) == -1)
- perror_with_name ("Couldn't write floating-point and SSE registers");
+ perror_with_name (_("Couldn't write floating-point and SSE registers"));
return 1;
}
-/* Fill the XMM registers in the register array with dummy values. For
- cases where we don't have access to the XMM registers. I think
- this is cleaner than printing a warning. For a cleaner solution,
- we should gdbarchify the i386 family. */
+#else
-static void
-dummy_sse_values (void)
+static int
+fetch_fpxregs (struct regcache *regcache, int tid)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
- /* C doesn't have a syntax for NaN's, so write it out as an array of
- longs. */
- static long dummy[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
- static long mxcsr = 0x1f80;
- int reg;
-
- for (reg = 0; reg < tdep->num_xmm_regs; reg++)
- supply_register (XMM0_REGNUM + reg, (char *) dummy);
- if (tdep->num_xmm_regs > 0)
- supply_register (MXCSR_REGNUM, (char *) &mxcsr);
+ return 0;
}
-#else
-
-static int fetch_fpxregs (int tid) { return 0; }
-static int store_fpxregs (int tid, int regno) { return 0; }
-static void dummy_sse_values (void) {}
+static int
+store_fpxregs (const struct regcache *regcache, int tid, int regno)
+{
+ return 0;
+}
#endif /* HAVE_PTRACE_GETFPXREGS */
/* 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). */
-void
-fetch_inferior_registers (int regno)
+static void
+i386_linux_fetch_inferior_registers (struct target_ops *ops,
+ struct regcache *regcache, int regno)
{
int tid;
@@ -522,17 +461,17 @@ fetch_inferior_registers (int regno)
{
int i;
- for (i = 0; i < NUM_REGS; i++)
+ for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
if (regno == -1 || regno == i)
- fetch_register (i);
+ fetch_register (regcache, i);
return;
}
/* GNU/Linux LWP ID's are process ID's. */
- tid = TIDGET (inferior_ptid);
+ tid = ptid_get_lwp (inferior_ptid);
if (tid == 0)
- tid = PIDGET (inferior_ptid); /* Not a threaded program. */
+ tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
/* Use the PTRACE_GETFPXREGS request whenever possible, since it
transfers more registers in one system call, and we'll cache the
@@ -540,30 +479,38 @@ fetch_inferior_registers (int regno)
zero. */
if (regno == -1)
{
- fetch_regs (tid);
+ fetch_regs (regcache, tid);
/* The call above might reset `have_ptrace_getregs'. */
if (!have_ptrace_getregs)
{
- fetch_inferior_registers (regno);
+ i386_linux_fetch_inferior_registers (ops, regcache, regno);
return;
}
- if (fetch_fpxregs (tid))
+ if (fetch_xstateregs (regcache, tid))
+ return;
+ 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 (GETXSTATEREGS_SUPPLIES (regno))
+ {
+ if (fetch_xstateregs (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
@@ -572,19 +519,20 @@ fetch_inferior_registers (int regno)
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;
}
internal_error (__FILE__, __LINE__,
- "Got request for bad register number %d.", regno);
+ _("Got request for bad register number %d."), regno);
}
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers (including the floating point and SSE
registers). */
-void
-store_inferior_registers (int regno)
+static void
+i386_linux_store_inferior_registers (struct target_ops *ops,
+ struct regcache *regcache, int regno)
{
int tid;
@@ -594,127 +542,58 @@ store_inferior_registers (int regno)
{
int i;
- for (i = 0; i < NUM_REGS; i++)
+ for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
if (regno == -1 || regno == i)
- store_register (i);
+ store_register (regcache, i);
return;
}
/* GNU/Linux LWP ID's are process ID's. */
- tid = TIDGET (inferior_ptid);
+ tid = ptid_get_lwp (inferior_ptid);
if (tid == 0)
- tid = PIDGET (inferior_ptid); /* Not a threaded program. */
+ tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
/* Use the PTRACE_SETFPXREGS requests whenever possible, since it
transfers more registers in one system call. But remember that
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_xstateregs (regcache, tid, regno))
return;
- store_fpregs (tid, regno);
+ if (store_fpxregs (regcache, tid, regno))
+ return;
+ store_fpregs (regcache, tid, regno);
return;
}
if (GETREGS_SUPPLIES (regno))
{
- store_regs (tid, regno);
+ store_regs (regcache, tid, regno);
return;
}
+ if (GETXSTATEREGS_SUPPLIES (regno))
+ {
+ if (store_xstateregs (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;
}
internal_error (__FILE__, __LINE__,
- "Got request to store bad register number %d.", regno);
-}
-
-
-/* Support for debug registers. */
-
-static unsigned long
-i386_linux_dr_get (int regnum)
-{
- int tid;
- unsigned long value;
-
- /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
- multi-threaded processes here. For now, pretend there is just
- one thread. */
- tid = PIDGET (inferior_ptid);
-
- /* FIXME: kettenis/2001-03-27: Calling perror_with_name if the
- ptrace call fails breaks debugging remote targets. The correct
- way to fix this is to add the hardware breakpoint and watchpoint
- stuff to the target vectore. For now, just return zero if the
- ptrace call fails. */
- errno = 0;
- value = ptrace (PTRACE_PEEKUSER, tid,
- offsetof (struct user, u_debugreg[regnum]), 0);
- if (errno != 0)
-#if 0
- perror_with_name ("Couldn't read debug register");
-#else
- return 0;
-#endif
-
- return value;
-}
-
-static void
-i386_linux_dr_set (int regnum, unsigned long value)
-{
- int tid;
-
- /* FIXME: kettenis/2001-01-29: It's not clear what we should do with
- multi-threaded processes here. For now, pretend there is just
- one thread. */
- tid = PIDGET (inferior_ptid);
-
- errno = 0;
- ptrace (PTRACE_POKEUSER, tid,
- offsetof (struct user, u_debugreg[regnum]), value);
- if (errno != 0)
- perror_with_name ("Couldn't write debug register");
-}
-
-void
-i386_linux_dr_set_control (unsigned long control)
-{
- i386_linux_dr_set (DR_CONTROL, control);
-}
-
-void
-i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
-{
- gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
-
- i386_linux_dr_set (DR_FIRSTADDR + regnum, addr);
-}
-
-void
-i386_linux_dr_reset_addr (int regnum)
-{
- gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
-
- i386_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
-}
-
-unsigned long
-i386_linux_dr_get_status (void)
-{
- return i386_linux_dr_get (DR_STATUS);
+ _("Got request to store bad register number %d."), regno);
}
@@ -722,39 +601,18 @@ i386_linux_dr_get_status (void)
storage (or its descriptor). */
ps_err_e
-ps_get_thread_area (const struct ps_prochandle *ph,
+ps_get_thread_area (const struct ps_prochandle *ph,
lwpid_t lwpid, int idx, void **base)
{
- /* NOTE: cagney/2003-08-26: The definition of this buffer is found
- in the kernel header . It, after padding, is 4 x
- 4 byte integers in size: `entry_number', `base_addr', `limit',
- and a bunch of status bits.
-
- The values returned by this ptrace call should be part of the
- regcache buffer, and ps_get_thread_area should channel its
- request through the regcache. That way remote targets could
- provide the value using the remote protocol and not this direct
- call.
-
- Is this function needed? I'm guessing that the `base' is the
- address of a a descriptor that libthread_db uses to find the
- thread local address base that GDB needs. Perhaphs that
- descriptor is defined by the ABI. Anyway, given that
- libthread_db calls this function without prompting (gdb
- requesting tls base) I guess it needs info in there anyway. */
- unsigned int desc[4];
- gdb_assert (sizeof (int) == 4);
-
-#ifndef PTRACE_GET_THREAD_AREA
-#define PTRACE_GET_THREAD_AREA 25
-#endif
+ unsigned int base_addr;
+ ps_err_e result;
- if (ptrace (PTRACE_GET_THREAD_AREA, lwpid,
- (void *) idx, (unsigned long) &desc) < 0)
- return PS_ERR;
+ result = x86_linux_get_thread_area (lwpid, (void *) idx, &base_addr);
- *(int *)base = desc[1];
- return PS_OK;
+ if (result == PS_OK)
+ *(int *) base = base_addr;
+
+ return result;
}
@@ -767,7 +625,7 @@ static const unsigned char linux_syscall[] = { 0xcd, 0x80 };
#define LINUX_SYSCALL_LEN (sizeof linux_syscall)
/* The system call number is stored in the %eax register. */
-#define LINUX_SYSCALL_REGNUM 0 /* %eax */
+#define LINUX_SYSCALL_REGNUM I386_EAX_REGNUM
/* We are specifically interested in the sigreturn and rt_sigreturn
system calls. */
@@ -786,26 +644,32 @@ static const unsigned char linux_syscall[] = { 0xcd, 0x80 };
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
-void
-child_resume (ptid_t ptid, int step, enum target_signal signal)
+static void
+i386_linux_resume (struct target_ops *ops,
+ ptid_t ptid, int step, enum gdb_signal signal)
{
- int pid = PIDGET (ptid);
+ int pid = ptid_get_pid (ptid);
- int request = PTRACE_CONT;
+ int request;
- if (pid == -1)
- /* Resume all threads. */
- /* I think this only gets used in the non-threaded case, where "resume
- all threads" and "resume inferior_ptid" are the same. */
- pid = PIDGET (inferior_ptid);
+ if (catch_syscall_enabled () > 0)
+ request = PTRACE_SYSCALL;
+ else
+ request = PTRACE_CONT;
if (step)
{
- CORE_ADDR pc = read_pc_pid (pid_to_ptid (pid));
- unsigned char buf[LINUX_SYSCALL_LEN];
+ struct regcache *regcache = get_thread_regcache (pid_to_ptid (pid));
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ ULONGEST pc;
+ gdb_byte buf[LINUX_SYSCALL_LEN];
request = PTRACE_SINGLESTEP;
+ regcache_cooked_read_unsigned (regcache,
+ gdbarch_pc_regnum (gdbarch), &pc);
+
/* Returning from a signal trampoline is done by calling a
special system call (sigreturn or rt_sigreturn, see
i386-linux-tdep.c for more information). This system call
@@ -815,39 +679,57 @@ child_resume (ptid_t ptid, int step, enum target_signal signal)
that's about to be restored, and set the trace flag there. */
/* First check if PC is at a system call. */
- if (read_memory_nobpt (pc, (char *) buf, LINUX_SYSCALL_LEN) == 0
+ if (target_read_memory (pc, buf, LINUX_SYSCALL_LEN) == 0
&& memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0)
{
- int syscall = read_register_pid (LINUX_SYSCALL_REGNUM,
- pid_to_ptid (pid));
+ ULONGEST syscall;
+ regcache_cooked_read_unsigned (regcache,
+ LINUX_SYSCALL_REGNUM, &syscall);
/* Then check the system call number. */
if (syscall == SYS_sigreturn || syscall == SYS_rt_sigreturn)
{
- CORE_ADDR sp = read_register (I386_ESP_REGNUM);
- CORE_ADDR addr = sp;
+ ULONGEST sp, addr;
unsigned long int eflags;
+ regcache_cooked_read_unsigned (regcache, I386_ESP_REGNUM, &sp);
if (syscall == SYS_rt_sigreturn)
- addr = read_memory_integer (sp + 8, 4) + 20;
+ addr = read_memory_unsigned_integer (sp + 8, 4, byte_order)
+ + 20;
+ else
+ addr = sp;
/* Set the trace flag in the context that's about to be
restored. */
addr += LINUX_SIGCONTEXT_EFLAGS_OFFSET;
- read_memory (addr, (char *) &eflags, 4);
+ read_memory (addr, (gdb_byte *) &eflags, 4);
eflags |= 0x0100;
- write_memory (addr, (char *) &eflags, 4);
+ write_memory (addr, (gdb_byte *) &eflags, 4);
}
}
}
- if (ptrace (request, pid, 0, target_signal_to_host (signal)) == -1)
- perror_with_name ("ptrace");
+ if (ptrace (request, pid, 0, gdb_signal_to_host (signal)) == -1)
+ perror_with_name (("ptrace"));
}
+
+
+/* -Wmissing-prototypes */
+extern initialize_file_ftype _initialize_i386_linux_nat;
void
-child_post_startup_inferior (ptid_t ptid)
+_initialize_i386_linux_nat (void)
{
- i386_cleanup_dregs ();
- linux_child_post_startup_inferior (ptid);
+ /* Create a generic x86 GNU/Linux target. */
+ struct target_ops *t = x86_linux_create_target ();
+
+ /* Override the default ptrace resume method. */
+ t->to_resume = i386_linux_resume;
+
+ /* Add our register access methods. */
+ t->to_fetch_registers = i386_linux_fetch_inferior_registers;
+ t->to_store_registers = i386_linux_store_inferior_registers;
+
+ /* Add the target. */
+ x86_linux_add_target (t);
}