[llvm-commits] [compiler-rt] r153249 - /compiler-rt/trunk/lib/asan/interception/mach_override/mach_override.c

Alexander Potapenko glider at google.com
Thu Mar 22 04:29:54 PDT 2012


Author: glider
Date: Thu Mar 22 06:29:53 2012
New Revision: 153249

URL: http://llvm.org/viewvc/llvm-project?rev=153249&view=rev
Log:
Handle two-byte short jumps in the relocated code.
After the instructions are moved to the branch island, fixupInstructions() expands every 2-byte ja/je instruction with a 1-byte offset into a 6-byte ja/je with 32-bit offset. The offset is fixed to point to the original function.


Modified:
    compiler-rt/trunk/lib/asan/interception/mach_override/mach_override.c

Modified: compiler-rt/trunk/lib/asan/interception/mach_override/mach_override.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/interception/mach_override/mach_override.c?rev=153249&r1=153248&r2=153249&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/interception/mach_override/mach_override.c (original)
+++ compiler-rt/trunk/lib/asan/interception/mach_override/mach_override.c Thu Mar 22 06:29:53 2012
@@ -157,6 +157,12 @@
     void		*instructionsToFix,
 	int			instructionCount,
 	uint8_t		*instructionSizes ) __attribute__((visibility("hidden")));
+
+#ifdef DEBUG_DISASM
+	static void
+dump16Bytes(
+	void	*ptr);
+#endif  // DEBUG_DISASM
 #endif
 
 /*******************************************************************************
@@ -830,9 +836,21 @@
 	int			instructionCount,
 	uint8_t		*instructionSizes )
 {
-	int	index;
+	void *initialOriginalFunction = originalFunction;
+	int	index, fixed_size, code_size = 0;
+	for (index = 0;index < instructionCount;index += 1)
+		code_size += instructionSizes[index];
+
+#ifdef DEBUG_DISASM
+	void *initialInstructionsToFix = instructionsToFix;
+	fprintf(stderr, "BEFORE FIXING:\n");
+	dump16Bytes(initialOriginalFunction);
+	dump16Bytes(initialInstructionsToFix);
+#endif  // DEBUG_DISASM
+
 	for (index = 0;index < instructionCount;index += 1)
 	{
+                fixed_size = instructionSizes[index];
 		if ((*(uint8_t*)instructionsToFix == 0xE9) || // 32-bit jump relative
 		    (*(uint8_t*)instructionsToFix == 0xE8))   // 32-bit call relative
 		{
@@ -840,13 +858,56 @@
 			uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instructionsToFix + 1);
 			*jumpOffsetPtr += offset;
 		}
-
+		if ((*(uint8_t*)instructionsToFix == 0x74) ||  // Near jump if equal (je), 2 bytes.
+		    (*(uint8_t*)instructionsToFix == 0x77))    // Near jump if above (ja), 2 bytes.
+		{
+			// We replace a near je/ja instruction, "7P JJ", with a 32-bit je/ja, "0F 8P WW XX YY ZZ".
+			// This is critical, otherwise a near jump will likely fall outside the original function.
+			uint32_t offset = (uintptr_t)initialOriginalFunction - (uintptr_t)escapeIsland;
+			uint32_t jumpOffset = *(uint8_t*)((uintptr_t)instructionsToFix + 1);
+			*(uint8_t*)(instructionsToFix + 1) = *(uint8_t*)instructionsToFix + 0x10;
+			*(uint8_t*)instructionsToFix = 0x0F;
+			uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instructionsToFix + 2 );
+			*jumpOffsetPtr = offset + jumpOffset;
+			fixed_size = 6;
+                }
 		
 		originalFunction = (void*)((uintptr_t)originalFunction + instructionSizes[index]);
 		escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSizes[index]);
-		instructionsToFix = (void*)((uintptr_t)instructionsToFix + instructionSizes[index]);
-    }
+		instructionsToFix = (void*)((uintptr_t)instructionsToFix + fixed_size);
+
+		// Expanding short instructions into longer ones may overwrite the next instructions,
+		// so we must restore them.
+		code_size -= fixed_size;
+		if ((code_size > 0) && (fixed_size != instructionSizes[index])) {
+			bcopy(originalFunction, instructionsToFix, code_size);
+		}
+	}
+#ifdef DEBUG_DISASM
+	fprintf(stderr, "AFTER_FIXING:\n");
+	dump16Bytes(initialOriginalFunction);
+	dump16Bytes(initialInstructionsToFix);
+#endif  // DEBUG_DISASM
+}
+
+#ifdef DEBUG_DISASM
+#define HEX_DIGIT(x) ((((x) % 16) < 10) ? ('0' + ((x) % 16)) : ('A' + ((x) % 16 - 10)))
+
+	static void
+dump16Bytes(
+	void 	*ptr) {
+	int i;
+	char buf[3];
+	uint8_t *bytes = (uint8_t*)ptr;
+	for (i = 0; i < 16; i++) {
+		buf[0] = HEX_DIGIT(bytes[i] / 16);
+		buf[1] = HEX_DIGIT(bytes[i] % 16);
+		buf[2] = ' ';
+		write(2, buf, 3);
+	}
+	write(2, "\n", 1);
 }
+#endif  // DEBUG_DISASM
 #endif
 
 #if defined(__i386__)





More information about the llvm-commits mailing list