Fix aarch64-freebsd build failure
[deliverable/binutils-gdb.git] / gdb / amd64-tdep.c
index a661b8831b4fecf11af5a0b5de699e1901c084ee..f1e2078ef5560cf602cacda12496505c108c9c6a 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 "disasm.h"
 #include "amd64-tdep.h"
 #include "i387-tdep.h"
-
-#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/x32.c"
-#include "features/i386/x32-avx.c"
-#include "features/i386/x32-avx512.c"
-
+#include "x86-xstate.h"
+#include <algorithm>
+#include "target-descriptions.h"
+#include "arch/amd64.h"
 #include "ax.h"
 #include "ax-gdb.h"
 
@@ -153,6 +147,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.  */
 
@@ -251,9 +249,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);
 
@@ -352,7 +348,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;
@@ -413,7 +409,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))
@@ -456,6 +452,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.  */
@@ -508,7 +533,7 @@ amd64_merge_classes (enum amd64_reg_class class1, enum amd64_reg_class class2)
   return AMD64_SSE;
 }
 
-static void amd64_classify (struct type *type, enum amd64_reg_class class[2]);
+static void amd64_classify (struct type *type, enum amd64_reg_class theclass[2]);
 
 /* Return non-zero if TYPE is a non-POD structure or union type.  */
 
@@ -527,19 +552,19 @@ amd64_non_pod_p (struct type *type)
    arrays) and union types, and store the result in CLASS.  */
 
 static void
-amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2])
+amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2])
 {
   /* 1. If the size of an object is larger than two eightbytes, or in
         C++, is a non-POD structure or union type, or contains
         unaligned fields, it has class memory.  */
   if (TYPE_LENGTH (type) > 16 || amd64_non_pod_p (type))
     {
-      class[0] = class[1] = AMD64_MEMORY;
+      theclass[0] = theclass[1] = AMD64_MEMORY;
       return;
     }
 
   /* 2. Both eightbytes get initialized to class NO_CLASS.  */
-  class[0] = class[1] = AMD64_NO_CLASS;
+  theclass[0] = theclass[1] = AMD64_NO_CLASS;
 
   /* 3. Each field of an object is classified recursively so that
         always two fields are considered. The resulting class is
@@ -551,9 +576,9 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2])
       struct type *subtype = check_typedef (TYPE_TARGET_TYPE (type));
 
       /* All fields in an array have the same type.  */
-      amd64_classify (subtype, class);
-      if (TYPE_LENGTH (type) > 8 && class[1] == AMD64_NO_CLASS)
-       class[1] = class[0];
+      amd64_classify (subtype, theclass);
+      if (TYPE_LENGTH (type) > 8 && theclass[1] == AMD64_NO_CLASS)
+       theclass[1] = theclass[0];
     }
   else
     {
@@ -582,7 +607,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2])
          gdb_assert (pos == 0 || pos == 1);
 
          amd64_classify (subtype, subclass);
-         class[pos] = amd64_merge_classes (class[pos], subclass[0]);
+         theclass[pos] = amd64_merge_classes (theclass[pos], subclass[0]);
          if (bitsize <= 64 && pos == 0 && endpos == 1)
            /* This is a bit of an odd case:  We have a field that would
               normally fit in one of the two eightbytes, except that
@@ -606,9 +631,9 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2])
               use up all 16 bytes of the aggregate, and are already
               handled just fine (because each portion sits on its own
               8-byte).  */
-           class[1] = amd64_merge_classes (class[1], subclass[0]);
+           theclass[1] = amd64_merge_classes (theclass[1], subclass[0]);
          if (pos == 0)
-           class[1] = amd64_merge_classes (class[1], subclass[1]);
+           theclass[1] = amd64_merge_classes (theclass[1], subclass[1]);
        }
     }
 
@@ -616,26 +641,26 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2])
 
   /* Rule (a): If one of the classes is MEMORY, the whole argument is
      passed in memory.  */
-  if (class[0] == AMD64_MEMORY || class[1] == AMD64_MEMORY)
-    class[0] = class[1] = AMD64_MEMORY;
+  if (theclass[0] == AMD64_MEMORY || theclass[1] == AMD64_MEMORY)
+    theclass[0] = theclass[1] = AMD64_MEMORY;
 
   /* Rule (b): If SSEUP is not preceded by SSE, it is converted to
      SSE.  */
