gdbserver: Use pattern rule for objects from target/
[deliverable/binutils-gdb.git] / gdb / amd64-tdep.c
index a2179ce74b16b5811cfce4e4ae50676d8b34a1bd..98710fedc74534041ed9bcbca1b54c45e50aca94 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for AMD64.
 
-   Copyright (C) 2001-2015 Free Software Foundation, Inc.
+   Copyright (C) 2001-2017 Free Software Foundation, Inc.
 
    Contributed by Jiri Smid, SuSE Labs.
 
 #include "amd64-tdep.h"
 #include "i387-tdep.h"
 #include "x86-xstate.h"
+#include <algorithm>
 
 #include "features/i386/amd64.c"
 #include "features/i386/amd64-avx.c"
 #include "features/i386/amd64-mpx.c"
-#include "features/i386/amd64-avx512.c"
+#include "features/i386/amd64-avx-mpx.c"
+#include "features/i386/amd64-avx-avx512.c"
+#include "features/i386/amd64-avx-mpx-avx512-pku.c"
 
 #include "features/i386/x32.c"
 #include "features/i386/x32-avx.c"
-#include "features/i386/x32-avx512.c"
+#include "features/i386/x32-avx-avx512.c"
 
 #include "ax.h"
 #include "ax-gdb.h"
@@ -154,6 +157,10 @@ static const char *amd64_xmm_avx512_names[] = {
     "xmm28",  "xmm29",  "xmm30",  "xmm31"
 };
 
+static const char *amd64_pkeys_names[] = {
+    "pkru"
+};
+
 /* DWARF Register Number Mapping as defined in the System V psABI,
    section 3.6.  */
 
@@ -252,9 +259,7 @@ amd64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
   if (reg >= 0 && reg < amd64_dwarf_regmap_len)
     regnum = amd64_dwarf_regmap[reg];
 
-  if (regnum == -1)
-    warning (_("Unmapped DWARF Register #%d encountered."), reg);
-  else if (ymm0_regnum >= 0
+  if (ymm0_regnum >= 0
           && i386_xmm_regnum_p (gdbarch, regnum))
     regnum += ymm0_regnum - I387_XMM0_REGNUM (tdep);
 
@@ -353,7 +358,7 @@ amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
                                  struct regcache *regcache,
                                  int regnum)
 {
-  gdb_byte raw_buf[MAX_REGISTER_SIZE];
+  gdb_byte *raw_buf = (gdb_byte *) alloca (register_size (gdbarch, regnum));
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum register_status status;
   struct value *result_value;
@@ -414,7 +419,7 @@ amd64_pseudo_register_write (struct gdbarch *gdbarch,
                             struct regcache *regcache,
                             int regnum, const gdb_byte *buf)
 {
-  gdb_byte raw_buf[MAX_REGISTER_SIZE];
+  gdb_byte *raw_buf = (gdb_byte *) alloca (register_size (gdbarch, regnum));
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (i386_byte_regnum_p (gdbarch, regnum))
@@ -457,6 +462,35 @@ amd64_pseudo_register_write (struct gdbarch *gdbarch,
     i386_pseudo_register_write (gdbarch, regcache, regnum, buf);
 }
 
+/* Implement the 'ax_pseudo_register_collect' gdbarch method.  */
+
+static int
+amd64_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+                                 struct agent_expr *ax, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (i386_byte_regnum_p (gdbarch, regnum))
+    {
+      int gpnum = regnum - tdep->al_regnum;
+
+      if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS)
+       ax_reg_mask (ax, gpnum - AMD64_NUM_LOWER_BYTE_REGS);
+      else
+       ax_reg_mask (ax, gpnum);
+      return 0;
+    }
+  else if (i386_dword_regnum_p (gdbarch, regnum))
+    {
+      int gpnum = regnum - tdep->eax_regnum;
+
+      ax_reg_mask (ax, gpnum);
+      return 0;
+    }
+  else
+    return i386_ax_pseudo_register_collect (gdbarch, ax, regnum);
+}
+
 \f
 
 /* Register classes as defined in the psABI.  */
@@ -818,10 +852,10 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
       gdb_assert (regnum != -1);
 
       if (readbuf)
-       regcache_raw_read_part (regcache, regnum, offset, min (len, 8),
+       regcache_raw_read_part (regcache, regnum, offset, std::min (len, 8),
                                readbuf + i * 8);
       if (writebuf)
-       regcache_raw_write_part (regcache, regnum, offset, min (len, 8),
+       regcache_raw_write_part (regcache, regnum, offset, std::min (len, 8),
                                 writebuf + i * 8);
     }
 
@@ -929,7 +963,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
 
              gdb_assert (regnum != -1);
              memset (buf, 0, sizeof buf);
-             memcpy (buf, valbuf + j * 8, min (len, 8));
+             memcpy (buf, valbuf + j * 8, std::min (len, 8));
              regcache_raw_write_part (regcache, regnum, offset, 8, buf);
            }
        }
