Plug target side conditions and commands leaks.
[deliverable/binutils-gdb.git] / gdb / amd64-linux-tdep.c
index ed75f97c9eaad5c978b98a8a7f4d244578849633..7fe92d1eea0183f9cd63fc010cce3944c7319ec7 100644 (file)
@@ -1,7 +1,6 @@
 /* Target-dependent code for GNU/Linux x86-64.
 
-   Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2001-2013 Free Software Foundation, Inc.
    Contributed by Jiri Smid, SuSE Labs.
 
    This file is part of GDB.
 #include "linux-tdep.h"
 #include "i386-xstate.h"
 
-#include "gdb_string.h"
+#include <string.h>
 
 #include "amd64-tdep.h"
 #include "solib-svr4.h"
 #include "xml-syscall.h"
+#include "glibc-tdep.h"
 
 #include "features/i386/amd64-linux.c"
 #include "features/i386/amd64-avx-linux.c"
+#include "features/i386/amd64-mpx-linux.c"
+#include "features/i386/x32-linux.c"
+#include "features/i386/x32-avx-linux.c"
 
 /* The syscall's XML filename for i386.  */
 #define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml"
 
-#include "record.h"
+#include "record-full.h"
 #include "linux-record.h"
 
 /* Supported register note sections.  */
@@ -72,7 +75,7 @@ int amd64_linux_gregset_reg_offset[] =
   14 * 8,                      /* %rdi */
   4 * 8,                       /* %rbp */
   19 * 8,                      /* %rsp */
-  9 * 8,                       /* %r8 ... */
+  9 * 8,                       /* %r8 ...  */
   8 * 8,
   7 * 8,
   6 * 8,
@@ -94,6 +97,8 @@ int amd64_linux_gregset_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,
+  -1, -1, -1, -1,              /* MPX registers BND0 ... BND3.  */
+  -1, -1,                      /* MPX registers BNDCFGU and BNDSTATUS.  */
   15 * 8                       /* "orig_rax" */
 };
 \f
@@ -105,7 +110,7 @@ int amd64_linux_gregset_reg_offset[] =
 #define LINUX_SIGTRAMP_INSN1   0x0f    /* syscall */
 #define LINUX_SIGTRAMP_OFFSET1 7
 
-static const gdb_byte linux_sigtramp_code[] =
+static const gdb_byte amd64_linux_sigtramp_code[] =
 {
   /* mov $__NR_rt_sigreturn, %rax */
   LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00,
@@ -113,7 +118,15 @@ static const gdb_byte linux_sigtramp_code[] =
   LINUX_SIGTRAMP_INSN1, 0x05
 };
 
-#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
+static const gdb_byte amd64_x32_linux_sigtramp_code[] =
+{
+  /* mov $__NR_rt_sigreturn, %rax.  */
+  LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x01, 0x02, 0x00, 0x40,
+  /* syscall */
+  LINUX_SIGTRAMP_INSN1, 0x05
+};
+
+#define LINUX_SIGTRAMP_LEN (sizeof amd64_linux_sigtramp_code)
 
 /* If PC is in a sigtramp routine, return the address of the start of
    the routine.  Otherwise, return 0.  */
@@ -121,6 +134,8 @@ static const gdb_byte linux_sigtramp_code[] =
 static CORE_ADDR
 amd64_linux_sigtramp_start (struct frame_info *this_frame)
 {
+  struct gdbarch *gdbarch;
+  const gdb_byte *sigtramp_code;
   CORE_ADDR pc = get_frame_pc (this_frame);
   gdb_byte buf[LINUX_SIGTRAMP_LEN];
 
@@ -144,7 +159,12 @@ amd64_linux_sigtramp_start (struct frame_info *this_frame)
        return 0;
     }
 
