Bug 333666

Summary: No MPX (bndmov) instruction support in VEX
Product: [Developer tools] valgrind Reporter: Mark Wielaard <mark>
Component: vexAssignee: Julian Seward <jseward>
Status: RESOLVED FIXED    
Severity: normal    
Priority: NOR    
Version First Reported In: 3.9.0   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed/Implemented In:
Sentry Crash Report:
Attachments: Recognize mpx instructions and bnd prefix
Add test for MPX instructions and bnd prefix.

Description Mark Wielaard 2014-04-20 20:27:04 UTC
VEX doesn't recognize bndmov one of the new intel MPX instructions. This is used on glibc 2.19 ld.so _dl_runtime_resolve (sysdeps/x86_64/dl-trampoline.S):

/* Area on stack to save and restore registers used for parameter
   passing when calling _dl_fixup.  */
[...]
/* X86-64 saves RCX, RDX, RSI, RDI, R8 and R9 plus RAX as well as BND0,
   BND1, BND2, BND3.  */
# define REGISTER_SAVE_AREA     (8 * 7 + 16 * 4)
/* Align bound register save area to 16 bytes.  */
# define REGISTER_SAVE_BND0     0
# define REGISTER_SAVE_BND1     (REGISTER_SAVE_BND0 + 16)
# define REGISTER_SAVE_BND2     (REGISTER_SAVE_BND1 + 16)
# define REGISTER_SAVE_BND3     (REGISTER_SAVE_BND2 + 16)
# define REGISTER_SAVE_RAX      (REGISTER_SAVE_BND3 + 16)
[...]
        # We also have to preserve bound registers.  These are nops if
        # Intel MPX isn't available or disabled.
# ifdef HAVE_MPX_SUPPORT
        bndmov %bnd0, REGISTER_SAVE_BND0(%rsp)
        bndmov %bnd1, REGISTER_SAVE_BND1(%rsp)
        bndmov %bnd2, REGISTER_SAVE_BND2(%rsp)
        bndmov %bnd3, REGISTER_SAVE_BND3(%rsp)
# else
        .byte 0x66,0x0f,0x1b,0x44,0x24,REGISTER_SAVE_BND0
        .byte 0x66,0x0f,0x1b,0x4c,0x24,REGISTER_SAVE_BND1
        .byte 0x66,0x0f,0x1b,0x54,0x24,REGISTER_SAVE_BND2
        .byte 0x66,0x0f,0x1b,0x5c,0x24,REGISTER_SAVE_BND3
# endif

Here is some more background on support of MPX in the GNU toolchain:
https://software.intel.com/en-us/blogs/2013/07/22/intel-memory-protection-extensions-intel-mpx-support-in-the-gnu-toolchain

This was reported against valgrind in fedora rawhide (valgrind-3.9.0-11.svn20140319r13879.fc21.x86_64 and glibc-2.19.90-11.fc21.x86_64. https://bugzilla.redhat.com/show_bug.cgi?id=1087933
Comment 1 Mark Wielaard 2014-05-08 14:18:10 UTC
Created attachment 86525 [details]
Recognize mpx instructions and bnd prefix

Recognize MPX instructions and bnd prefix. Bug #333666.

Recognize and parse operands of new MPX instructions BNDMK, BNDCL, 
BNDCU, BNDCN, BNDMOV, BNDLDX and BNDSTX. Also recognize bnd (F2) prefix 
for CALL (E8,FF/2), RET (C2,C3), JMP (E9,FF/4) and Jcc (70-7F,0F 80-8F).
All new MPX instructions are currently NOPs and the bnd prefix is ignored.

Tested by running against glibc 2.19 and looking at some disassembly from binutils/gas MPX testcases.
Current GCC doesn't have support for enabling MPX yet.
Comment 2 Mark Wielaard 2014-05-08 20:09:50 UTC
Created attachment 86534 [details]
Add test for MPX instructions and bnd prefix.

This test also showed a bug in the implementation. A bnd prefixed short JMP (JMP rel 8, opcode EB) wasn't recognized. Which is fixed by:

diff --git a/priv/guest_amd64_toIR.c b/priv/guest_amd64_toIR.c
index 86c6c2f..c69a71e 100644
--- a/priv/guest_amd64_toIR.c
+++ b/priv/guest_amd64_toIR.c
@@ -20837,9 +20837,10 @@ Long dis_ESC_NONE (
       return delta;
 
    case 0xEB: /* Jb (jump, byte offset) */
-      if (haveF2orF3(pfx)) goto decode_failure;
+      if (haveF3(pfx)) goto decode_failure;
       if (sz != 4) 
          goto decode_failure; /* JRS added 2004 July 11 */
+      if (haveF2(pfx)) DIP("bnd ; "); /* MPX bnd prefix. */
       d64 = (guest_RIP_bbstart+delta+1) + getSDisp8(delta); 
       delta++;
       if (resteerOkFn(callback_opaque,d64)) {
Comment 3 Mark Wielaard 2014-05-09 11:44:17 UTC
committed as VEX  r2858 and valgrind r13948