Multi-target support
[deliverable/binutils-gdb.git] / gdb / amd64-linux-nat.c
index e4ae88db096bafd347ab5dde459c4d8c712bbd90..27748ff9860081f577de143b1b197ab314dc2e4f 100644 (file)
@@ -1,7 +1,6 @@
 /* Native-dependent code for GNU/Linux x86-64.
 
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
    Contributed by Jiri Smid, SuSE Labs.
 
    This file is part of GDB.
 
 #include "defs.h"
 #include "inferior.h"
-#include "gdbcore.h"
 #include "regcache.h"
-#include "linux-nat.h"
-#include "amd64-linux-tdep.h"
-
-#include "gdb_assert.h"
-#include "gdb_string.h"
-#include <sys/ptrace.h>
-#include <sys/debugreg.h>
-#include <sys/syscall.h>
-#include <sys/procfs.h>
+#include "elf/common.h"
+#include <sys/uio.h>
+#include "nat/gdb_ptrace.h"
 #include <asm/prctl.h>
-/* FIXME ezannoni-2003-07-09: we need <sys/reg.h> to be included after
-   <asm/ptrace.h> because the latter redefines FS and GS for no apparent
-   reason, and those definitions don't match the ones that libpthread_db
-   uses, which come from <sys/reg.h>.  */
-/* ezannoni-2003-07-09: I think this is fixed. The extraneous defs have
-   been removed from ptrace.h in the kernel.  However, better safe than
-   sorry.  */
-#include <asm/ptrace.h>
 #include <sys/reg.h>
-#include "gdb_proc_service.h"
-
-/* Prototypes for supply_gregset etc.  */
 #include "gregset.h"
+#include "gdb_proc_service.h"
 
+#include "amd64-nat.h"
 #include "amd64-tdep.h"
+#include "amd64-linux-tdep.h"
 #include "i386-linux-tdep.h"
-#include "amd64-nat.h"
+#include "gdbsupport/x86-xstate.h"
 
-/* Mapping between the general-purpose registers in GNU/Linux x86-64
-   `struct user' format and GDB's register cache layout.  */
+#include "x86-linux-nat.h"
+#include "nat/linux-ptrace.h"
+#include "nat/amd64-linux-siginfo.h"
 
-static int amd64_linux_gregset64_reg_offset[] =
+/* This definition comes from prctl.h.  Kernels older than 2.5.64
+   do not have it.  */
+#ifndef PTRACE_ARCH_PRCTL
+#define PTRACE_ARCH_PRCTL      30
+#endif
+
+struct amd64_linux_nat_target final : public x86_linux_nat_target
 {
-  RAX * 8, RBX * 8,            /* %rax, %rbx */
-  RCX * 8, RDX * 8,            /* %rcx, %rdx */
-  RSI * 8, RDI * 8,            /* %rsi, %rdi */
-  RBP * 8, RSP * 8,            /* %rbp, %rsp */
-  R8 * 8, R9 * 8,              /* %r8 ... */
-  R10 * 8, R11 * 8,
-  R12 * 8, R13 * 8,
-  R14 * 8, R15 * 8,            /* ... %r15 */
-  RIP * 8, EFLAGS * 8,         /* %rip, %eflags */
-  CS * 8, SS * 8,              /* %cs, %ss */
-  DS * 8, ES * 8,              /* %ds, %es */
-  FS * 8, GS * 8,              /* %fs, %gs */
-  -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  ORIG_RAX * 8
+  /* Add our register access methods.  */
+  void fetch_registers (struct regcache *, int) override;
+  void store_registers (struct regcache *, int) override;
+
+  bool low_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction)
+    override;
 };
-\f
+
+static amd64_linux_nat_target the_amd64_linux_nat_target;
 
 /* Mapping between the general-purpose registers in GNU/Linux x86-64
    `struct user' format and GDB's register cache layout for GNU/Linux
@@ -98,13 +79,84 @@ static int amd64_linux_gregset32_reg_offset[] =
   -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1,
-  ORIG_RAX * 8                 /* "orig_eax" */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1,                /* MPX registers BND0 ... BND3.  */
+  -1, -1,                        /* MPX registers BNDCFGU, BNDSTATUS.  */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* k0 ... k7 (AVX512)  */
+  -1, -1, -1, -1, -1, -1, -1, -1, /* zmm0 ... zmm7 (AVX512)  */
+  -1,                            /* PKEYS register PKRU  */
+  ORIG_RAX * 8                   /* "orig_eax"  */
 };
 \f
 
 /* Transfering the general-purpose registers between GDB, inferiors
    and core files.  */
 