-  if (class[0] == AMD64_SSEUP)
-    class[0] = AMD64_SSE;
-  if (class[1] == AMD64_SSEUP && class[0] != AMD64_SSE)
-    class[1] = AMD64_SSE;
+  if (theclass[0] == AMD64_SSEUP)
+    theclass[0] = AMD64_SSE;
+  if (theclass[1] == AMD64_SSEUP && theclass[0] != AMD64_SSE)
+    theclass[1] = AMD64_SSE;
 }
 
 /* Classify TYPE, and store the result in CLASS.  */
 
 static void
-amd64_classify (struct type *type, enum amd64_reg_class class[2])
+amd64_classify (struct type *type, enum amd64_reg_class theclass[2])
 {
   enum type_code code = TYPE_CODE (type);
   int len = TYPE_LENGTH (type);
 
-  class[0] = class[1] = AMD64_NO_CLASS;
+  theclass[0] = theclass[1] = AMD64_NO_CLASS;
 
   /* Arguments of types (signed and unsigned) _Bool, char, short, int,
      long, long long, and pointers are in the INTEGER class.  Similarly,
@@ -644,30 +669,30 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2])
   if ((code == TYPE_CODE_INT || code == TYPE_CODE_ENUM
        || code == TYPE_CODE_BOOL || code == TYPE_CODE_RANGE
        || code == TYPE_CODE_CHAR
-       || code == TYPE_CODE_PTR || code == TYPE_CODE_REF)
+       || code == TYPE_CODE_PTR || TYPE_IS_REFERENCE (type))
       && (len == 1 || len == 2 || len == 4 || len == 8))
-    class[0] = AMD64_INTEGER;
+    theclass[0] = AMD64_INTEGER;
 
   /* Arguments of types float, double, _Decimal32, _Decimal64 and __m64
      are in class SSE.  */
   else if ((code == TYPE_CODE_FLT || code == TYPE_CODE_DECFLOAT)
           && (len == 4 || len == 8))
     /* FIXME: __m64 .  */
-    class[0] = AMD64_SSE;
+    theclass[0] = AMD64_SSE;
 
   /* Arguments of types __float128, _Decimal128 and __m128 are split into
      two halves.  The least significant ones belong to class SSE, the most
      significant one to class SSEUP.  */
   else if (code == TYPE_CODE_DECFLOAT && len == 16)
     /* FIXME: __float128, __m128.  */
-    class[0] = AMD64_SSE, class[1] = AMD64_SSEUP;
+    theclass[0] = AMD64_SSE, theclass[1] = AMD64_SSEUP;
 
   /* The 64-bit mantissa of arguments of type long double belongs to
      class X87, the 16-bit exponent plus 6 bytes of padding belongs to
      class X87UP.  */
   else if (code == TYPE_CODE_FLT && len == 16)
     /* Class X87 and X87UP.  */
-    class[0] = AMD64_X87, class[1] = AMD64_X87UP;
+    theclass[0] = AMD64_X87, theclass[1] = AMD64_X87UP;
 
   /* Arguments of complex T where T is one of the types float or
      double get treated as if they are implemented as:
@@ -679,19 +704,19 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2])
 
   */
   else if (code == TYPE_CODE_COMPLEX && len == 8)
-    class[0] = AMD64_SSE;
+    theclass[0] = AMD64_SSE;
   else if (code == TYPE_CODE_COMPLEX && len == 16)
-    class[0] = class[1] = AMD64_SSE;
+    theclass[0] = theclass[1] = AMD64_SSE;
 
   /* A variable of type complex long double is classified as type
      COMPLEX_X87.  */
   else if (code == TYPE_CODE_COMPLEX && len == 32)
-    class[0] = AMD64_COMPLEX_X87;
+    theclass[0] = AMD64_COMPLEX_X87;
 
   /* Aggregates.  */
   else if (code == TYPE_CODE_ARRAY || code == TYPE_CODE_STRUCT
           || code == TYPE_CODE_UNION)
-    amd64_classify_aggregate (type, class);
+    amd64_classify_aggregate (type, theclass);
 }
 
 static enum return_value_convention
@@ -699,7 +724,7 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
                    struct type *type, struct regcache *regcache,
                    gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  enum amd64_reg_class class[2];
+  enum amd64_reg_class theclass[2];
   int len = TYPE_LENGTH (type);
   static int integer_regnum[] = { AMD64_RAX_REGNUM, AMD64_RDX_REGNUM };
   static int sse_regnum[] = { AMD64_XMM0_REGNUM, AMD64_XMM1_REGNUM };
