Skip to content

Commit

Permalink
[compiler-rt] Add support for relative offset adjustment in interception
Browse files Browse the repository at this point in the history
Summary:
Some instructions can only be copied if the relative offset is adjusted.

This patch adds support for two common instruction.
It's quite common to have a indirect load in the prologue 
(loading the security cookie).

Reviewers: rnk

Subscribers: llvm-commits, wang0109, chrisha

Differential Revision: https://reviews.llvm.org/D22647

llvm-svn: 276336
  • Loading branch information
bergeret committed Jul 21, 2016
1 parent 07915f6 commit 901b0dc
Showing 1 changed file with 32 additions and 9 deletions.
41 changes: 32 additions & 9 deletions compiler-rt/lib/interception/interception_win.cc
Expand Up @@ -229,10 +229,6 @@ static void WritePadding(uptr from, uptr size) {
_memset((void*)from, 0xCC, (size_t)size);
}

static void CopyInstructions(uptr from, uptr to, uptr size) {
_memcpy((void*)from, (void*)to, (size_t)size);
}

static void WriteJumpInstruction(uptr from, uptr target) {
if (!DistanceIsWithin2Gig(from + kJumpInstructionLength, target))
InterceptionFailed();
Expand Down Expand Up @@ -384,7 +380,7 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
}

// Returns 0 on error.
static size_t GetInstructionSize(uptr address) {
static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
switch (*(u64*)address) {
case 0x90909090909006EB: // stub: jmp over 6 x nop.
return 8;
Expand Down Expand Up @@ -505,8 +501,11 @@ static size_t GetInstructionSize(uptr address) {
// mov rax, QWORD PTR [rip + XXXXXXXX]
case 0x25ff48: // 48 ff 25 XX XX XX XX :
// rex.W jmp QWORD PTR [rip + XXXXXXXX]
// Instructions having offset relative to 'rip' cannot be copied.
return 0;

// Instructions having offset relative to 'rip' need offset adjustment.
if (rel_offset)
*rel_offset = 3;
return 7;

case 0x2444c7: // C7 44 24 XX YY YY YY YY
// mov dword ptr [rsp + XX], YYYYYYYY
Expand Down Expand Up @@ -580,6 +579,28 @@ static size_t RoundUpToInstrBoundary(size_t size, uptr address) {
return cursor;
}

static bool CopyInstructions(uptr to, uptr from, size_t size) {
size_t cursor = 0;
while (cursor != size) {
size_t rel_offset = 0;
size_t instruction_size = GetInstructionSize(from + cursor, &rel_offset);
_memcpy((void*)(to + cursor), (void*)(from + cursor),
(size_t)instruction_size);
if (rel_offset) {
uptr delta = to - from;
uptr relocated_offset = *(u32*)(to + cursor + rel_offset) - delta;
#if SANITIZER_WINDOWS64
if (relocated_offset + 0x80000000U >= 0xFFFFFFFFU)
return false;
#endif
*(u32*)(to + cursor + rel_offset) = relocated_offset;
}
cursor += instruction_size;
}
return true;
}


#if !SANITIZER_WINDOWS64
bool OverrideFunctionWithDetour(
uptr old_func, uptr new_func, uptr *orig_old_func) {
Expand Down Expand Up @@ -670,7 +691,8 @@ bool OverrideFunctionWithHotPatch(
uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
if (!trampoline)
return false;
CopyInstructions(trampoline, old_func, instruction_size);
if (!CopyInstructions(trampoline, old_func, instruction_size))
return false;
WriteDirectBranch(trampoline + instruction_size,
old_func + instruction_size);
*orig_old_func = trampoline;
Expand Down Expand Up @@ -719,7 +741,8 @@ bool OverrideFunctionWithTrampoline(
uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
if (!trampoline)
return false;
CopyInstructions(trampoline, old_func, instructions_length);
if (!CopyInstructions(trampoline, old_func, instructions_length))
return false;
WriteDirectBranch(trampoline + instructions_length,
old_func + instructions_length);
*orig_old_func = trampoline;
Expand Down

0 comments on commit 901b0dc

Please sign in to comment.