@@ -970,6 +1004,13 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte buf[8];
 
+  /* BND registers can be in arbitrary values at the moment of the
+     inferior call.  This can cause boundary violations that are not
+     due to a real bug or even desired by the user.  The best to be done
+     is set the BND registers to allow access to the whole memory, INIT
+     state, before pushing the inferior call.   */
+  i387_reset_bnd_regs (gdbarch, regcache);
+
   /* Pass arguments.  */
   sp = amd64_push_arguments (regcache, nargs, args, sp, struct_return);
 
@@ -1274,12 +1315,10 @@ static void
 fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc,
              CORE_ADDR from, CORE_ADDR to, struct regcache *regs)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   const struct amd64_insn *insn_details = &dsc->insn_details;
   int modrm_offset = insn_details->modrm_offset;
   gdb_byte *insn = insn_details->raw_insn + modrm_offset;
   CORE_ADDR rip_base;
-  int32_t disp;
   int insn_length;
   int arch_tmp_regno, tmp_regno;
   ULONGEST orig_value;
@@ -1288,7 +1327,6 @@ fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc,
   ++insn;
 
   /* Compute the rip-relative address. */
-  disp = extract_signed_integer (insn, sizeof (int32_t), byte_order);
   insn_length = gdb_buffered_insn_length (gdbarch, dsc->insn_buf,
                                          dsc->max_len, from);
   rip_base = from + insn_length;
@@ -1739,15 +1777,47 @@ amd64_relocate_instruction (struct gdbarch *gdbarch,
      the user program would return to.  */
   if (insn[0] == 0xe8)
     {
-      gdb_byte push_buf[16];
-      unsigned int ret_addr;
+      gdb_byte push_buf[32];
+      CORE_ADDR ret_addr;
+      int i = 0;
 
       /* Where "ret" in the original code will return to.  */
       ret_addr = oldloc + insn_length;
-      push_buf[0] = 0x68; /* pushq $...  */
-      store_unsigned_integer (&push_buf[1], 4, byte_order, ret_addr);
+
+      /* If pushing an address higher than or equal to 0x80000000,
+        avoid 'pushq', as that sign extends its 32-bit operand, which
+        would be incorrect.  */
+      if (ret_addr <= 0x7fffffff)
+       {
+         push_buf[0] = 0x68; /* pushq $...  */
+         store_unsigned_integer (&push_buf[1], 4, byte_order, ret_addr);
+         i = 5;
+       }
+      else
+       {
+         push_buf[i++] = 0x48; /* sub    $0x8,%rsp */
+         push_buf[i++] = 0x83;
+         push_buf[i++] = 0xec;
+         push_buf[i++] = 0x08;
+
+         push_buf[i++] = 0xc7; /* movl    $imm,(%rsp) */
+         push_buf[i++] = 0x04;
+         push_buf[i++] = 0x24;
+         store_unsigned_integer (&push_buf[i], 4, byte_order,
+                                 ret_addr & 0xffffffff);
+         i += 4;
+
+         push_buf[i++] = 0xc7; /* movl    $imm,4(%rsp) */
+         push_buf[i++] = 0x44;
+         push_buf[i++] = 0x24;
+         push_buf[i++] = 0x04;
+         store_unsigned_integer (&push_buf[i], 4, byte_order,
+                                 ret_addr >> 32);
+         i += 4;
+       }
+      gdb_assert (i <= sizeof (push_buf));
       /* Push the push.  */
-      append_insns (to, 5, push_buf);
+      append_insns (to, i, push_buf);
 
       /* Convert the relative call to a relative jump.  */
       insn[0] = 0xe9;
@@ -2010,7 +2080,7 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
   if (current_pc > pc + offset_and)
     cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg);
 
-  return min (pc + offset + 2, current_pc);
+  return std::min (pc + offset + 2, current_pc);
 }
 
 /* Similar to amd64_analyze_stack_align for x32.  */
@@ -2192,7 +2262,7 @@ amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
   if (current_pc > pc + offset_and)
     cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg);
 