@@ -710,7 +735,7 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
   gdb_assert (!(readbuf && writebuf));
 
   /* 1. Classify the return type with the classification algorithm.  */
-  amd64_classify (type, class);
+  amd64_classify (type, theclass);
 
   /* 2. If the type has class MEMORY, then the caller provides space
      for the return value and passes the address of this storage in
@@ -719,7 +744,7 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
 
      On return %rax will contain the address that has been passed in
      by the caller in %rdi.  */
-  if (class[0] == AMD64_MEMORY)
+  if (theclass[0] == AMD64_MEMORY)
     {
       /* As indicated by the comment above, the ABI guarantees that we
          can always find the return value just after the function has
@@ -738,7 +763,7 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
 
   /* 8. If the class is COMPLEX_X87, the real part of the value is
         returned in %st0 and the imaginary part in %st1.  */
-  if (class[0] == AMD64_COMPLEX_X87)
+  if (theclass[0] == AMD64_COMPLEX_X87)
     {
       if (readbuf)
        {
@@ -760,7 +785,7 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
 
-  gdb_assert (class[1] != AMD64_MEMORY);
+  gdb_assert (theclass[1] != AMD64_MEMORY);
   gdb_assert (len <= 16);
 
   for (i = 0; len > 0; i++, len -= 8)
@@ -768,7 +793,7 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
       int regnum = -1;
       int offset = 0;
 
-      switch (class[i])
+      switch (theclass[i])
        {
        case AMD64_INTEGER:
          /* 3. If the class is INTEGER, the next available register
@@ -801,7 +826,7 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
        case AMD64_X87UP:
          /* 7. If the class is X87UP, the value is returned together
              with the previous X87 value in %st0.  */
-         gdb_assert (i > 0 && class[0] == AMD64_X87);
+         gdb_assert (i > 0 && theclass[0] == AMD64_X87);
          regnum = AMD64_ST0_REGNUM;
          offset = 8;
          len = 2;
@@ -817,10 +842,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);
     }
 
@@ -849,7 +874,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
     AMD64_XMM0_REGNUM + 4, AMD64_XMM0_REGNUM + 5,
     AMD64_XMM0_REGNUM + 6, AMD64_XMM0_REGNUM + 7,
   };
-  struct value **stack_args = alloca (nargs * sizeof (struct value *));
+  struct value **stack_args = XALLOCAVEC (struct value *, nargs);
   int num_stack_args = 0;
   int num_elements = 0;
   int element = 0;
@@ -865,21 +890,21 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
     {
       struct type *type = value_type (args[i]);
       int len = TYPE_LENGTH (type);
-      enum amd64_reg_class class[2];
+      enum amd64_reg_class theclass[2];
       int needed_integer_regs = 0;
       int needed_sse_regs = 0;
       int j;
 
       /* Classify argument.  */
-      amd64_classify (type, class);
+      amd64_classify (type, theclass);
 
       /* Calculate the number of integer and SSE registers needed for
          this argument.  */
       for (j = 0; j < 2; j++)
        {
-         if (class[j] == AMD64_INTEGER)
+         if (theclass[j] == AMD64_INTEGER)
            needed_integer_regs++;
-         else if (class[j] == AMD64_SSE)
+         else if (theclass[j] == AMD64_SSE)
            needed_sse_regs++;
        }
 
@@ -906,7 +931,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
              int regnum = -1;
              int offset = 0;
 
-             switch (class[j])
+             switch (theclass[j])
                {
                case AMD64_INTEGER:
                  regnum = integer_regnum[integer_reg++];
@@ -928,7 +953,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);
            }
        }
@@ -969,6 +994,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);
 
@@ -1273,12 +1305,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;
@@ -1287,7 +1317,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;
@@ -1350,8 +1379,9 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch,
   /* Extra space for sentinels so fixup_{riprel,displaced_copy} don't have to
      continually watch for running off the end of the buffer.  */
   int fixup_sentinel_space = len;
-  struct displaced_step_closure *dsc =
-    xmalloc (sizeof (*dsc) + len + fixup_sentinel_space);
+  struct displaced_step_closure *dsc
+    = ((struct displaced_step_closure *)
+       xmalloc (sizeof (*dsc) + len + fixup_sentinel_space));
   gdb_byte *buf = &dsc->insn_buf[0];
   struct amd64_insn *details = &dsc->insn_details;
 
