Add MPX support to gdbserver.
authorWalfred Tedeschi <walfred.tedeschi@intel.com>
Thu, 10 Oct 2013 07:12:49 +0000 (07:12 +0000)
committerWalfred Tedeschi <walfred.tedeschi@intel.com>
Wed, 20 Nov 2013 13:42:52 +0000 (14:42 +0100)
2013-05-22  Walfred Tedeschi  <walfred.tedeschi@intel.com>

gdbserver/
* Makefile.in: Add i386-mpx.c, i386-mpx-linux.c, amd64-mpx.c,
amd64-mpx-linux.c, x32-mpx.c and x32-mpx-linux.c generation.

* configure.srv (srv_i386_regobj): Add i386-mpx.o.
(srv_i386_linux_regobj): Add i386-mpx-linux.o.
(srv_amd64_regobj): Add amd64-mpx.o.
(srv_amd64_linux_regobj): Add amd64-mpx-linux.o.
(srv_i386_32bit_xmlfiles): Add i386/32bit-mpx.xml.
(srv_i386_64bit_xmlfiles): Add i386/64bit-mpx.xml.

* i387-fp.c (num_pl_bnd_register) Added constant.
(num_pl_bnd_cfg_registers) Added constant.
(struct i387_xsave) Added reserved area and MPX fields.
(i387_cache_to_xsave, i387_xsave_to_cache) Add MPX.

* linux-x86-low.c (init_registers_i386_mpx_linux): Declare new
function.
(tdesc_i386_mpx_linux): Add MPX amd64 target.
(init_registers_amd64_mpx_linux): Declare new function.
(tdesc_amd64_mpx_linux): Add MPX amd64 target.
(x86_64_regmap): Add MPX registers.
(x86_linux_read_description): Add MPX case.
(initialize_low_arch): Initialize MPX targets.

Change-Id: I394d81afa76d11375ce792cefad0ceb9825fb379
Signed-off-by: Walfred Tedeschi <walfred.tedeschi@intel.com>
gdb/gdbserver/ChangeLog
gdb/gdbserver/Makefile.in
gdb/gdbserver/configure.srv
gdb/gdbserver/i387-fp.c
gdb/gdbserver/linux-x86-low.c

index ee4aa32..f3fdbb3 100644 (file)
@@ -1,3 +1,26 @@
+2013-11-20  Walfred Tedeschi  <walfred.tedeschi@intel.com>
+
+       * Makefile.in: Add i386-mpx.c, i386-mpx-linux.c, amd64-mpx.c,
+       amd64-mpx-linux.c, x32-mpx.c and x32-mpx-linux.c generation.
+       * configure.srv (srv_i386_regobj): Add i386-mpx.o.
+       (srv_i386_linux_regobj): Add i386-mpx-linux.o.
+       (srv_amd64_regobj): Add amd64-mpx.o.
+       (srv_amd64_linux_regobj): Add amd64-mpx-linux.o.
+       (srv_i386_32bit_xmlfiles): Add i386/32bit-mpx.xml.
+       (srv_i386_64bit_xmlfiles): Add i386/64bit-mpx.xml.
+       * i387-fp.c (num_pl_bnd_register) Added constant.
+       (num_pl_bnd_cfg_registers) Added constant.
+       (struct i387_xsave) Added reserved area and MPX fields.
+       (i387_cache_to_xsave, i387_xsave_to_cache) Add MPX.
+       * linux-x86-low.c (init_registers_i386_mpx_linux): Declare new
+       function.
+       (tdesc_i386_mpx_linux): Add MPX amd64 target.
+       (init_registers_amd64_mpx_linux): Declare new function.
+       (tdesc_amd64_mpx_linux): Add MPX amd64 target.
+       (x86_64_regmap): Add MPX registers.
+       (x86_linux_read_description): Add MPX case.
+       (initialize_low_arch): Initialize MPX targets.
+
 2013-11-18  Tom Tromey  <tromey@redhat.com>
 
        * configure: Rebuild.