+/* See amd64_collect_native_gregset.  This linux specific version handles
+   issues with negative EAX values not being restored correctly upon syscall
+   return when debugging 32-bit targets.  It has no effect on 64-bit
+   targets.  */
+
+static void
+amd64_linux_collect_native_gregset (const struct regcache *regcache,
+                                   void *gregs, int regnum)
+{
+  amd64_collect_native_gregset (regcache, gregs, regnum);
+
+  struct gdbarch *gdbarch = regcache->arch ();
+  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+    {
+      /* Sign extend EAX value to avoid potential syscall restart
+        problems.  
+
+        On Linux, when a syscall is interrupted by a signal, the
+        (kernel function implementing the) syscall may return
+        -ERESTARTSYS when a signal occurs.  Doing so indicates that
+        the syscall is restartable.  Then, depending on settings
+        associated with the signal handler, and after the signal
+        handler is called, the kernel can then either return -EINTR
+        or it can cause the syscall to be restarted.  We are
+        concerned with the latter case here.
+        
+        On (32-bit) i386, the status (-ERESTARTSYS) is placed in the
+        EAX register.  When debugging a 32-bit process from a 64-bit
+        (amd64) GDB, the debugger fetches 64-bit registers even
+        though the process being debugged is only 32-bit.  The
+        register cache is only 32 bits wide though; GDB discards the
+        high 32 bits when placing 64-bit values in the 32-bit
+        regcache.  Normally, this is not a problem since the 32-bit
+        process should only care about the lower 32-bit portions of
+        these registers.  That said, it can happen that the 64-bit
+        value being restored will be different from the 64-bit value
+        that was originally retrieved from the kernel.  The one place
+        (that we know of) where it does matter is in the kernel's
+        syscall restart code.  The kernel's code for restarting a
+        syscall after a signal expects to see a negative value
+        (specifically -ERESTARTSYS) in the 64-bit RAX register in
+        order to correctly cause a syscall to be restarted.
+        
+        The call to amd64_collect_native_gregset, above, is setting
+        the high 32 bits of RAX (and other registers too) to 0.  For
+        syscall restart, we need to sign extend EAX so that RAX will
+        appear as a negative value when EAX is set to -ERESTARTSYS. 
+        This in turn will cause the signal handling code in the
+        kernel to recognize -ERESTARTSYS which will in turn cause the
+        syscall to be restarted.
+
+        The test case gdb.base/interrupt.exp tests for this problem.
+        Without this sign extension code in place, it'll show
+        a number of failures when testing against unix/-m32.  */
+
+      if (regnum == -1 || regnum == I386_EAX_REGNUM)
+       {
+         void *ptr = ((gdb_byte *) gregs 
+                      + amd64_linux_gregset32_reg_offset[I386_EAX_REGNUM]);
+
+         *(int64_t *) ptr = *(int32_t *) ptr;
+       }
+    }
+}
+
 /* Fill GDB's register cache with the general-purpose register values
    in *GREGSETP.  */
 
@@ -122,7 +174,7 @@ void
 fill_gregset (const struct regcache *regcache,
              elf_gregset_t *gregsetp, int regnum)
 {
-  amd64_collect_native_gregset (regcache, gregsetp, regnum);
+  amd64_linux_collect_native_gregset (regcache, gregsetp, regnum);
 }
 
 /* Transfering floating-point registers between GDB, inferiors and cores.  */
