Bug 1322554: Interceptor fixes to support kernel32!BaseThreadInitThunk; r=m_kato
MozReview-Commit-ID: A3JqyhHb6nD
--- a/xpcom/build/nsWindowsDllInterceptor.h
+++ b/xpcom/build/nsWindowsDllInterceptor.h
@@ -572,16 +572,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)
{
@@ -595,16 +596,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.
@@ -878,18 +884,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) {
@@ -1058,16 +1064,19 @@ 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
+ COPY_CODES(2);
} 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);
@@ -1079,16 +1088,23 @@ 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] == 0x75) {
+ // jne rel8
+ char offset = origBytes[nOrigBytes + 1];
+ JumpPatch jump(nTrampBytes, (intptr_t)(origBytes + nOrigBytes + 2 +
+ offset), JumpType::Jne);
+ nTrampBytes = jump.GenerateJump(tramp);
+ nOrigBytes += 2;
} else if (origBytes[nOrigBytes] == 0xff) {
COPY_CODES(1);
if ((origBytes[nOrigBytes] & (kMaskMod|kMaskReg)) == 0xf0) {
// push r64
COPY_CODES(1);
} else if (origBytes[nOrigBytes] == 0x25) {
// jmp absolute indirect m32
foundJmp = true;