index 539a66f..641ea17 100644 (file)
@@ -342,7 +342,9 @@ clean:
        rm -f tic6x-c64xp-linux.c tic6x-c64x-linux.c tic6x-c62x-linux.c
        rm -f xml-builtin.c stamp-xml
        rm -f i386-avx.c i386-avx-linux.c
+       rm -f i386-mpx.c i386-mpx-linux.c
        rm -f amd64-avx.c amd64-avx-linux.c
+       rm -f amd64-mpx.c amd64-mpx-linux.c
        rm -f i386-mmx.c i386-mmx-linux.c
        rm -f x32.c x32-linux.c
        rm -f x32-avx.c x32-avx-linux.c
@@ -568,6 +570,10 @@ i386-avx.c : $(srcdir)/../regformats/i386/i386-avx.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-avx.dat i386-avx.c
 i386-avx-linux.c : $(srcdir)/../regformats/i386/i386-avx-linux.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-avx-linux.dat i386-avx-linux.c
+i386-mpx.c : $(srcdir)/../regformats/i386/i386-mpx.dat $(regdat_sh)
+       $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-mpx.dat i386-mpx.c
+i386-mpx-linux.c : $(srcdir)/../regformats/i386/i386-mpx-linux.dat $(regdat_sh)
+       $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-mpx-linux.dat i386-mpx-linux.c
 i386-mmx.c : $(srcdir)/../regformats/i386/i386-mmx.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/i386-mmx.dat i386-mmx.c
 i386-mmx-linux.c : $(srcdir)/../regformats/i386/i386-mmx-linux.dat $(regdat_sh)
@@ -664,8 +670,12 @@ amd64-linux.c : $(srcdir)/../regformats/i386/amd64-linux.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-linux.dat amd64-linux.c
 amd64-avx.c : $(srcdir)/../regformats/i386/amd64-avx.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-avx.dat amd64-avx.c
+amd64-mpx.c : $(srcdir)/../regformats/i386/amd64-mpx.dat $(regdat_sh)
+       $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-mpx.dat amd64-mpx.c
 amd64-avx-linux.c : $(srcdir)/../regformats/i386/amd64-avx-linux.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-avx-linux.dat amd64-avx-linux.c
+amd64-mpx-linux.c : $(srcdir)/../regformats/i386/amd64-mpx-linux.dat $(regdat_sh)
+       $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/amd64-mpx-linux.dat amd64-mpx-linux.c
 x32.c : $(srcdir)/../regformats/i386/x32.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/i386/x32.dat x32.c
 x32-linux.c : $(srcdir)/../regformats/i386/x32-linux.dat $(regdat_sh)
index f65dd10..32d935a 100644 (file)
 # Default hostio_last_error implementation
 srv_hostio_err_objs="hostio-errno.o"
 
-srv_i386_regobj="i386.o i386-avx.o i386-mmx.o"
-srv_i386_linux_regobj="i386-linux.o i386-avx-linux.o i386-mmx-linux.o"
-srv_amd64_regobj="amd64.o amd64-avx.o x32.o x32-avx.o"
-srv_amd64_linux_regobj="amd64-linux.o amd64-avx-linux.o x32-linux.o x32-avx-linux.o"
+srv_i386_regobj="i386.o i386-avx.o i386-mpx.o i386-mmx.o"
+srv_i386_linux_regobj="i386-linux.o i386-avx-linux.o i386-mpx-linux.o i386-mmx-linux.o"
+srv_amd64_regobj="amd64.o amd64-avx.o amd64-mpx.o x32.o x32-avx.o"
+srv_amd64_linux_regobj="amd64-linux.o amd64-avx-linux.o amd64-mpx-linux.o x32-linux.o x32-avx-linux.o"
 
 ipa_i386_linux_regobj=i386-linux-ipa.o
 ipa_amd64_linux_regobj=amd64-linux-ipa.o
 