@@ -1513,7 +1543,7 @@ amd64_classify_insn_at (struct gdbarch *gdbarch, CORE_ADDR addr,
   int len, classification;
 
   len = gdbarch_max_insn_length (gdbarch);
-  buf = alloca (len);
+  buf = (gdb_byte *) alloca (len);
 
   read_code (addr, buf, len);
   amd64_get_insn_details (buf, &details);
@@ -1661,7 +1691,7 @@ amd64_displaced_step_fixup (struct gdbarch *gdbarch,
 
       regcache_cooked_read_unsigned (regs, AMD64_RSP_REGNUM, &rsp);
       retaddr = read_memory_unsigned_integer (rsp, retaddr_len, byte_order);
-      retaddr = (retaddr - insn_offset) & 0xffffffffUL;
+      retaddr = (retaddr - insn_offset) & 0xffffffffffffffffULL;
       write_memory_unsigned_integer (rsp, retaddr_len, byte_order, retaddr);
 
       if (debug_displaced)
@@ -1710,7 +1740,7 @@ amd64_relocate_instruction (struct gdbarch *gdbarch,
   int len = gdbarch_max_insn_length (gdbarch);
   /* Extra space for sentinels.  */
   int fixup_sentinel_space = len;
-  gdb_byte *buf = xmalloc (len + fixup_sentinel_space);
+  gdb_byte *buf = (gdb_byte *) xmalloc (len + fixup_sentinel_space);
   struct amd64_insn insn_details;
   int offset = 0;
   LONGEST rel32, newrel;
@@ -1737,15 +1767,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;
@@ -2008,7 +2070,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.  */
@@ -2190,7 +2252,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
@@ -2378,9 +2440,8 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
       if (post_prologue_pc
          && (cust != NULL
              && COMPUNIT_PRODUCER (cust) != NULL
-             && strncmp (COMPUNIT_PRODUCER (cust), "clang ",
-                         sizeof ("clang ") - 1) == 0))
-        return max (start_pc, post_prologue_pc);
+             && startswith (COMPUNIT_PRODUCER (cust), "clang ")))
+        return std::max (start_pc, post_prologue_pc);
     }
 
   amd64_init_frame_cache (&cache);
@@ -2467,21 +2528,24 @@ amd64_frame_cache_1 (struct frame_info *this_frame,
 static struct amd64_frame_cache *
 amd64_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
-  volatile struct gdb_exception ex;
   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;
 
-  TRY_CATCH (ex, RETURN_MASK_ERROR)
+  TRY
     {
       amd64_frame_cache_1 (this_frame, cache);
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
-    throw_exception (ex);
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (ex.error != NOT_AVAILABLE_ERROR)
+       throw_exception (ex);
+    }
+  END_CATCH
 
   return cache;
 }
@@ -2580,18 +2644,17 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  volatile struct gdb_exception ex;
   struct amd64_frame_cache *cache;
   CORE_ADDR addr;
   gdb_byte buf[8];
   int i;
 
   if (*this_cache)
-    return *this_cache;
+    return (struct amd64_frame_cache *) *this_cache;
 
   cache = amd64_alloc_frame_cache ();
 
-  TRY_CATCH (ex, RETURN_MASK_ERROR)
+  TRY
     {
       get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
       cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8;
@@ -2605,8 +2668,12 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
 
       cache->base_p = 1;
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
-    throw_exception (ex);
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (ex.error != NOT_AVAILABLE_ERROR)
+       throw_exception (ex);
+    }
+  END_CATCH
 
   *this_cache = cache;
   return cache;
@@ -2713,12 +2780,14 @@ static const struct frame_base amd64_frame_base =
 
 /* Normal frames, but in a function epilogue.  */
 
-/* The epilogue is defined here as the 'ret' instruction, which will
+/* Implement the stack_frame_destroyed_p gdbarch method.
+
+   The epilogue is defined here as the 'ret' instruction, which will
    follow any instruction such as 'leave' or 'pop %ebp' that destroys
    the function's stack frame.  */
 
 static int
-amd64_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+amd64_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   gdb_byte insn;
   struct compunit_symtab *cust;