@@ -154,16 +206,16 @@ fill_fpregset (const struct regcache *regcache,
    this for all registers (including the floating point and SSE
    registers).  */
 
-static void
-amd64_linux_fetch_inferior_registers (struct regcache *regcache, int regnum)
+void
+amd64_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   int tid;
 
   /* GNU/Linux LWP ID's are process ID's.  */
-  tid = TIDGET (inferior_ptid);
+  tid = regcache->ptid ().lwp ();
   if (tid == 0)
-    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
+    tid = regcache->ptid ().pid (); /* Not a threaded program.  */
 
   if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
     {
@@ -181,10 +233,56 @@ amd64_linux_fetch_inferior_registers (struct regcache *regcache, int regnum)
     {
       elf_fpregset_t fpregs;
 
-      if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
-       perror_with_name (_("Couldn't get floating point status"));
+      if (have_ptrace_getregset == TRIBOOL_TRUE)
+       {
+         char xstateregs[X86_XSTATE_MAX_SIZE];
+         struct iovec iov;
+
+         /* Pre-4.14 kernels have a bug (fixed by commit 0852b374173b
+            "x86/fpu: Add FPU state copying quirk to handle XRSTOR failure on
+            Intel Skylake CPUs") that sometimes causes the mxcsr location in
+            xstateregs not to be copied by PTRACE_GETREGSET.  Make sure that
+            the location is at least initialized with a defined value.  */
+         memset (xstateregs, 0, sizeof (xstateregs));
+         iov.iov_base = xstateregs;
+         iov.iov_len = sizeof (xstateregs);
+         if (ptrace (PTRACE_GETREGSET, tid,
+                     (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
+           perror_with_name (_("Couldn't get extended state status"));
+
+         amd64_supply_xsave (regcache, -1, xstateregs);
+       }
+      else
+       {
+         if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
+           perror_with_name (_("Couldn't get floating point status"));
 
-      amd64_supply_fxsave (regcache, -1, &fpregs);
+         amd64_supply_fxsave (regcache, -1, &fpregs);
+       }
+#ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
+      {
+       /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
+          fs_base and gs_base fields of user_regs_struct can be
+          used directly.  */
+       unsigned long base;
+
+       if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM)
+         {
+           if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_FS) < 0)
+             perror_with_name (_("Couldn't get segment register fs_base"));
+
+           regcache->raw_supply (AMD64_FSBASE_REGNUM, &base);
+         }
+
+       if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM)
+         {
+           if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_GS) < 0)
+             perror_with_name (_("Couldn't get segment register gs_base"));
+
+           regcache->raw_supply (AMD64_GSBASE_REGNUM, &base);
+         }
+      }
+#endif
     }
 }
 
@@ -192,16 +290,16 @@ amd64_linux_fetch_inferior_registers (struct regcache *regcache, int regnum)
    -1, do this for all registers (including the floating-point and SSE
    registers).  */
 
-static void
-amd64_linux_store_inferior_registers (struct regcache *regcache, int regnum)
+void
+amd64_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   int tid;
 
   /* GNU/Linux LWP ID's are process ID's.  */
-  tid = TIDGET (inferior_ptid);
+  tid = regcache->ptid ().lwp ();
   if (tid == 0)