-srv_i386_32bit_xmlfiles="i386/32bit-core.xml i386/32bit-sse.xml i386/32bit-avx.xml"
-srv_i386_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-sse.xml i386/64bit-avx.xml i386/x32-core.xml"
-srv_i386_xmlfiles="i386/i386.xml i386/i386-avx.xml i386/i386-mmx.xml $srv_i386_32bit_xmlfiles"
-srv_amd64_xmlfiles="i386/amd64.xml i386/amd64-avx.xml i386/x32.xml i386/x32-avx.xml $srv_i386_64bit_xmlfiles"
-srv_i386_linux_xmlfiles="i386/i386-linux.xml i386/i386-avx-linux.xml i386/i386-mmx-linux.xml i386/32bit-linux.xml $srv_i386_32bit_xmlfiles"
-srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/amd64-avx-linux.xml i386/64bit-linux.xml i386/x32-linux.xml i386/x32-avx-linux.xml $srv_i386_64bit_xmlfiles"
+srv_i386_32bit_xmlfiles="i386/32bit-core.xml i386/32bit-sse.xml i386/32bit-avx.xml i386/32bit-mpx.xml"
+srv_i386_64bit_xmlfiles="i386/64bit-core.xml i386/64bit-sse.xml i386/64bit-avx.xml i386/x32-core.xml i386/64bit-mpx.xml"
+srv_i386_xmlfiles="i386/i386.xml i386/i386-avx.xml i386/i386-mpx.xml i386/i386-mmx.xml $srv_i386_32bit_xmlfiles"
+srv_amd64_xmlfiles="i386/amd64.xml i386/amd64-avx.xml i386/x32.xml i386/x32-avx.xml i386/amd64-mpx.xml $srv_i386_64bit_xmlfiles"
+srv_i386_linux_xmlfiles="i386/i386-linux.xml i386/i386-avx-linux.xml i386/i386-mmx-linux.xml i386/32bit-linux.xml i386/i386-mpx-linux.xml $srv_i386_32bit_xmlfiles"
+srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/amd64-avx-linux.xml i386/64bit-linux.xml i386/amd64-mpx-linux.xml i386/x32-linux.xml i386/x32-avx-linux.xml $srv_i386_64bit_xmlfiles"
 
 
 # Linux object files.  This is so we don't have to repeat
index 2886519..1240b67 100644 (file)
@@ -20,6 +20,9 @@
 #include "i387-fp.h"
 #include "i386-xstate.h"
 
+static const int num_mpx_bnd_registers = 4;
+static const int num_mpx_cfg_registers = 2;
+
 /* Note: These functions preserve the reserved bits in control registers.
    However, gdbserver promptly throws away that information.  */
 
@@ -108,6 +111,15 @@ struct i387_xsave {
 
   /* Space for eight upper 128-bit YMM values, or 16 on x86-64.  */
   unsigned char ymmh_space[256];
+
+  unsigned char reserved4[128];
+
+  /* Space for 4 bound registers values of 128 bits.  */
+  unsigned char mpx_bnd_space[64];
+
+  /* Space for 2 MPX configuration registers of 64 bits
+     plus reserved space.  */
+  unsigned char mpx_cfg_space[16];
 };
 
 void
@@ -271,6 +283,14 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       if ((clear_bv & I386_XSTATE_AVX))
        for (i = 0; i < num_xmm_registers; i++) 
          memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
+
+      if ((clear_bv & I386_XSTATE_BNDREGS))
+       for (i = 0; i < num_mpx_bnd_registers; i++)
+         memset (((char *) &fp->mpx_bnd_space[0]) + i * 16, 0, 16);
+
+      if ((clear_bv & I386_XSTATE_BNDCFG))
+       for (i = 0; i < num_mpx_cfg_registers; i++)
+         memset (((char *) &fp->mpx_cfg_space[0]) + i * 8, 0, 8);
     }
 
   /* Check if any x87 registers are changed.  */
@@ -324,6 +344,40 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
        }
     }
 
