/* Native-dependent code for GNU/Linux i386.
- Copyright (C) 1999-2014 Free Software Foundation, Inc.
+ Copyright (C) 1999-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbcore.h"
#include "regcache.h"
#include "elf/common.h"
-#include <sys/ptrace.h>
+#include "nat/gdb_ptrace.h"
#include <sys/uio.h>
#include "gregset.h"
#include "gdb_proc_service.h"
#include "i387-tdep.h"
#include "i386-tdep.h"
#include "i386-linux-tdep.h"
-#include "x86-xstate.h"
+#include "common/x86-xstate.h"
#include "x86-linux-nat.h"
+#include "nat/linux-ptrace.h"
+#include "inf-ptrace.h"
+
+struct i386_linux_nat_target final : public x86_linux_nat_target
+{
+ /* Add our register access methods. */
+ void fetch_registers (struct regcache *, int) override;
+ void store_registers (struct regcache *, int) override;
+
+ /* Override the default ptrace resume method. */
+ void low_resume (ptid_t ptid, int step, enum gdb_signal sig) override;
+};
+
+static i386_linux_nat_target the_i386_linux_nat_target;
/* 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
(I386_ST0_REGNUM <= (regno) && (regno) < I386_SSE_NUM_REGS)
#define GETXSTATEREGS_SUPPLIES(regno) \
- (I386_ST0_REGNUM <= (regno) && (regno) < I386_AVX512_NUM_REGS)
+ (I386_ST0_REGNUM <= (regno) && (regno) < I386_PKEYS_NUM_REGS)
/* Does the current host support the GETREGS request? */
int have_ptrace_getregs =
static void
fetch_register (struct regcache *regcache, int regno)
{
- int tid;
+ pid_t tid;
int val;
gdb_assert (!have_ptrace_getregs);
if (i386_linux_gregset_reg_offset[regno] == -1)
{
- regcache_raw_supply (regcache, regno, NULL);
+ regcache->raw_supply (regno, NULL);
return;
}
- /* GNU/Linux LWP ID's are process ID's. */
- tid = ptid_get_lwp (inferior_ptid);
- if (tid == 0)
- tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
+ tid = get_ptrace_pid (regcache->ptid ());
errno = 0;
val = ptrace (PTRACE_PEEKUSER, tid,
i386_linux_gregset_reg_offset[regno], 0);
if (errno != 0)
error (_("Couldn't read register %s (#%d): %s."),
- gdbarch_register_name (get_regcache_arch (regcache), regno),
+ gdbarch_register_name (regcache->arch (), regno),
regno, safe_strerror (errno));
- regcache_raw_supply (regcache, regno, &val);
+ regcache->raw_supply (regno, &val);
}
/* Store one register. */
static void
store_register (const struct regcache *regcache, int regno)
{
- int tid;
+ pid_t tid;
int val;
gdb_assert (!have_ptrace_getregs);
if (i386_linux_gregset_reg_offset[regno] == -1)
return;
- /* GNU/Linux LWP ID's are process ID's. */
- tid = ptid_get_lwp (inferior_ptid);
- if (tid == 0)
- tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
+ tid = get_ptrace_pid (regcache->ptid ());
errno = 0;
- regcache_raw_collect (regcache, regno, &val);
+ regcache->raw_collect (regno, &val);
ptrace (PTRACE_POKEUSER, tid,
i386_linux_gregset_reg_offset[regno], val);
if (errno != 0)
error (_("Couldn't write register %s (#%d): %s."),
- gdbarch_register_name (get_regcache_arch (regcache), regno),
+ gdbarch_register_name (regcache->arch (), regno),
regno, safe_strerror (errno));
}
\f
int i;
for (i = 0; i < I386_NUM_GREGS; i++)
- regcache_raw_supply (regcache, i,
- regp + i386_linux_gregset_reg_offset[i]);
+ regcache->raw_supply (i, regp + i386_linux_gregset_reg_offset[i]);
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]);
+ < gdbarch_num_regs (regcache->arch ()))
+ regcache->raw_supply
+ (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
for (i = 0; i < I386_NUM_GREGS; i++)
if (regno == -1 || regno == i)
- regcache_raw_collect (regcache, i,
- regp + i386_linux_gregset_reg_offset[i]);
+ regcache->raw_collect (i, regp + i386_linux_gregset_reg_offset[i]);
if ((regno == -1 || regno == I386_LINUX_ORIG_EAX_REGNUM)
&& 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]);
+ < gdbarch_num_regs (regcache->arch ()))
+ regcache->raw_collect
+ (I386_LINUX_ORIG_EAX_REGNUM,
+ regp + i386_linux_gregset_reg_offset[I386_LINUX_ORIG_EAX_REGNUM]);
}
#ifdef HAVE_PTRACE_GETREGS
char xstateregs[X86_XSTATE_MAX_SIZE];
struct iovec iov;
- if (!have_ptrace_getregset)
+ if (have_ptrace_getregset != TRIBOOL_TRUE)
return 0;
iov.iov_base = xstateregs;
char xstateregs[X86_XSTATE_MAX_SIZE];
struct iovec iov;
- if (!have_ptrace_getregset)
+ if (have_ptrace_getregset != TRIBOOL_TRUE)
return 0;
iov.iov_base = xstateregs;
this for all registers (including the floating point and SSE
registers). */
-static void
-i386_linux_fetch_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
+void
+i386_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
- int tid;
+ pid_t tid;
/* Use the old method of peeking around in `struct user' if the
GETREGS request isn't available. */
{
int i;
- for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
+ for (i = 0; i < gdbarch_num_regs (regcache->arch ()); i++)
if (regno == -1 || regno == i)
fetch_register (regcache, i);
return;
}
- /* GNU/Linux LWP ID's are process ID's. */
- tid = ptid_get_lwp (inferior_ptid);
- if (tid == 0)
- tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
+ tid = get_ptrace_pid (regcache->ptid ());
/* Use the PTRACE_GETFPXREGS request whenever possible, since it
transfers more registers in one system call, and we'll cache the
/* The call above might reset `have_ptrace_getregs'. */
if (!have_ptrace_getregs)
{
- i386_linux_fetch_inferior_registers (ops, regcache, regno);
+ fetch_registers (regcache, regno);
return;
}
/* Store register REGNO back into the child process. If REGNO is -1,
do this for all registers (including the floating point and SSE
registers). */
-static void
-i386_linux_store_inferior_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
+void
+i386_linux_nat_target::store_registers (struct regcache *regcache, int regno)
{
- int tid;
+ pid_t tid;
/* Use the old method of poking around in `struct user' if the
SETREGS request isn't available. */
{
int i;
- for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
+ for (i = 0; i < gdbarch_num_regs (regcache->arch ()); i++)
if (regno == -1 || regno == i)
store_register (regcache, i);
return;
}
- /* GNU/Linux LWP ID's are process ID's. */
- tid = ptid_get_lwp (inferior_ptid);
- if (tid == 0)
- tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */
+ tid = get_ptrace_pid (regcache->ptid ());
/* Use the PTRACE_SETFPXREGS requests whenever possible, since it
transfers more registers in one system call. But remember that
storage (or its descriptor). */
ps_err_e
-ps_get_thread_area (const struct ps_prochandle *ph,
+ps_get_thread_area (struct ps_prochandle *ph,
lwpid_t lwpid, int idx, void **base)
{
unsigned int base_addr;
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
-static void
-i386_linux_resume (struct target_ops *ops,
- ptid_t ptid, int step, enum gdb_signal signal)
+void
+i386_linux_nat_target::low_resume (ptid_t ptid, int step, enum gdb_signal signal)
{
- int pid = ptid_get_pid (ptid);
-
+ int pid = ptid.lwp ();
int request;
if (catch_syscall_enabled () > 0)
if (step)
{
- struct regcache *regcache = get_thread_regcache (pid_to_ptid (pid));
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct regcache *regcache = get_thread_regcache (ptid);
+ struct gdbarch *gdbarch = regcache->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
ULONGEST pc;
gdb_byte buf[LINUX_SYSCALL_LEN];
if (ptrace (request, pid, 0, gdb_signal_to_host (signal)) == -1)
perror_with_name (("ptrace"));
}
-\f
-
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_i386_linux_nat;
void
_initialize_i386_linux_nat (void)
{
- /* 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;
+ linux_target = &the_i386_linux_nat_target;
/* Add the target. */
- x86_linux_add_target (t);
+ add_inf_child_target (linux_target);
}