-    tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
+    tid = regcache->ptid ().pid (); /* Not a threaded program.  */
 
   if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum))
     {
@@ -210,7 +308,7 @@ amd64_linux_store_inferior_registers (struct regcache *regcache, int regnum)
       if (ptrace (PTRACE_GETREGS, tid, 0, (long) &regs) < 0)
        perror_with_name (_("Couldn't get registers"));
 
-      amd64_collect_native_gregset (regcache, &regs, regnum);
+      amd64_linux_collect_native_gregset (regcache, &regs, regnum);
 
       if (ptrace (PTRACE_SETREGS, tid, 0, (long) &regs) < 0)
        perror_with_name (_("Couldn't write registers"));
@@ -223,111 +321,58 @@ amd64_linux_store_inferior_registers (struct regcache *regcache, int regnum)
     {
       elf_fpregset_t fpregs;
 
-      if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
-       perror_with_name (_("Couldn't get floating point status"));
+      if (have_ptrace_getregset == TRIBOOL_TRUE)
+       {
+         char xstateregs[X86_XSTATE_MAX_SIZE];
+         struct iovec iov;
 
-      amd64_collect_fxsave (regcache, regnum, &fpregs);
+         iov.iov_base = xstateregs;
+         iov.iov_len = sizeof (xstateregs);
+         if (ptrace (PTRACE_GETREGSET, tid,
+                     (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
+           perror_with_name (_("Couldn't get extended state status"));
 
-      if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
-       perror_with_name (_("Couldn't write floating point status"));
+         amd64_collect_xsave (regcache, regnum, xstateregs, 0);
 
-      return;
-    }
-}
-\f
-/* Support for debug registers.  */
+         if (ptrace (PTRACE_SETREGSET, tid,
+                     (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
+           perror_with_name (_("Couldn't write extended state status"));
+       }
+      else
+       {
+         if (ptrace (PTRACE_GETFPREGS, tid, 0, (long) &fpregs) < 0)
+           perror_with_name (_("Couldn't get floating point status"));
 
-static unsigned long amd64_linux_dr[DR_CONTROL + 1];
+         amd64_collect_fxsave (regcache, regnum, &fpregs);
 
-static unsigned long
-amd64_linux_dr_get (ptid_t ptid, int regnum)
-{
-  int tid;
-  unsigned long value;
+         if (ptrace (PTRACE_SETFPREGS, tid, 0, (long) &fpregs) < 0)
+           perror_with_name (_("Couldn't write floating point status"));
+       }
 
-  tid = TIDGET (ptid);
-  if (tid == 0)
-    tid = PIDGET (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 vector.  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;
+#ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
+      {
+       /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
+          fs_base and gs_base fields of user_regs_struct can be
+          used directly.  */
+       void *base;
+
+       if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM)
+         {
+           regcache->raw_collect (AMD64_FSBASE_REGNUM, &base);
+
+           if (ptrace (PTRACE_ARCH_PRCTL, tid, base, ARCH_SET_FS) < 0)
+             perror_with_name (_("Couldn't write segment register fs_base"));
+         }
+       if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM)
+         {
+
+           regcache->raw_collect (AMD64_GSBASE_REGNUM, &base);
+           if (ptrace (PTRACE_ARCH_PRCTL, tid, base, ARCH_SET_GS) < 0)
+             perror_with_name (_("Couldn't write segment register gs_base"));
+         }
+      }
 #endif
-
-  return value;
-}
-
-static void
-amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
-{
-  int tid;
-
-  tid = TIDGET (ptid);
-  if (tid == 0)
-    tid = PIDGET (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
-amd64_linux_dr_set_control (unsigned long control)
-{
-  struct lwp_info *lp;
-  ptid_t ptid;
-
-  amd64_linux_dr[DR_CONTROL] = control;
-  ALL_LWPS (lp, ptid)
-    amd64_linux_dr_set (ptid, DR_CONTROL, control);
-}
-
-void
-amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
-{
-  struct lwp_info *lp;
-  ptid_t ptid;
-
-  gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
-
-  amd64_linux_dr[DR_FIRSTADDR + regnum] = addr;
-  ALL_LWPS (lp, ptid)
-    amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
-}
-
-void
-amd64_linux_dr_reset_addr (int regnum)
-{
-  amd64_linux_dr_set_addr (regnum, 0);
-}
-
-unsigned long
-amd64_linux_dr_get_status (void)
-{
-  return amd64_linux_dr_get (inferior_ptid, DR_STATUS);
-}
-
-static void
-amd64_linux_new_thread (ptid_t ptid)
-{
-  int i;
-
-  for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
-    amd64_linux_dr_set (ptid, i, amd64_linux_dr[i]);
-
-  amd64_linux_dr_set (ptid, DR_CONTROL, amd64_linux_dr[DR_CONTROL]);
+    }
 }
 \f
 
@@ -335,39 +380,27 @@ amd64_linux_new_thread (ptid_t ptid)
    a request for a thread's local storage address.  */
 
 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)
 {
-  if (gdbarch_ptr_bit (current_gdbarch) == 32)
+  if (gdbarch_bfd_arch_info (ph->thread->inf->gdbarch)->bits_per_word == 32)
     {
-      /* The full structure is found in <asm-i386/ldt.h>.  The second
-        integer is the LDT's base_address and that is used to locate
-        the thread's local storage.  See i386-linux-nat.c more
-        info.  */
-      unsigned int desc[4];
-
-      /* This code assumes that "int" is 32 bits and that
-        GET_THREAD_AREA returns no more than 4 int values.  */
-      gdb_assert (sizeof (int) == 4);  
-#ifndef PTRACE_GET_THREAD_AREA
-#define PTRACE_GET_THREAD_AREA 25
-#endif
-      if  (ptrace (PTRACE_GET_THREAD_AREA, 
-                  lwpid, (void *) (long) idx, (unsigned long) &desc) < 0)
-       return PS_ERR;
-      
-      /* Extend the value to 64 bits.  Here it's assumed that a "long"
-        and a "void *" are the same.  */
-      (*base) = (void *) (long) desc[1];
-      return PS_OK;
+      unsigned int base_addr;
+      ps_err_e result;
+
+      result = x86_linux_get_thread_area (lwpid, (void *) (long) idx,
+                                         &base_addr);
+      if (result == PS_OK)
+       {
+         /* Extend the value to 64 bits.  Here it's assumed that
+            a "long" and a "void *" are the same.  */
+         (*base) = (void *) (long) base_addr;
+       }
+      return result;
     }
   else
     {
-      /* This definition comes from prctl.h, but some kernels may not
-         have it.  */
-#ifndef PTRACE_ARCH_PRCTL
-#define PTRACE_ARCH_PRCTL      30
-#endif
+
       /* FIXME: ezannoni-2003-07-09 see comment above about include
         file order.  We could be getting bogus values for these two.  */
       gdb_assert (FS < ELF_NGREG);
@@ -375,10 +408,39 @@ ps_get_thread_area (const struct ps_prochandle *ph,
       switch (idx)
        {
        case FS:
+#ifdef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
+           {
+             /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
+                fs_base and gs_base fields of user_regs_struct can be
+                used directly.  */
+             unsigned long fs;
+             errno = 0;
+             fs = ptrace (PTRACE_PEEKUSER, lwpid,
+                          offsetof (struct user_regs_struct, fs_base), 0);
+             if (errno == 0)
+               {
+                 *base = (void *) fs;
+                 return PS_OK;
+               }
+           }
+#endif
          if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
            return PS_OK;
          break;
        case GS:
+#ifdef HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE
+           {
+             unsigned long gs;
+             errno = 0;
+             gs = ptrace (PTRACE_PEEKUSER, lwpid,
+                          offsetof (struct user_regs_struct, gs_base), 0);
+             if (errno == 0)
+               {
+                 *base = (void *) gs;
+                 return PS_OK;
+               }
+           }
+#endif
          if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
            return PS_OK;
          break;
@@ -390,48 +452,45 @@ ps_get_thread_area (const struct ps_prochandle *ph,
 }
 \f
 
-static void (*super_post_startup_inferior) (ptid_t ptid);
+/* Convert a ptrace/host siginfo object, into/from the siginfo in the
+   layout of the inferiors' architecture.  Returns true if any
+   conversion was done; false otherwise.  If DIRECTION is 1, then copy
+   from INF to PTRACE.  If DIRECTION is 0, copy from PTRACE to
+   INF.  */
 
-static void
-amd64_linux_child_post_startup_inferior (ptid_t ptid)
+bool
+amd64_linux_nat_target::low_siginfo_fixup (siginfo_t *ptrace,
+                                          gdb_byte *inf,
+                                          int direction)
 {
-  i386_cleanup_dregs ();
-  super_post_startup_inferior (ptid);
+  struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
+
+  /* Is the inferior 32-bit?  If so, then do fixup the siginfo
+     object.  */
+  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+    return amd64_linux_siginfo_fixup_common (ptrace, inf, direction,
+                                            FIXUP_32);
+  /* No fixup for native x32 GDB.  */
+  else if (gdbarch_addr_bit (gdbarch) == 32 && sizeof (void *) == 8)
+    return amd64_linux_siginfo_fixup_common (ptrace, inf, direction,
+                                            FIXUP_X32);
+  else
+    return false;
 }
-\f
-
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-void _initialize_amd64_linux_nat (void);
 
 void
 _initialize_amd64_linux_nat (void)
 {
-  struct target_ops *t;
-
   amd64_native_gregset32_reg_offset = amd64_linux_gregset32_reg_offset;
   amd64_native_gregset32_num_regs = I386_LINUX_NUM_REGS;
-  amd64_native_gregset64_reg_offset = amd64_linux_gregset64_reg_offset;
+  amd64_native_gregset64_reg_offset = amd64_linux_gregset_reg_offset;
   amd64_native_gregset64_num_regs = AMD64_LINUX_NUM_REGS;
 
   gdb_assert (ARRAY_SIZE (amd64_linux_gregset32_reg_offset)
              == amd64_native_gregset32_num_regs);
-  gdb_assert (ARRAY_SIZE (amd64_linux_gregset64_reg_offset)
-             == amd64_native_gregset64_num_regs);
-
-  /* Fill in the generic GNU/Linux methods.  */
-  t = linux_target ();
 
-  i386_use_watchpoints (t);
-
-  /* Override the GNU/Linux inferior startup hook.  */
-  super_post_startup_inferior = t->to_post_startup_inferior;
-  t->to_post_startup_inferior = amd64_linux_child_post_startup_inferior;
-
-  /* Add our register access methods.  */
-  t->to_fetch_registers = amd64_linux_fetch_inferior_registers;
-  t->to_store_registers = amd64_linux_store_inferior_registers;
+  linux_target = &the_amd64_linux_nat_target;
 
-  /* Register the target.  */
-  linux_nat_add_target (t);
-  linux_nat_set_new_thread (t, amd64_linux_new_thread);
+  /* Add the target.  */
+  add_inf_child_target (linux_target);
 }
This page took 0.039073 seconds and 4 git commands to generate.