forked from OSchip/llvm-project
[compiler-rt] Add support for relative offset adjustment in interception
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
This commit is contained in:
parent
07915f6cb0
commit
901b0dc96a
|
@ -229,10 +229,6 @@ static void WritePadding(uptr from, uptr size) {
|
||||||
_memset((void*)from, 0xCC, (size_t)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) {
|
static void WriteJumpInstruction(uptr from, uptr target) {
|
||||||
if (!DistanceIsWithin2Gig(from + kJumpInstructionLength, target))
|
if (!DistanceIsWithin2Gig(from + kJumpInstructionLength, target))
|
||||||
InterceptionFailed();
|
InterceptionFailed();
|
||||||
|
@ -384,7 +380,7 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns 0 on error.
|
// Returns 0 on error.
|
||||||
static size_t GetInstructionSize(uptr address) {
|
static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
|
||||||
switch (*(u64*)address) {
|
switch (*(u64*)address) {
|
||||||
case 0x90909090909006EB: // stub: jmp over 6 x nop.
|
case 0x90909090909006EB: // stub: jmp over 6 x nop.
|
||||||
return 8;
|
return 8;
|
||||||
|
@ -505,8 +501,11 @@ static size_t GetInstructionSize(uptr address) {
|
||||||
// mov rax, QWORD PTR [rip + XXXXXXXX]
|
// mov rax, QWORD PTR [rip + XXXXXXXX]
|
||||||
case 0x25ff48: // 48 ff 25 XX XX XX XX :
|
case 0x25ff48: // 48 ff 25 XX XX XX XX :
|
||||||
// rex.W jmp QWORD PTR [rip + XXXXXXXX]
|
// 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
|
case 0x2444c7: // C7 44 24 XX YY YY YY YY
|
||||||
// mov dword ptr [rsp + XX], YYYYYYYY
|
// mov dword ptr [rsp + XX], YYYYYYYY
|
||||||
|
@ -580,6 +579,28 @@ static size_t RoundUpToInstrBoundary(size_t size, uptr address) {
|
||||||
return cursor;
|
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
|
#if !SANITIZER_WINDOWS64
|
||||||
bool OverrideFunctionWithDetour(
|
bool OverrideFunctionWithDetour(
|
||||||
uptr old_func, uptr new_func, uptr *orig_old_func) {
|
uptr old_func, uptr new_func, uptr *orig_old_func) {
|
||||||
|
@ -670,7 +691,8 @@ bool OverrideFunctionWithHotPatch(
|
||||||
uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
|
uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
|
||||||
if (!trampoline)
|
if (!trampoline)
|
||||||
return false;
|
return false;
|
||||||
CopyInstructions(trampoline, old_func, instruction_size);
|
if (!CopyInstructions(trampoline, old_func, instruction_size))
|
||||||
|
return false;
|
||||||
WriteDirectBranch(trampoline + instruction_size,
|
WriteDirectBranch(trampoline + instruction_size,
|
||||||
old_func + instruction_size);
|
old_func + instruction_size);
|
||||||
*orig_old_func = trampoline;
|
*orig_old_func = trampoline;
|
||||||
|
@ -719,7 +741,8 @@ bool OverrideFunctionWithTrampoline(
|
||||||
uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
|
uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
|
||||||
if (!trampoline)
|
if (!trampoline)
|
||||||
return false;
|
return false;
|
||||||
CopyInstructions(trampoline, old_func, instructions_length);
|
if (!CopyInstructions(trampoline, old_func, instructions_length))
|
||||||
|
return false;
|
||||||
WriteDirectBranch(trampoline + instructions_length,
|
WriteDirectBranch(trampoline + instructions_length,
|
||||||
old_func + instructions_length);
|
old_func + instructions_length);
|
||||||
*orig_old_func = trampoline;
|
*orig_old_func = trampoline;
|
||||||
|
|
Loading…
Reference in New Issue