[compiler-rt] r276336 - [compiler-rt] Add support for relative offset adjustment in interception

Etienne Bergeron via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 21 14:08:54 PDT 2016


Author: etienneb
Date: Thu Jul 21 16:08:54 2016
New Revision: 276336

URL: http://llvm.org/viewvc/llvm-project?rev=276336&view=rev
Log:
[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

Modified:
    compiler-rt/trunk/lib/interception/interception_win.cc

Modified: compiler-rt/trunk/lib/interception/interception_win.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_win.cc?rev=276336&r1=276335&r2=276336&view=diff
==============================================================================
--- compiler-rt/trunk/lib/interception/interception_win.cc (original)
+++ compiler-rt/trunk/lib/interception/interception_win.cc Thu Jul 21 16:08:54 2016
@@ -229,10 +229,6 @@ static void WritePadding(uptr from, uptr
   _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();
@@ -384,7 +380,7 @@ static uptr AllocateMemoryForTrampoline(
 }
 
 // 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;
@@ -505,8 +501,11 @@ static size_t GetInstructionSize(uptr ad
                       //   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
@@ -580,6 +579,28 @@ static size_t RoundUpToInstrBoundary(siz
   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) {
@@ -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;
@@ -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;




More information about the llvm-commits mailing list