@@ -2742,8 +2811,8 @@ amd64_epilogue_frame_sniffer (const struct frame_unwind *self,
                              void **this_prologue_cache)
 {
   if (frame_relative_level (this_frame) == 0)
-    return amd64_in_function_epilogue_p (get_frame_arch (this_frame),
-                                        get_frame_pc (this_frame));
+    return amd64_stack_frame_destroyed_p (get_frame_arch (this_frame),
+                                         get_frame_pc (this_frame));
   else
     return 0;
 }
@@ -2753,17 +2822,16 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  volatile struct gdb_exception ex;
   struct amd64_frame_cache *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;
 
-  TRY_CATCH (ex, RETURN_MASK_ERROR)
+  TRY
     {
       /* Cache base will be %esp plus cache->sp_offset (-8).  */
       get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
@@ -2781,8 +2849,12 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
 
       cache->base_p = 1;
     }
-  if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
-    throw_exception (ex);
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (ex.error != NOT_AVAILABLE_ERROR)
+       throw_exception (ex);
+    }
+  END_CATCH
 
   return cache;
 }
@@ -2923,7 +2995,8 @@ static const int amd64_record_regmap[] =
 };
 
 void
-amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
+               const target_desc *default_tdesc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   const struct target_desc *tdesc = info.target_desc;
@@ -2940,7 +3013,7 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->fpregset = &amd64_fpregset;
 
   if (! tdesc_has_registers (tdesc))
-    tdesc = tdesc_amd64;
+    tdesc = default_tdesc;
   tdep->tdesc = tdesc;
 
   tdep->num_core_regs = AMD64_NUM_GREGS + I387_NUM_REGS;
@@ -2977,6 +3050,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;
@@ -2987,6 +3080,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);
 
@@ -3092,16 +3187,12 @@ amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 }
 
 void
-amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
+                   const target_desc *default_tdesc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  const struct target_desc *tdesc = info.target_desc;
-
-  amd64_init_abi (info, gdbarch);
 
-  if (! tdesc_has_registers (tdesc))
-    tdesc = tdesc_x32;
-  tdep->tdesc = tdesc;
+  amd64_init_abi (info, gdbarch, default_tdesc);
 
   tdep->num_dword_regs = 17;
   set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type);
@@ -3110,20 +3201,51 @@ amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_ptr_bit (gdbarch, 32);
 }
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-void _initialize_amd64_tdep (void);
+/* Return the target description for a specified XSAVE feature mask.  */
+
+const struct target_desc *
+amd64_target_description (uint64_t xcr0)
+{
+  static target_desc *amd64_tdescs \
+    [2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/] = {};
+  target_desc **tdesc;
+
+  tdesc = &amd64_tdescs[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
+    [(xcr0 & X86_XSTATE_MPX) ? 1 : 0]
+    [(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
+    [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0];
+
+  if (*tdesc == NULL)
+    *tdesc = amd64_create_target_description (xcr0, false, false);
+
+  return *tdesc;
+}
 
 void
 _initialize_amd64_tdep (void)
 {
-  initialize_tdesc_amd64 ();
-  initialize_tdesc_amd64_avx ();
-  initialize_tdesc_amd64_mpx ();
-  initialize_tdesc_amd64_avx512 ();
+#if GDB_SELF_TEST
+  struct
+  {
+    const char *xml;
+    uint64_t mask;
+  } xml_masks[] = {
+    { "i386/amd64.xml", X86_XSTATE_SSE_MASK },
+    { "i386/amd64-avx.xml", X86_XSTATE_AVX_MASK },
+    { "i386/amd64-mpx.xml", X86_XSTATE_MPX_MASK },
+    { "i386/amd64-avx-mpx.xml", X86_XSTATE_AVX_MPX_MASK },
+    { "i386/amd64-avx-avx512.xml", X86_XSTATE_AVX_AVX512_MASK },
+    { "i386/amd64-avx-mpx-avx512-pku.xml",
+      X86_XSTATE_AVX_MPX_AVX512_PKU_MASK },
+  };
 
-  initialize_tdesc_x32 ();
-  initialize_tdesc_x32_avx ();
-  initialize_tdesc_x32_avx512 ();
+  for (auto &a : xml_masks)
+    {
+      auto tdesc = amd64_target_description (a.mask);
+
+      selftests::record_xml_tdesc (a.xml, tdesc);
+    }
+#endif /* GDB_SELF_TEST */
 }
 \f
 
@@ -3151,7 +3273,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);
@@ -3174,7 +3296,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),
@@ -3196,7 +3318,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);
 
@@ -3217,7 +3339,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.063838 seconds and 4 git commands to generate.