-  if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
+  gdbarch = get_frame_arch (this_frame);
+  if (gdbarch_ptr_bit (gdbarch) == 32)
+    sigtramp_code = amd64_x32_linux_sigtramp_code;
+  else
+    sigtramp_code = amd64_linux_sigtramp_code;
+  if (memcmp (buf, sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
     return 0;
 
   return pc;
@@ -157,7 +177,7 @@ static int
 amd64_linux_sigtramp_p (struct frame_info *this_frame)
 {
   CORE_ADDR pc = get_frame_pc (this_frame);
-  char *name;
+  const char *name;
 
   find_pc_partial_function (pc, &name, NULL, NULL);
 
@@ -296,39 +316,39 @@ amd64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
 static int
 amd64_all_but_ip_registers_record (struct regcache *regcache)
 {
-  if (record_arch_list_add_reg (regcache, AMD64_RAX_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RAX_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_RCX_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RCX_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_RDX_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RDX_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_RBX_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RBX_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_RSP_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RSP_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_RBP_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RBP_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_RSI_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RSI_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_RDI_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RDI_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_R8_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_R8_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_R9_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_R9_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_R10_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_R10_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_R11_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_R11_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_R12_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_R12_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_R13_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_R13_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_R14_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_R14_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_R15_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_R15_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_EFLAGS_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_EFLAGS_REGNUM))
     return -1;
 
   return 0;
@@ -339,9 +359,9 @@ amd64_all_but_ip_registers_record (struct regcache *regcache)
    process record.  */
 
 static enum gdb_syscall
-amd64_canonicalize_syscall (enum amd64_syscall syscall)
+amd64_canonicalize_syscall (enum amd64_syscall syscall_number)
 {
-  switch (syscall) {
+  switch (syscall_number) {
   case amd64_sys_read:
     return gdb_sys_read;
 
@@ -1147,7 +1167,7 @@ amd64_canonicalize_syscall (enum amd64_syscall syscall)
 
 /* Parse the arguments of current system call instruction and record
    the values of the registers and memory that will be changed into
-   "record_arch_list".  This instruction is "syscall".
+   "record_full_arch_list".  This instruction is "syscall".
 
    Return -1 if something wrong.  */
 
@@ -1174,25 +1194,24 @@ amd64_linux_syscall_record (struct regcache *regcache)
       break;
 
     case amd64_sys_arch_prctl:
-      if (syscall_native == amd64_sys_arch_prctl)
-        {
-          ULONGEST arg3;
-
-          regcache_raw_read_unsigned (regcache, amd64_linux_record_tdep.arg3,
-                                      &arg3);
-          if (arg3 == RECORD_ARCH_GET_FS || arg3 == RECORD_ARCH_GET_GS)
-            {
-             CORE_ADDR addr;
-
-             regcache_raw_read_unsigned (regcache,
-                                          amd64_linux_record_tdep.arg2,
-                                          &addr);
-             if (record_arch_list_add_mem (addr,
-                                            amd64_linux_record_tdep.size_ulong))
-                return -1;
-            }
-          goto record_regs;
-        }
+      {
+       ULONGEST arg3;
+
+       regcache_raw_read_unsigned (regcache, amd64_linux_record_tdep.arg3,
+                                   &arg3);
+       if (arg3 == RECORD_ARCH_GET_FS || arg3 == RECORD_ARCH_GET_GS)
+         {
+           CORE_ADDR addr;
+
+           regcache_raw_read_unsigned (regcache,
+                                       amd64_linux_record_tdep.arg2,
+                                       &addr);
+           if (record_full_arch_list_add_mem
+               (addr, amd64_linux_record_tdep.size_ulong))
+             return -1;
+         }
+       goto record_regs;
+      }
       break;
     }
 
@@ -1215,9 +1234,9 @@ amd64_linux_syscall_record (struct regcache *regcache)
 
  record_regs:
   /* Record the return value of the system call.  */
-  if (record_arch_list_add_reg (regcache, AMD64_RCX_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RCX_REGNUM))
     return -1;
-  if (record_arch_list_add_reg (regcache, AMD64_R11_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_R11_REGNUM))
     return -1;
 
   return 0;
@@ -1227,17 +1246,17 @@ amd64_linux_syscall_record (struct regcache *regcache)
 #define AMD64_LINUX_xstate     512
 #define AMD64_LINUX_frame_size 560
 
-int
+static int
 amd64_linux_record_signal (struct gdbarch *gdbarch,
                            struct regcache *regcache,
-                           enum target_signal signal)
+                           enum gdb_signal signal)
 {
   ULONGEST rsp;
 
   if (amd64_all_but_ip_registers_record (regcache))
     return -1;
 
-  if (record_arch_list_add_reg (regcache, AMD64_RIP_REGNUM))
+  if (record_full_arch_list_add_reg (regcache, AMD64_RIP_REGNUM))
     return -1;
 
   /* Record the change in the stack.  */
@@ -1251,12 +1270,12 @@ amd64_linux_record_signal (struct gdbarch *gdbarch,
   /* This is for frame_size.
      sp -= sizeof (struct rt_sigframe);  */
   rsp -= AMD64_LINUX_frame_size;
-  if (record_arch_list_add_mem (rsp, AMD64_LINUX_redzone
+  if (record_full_arch_list_add_mem (rsp, AMD64_LINUX_redzone
                                      + AMD64_LINUX_xstate
                                      + AMD64_LINUX_frame_size))
     return -1;
 
-  if (record_arch_list_add_end ())
+  if (record_full_arch_list_add_end ())
     return -1;
 
   return 0;
@@ -1270,49 +1289,34 @@ amd64_linux_core_read_description (struct gdbarch *gdbarch,
                                  bfd *abfd)
 {
   /* Linux/x86-64.  */
-  uint64_t xcr0 = i386_linux_core_read_xcr0 (gdbarch, target, abfd);
-  switch ((xcr0 & I386_XSTATE_AVX_MASK))
+  uint64_t xcr0 = i386_linux_core_read_xcr0 (abfd);
+
+  switch (xcr0 & I386_XSTATE_ALL_MASK)
     {
+    case I386_XSTATE_MPX_MASK:
+      if (gdbarch_ptr_bit (gdbarch) == 32)
+       return tdesc_x32_avx_linux;  /* No x32 MPX falling back to AVX.  */
+      else
+       return tdesc_amd64_mpx_linux;
     case I386_XSTATE_AVX_MASK:
-      return tdesc_amd64_avx_linux;
+      if (gdbarch_ptr_bit (gdbarch) == 32)
+       return tdesc_x32_avx_linux;
+      else
+       return tdesc_amd64_avx_linux;
     default:
-      return tdesc_amd64_linux;
+      if (gdbarch_ptr_bit (gdbarch) == 32)
+       return tdesc_x32_linux;
+      else
+       return tdesc_amd64_linux;
     }
 }
 
 static void
-amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  const struct target_desc *tdesc = info.target_desc;
-  struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
-  const struct tdesc_feature *feature;
-  int valid_p;
-
-  gdb_assert (tdesc_data);
 
-  tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset;
-  tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset);
-  tdep->sizeof_gregset = 27 * 8;
-
-  amd64_init_abi (info, gdbarch);
-
-  /* Reserve a number for orig_rax.  */
-  set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS);
-
-  if (! tdesc_has_registers (tdesc))
-    tdesc = tdesc_amd64_linux;
-  tdep->tdesc = tdesc;
-
-  feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux");
-  if (feature == NULL)
-    return;
-
-  valid_p = tdesc_numbered_register (feature, tdesc_data,
-                                    AMD64_LINUX_ORIG_RAX_REGNUM,
-                                    "orig_rax");
-  if (!valid_p)
-    return;
+  linux_init_abi (info, gdbarch);
 
   tdep->sigtramp_p = amd64_linux_sigtramp_p;
   tdep->sigcontext_addr = amd64_linux_sigcontext_addr;
@@ -1321,10 +1325,6 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   tdep->xsave_xcr0_offset = I386_LINUX_XSAVE_XCR0_OFFSET;
 
-  /* GNU/Linux uses SVR4-style shared libraries.  */
-  set_solib_svr4_fetch_link_map_offsets
-    (gdbarch, svr4_lp64_fetch_link_map_offsets);
-
   /* Add the %orig_rax register used for syscall restarting.  */
   set_gdbarch_write_pc (gdbarch, amd64_linux_write_pc);
 
@@ -1342,6 +1342,9 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* GNU/Linux uses SVR4-style shared libraries.  */
   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
 
+  /* GNU/Linux uses the dynamic linker included in the GNU C Library.  */
+  set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
+
   /* Install supported register note sections.  */
   set_gdbarch_core_regset_sections (gdbarch, amd64_linux_regset_sections);
 
@@ -1531,6 +1534,88 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   tdep->i386_syscall_record = amd64_linux_syscall_record;
 }
+
+static void
+amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const struct target_desc *tdesc = info.target_desc;
+  struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
+  const struct tdesc_feature *feature;
+  int valid_p;
+
+  gdb_assert (tdesc_data);
+
+  tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset;
+  tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset);
+  tdep->sizeof_gregset = 27 * 8;
+
+  amd64_init_abi (info, gdbarch);
+
+  /* Reserve a number for orig_rax.  */
+  set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS);
+
+  if (! tdesc_has_registers (tdesc))
+    tdesc = tdesc_amd64_linux;
+  tdep->tdesc = tdesc;
+
+  feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux");
+  if (feature == NULL)
+    return;
+
+  valid_p = tdesc_numbered_register (feature, tdesc_data,
+                                    AMD64_LINUX_ORIG_RAX_REGNUM,
+                                    "orig_rax");
+  if (!valid_p)
+    return;
+
+  amd64_linux_init_abi_common (info, gdbarch);
+
+  /* GNU/Linux uses SVR4-style shared libraries.  */
+  set_solib_svr4_fetch_link_map_offsets
+    (gdbarch, svr4_lp64_fetch_link_map_offsets);
+}
+
+static void
+amd64_x32_linux_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  const struct target_desc *tdesc = info.target_desc;
+  struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
+  const struct tdesc_feature *feature;
+  int valid_p;
+
+  gdb_assert (tdesc_data);
+
+  tdep->gregset_reg_offset = amd64_linux_gregset_reg_offset;
+  tdep->gregset_num_regs = ARRAY_SIZE (amd64_linux_gregset_reg_offset);
+  tdep->sizeof_gregset = 27 * 8;
+
+  amd64_x32_init_abi (info, gdbarch);
+
+  /* Reserve a number for orig_rax.  */
+  set_gdbarch_num_regs (gdbarch, AMD64_LINUX_NUM_REGS);
+
+  if (! tdesc_has_registers (tdesc))
+    tdesc = tdesc_x32_linux;
+  tdep->tdesc = tdesc;
+
+  feature = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.linux");
+  if (feature == NULL)
+    return;
+
+  valid_p = tdesc_numbered_register (feature, tdesc_data,
+                                    AMD64_LINUX_ORIG_RAX_REGNUM,
+                                    "orig_rax");
+  if (!valid_p)
+    return;
+
+  amd64_linux_init_abi_common (info, gdbarch);
+
+  /* GNU/Linux uses SVR4-style shared libraries.  */
+  set_solib_svr4_fetch_link_map_offsets
+    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+}
 \f
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
@@ -1541,8 +1626,13 @@ _initialize_amd64_linux_tdep (void)
 {
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
                          GDB_OSABI_LINUX, amd64_linux_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x64_32,
+                         GDB_OSABI_LINUX, amd64_x32_linux_init_abi);
 
-  /* Initialize the Linux target description  */
+  /* Initialize the Linux target description.  */
   initialize_tdesc_amd64_linux ();
   initialize_tdesc_amd64_avx_linux ();
+  initialize_tdesc_amd64_mpx_linux ();
+  initialize_tdesc_x32_linux ();
+  initialize_tdesc_x32_avx_linux ();
 }
This page took 0.032264 seconds and 4 git commands to generate.