+  /* Check if any bound register has changed.  */
+  if ((x86_xcr0 & I386_XSTATE_BNDREGS))
+    {
+     int bnd0r_regnum = find_regno (regcache->tdesc, "bnd0raw");
+
+      for (i = 0; i < num_mpx_bnd_registers; i++)
+       {
+         collect_register (regcache, i + bnd0r_regnum, raw);
+         p = ((char *) &fp->mpx_bnd_space[0]) + i * 16;
+         if (memcmp (raw, p, 16))
+           {
+             xstate_bv |= I386_XSTATE_BNDREGS;
+             memcpy (p, raw, 16);
+           }
+       }
+    }
+
+  /* Check if any status register has changed.  */
+  if ((x86_xcr0 & I386_XSTATE_BNDCFG))
+    {
+      int bndcfg_regnum = find_regno (regcache->tdesc, "bndcfgu");
+
+      for (i = 0; i < num_mpx_cfg_registers; i++)
+       {
+         collect_register (regcache, i + bndcfg_regnum, raw);
+         p = ((char *) &fp->mpx_cfg_space[0]) + i * 8;
+         if (memcmp (raw, p, 8))
+           {
+             xstate_bv |= I386_XSTATE_BNDCFG;
+             memcpy (p, raw, 8);
+           }
+       }
+    }
+
   /* Update the corresponding bits in xstate_bv if any SSE/AVX
      registers are changed.  */
   fp->xstate_bv |= xstate_bv;
@@ -531,6 +585,42 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
        }
     }
 
+  if ((x86_xcr0 & I386_XSTATE_BNDREGS))
+    {
+      int bnd0r_regnum = find_regno (regcache->tdesc, "bnd0raw");
+
+
+      if ((clear_bv & I386_XSTATE_BNDREGS) != 0)
+       {
+         for (i = 0; i < num_mpx_bnd_registers; i++)
+           supply_register_zeroed (regcache, i + bnd0r_regnum);
+       }
+      else
+       {
+         p = (gdb_byte *) &fp->mpx_bnd_space[0];
+         for (i = 0; i < num_mpx_bnd_registers; i++)
+           supply_register (regcache, i + bnd0r_regnum, p + i * 16);
+       }
+
+    }
+
+  if ((x86_xcr0 & I386_XSTATE_BNDCFG))
+    {
+      int bndcfg_regnum = find_regno (regcache->tdesc, "bndcfgu");
+
+      if ((clear_bv & I386_XSTATE_BNDCFG) != 0)
+       {
+         for (i = 0; i < num_mpx_cfg_registers; i++)
+           supply_register_zeroed (regcache, i + bndcfg_regnum);
+       }
+      else
+       {
+         p = (gdb_byte *) &fp->mpx_cfg_space[0];
+         for (i = 0; i < num_mpx_cfg_registers; i++)
+           supply_register (regcache, i + bndcfg_regnum, p + i * 8);
+       }
+    }
+
   supply_register_by_name (regcache, "fioff", &fp->fioff);
   supply_register_by_name (regcache, "fooff", &fp->fooff);
   supply_register_by_name (regcache, "mxcsr", &fp->mxcsr);
index cf61872..e8505bf 100644 (file)
@@ -43,6 +43,10 @@ extern const struct target_desc *tdesc_amd64_linux;
 void init_registers_amd64_avx_linux (void);
 extern const struct target_desc *tdesc_amd64_avx_linux;
 
+/* Defined in auto-generated file amd64-mpx-linux.c.  */
+void init_registers_amd64_mpx_linux (void);
+extern const struct target_desc *tdesc_amd64_mpx_linux;
+
 /* Defined in auto-generated file x32-linux.c.  */
 void init_registers_x32_linux (void);
 extern const struct target_desc *tdesc_x32_linux;
@@ -50,6 +54,7 @@ extern const struct target_desc *tdesc_x32_linux;
 /* Defined in auto-generated file x32-avx-linux.c.  */
 void init_registers_x32_avx_linux (void);
 extern const struct target_desc *tdesc_x32_avx_linux;
+
 #endif
 
 /* Defined in auto-generated file i386-linux.c.  */
@@ -64,6 +69,10 @@ extern const struct target_desc *tdesc_i386_mmx_linux;
 void init_registers_i386_avx_linux (void);
 extern const struct target_desc *tdesc_i386_avx_linux;
 
