summaryrefslogtreecommitdiffstats
path: root/third_party/mach_override
diff options
context:
space:
mode:
authorthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-09 21:18:26 +0000
committerthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-09 21:18:26 +0000
commitf7e48f1526964d61b40e0cdad33e0e13b04fc12b (patch)
treecdd09864603ba1cb19844ec169b3d86bf6267fa3 /third_party/mach_override
parentdd6210f7b59c64637dfe907b0bd2cf693329c037 (diff)
downloadchromium_src-f7e48f1526964d61b40e0cdad33e0e13b04fc12b.zip
chromium_src-f7e48f1526964d61b40e0cdad33e0e13b04fc12b.tar.gz
chromium_src-f7e48f1526964d61b40e0cdad33e0e13b04fc12b.tar.bz2
Revert 150529 (very likely caused http://crbug.com/141707
- Update third_party/mach_override from https://github.com/rentzsch/mach_star/mach_override to include the fix for building Chromium on 64 bits. BUG=138535 Review URL: https://chromiumcodereview.appspot.com/10834127 TBR=mmaerean@adobe.com Review URL: https://chromiumcodereview.appspot.com/10830249 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150901 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party/mach_override')
-rw-r--r--third_party/mach_override/README.chromium16
-rw-r--r--third_party/mach_override/mach_override.c218
2 files changed, 103 insertions, 131 deletions
diff --git a/third_party/mach_override/README.chromium b/third_party/mach_override/README.chromium
index a2625ac..96b0cf7 100644
--- a/third_party/mach_override/README.chromium
+++ b/third_party/mach_override/README.chromium
@@ -2,8 +2,8 @@ Name: mach_override
Short Name: Part of the mach_star project
Version: Unknown
URL: https://github.com/rentzsch/mach_star
-Date: 08/01/2012
-Revision: 6c4965586d28b931d19b428832fe5de968fd7d82
+Date: 08/19/2011
+Revision: 87f491f8acef924d2ba90dd55fc23ad64f9d5bbd
License: MIT
Security Critical: Yes
@@ -11,10 +11,18 @@ Security Critical: Yes
Description:
This is the mach_override part of mach_star, namely:
- https://github.com/rentzsch/mach_star/tree/6c4965586d28b931d19b428832fe5de968fd7d82
+ https://github.com/rentzsch/mach_star/tree/87f491f8acef924d2ba90dd55fc23ad64f9d5bbd
This package is used to replace framework functions with different
implementations at run time.
-Local Modifications: None
+Local Modifications:
+
+reentryIsland is allocated in high memory with vm_allocate rather than the
+heap with malloc by changing the allocation policy to kAllocateHigh. It
+appears probable that putting the reentry island in the heap causes its page
+to lose execute permission at some point under some circumstances, which
+results in a crash on Lion. This modification is temoprary to simply test
+out the theory. If proven, the code will be improved somewhat.
+http://crbug.com/93736.
diff --git a/third_party/mach_override/mach_override.c b/third_party/mach_override/mach_override.c
index fc04cc2..4768a57 100644
--- a/third_party/mach_override/mach_override.c
+++ b/third_party/mach_override/mach_override.c
@@ -23,7 +23,6 @@
#pragma mark -
#pragma mark (Constants)
-#define kPageSize 4096
#if defined(__ppc__) || defined(__POWERPC__)
long kIslandTemplate[] = {
@@ -77,6 +76,9 @@ char kIslandTemplate[] = {
#endif
+#define kAllocateHigh 1
+#define kAllocateNormal 0
+
/**************************
*
* Data Types
@@ -87,6 +89,7 @@ char kIslandTemplate[] = {
typedef struct {
char instructions[sizeof(kIslandTemplate)];
+ int allocatedHigh;
} BranchIsland;
/**************************
@@ -100,6 +103,7 @@ typedef struct {
mach_error_t
allocateBranchIsland(
BranchIsland **island,
+ int allocateHigh,
void *originalFunctionAddress);
mach_error_t
@@ -130,17 +134,7 @@ eatKnownInstructions(
unsigned char *code,
uint64_t *newInstruction,
int *howManyEaten,
- char *originalInstructions,
- int *originalInstructionCount,
- uint8_t *originalInstructionSizes );
-
- static void
-fixupInstructions(
- void *originalFunction,
- void *escapeIsland,
- void *instructionsToFix,
- int instructionCount,
- uint8_t *instructionSizes );
+ char *originalInstructions );
#endif
/*******************************************************************************
@@ -154,10 +148,12 @@ fixupInstructions(
#if defined(__i386__) || defined(__x86_64__)
mach_error_t makeIslandExecutable(void *address) {
mach_error_t err = err_none;
- uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1);
+ vm_size_t pageSize;
+ host_page_size( mach_host_self(), &pageSize );
+ uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1);
int e = err_none;
- e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
- e |= msync((void *)page, kPageSize, MS_INVALIDATE );
+ e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
+ e |= msync((void *)page, pageSize, MS_INVALIDATE );
if (e) {
err = err_cannot_override;
}
@@ -176,16 +172,17 @@ mach_override_ptr(
// this addresses overriding such functions as AudioOutputUnitStart()
// test with modified DefaultOutputUnit project
-#if defined(__x86_64__)
+#if defined(__x86_64__) || defined(__i386__)
for(;;){
- if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp qword near [rip+0x????????]
+ if(*(unsigned char*)originalFunctionAddress==0xE9) // jmp .+0x????????
+ originalFunctionAddress=(void*)((char*)originalFunctionAddress+5+*(int32_t *)((char*)originalFunctionAddress+1));
+#if defined(__x86_64__)
+ else if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp qword near [rip+0x????????]
originalFunctionAddress=*(void**)((char*)originalFunctionAddress+6+*(int32_t *)((uint16_t*)originalFunctionAddress+1));
- else break;
- }
#elif defined(__i386__)
- for(;;){
- if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp *0x????????
+ else if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp *0x????????
originalFunctionAddress=**(void***)((uint16_t*)originalFunctionAddress+1);
+#endif
else break;
}
#endif
@@ -203,15 +200,11 @@ mach_override_ptr(
err = err_cannot_override;
#elif defined(__i386__) || defined(__x86_64__)
int eatenCount = 0;
- int originalInstructionCount = 0;
char originalInstructions[kOriginalInstructionsSize];
- uint8_t originalInstructionSizes[kOriginalInstructionsSize];
uint64_t jumpRelativeInstruction = 0; // JMP
Boolean overridePossible = eatKnownInstructions ((unsigned char *)originalFunctionPtr,
- &jumpRelativeInstruction, &eatenCount,
- originalInstructions, &originalInstructionCount,
- originalInstructionSizes );
+ &jumpRelativeInstruction, &eatenCount, originalInstructions);
if (eatenCount > kOriginalInstructionsSize) {
//printf ("Too many instructions eaten\n");
overridePossible = false;
@@ -235,7 +228,7 @@ mach_override_ptr(
// Allocate and target the escape island to the overriding function.
BranchIsland *escapeIsland = NULL;
if( !err )
- err = allocateBranchIsland( &escapeIsland, originalFunctionAddress );
+ err = allocateBranchIsland( &escapeIsland, kAllocateHigh, originalFunctionAddress );
if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
@@ -271,13 +264,10 @@ mach_override_ptr(
}
#endif
- // Optionally allocate & return the reentry island. This may contain relocated
- // jmp instructions and so has all the same addressing reachability requirements
- // the escape island has to the original function, except the escape island is
- // technically our original function.
+ // Optionally allocate & return the reentry island.
BranchIsland *reentryIsland = NULL;
if( !err && originalFunctionReentryIsland ) {
- err = allocateBranchIsland( &reentryIsland, escapeIsland);
+ err = allocateBranchIsland( &reentryIsland, kAllocateHigh, NULL);
if( !err )
*originalFunctionReentryIsland = reentryIsland;
}
@@ -320,9 +310,6 @@ mach_override_ptr(
//
// Note that on i386, we do not support someone else changing the code under our feet
if ( !err ) {
- fixupInstructions(originalFunctionPtr, reentryIsland, originalInstructions,
- originalInstructionCount, originalInstructionSizes );
-
if( reentryIsland )
err = setBranchIslandTarget_i386( reentryIsland,
(void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions );
@@ -361,6 +348,9 @@ mach_override_ptr(
Implementation: Allocates memory for a branch island.
@param island <- The allocated island.
+ @param allocateHigh -> Whether to allocate the island at the end of the
+ address space (for use with the branch absolute
+ instruction).
@result <- mach_error_t
***************************************************************************/
@@ -368,63 +358,60 @@ mach_override_ptr(
mach_error_t
allocateBranchIsland(
BranchIsland **island,
+ int allocateHigh,
void *originalFunctionAddress)
{
assert( island );
- assert( sizeof( BranchIsland ) <= kPageSize );
-
- vm_map_t task_self = mach_task_self();
- vm_address_t original_address = (vm_address_t) originalFunctionAddress;
- static vm_address_t last_allocated = 0;
- vm_address_t address =
- last_allocated ? last_allocated : original_address;
-
- for (;;) {
- vm_size_t vmsize = 0;
- memory_object_name_t object = 0;
- kern_return_t kr = 0;
- vm_region_flavor_t flavor = VM_REGION_BASIC_INFO;
- // Find the page the address is in.
-#if __WORDSIZE == 32
- vm_region_basic_info_data_t info;
- mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
- kr = vm_region(task_self, &address, &vmsize, flavor,
- (vm_region_info_t)&info, &info_count, &object);
+
+ mach_error_t err = err_none;
+
+ if( allocateHigh ) {
+ vm_size_t pageSize;
+ err = host_page_size( mach_host_self(), &pageSize );
+ if( !err ) {
+ assert( sizeof( BranchIsland ) <= pageSize );
+#if defined(__x86_64__)
+ vm_address_t first = (uint64_t)originalFunctionAddress & ~(uint64_t)(((uint64_t)1 << 31) - 1) | ((uint64_t)1 << 31); // start in the middle of the page?
+ vm_address_t last = 0x0;
#else
- vm_region_basic_info_data_64_t info;
- mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
- kr = vm_region_64(task_self, &address, &vmsize, flavor,
- (vm_region_info_t)&info, &info_count, &object);
+ vm_address_t first = 0xffc00000;
+ vm_address_t last = 0xfffe0000;
#endif
- if (kr != KERN_SUCCESS)
- return kr;
- // Don't underflow. This could be made to work, but this is a
- // convenient place to give up.
- assert((address & (kPageSize - 1)) == 0);
- if (address == 0)
- break;
+ vm_address_t page = first;
+ int allocated = 0;
+ vm_map_t task_self = mach_task_self();
+
+ while( !err && !allocated && page != last ) {
- // Go back one page.
- vm_address_t new_address = address - kPageSize;
-#if __WORDSIZE == 64
- if(original_address - new_address - 5 > INT32_MAX)
- break;
+ err = vm_allocate( task_self, &page, pageSize, 0 );
+ if( err == err_none )
+ allocated = 1;
+ else if( err == KERN_NO_SPACE ) {
+#if defined(__x86_64__)
+ page -= pageSize;
+#else
+ page += pageSize;
#endif
- address = new_address;
-
- // Try to allocate this page.
- kr = vm_allocate(task_self, &address, kPageSize, 0);
- if (kr == KERN_SUCCESS) {
- *island = (BranchIsland*) address;
- last_allocated = address;
- return err_none;
+ err = err_none;
+ }
+ }
+ if( allocated )
+ *island = (BranchIsland*) page;
+ else if( !allocated && !err )
+ err = KERN_NO_SPACE;
}
- if (kr != KERN_NO_SPACE)
- return kr;
+ } else {
+ void *block = malloc( sizeof( BranchIsland ) );
+ if( block )
+ *island = block;
+ else
+ err = KERN_NO_SPACE;
}
-
- return KERN_NO_SPACE;
+ if( !err )
+ (**island).allocatedHigh = allocateHigh;
+
+ return err;
}
/***************************************************************************//**
@@ -441,9 +428,24 @@ freeBranchIsland(
{
assert( island );
assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] );
- assert( sizeof( BranchIsland ) <= kPageSize );
- return vm_deallocate( mach_task_self(), (vm_address_t) island,
- kPageSize );
+ assert( island->allocatedHigh );
+
+ mach_error_t err = err_none;
+
+ if( island->allocatedHigh ) {
+ vm_size_t pageSize;
+ err = host_page_size( mach_host_self(), &pageSize );
+ if( !err ) {
+ assert( sizeof( BranchIsland ) <= pageSize );
+ err = vm_deallocate(
+ mach_task_self(),
+ (vm_address_t) island, pageSize );
+ }
+ } else {
+ free( island );
+ }
+
+ return err;
}
/***************************************************************************//**
@@ -545,7 +547,6 @@ typedef struct {
#if defined(__i386__)
static AsmInstructionMatch possibleInstructions[] = {
- { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x????????
{ 0x5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x55, 0x89, 0xe5, 0xc9, 0xc3} }, // push %ebp; mov %esp,%ebp; leave; ret
{ 0x1, {0xFF}, {0x90} }, // nop
{ 0x1, {0xFF}, {0x55} }, // push %esp
@@ -559,24 +560,19 @@ static AsmInstructionMatch possibleInstructions[] = {
{ 0x3, {0xFF, 0x4F, 0x00}, {0x8B, 0x45, 0x00} }, // mov $imm(%ebp), %reg
{ 0x3, {0xFF, 0x4C, 0x00}, {0x8B, 0x40, 0x00} }, // mov $imm(%eax-%edx), %reg
{ 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x8B, 0x4C, 0x24, 0x00} }, // mov $imm(%esp), %ecx
- { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %eax
{ 0x0 }
};
#elif defined(__x86_64__)
static AsmInstructionMatch possibleInstructions[] = {
- { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x????????
{ 0x1, {0xFF}, {0x90} }, // nop
{ 0x1, {0xF8}, {0x50} }, // push %rX
{ 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp
{ 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp
{ 0x4, {0xFB, 0xFF, 0x00, 0x00}, {0x48, 0x89, 0x00, 0x00} }, // move onto rbp
- { 0x4, {0xFF, 0xFF, 0xFF, 0xFF}, {0x40, 0x0f, 0xbe, 0xce} }, // movsbl %sil, %ecx
{ 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX
{ 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX
{ 0x5, {0xF8, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %reg
{ 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi)
- { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax
- { 0x2, {0xFF, 0xFF}, {0x89, 0xF8} }, // mov %edi, %eax
{ 0x0 }
};
#endif
@@ -601,21 +597,17 @@ static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch*
#if defined(__i386__) || defined(__x86_64__)
static Boolean
eatKnownInstructions(
- unsigned char *code,
- uint64_t *newInstruction,
- int *howManyEaten,
- char *originalInstructions,
- int *originalInstructionCount,
- uint8_t *originalInstructionSizes )
+ unsigned char *code,
+ uint64_t* newInstruction,
+ int* howManyEaten,
+ char* originalInstructions )
{
Boolean allInstructionsKnown = true;
int totalEaten = 0;
unsigned char* ptr = code;
int remainsToEat = 5; // a JMP instruction takes 5 bytes
- int instructionIndex = 0;
if (howManyEaten) *howManyEaten = 0;
- if (originalInstructionCount) *originalInstructionCount = 0;
while (remainsToEat > 0) {
Boolean curInstructionKnown = false;
@@ -638,10 +630,6 @@ eatKnownInstructions(
ptr += eaten;
remainsToEat -= eaten;
totalEaten += eaten;
-
- if (originalInstructionSizes) originalInstructionSizes[instructionIndex] = eaten;
- instructionIndex += 1;
- if (originalInstructionCount) *originalInstructionCount = instructionIndex;
}
@@ -672,30 +660,6 @@ eatKnownInstructions(
return allInstructionsKnown;
}
-
- static void
-fixupInstructions(
- void *originalFunction,
- void *escapeIsland,
- void *instructionsToFix,
- int instructionCount,
- uint8_t *instructionSizes )
-{
- int index;
- for (index = 0;index < instructionCount;index += 1)
- {
- if (*(uint8_t*)instructionsToFix == 0xE9) // 32-bit jump relative
- {
- uint32_t offset = (uintptr_t)originalFunction - (uintptr_t)escapeIsland;
- uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instructionsToFix + 1);
- *jumpOffsetPtr += offset;
- }
-
- originalFunction = (void*)((uintptr_t)originalFunction + instructionSizes[index]);
- escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSizes[index]);
- instructionsToFix = (void*)((uintptr_t)instructionsToFix + instructionSizes[index]);
- }
-}
#endif
#if defined(__i386__)