Rename target descriptions to reflect actual content of description.
[deliverable/binutils-gdb.git] / gdb / amd64-tdep.c
index f0720c8c249b54bae969acf7a3abd5a117da6ce6..863f67cf7d2463f5b0225dd1293d550d65a5bd16 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-mpx-avx512.c"
 
 #include "features/i386/x32.c"
 #include "features/i386/x32-avx.c"
-#include "features/i386/x32-avx512.c"
+#include "features/i386/x32-avx-mpx-avx512.c"
 
 #include "ax.h"
 #include "ax-gdb.h"
@@ -252,9 +254,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 +353,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 +414,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 +457,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 +847,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 +958,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);
            }
        }
@@ -1274,12 +1303,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 +1315,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 +1765,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 +2068,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 +2250,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 +2439,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);
@@ -2989,6 +3047,19 @@ 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");
+    }
+
   tdep->num_byte_regs = 20;
   tdep->num_word_regs = 16;
   tdep->num_dword_regs = 16;
@@ -2999,6 +3070,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 +3202,13 @@ 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_MASK:
+    case X86_XSTATE_AVX_AVX512_MASK:
+      return tdesc_amd64_avx_mpx_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 +3225,12 @@ _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_mpx_avx512 ();
 
   initialize_tdesc_x32 ();
   initialize_tdesc_x32_avx ();
-  initialize_tdesc_x32_avx512 ();
+  initialize_tdesc_x32_avx_mpx_avx512 ();
 }
 \f
 
This page took 0.028043 seconds and 4 git commands to generate.