+/* Defined in auto-generated file i386-mpx-linux.c.  */
+void init_registers_i386_mpx_linux (void);
+extern const struct target_desc *tdesc_i386_mpx_linux;
+
 #ifdef __x86_64__
 static struct target_desc *tdesc_amd64_linux_no_xml;
 #endif
@@ -163,8 +172,11 @@ static const int x86_64_regmap[] =
   -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
+  -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  ORIG_RAX * 8,
+  -1, -1, -1, -1,                      /* MPX registers BND0 ... BND3.  */
+  -1, -1                               /* MPX registers BNDCFGU, BNDSTATUS.  */
 };
 
 #define X86_64_NUM_REGS (sizeof (x86_64_regmap) / sizeof (x86_64_regmap[0]))
@@ -1233,7 +1245,7 @@ x86_linux_read_description (void)
 {
   unsigned int machine;
   int is_elf64;
-  int avx;
+  int xcr0_features;
   int tid;
   static uint64_t xcr0;
   struct regset_info *regset;
@@ -1312,36 +1324,69 @@ x86_linux_read_description (void)
     }
 
   /* Check the native XCR0 only if PTRACE_GETREGSET is available.  */
-  avx = (have_ptrace_getregset
-        && (xcr0 & I386_XSTATE_AVX_MASK) == I386_XSTATE_AVX_MASK);
+  xcr0_features = (have_ptrace_getregset
+         && (xcr0 & I386_XSTATE_ALL_MASK));
 
-  /* AVX is the highest feature we support.  */
-  if (avx)
+  if (xcr0_features)
     x86_xcr0 = xcr0;
 
   if (machine == EM_X86_64)
     {
 #ifdef __x86_64__
-      if (avx)
+      if (is_elf64)
        {
-         if (!is_elf64)
-           return tdesc_x32_avx_linux;
+         if (xcr0_features)
+           {
+             switch (xcr0 & I386_XSTATE_ALL_MASK)
+               {
+               case I386_XSTATE_MPX_MASK:
+                 return tdesc_amd64_mpx_linux;
+
+               case I386_XSTATE_AVX_MASK:
+                 return tdesc_amd64_avx_linux;
+
+               default:
+                 return tdesc_amd64_linux;
+               }
+           }
          else
-           return tdesc_amd64_avx_linux;
+           return tdesc_amd64_linux;
        }
       else
        {
-         if (!is_elf64)
-           return tdesc_x32_linux;
+         if (xcr0_features)
+           {
+             switch (xcr0 & I386_XSTATE_ALL_MASK)
+               {
+               case I386_XSTATE_MPX_MASK: /* No MPX on x32.  */
+               case I386_XSTATE_AVX_MASK:
+                 return tdesc_x32_avx_linux;
+
+               default:
+                 return tdesc_x32_linux;
+               }
+           }
          else
-           return tdesc_amd64_linux;
+           return tdesc_x32_linux;
        }
 #endif
     }
   else
     {
-      if (avx)
-       return tdesc_i386_avx_linux;
+      if (xcr0_features)
+       {
+         switch (xcr0 & I386_XSTATE_ALL_MASK)
+           {
+           case (I386_XSTATE_MPX_MASK):
+             return tdesc_i386_mpx_linux;
+
+           case (I386_XSTATE_AVX_MASK):
+             return tdesc_i386_avx_linux;
+
+           default:
+             return tdesc_i386_linux;
+           }
+       }
       else
        return tdesc_i386_linux;
     }
@@ -3338,6 +3383,8 @@ initialize_low_arch (void)
 #ifdef __x86_64__
   init_registers_amd64_linux ();
   init_registers_amd64_avx_linux ();
+  init_registers_amd64_mpx_linux ();
+
   init_registers_x32_linux ();
   init_registers_x32_avx_linux ();
 
@@ -3348,6 +3395,7 @@ initialize_low_arch (void)
   init_registers_i386_linux ();
   init_registers_i386_mmx_linux ();
   init_registers_i386_avx_linux ();
+  init_registers_i386_mpx_linux ();
 
   tdesc_i386_linux_no_xml = xmalloc (sizeof (struct target_desc));
   copy_target_description (tdesc_i386_linux_no_xml, tdesc_i386_linux);