Bug 951827 - Part 3: Give trampolines some structure. r=ehsan

This commit is contained in:
David Major 2014-02-14 14:55:46 -08:00
parent bc116ff55b
commit 4a4492190f

View File

@ -236,7 +236,8 @@ public:
#else
#error "Unknown processor type"
#endif
byteptr_t origBytes = *((byteptr_t *)p);
Trampoline *tramp = (Trampoline*)p;
byteptr_t origBytes = (byteptr_t)tramp->origFunction;
// If CreateTrampoline failed, we may have an empty trampoline.
if (!origBytes) {
@ -264,7 +265,7 @@ public:
}
// Remove the hook by making the original function jump directly
// in the trampoline.
intptr_t dest = (intptr_t)(p + sizeof(void *));
intptr_t dest = (intptr_t)(&tramp->code[0]);
#if defined(_M_IX86)
*((intptr_t*)(origBytes+1)) = dest - (intptr_t)(origBytes+5); // target displacement
#elif defined(_M_X64)
@ -344,6 +345,7 @@ public:
protected:
const static int kPageSize = 4096;
const static int kHookSize = 128;
const static int kCodeSize = 100;
const static uint8_t opTrampolineRelativeJump = 0xe9;
const static uint16_t opTrampolineRegLoad = 0xbb49;
@ -353,13 +355,21 @@ protected:
int mMaxHooks;
int mCurHooks;
struct Trampoline
{
void *origFunction;
uint8_t code[kCodeSize];
};
static_assert(sizeof(Trampoline) <= kHookSize, "Trampolines too big");
void CreateTrampoline(void *origFunction,
intptr_t dest,
void **outTramp)
{
*outTramp = nullptr;
byteptr_t tramp = FindTrampolineSpace();
Trampoline *tramp = FindTrampolineSpace();
if (!tramp)
return;
@ -580,17 +590,16 @@ protected:
#error "Unknown processor type"
#endif
if (nBytes > 100) {
if (nBytes > kCodeSize) {
//printf ("Too big!");
return;
}
// We keep the address of the original function in the first bytes of
// the trampoline buffer
*((void **)tramp) = origFunction;
tramp += sizeof(void *);
tramp->origFunction = origFunction;
memcpy(tramp, origFunction, nBytes);
memcpy(&tramp->code[0], origFunction, nBytes);
// OrigFunction+N, the target of the trampoline
byteptr_t trampDest = origBytes + nBytes;
@ -600,36 +609,36 @@ protected:
// Jump directly to the original target of the jump instead of jumping to the
// original function.
// Adjust jump target displacement to jump location in the trampoline.
*((intptr_t*)(tramp+pJmp32+1)) += origBytes - tramp;
*((intptr_t*)(&tramp->code[pJmp32+1])) += origBytes - &tramp->code[0];
} else {
tramp[nBytes] = opTrampolineRelativeJump; // jmp
*((intptr_t*)(tramp+nBytes+1)) = (intptr_t)trampDest - (intptr_t)(tramp+nBytes+5); // target displacement
tramp->code[nBytes] = opTrampolineRelativeJump; // jmp
*((intptr_t*)(&tramp->code[nBytes+1])) = (intptr_t)trampDest - (intptr_t)(&tramp->code[nBytes+5]); // target displacement
}
#elif defined(_M_X64)
// If JMP32 opcode found, we don't insert to trampoline jump
if (pJmp32 >= 0) {
// mov r11, address
*((uint16_t*)(tramp+pJmp32)) = opTrampolineRegLoad;
*((intptr_t*)(tramp+pJmp32+2)) = (intptr_t)directJmpAddr;
*((uint16_t*)(&tramp->code[pJmp32])) = opTrampolineRegLoad;
*((intptr_t*)(&tramp->code[pJmp32+2])) = (intptr_t)directJmpAddr;
// jmp r11
tramp[pJmp32+10] = 0x41;
tramp[pJmp32+11] = 0xff;
tramp[pJmp32+12] = 0xe3;
tramp->code[pJmp32+10] = 0x41;
tramp->code[pJmp32+11] = 0xff;
tramp->code[pJmp32+12] = 0xe3;
} else {
// mov r11, address
*((uint16_t*)(tramp+nBytes)) = opTrampolineRegLoad;
*((intptr_t*)(tramp+nBytes+2)) = (intptr_t)trampDest;
*((uint16_t*)(&tramp->code[nBytes])) = opTrampolineRegLoad;
*((intptr_t*)(&tramp->code[nBytes+2])) = (intptr_t)trampDest;
// jmp r11
tramp[nBytes+10] = 0x41;
tramp[nBytes+11] = 0xff;
tramp[nBytes+12] = 0xe3;
tramp->code[nBytes+10] = 0x41;
tramp->code[nBytes+11] = 0xff;
tramp->code[nBytes+12] = 0xe3;
}
#endif
// The trampoline is now valid.
*outTramp = tramp;
*outTramp = &tramp->code[0];
// ensure we can modify the original code
DWORD op;
@ -657,16 +666,16 @@ protected:
VirtualProtectEx(GetCurrentProcess(), origFunction, nBytes, op, &op);
}
byteptr_t FindTrampolineSpace()
Trampoline* FindTrampolineSpace()
{
if (mCurHooks >= mMaxHooks)
return 0;
return nullptr;
byteptr_t p = mHookPage + mCurHooks*kHookSize;
mCurHooks++;
return p;
return (Trampoline*)p;
}
};