author | Aaron Klotz <aklotz@mozilla.com> |
Wed, 20 Jan 2016 10:44:17 -0700 | |
changeset 280841 | 9f34b95fa1d029c7eae575190efed6e2536547ad |
parent 280840 | 1ba31786ecfd539f6fd681a4f897d788027bbb77 |
child 280842 | c0be07690562d76bd836a24c817c015b1086f3a2 |
push id | 70611 |
push user | cbook@mozilla.com |
push date | Thu, 21 Jan 2016 08:27:17 +0000 |
treeherder | mozilla-inbound@c0be07690562 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ehsan |
bugs | 1240977 |
milestone | 46.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
|
--- a/xpcom/build/nsWindowsDllInterceptor.h +++ b/xpcom/build/nsWindowsDllInterceptor.h @@ -463,16 +463,79 @@ protected: const static int kPageSize = 4096; const static int kHookSize = 128; HMODULE mModule; byteptr_t mHookPage; int mMaxHooks; int mCurHooks; + // rex bits + static const BYTE kMaskHighNibble = 0xF0; + static const BYTE kRexOpcode = 0x40; + static const BYTE kMaskRexW = 0x08; + static const BYTE kMaskRexR = 0x04; + static const BYTE kMaskRexX = 0x02; + static const BYTE kMaskRexB = 0x01; + + // mod r/m bits + static const BYTE kRegFieldShift = 3; + static const BYTE kMaskMod = 0xC0; + static const BYTE kMaskReg = 0x38; + static const BYTE kMaskRm = 0x07; + static const BYTE kRmNeedSib = 0x04; + static const BYTE kModReg = 0xC0; + static const BYTE kModDisp32 = 0x80; + static const BYTE kModDisp8 = 0x40; + static const BYTE kModNoRegDisp = 0x00; + static const BYTE kRmNoRegDispDisp32 = 0x05; + + // sib bits + static const BYTE kMaskSibScale = 0xC0; + static const BYTE kMaskSibIndex = 0x38; + static const BYTE kMaskSibBase = 0x07; + static const BYTE kSibBaseEbp = 0x05; + + int CountModRmSib(const BYTE *aModRm, BYTE* aSubOpcode) + { + if (!aModRm) { + return -1; + } + int numBytes = 1; // Start with 1 for mod r/m byte itself + switch (*aModRm & kMaskMod) { + case kModReg: + return numBytes; + case kModDisp8: + numBytes += 1; + break; + case kModDisp32: + numBytes += 4; + break; + case kModNoRegDisp: + if ((*aModRm & kMaskRm) == kRmNoRegDispDisp32 || + ((*aModRm & kMaskRm) == kRmNeedSib && + (*(aModRm + 1) & kMaskSibBase) == kSibBaseEbp)) { + numBytes += 4; + } + break; + default: + // This should not be reachable + MOZ_ASSERT_UNREACHABLE("Impossible value for modr/m byte mod bits"); + return -1; + } + if ((*aModRm & kMaskRm) == kRmNeedSib) { + // SIB byte + numBytes += 1; + } + if (aSubOpcode) { + *aSubOpcode = (*aModRm & kMaskReg) >> kRegFieldShift; + } + return numBytes; + } + #if defined(_M_X64) // To patch for JMP and JE enum JumpType { Je, Jmp }; @@ -770,16 +833,27 @@ protected: // nop nBytes++; } else if (origBytes[nBytes] == 0xb8) { // MOV 0xB8: http://ref.x86asm.net/coder32.html#xB8 nBytes += 5; } else if (origBytes[nBytes] == 0x33) { // xor r32, r/m32 nBytes += 2; + } else if (origBytes[nBytes] == 0xf6) { + // test r/m8, imm8 (used by ntdll on Windows 10 x64) + // (no flags are affected by near jmp since there is no task switch, + // so it is ok for a jmp to be written immediately after a test) + BYTE subOpcode = 0; + int nModRmSibBytes = CountModRmSib(&origBytes[nBytes + 1], &subOpcode); + if (nModRmSibBytes < 0 || subOpcode != 0) { + // Unsupported + return; + } + nBytes += 2 + nModRmSibBytes; } else if (origBytes[nBytes] == 0xc3) { // ret nBytes++; } else if (origBytes[nBytes] == 0xcc) { // int 3 nBytes++; } else if (origBytes[nBytes] == 0xe9) { // jmp 32bit offset