Bug 1367899: Add handling for test r/m32, r32 and jne rel8 opcodes; r=dmajor
authorCarl Corcoran <carlco@gmail.com>
Fri, 26 May 2017 01:56:07 +0200
changeset 361494 5945f26f0ad66f9c2c900991728af87158191c5c
parent 361493 8fb7e770d89f935ed0c7a13792f0fd8a582a0434
child 361495 794a1edad2b4ba97a9c79ad3d6c24833e50dd91a
push id31932
push userryanvm@gmail.com
push dateWed, 31 May 2017 18:20:33 +0000
treeherdermozilla-central@2645d067b1e3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmajor
bugs1367899
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1367899: Add handling for test r/m32, r32 and jne rel8 opcodes; r=dmajor MozReview-Commit-ID: 3Cnx5tYrqMT
xpcom/build/nsWindowsDllInterceptor.h
--- a/xpcom/build/nsWindowsDllInterceptor.h
+++ b/xpcom/build/nsWindowsDllInterceptor.h
@@ -592,16 +592,17 @@ protected:
     return numBytes;
   }
 
 #if defined(_M_X64)
   // To patch for JMP and JE
 
   enum JumpType {
    Je,
+   Jne,
    Jmp,
    Call
   };
 
   struct JumpPatch {
     JumpPatch()
       : mHookOffset(0), mJumpAddress(0), mType(JumpType::Jmp)
     {
@@ -615,16 +616,21 @@ protected:
     size_t GenerateJump(uint8_t* aCode)
     {
       size_t offset = mHookOffset;
       if (mType == JumpType::Je) {
         // JNE RIP+14
         aCode[offset]     = 0x75;
         aCode[offset + 1] = 14;
         offset += 2;
+      } else if (mType == JumpType::Jne) {
+        // JE RIP+14
+        aCode[offset]     = 0x74;
+        aCode[offset + 1] = 14;
+        offset += 2;
       }
 
       // Near call/jmp, absolute indirect, address given in r/m32
       if (mType == JumpType::Call) {
         // CALL [RIP+0]
         aCode[offset] = 0xff;
         aCode[offset + 1] = 0x15;
         // The offset to jump destination -- ie it is placed 2 bytes after the offset.
@@ -910,18 +916,18 @@ protected:
 
         if (origBytes[nOrigBytes] == 0x33) {
           // xor r32, r32
           COPY_CODES(2);
         } else {
           MOZ_ASSERT_UNREACHABLE("Unrecognized opcode sequence");
           return;
         }
-      } else if ((origBytes[nOrigBytes] & 0xfb) == 0x48) {
-        // REX.W | REX.WR
+      } else if ((origBytes[nOrigBytes] & 0xfa) == 0x48) {
+        // REX.W | REX.WR | REX.WRB | REX.WB
         COPY_CODES(1);
 
         if (origBytes[nOrigBytes] == 0x81 &&
             (origBytes[nOrigBytes + 1] & 0xf8) == 0xe8) {
           // sub r, dword
           COPY_CODES(6);
         } else if (origBytes[nOrigBytes] == 0x83 &&
                    (origBytes[nOrigBytes + 1] & 0xf8) == 0xe8) {
@@ -1135,16 +1141,24 @@ protected:
         BYTE subOpcode = 0;
         int nModRmSibBytes = CountModRmSib(&origBytes[nOrigBytes + 1], &subOpcode);
         if (nModRmSibBytes < 0 || subOpcode != 0) {
           // Unsupported
           MOZ_ASSERT_UNREACHABLE("Unrecognized opcode sequence");
           return;
         }
         COPY_CODES(2 + nModRmSibBytes);
+      } else if (origBytes[nOrigBytes] == 0x85) {
+        // test r/m32, r32
+        int nModRmSibBytes = CountModRmSib(&origBytes[nOrigBytes + 1]);
+        if (nModRmSibBytes < 0) {
+          MOZ_ASSERT_UNREACHABLE("Unrecognized opcode sequence");
+          return;
+        }
+        COPY_CODES(1 + nModRmSibBytes);
       } else if (origBytes[nOrigBytes] == 0xd1 &&
                   (origBytes[nOrigBytes+1] & kMaskMod) == kModReg) {
         // bit shifts/rotates : (SA|SH|RO|RC)(R|L) r32
         // (e.g. 0xd1 0xe0 is SAL, 0xd1 0xc8 is ROR)
         COPY_CODES(2);
       } else if (origBytes[nOrigBytes] == 0xc3) {
         // ret
         COPY_CODES(1);
@@ -1156,16 +1170,26 @@ protected:
         // CALL (0xe8) or JMP (0xe9) 32bit offset
         foundJmp = origBytes[nOrigBytes] == 0xe9;
         JumpPatch jump(nTrampBytes,
                        (intptr_t)(origBytes + nOrigBytes + 5 +
                                   *(reinterpret_cast<int32_t*>(origBytes + nOrigBytes + 1))),
                        origBytes[nOrigBytes] == 0xe8 ? JumpType::Call : JumpType::Jmp);
         nTrampBytes = jump.GenerateJump(tramp);
         nOrigBytes += 5;
+      } else if (origBytes[nOrigBytes] == 0x74 || // je rel8 (0x74)
+                 origBytes[nOrigBytes] == 0x75) { // jne rel8 (0x75)
+        char offset = origBytes[nOrigBytes + 1];
+        auto jumpType = JumpType::Je;
+        if (origBytes[nOrigBytes] == 0x75)
+          jumpType = JumpType::Jne;
+        JumpPatch jump(nTrampBytes,
+          (intptr_t)(origBytes + nOrigBytes + 2 + offset), jumpType);
+        nTrampBytes = jump.GenerateJump(tramp);
+        nOrigBytes += 2;
       } else if (origBytes[nOrigBytes] == 0xff) {
         if ((origBytes[nOrigBytes + 1] & (kMaskMod|kMaskReg)) == 0xf0) {
           // push r64
           COPY_CODES(2);
         } else if (origBytes[nOrigBytes + 1] == 0x25) {
           // jmp absolute indirect m32
           foundJmp = true;
           int32_t offset = *(reinterpret_cast<int32_t*>(origBytes + nOrigBytes + 2));