diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-09 21:18:26 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-09 21:18:26 +0000 |
commit | f7e48f1526964d61b40e0cdad33e0e13b04fc12b (patch) | |
tree | cdd09864603ba1cb19844ec169b3d86bf6267fa3 /third_party/mach_override/mach_override.c | |
parent | dd6210f7b59c64637dfe907b0bd2cf693329c037 (diff) | |
download | chromium_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/mach_override.c')
-rw-r--r-- | third_party/mach_override/mach_override.c | 218 |
1 files changed, 91 insertions, 127 deletions
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__) |