]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
x86 front ends: tighten up decoding of MOV Ib,Eb and MOV Iv,Ev. This
authorJulian Seward <jseward@acm.org>
Wed, 18 Sep 2013 18:27:55 +0000 (18:27 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 18 Sep 2013 18:27:55 +0000 (18:27 +0000)
failed to check the g-register in the modrm byte, with the result that
it will mis-decode the AVX2 XABORT and XBEGIN instructions as these
instead, with obviously-bizarre consequences.

git-svn-id: svn://svn.valgrind.org/vex/trunk@2768

VEX/priv/guest_amd64_toIR.c
VEX/priv/guest_x86_toIR.c

index 522bfbe14717a64696c6c1e1b7afcd489c0795c6..4fa83f9bcba72c6fe097345391f9822fedb3c205 100644 (file)
@@ -20035,34 +20035,37 @@ Long dis_ESC_NONE (
       DIP(haveF3(pfx) ? "rep ; ret\n" : "ret\n");
       return delta;
 
-   case 0xC6: /* MOV Ib,Eb */
+   case 0xC6: /* C6 /0 = MOV Ib,Eb */
       sz = 1;
-      goto do_Mov_I_E;
-   case 0xC7: /* MOV Iv,Ev */
-      goto do_Mov_I_E;
-   do_Mov_I_E:
-      if (haveF2orF3(pfx)) goto decode_failure;
+      goto maybe_do_Mov_I_E;
+   case 0xC7: /* C7 /0 = MOV Iv,Ev */
+      goto maybe_do_Mov_I_E;
+   maybe_do_Mov_I_E:
       modrm = getUChar(delta);
-      if (epartIsReg(modrm)) {
-         delta++; /* mod/rm byte */
-         d64 = getSDisp(imin(4,sz),delta); 
-         delta += imin(4,sz);
-         putIRegE(sz, pfx, modrm, 
-                      mkU(szToITy(sz), d64 & mkSizeMask(sz)));
-         DIP("mov%c $%lld, %s\n", nameISize(sz), 
-                                  (Long)d64, 
-                                  nameIRegE(sz,pfx,modrm));
-      } else {
-         addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 
-                           /*xtra*/imin(4,sz) );
-         delta += alen;
-         d64 = getSDisp(imin(4,sz),delta);
-         delta += imin(4,sz);
-         storeLE(mkexpr(addr), 
-                 mkU(szToITy(sz), d64 & mkSizeMask(sz)));
-         DIP("mov%c $%lld, %s\n", nameISize(sz), (Long)d64, dis_buf);
+      if (gregLO3ofRM(modrm) == 0) {
+         if (haveF2orF3(pfx)) goto decode_failure;
+         if (epartIsReg(modrm)) {
+            delta++; /* mod/rm byte */
+            d64 = getSDisp(imin(4,sz),delta); 
+            delta += imin(4,sz);
+            putIRegE(sz, pfx, modrm, 
+                         mkU(szToITy(sz), d64 & mkSizeMask(sz)));
+            DIP("mov%c $%lld, %s\n", nameISize(sz), 
+                                     (Long)d64, 
+                                     nameIRegE(sz,pfx,modrm));
+         } else {
+            addr = disAMode ( &alen, vbi, pfx, delta, dis_buf, 
+                              /*xtra*/imin(4,sz) );
+            delta += alen;
+            d64 = getSDisp(imin(4,sz),delta);
+            delta += imin(4,sz);
+            storeLE(mkexpr(addr), 
+                    mkU(szToITy(sz), d64 & mkSizeMask(sz)));
+            DIP("mov%c $%lld, %s\n", nameISize(sz), (Long)d64, dis_buf);
+         }
+         return delta;
       }
-      return delta;
+      goto decode_failure;
 
    case 0xC8: /* ENTER */
       /* Same comments re operand size as for LEAVE below apply.
index e98f19cb297742084deaea735f295e78dd4a1ad1..d3b93ddb551d757ca27d4ec05a122df6c38e85fc 100644 (file)
@@ -13503,28 +13503,31 @@ DisResult disInstr_X86_WRK (
       DIP("mov%c $0x%x,%s\n", nameISize(sz), d32, nameIReg(sz,opc-0xB8));
       break;
 
-   case 0xC6: /* MOV Ib,Eb */
+   case 0xC6: /* C6 /0 = MOV Ib,Eb */
       sz = 1;
-      goto do_Mov_I_E;
-   case 0xC7: /* MOV Iv,Ev */
-      goto do_Mov_I_E;
+      goto maybe_do_Mov_I_E;
+   case 0xC7: /* C7 /0 = MOV Iv,Ev */
+      goto maybe_do_Mov_I_E;
 
-   do_Mov_I_E:
+   maybe_do_Mov_I_E:
       modrm = getIByte(delta);
-      if (epartIsReg(modrm)) {
-         delta++; /* mod/rm byte */
-         d32 = getUDisp(sz,delta); delta += sz;
-         putIReg(sz, eregOfRM(modrm), mkU(szToITy(sz), d32));
-         DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, 
-                                  nameIReg(sz,eregOfRM(modrm)));
-      } else {
-         addr = disAMode ( &alen, sorb, delta, dis_buf );
-         delta += alen;
-         d32 = getUDisp(sz,delta); delta += sz;
-         storeLE(mkexpr(addr), mkU(szToITy(sz), d32));
-         DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
+      if (gregOfRM(modrm) == 0) {
+         if (epartIsReg(modrm)) {
+            delta++; /* mod/rm byte */
+            d32 = getUDisp(sz,delta); delta += sz;
+            putIReg(sz, eregOfRM(modrm), mkU(szToITy(sz), d32));
+            DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, 
+                                     nameIReg(sz,eregOfRM(modrm)));
+         } else {
+            addr = disAMode ( &alen, sorb, delta, dis_buf );
+            delta += alen;
+            d32 = getUDisp(sz,delta); delta += sz;
+            storeLE(mkexpr(addr), mkU(szToITy(sz), d32));
+            DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
+         }
+         break;
       }
-      break;
+      goto decode_failure;
 
    /* ------------------------ opl imm, A ----------------- */