-  return min (pc + offset + 2, current_pc);
+  return std::min (pc + offset + 2, current_pc);
 }
 
 /* Do a limited analysis of the prologue at PC and update CACHE
@@ -2381,7 +2451,7 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
          && (cust != NULL
              && COMPUNIT_PRODUCER (cust) != NULL
              && startswith (COMPUNIT_PRODUCER (cust), "clang ")))
-        return max (start_pc, post_prologue_pc);
+        return std::max (start_pc, post_prologue_pc);
     }
 
   amd64_init_frame_cache (&cache);
@@ -2471,7 +2541,7 @@ amd64_frame_cache (struct frame_info *this_frame, void **this_cache)
   struct amd64_frame_cache *cache;
 
   if (*this_cache)
-    return *this_cache;
+    return (struct amd64_frame_cache *) *this_cache;
 
   cache = amd64_alloc_frame_cache ();
   *this_cache = cache;
@@ -2590,7 +2660,7 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
   int i;
 
   if (*this_cache)
-    return *this_cache;
+    return (struct amd64_frame_cache *) *this_cache;
 
   cache = amd64_alloc_frame_cache ();
 
@@ -2766,7 +2836,7 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
   gdb_byte buf[8];
 
   if (*this_cache)
-    return *this_cache;
+    return (struct amd64_frame_cache *) *this_cache;
 
   cache = amd64_alloc_frame_cache ();
   *this_cache = cache;
@@ -2989,6 +3059,26 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
       tdep->bnd0r_regnum = AMD64_BND0R_REGNUM;
     }
 
+  if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments") != NULL)
+    {
+      const struct tdesc_feature *feature =
+         tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments");
+      struct tdesc_arch_data *tdesc_data_segments =
+         (struct tdesc_arch_data *) info.tdep_info;
+
+      tdesc_numbered_register (feature, tdesc_data_segments,
+                      AMD64_FSBASE_REGNUM, "fs_base");
+      tdesc_numbered_register (feature, tdesc_data_segments,
+                      AMD64_GSBASE_REGNUM, "gs_base");
+    }
+
+  if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys") != NULL)
+    {
+      tdep->pkeys_register_names = amd64_pkeys_names;
+      tdep->pkru_regnum = AMD64_PKRU_REGNUM;
+      tdep->num_pkeys_regs = 1;
+    }
+
   tdep->num_byte_regs = 20;
   tdep->num_word_regs = 16;
   tdep->num_dword_regs = 16;
@@ -2999,6 +3089,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
                                          amd64_pseudo_register_read_value);
   set_gdbarch_pseudo_register_write (gdbarch,
                                     amd64_pseudo_register_write);
+  set_gdbarch_ax_pseudo_register_collect (gdbarch,
+                                         amd64_ax_pseudo_register_collect);
 
   set_tdesc_pseudo_register_name (gdbarch, amd64_pseudo_register_name);
 
@@ -3129,11 +3221,14 @@ amd64_target_description (uint64_t xcr0)
 {
   switch (xcr0 & X86_XSTATE_ALL_MASK)
     {
-    case X86_XSTATE_MPX_AVX512_MASK:
-    case X86_XSTATE_AVX512_MASK:
-      return tdesc_amd64_avx512;
+    case X86_XSTATE_AVX_MPX_AVX512_PKU_MASK:
+      return tdesc_amd64_avx_mpx_avx512_pku;
+    case X86_XSTATE_AVX_AVX512_MASK:
+      return tdesc_amd64_avx_avx512;
     case X86_XSTATE_MPX_MASK:
       return tdesc_amd64_mpx;
+    case X86_XSTATE_AVX_MPX_MASK:
+      return tdesc_amd64_avx_mpx;
     case X86_XSTATE_AVX_MASK:
       return tdesc_amd64_avx;
     default:
@@ -3150,11 +3245,13 @@ _initialize_amd64_tdep (void)
   initialize_tdesc_amd64 ();
   initialize_tdesc_amd64_avx ();
   initialize_tdesc_amd64_mpx ();
-  initialize_tdesc_amd64_avx512 ();
+  initialize_tdesc_amd64_avx_mpx ();
+  initialize_tdesc_amd64_avx_avx512 ();
+  initialize_tdesc_amd64_avx_mpx_avx512_pku ();
 
   initialize_tdesc_x32 ();
   initialize_tdesc_x32_avx ();
-  initialize_tdesc_x32_avx512 ();
+  initialize_tdesc_x32_avx_avx512 ();
 }
 \f
 
@@ -3182,7 +3279,7 @@ amd64_supply_fxsave (struct regcache *regcache, int regnum,
   if (fxsave
       && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
-      const gdb_byte *regs = fxsave;
+      const gdb_byte *regs = (const gdb_byte *) fxsave;
 
       if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
        regcache_raw_supply (regcache, I387_FISEG_REGNUM (tdep), regs + 12);
@@ -3205,7 +3302,7 @@ amd64_supply_xsave (struct regcache *regcache, int regnum,
   if (xsave
       && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
-      const gdb_byte *regs = xsave;
+      const gdb_byte *regs = (const gdb_byte *) xsave;
 
       if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
        regcache_raw_supply (regcache, I387_FISEG_REGNUM (tdep),
@@ -3227,7 +3324,7 @@ amd64_collect_fxsave (const struct regcache *regcache, int regnum,
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  gdb_byte *regs = fxsave;
+  gdb_byte *regs = (gdb_byte *) fxsave;
 
   i387_collect_fxsave (regcache, regnum, fxsave);
 
@@ -3248,7 +3345,7 @@ amd64_collect_xsave (const struct regcache *regcache, int regnum,
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  gdb_byte *regs = xsave;
+  gdb_byte *regs = (gdb_byte *) xsave;
 
   i387_collect_xsave (regcache, regnum, xsave, gcore);
 
This page took 0.033383 seconds and 4 git commands to generate.