Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(728)

Side by Side Diff: third_party/mach_override/mach_override.c

Issue 2946753003: Sped up allocateBranchIsland by skipping whole regions of allocated memory. (Closed)
Patch Set: Fixing release build Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/mach_override/chromium.patch ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // mach_override.c semver:1.2.0 1 // mach_override.c semver:1.2.0
2 // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com 2 // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com
3 // Some rights reserved: http://opensource.org/licenses/mit 3 // Some rights reserved: http://opensource.org/licenses/mit
4 // https://github.com/rentzsch/mach_override 4 // https://github.com/rentzsch/mach_override
5 5
6 #include "mach_override.h" 6 #include "mach_override.h"
7 #if defined(__i386__) || defined(__x86_64__) 7 #if defined(__i386__) || defined(__x86_64__)
8 #include "udis86.h" 8 #include "udis86.h"
9 #endif 9 #endif
10 10
(...skipping 23 matching lines...) Expand all
34 0x8001FFFC, // lwz r0,-4(SP) 34 0x8001FFFC, // lwz r0,-4(SP)
35 0x60000000, // nop ; optionally replaced 35 0x60000000, // nop ; optionally replaced
36 0x4E800420 // bctr 36 0x4E800420 // bctr
37 }; 37 };
38 38
39 #define kAddressHi 3 39 #define kAddressHi 3
40 #define kAddressLo 5 40 #define kAddressLo 5
41 #define kInstructionHi 10 41 #define kInstructionHi 10
42 #define kInstructionLo 11 42 #define kInstructionLo 11
43 43
44 #elif defined(__i386__) 44 #elif defined(__i386__)
45 45
46 #define kOriginalInstructionsSize 16 46 #define kOriginalInstructionsSize 16
47 47
48 char kIslandTemplate[] = { 48 char kIslandTemplate[] = {
49 // kOriginalInstructionsSize nop instructions so that we 49 // kOriginalInstructionsSize nop instructions so that we
50 // should have enough space to host original instructions 50 // should have enough space to host original instructions
51 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 51 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
52 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 52 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
53 // Now the real jump instruction 53 // Now the real jump instruction
54 0xE9, 0xEF, 0xBE, 0xAD, 0xDE 54 0xE9, 0xEF, 0xBE, 0xAD, 0xDE
55 }; 55 };
56 56
57 #define kInstructions 0 57 #define kInstructions 0
58 #define kJumpAddress kInstructions + kOriginalInstructionsSize + 1 58 #define kJumpAddress kInstructions + kOriginalInstructionsSize + 1
59 #elif defined(__x86_64__) 59 #elif defined(__x86_64__)
60 60
61 #define kOriginalInstructionsSize 32 61 #define kOriginalInstructionsSize 32
62 62
63 #define kJumpAddress kOriginalInstructionsSize + 6 63 #define kJumpAddress kOriginalInstructionsSize + 6
64 #define kMaxJumpOffset (0x7fffffffUL)
64 65
65 char kIslandTemplate[] = { 66 char kIslandTemplate[] = {
66 // kOriginalInstructionsSize nop instructions so that we 67 // kOriginalInstructionsSize nop instructions so that we
67 // should have enough space to host original instructions 68 // should have enough space to host original instructions
68 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 69 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
69 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 70 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
70 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 71 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
71 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 72 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
72 // Now the real jump instruction 73 // Now the real jump instruction
73 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 74 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 if( !err ) 261 if( !err )
261 err = setBranchIslandTarget_i386( escapeIsland, overrideFunction Address, 0 ); 262 err = setBranchIslandTarget_i386( escapeIsland, overrideFunction Address, 0 );
262 263
263 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); 264 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
264 // Build the jump relative instruction to the escape island 265 // Build the jump relative instruction to the escape island
265 #endif 266 #endif
266 267
267 268
268 #if defined(__i386__) || defined(__x86_64__) 269 #if defined(__i386__) || defined(__x86_64__)
269 if (!err) { 270 if (!err) {
270 » » uint32_t addressOffset = ((char*)escapeIsland - (char*)originalF unctionPtr - 5); 271 » » // TODO: On 64-bit, move to opcode FF/4 (jmp 64-bit absolute ind irect)
272 » » // instead of E9 (jmp 32-bit relative to RIP). Then we should up date
273 » » // allocateBranchIsland to simply allocate any page in the addre ss space.
274 » » // See the 64-bit version of kIslandTemplate array.
275 » » int64_t addressOffset64 = ((char*)escapeIsland - (char*)original FunctionPtr - 5);
276 » » int32_t addressOffset = addressOffset64;
277 » » assert(addressOffset64 == addressOffset);
271 addressOffset = OSSwapInt32(addressOffset); 278 addressOffset = OSSwapInt32(addressOffset);
272 279
273 jumpRelativeInstruction |= 0xE900000000000000LL; 280 jumpRelativeInstruction |= 0xE900000000000000LL;
274 jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff ) << 24; 281 jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff ) << 24;
275 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); 282 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction);
276 } 283 }
277 #endif 284 #endif
278 285
279 // Optionally allocate & return the reentry island. This may contai n relocated 286 // Optionally allocate & return the reentry island. This may contai n relocated
280 // jmp instructions and so has all the same addressing reachability req uirements 287 // jmp instructions and so has all the same addressing reachability req uirements
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 385
379 ************************************************************************ ***/ 386 ************************************************************************ ***/
380 387
381 mach_error_t 388 mach_error_t
382 allocateBranchIsland( 389 allocateBranchIsland(
383 BranchIsland **island, 390 BranchIsland **island,
384 int allocateHigh, 391 int allocateHigh,
385 void *originalFunctionAddress) 392 void *originalFunctionAddress)
386 { 393 {
387 assert( island ); 394 assert( island );
388 » 395
389 mach_error_t err = err_none; 396 mach_error_t err = err_none;
390 397
391 if( allocateHigh ) { 398 if( allocateHigh ) {
392 assert( sizeof( BranchIsland ) <= PAGE_SIZE ); 399 assert( sizeof( BranchIsland ) <= PAGE_SIZE );
393 vm_address_t page = 0; 400 vm_address_t page = 0;
394 #if defined(__i386__) 401 #if defined(__i386__)
395 err = vm_allocate( mach_task_self(), &page, PAGE_SIZE, VM_FLAGS_ ANYWHERE ); 402 err = vm_allocate( mach_task_self(), &page, PAGE_SIZE, VM_FLAGS_ ANYWHERE );
396 if( err == err_none ) 403 if( err == err_none )
397 *island = (BranchIsland*) page; 404 *island = (BranchIsland*) page;
398 #else 405 #else
399 406
400 #if defined(__ppc__) || defined(__POWERPC__) 407 #if defined(__ppc__) || defined(__POWERPC__)
401 vm_address_t first = 0xfeffffff; 408 vm_address_t first = 0xfeffffff;
402 vm_address_t last = 0xfe000000 + PAGE_SIZE; 409 vm_address_t last = 0xfe000000 + PAGE_SIZE;
403 #elif defined(__x86_64__) 410 #elif defined(__x86_64__)
404 » » // 64-bit ASLR is in bits 13-28 411 » » // This logic is more complex due to the 32-bit limit of the jum p out
405 » » vm_address_t first = ((uint64_t)originalFunctionAddress & ~( (0x FUL << 28) | (PAGE_SIZE - 1) ) ) | (0x1UL << 31); 412 » » // of the original function. Once that limitation is removed, we can
406 » » vm_address_t last = (uint64_t)originalFunctionAddress & ~((0x1UL << 32) - 1); 413 » » // use vm_allocate with VM_FLAGS_ANYWHERE as in the i386 code ab ove.
414 » » const uint64_t kPageMask = ~(PAGE_SIZE - 1);
415 » » vm_address_t first = (uint64_t)originalFunctionAddress - kMaxJum pOffset;
416 » » first = (first & kPageMask) + PAGE_SIZE; // Align up to the next page start
417 » » if (first > (uint64_t)originalFunctionAddress) first = 0;
418 » » vm_address_t last = (uint64_t)originalFunctionAddress + kMaxJump Offset;
419 » » if (last < (uint64_t)originalFunctionAddress) last = ULONG_MAX;
407 #endif 420 #endif
408 421
409 page = first; 422 page = first;
410 int allocated = 0; 423 int allocated = 0;
411 vm_map_t task_self = mach_task_self(); 424 vm_map_t task_self = mach_task_self();
412 425
413 » » while( !err && !allocated && page != last ) { 426 » » while( !err && !allocated && page < last ) {
414 427
415 err = vm_allocate( task_self, &page, PAGE_SIZE, 0 ); 428 err = vm_allocate( task_self, &page, PAGE_SIZE, 0 );
416 if( err == err_none ) 429 if( err == err_none )
417 allocated = 1; 430 allocated = 1;
418 else if( err == KERN_NO_SPACE ) { 431 else if( err == KERN_NO_SPACE ) {
419 #if defined(__x86_64__) 432 #if defined(__x86_64__)
420 » » » » page -= PAGE_SIZE; 433 » » » » // This memory region is not suitable, skip it:
434 » » » » vm_size_t region_size;
435 » » » » mach_msg_type_number_t int_count = VM_REGION_BAS IC_INFO_COUNT_64;
436 » » » » vm_region_basic_info_data_64_t vm_region_info;
437 » » » » mach_port_t object_name;
438 » » » » // The call will move 'page' to the beginning of the region:
439 » » » » err = vm_region_64(task_self, &page, &region_siz e,
440 » » » » » » » VM_REGION_BASIC_INFO_64, (vm_region_info_t)&vm_region_info,
441 » » » » » » » &int_count, &object_name );
442 » » » » if (err == KERN_SUCCESS)
443 » » » » » page += region_size;
444 » » » » else
445 » » » » » break;
421 #else 446 #else
422 page += PAGE_SIZE; 447 page += PAGE_SIZE;
423 #endif 448 #endif
424 err = err_none; 449 err = err_none;
425 } 450 }
426 } 451 }
427 if( allocated ) 452 if( allocated )
428 *island = (BranchIsland*) page; 453 *island = (BranchIsland*) page;
429 else if( !allocated && !err ) 454 else if( !allocated && !err )
430 err = KERN_NO_SPACE; 455 err = KERN_NO_SPACE;
431 #endif 456 #endif
432 } else { 457 } else {
433 void *block = malloc( sizeof( BranchIsland ) ); 458 void *block = malloc( sizeof( BranchIsland ) );
434 if( block ) 459 if( block )
435 *island = block; 460 *island = block;
436 else 461 else
437 err = KERN_NO_SPACE; 462 err = KERN_NO_SPACE;
438 } 463 }
439 if( !err ) 464 if( !err )
440 (**island).allocatedHigh = allocateHigh; 465 (**island).allocatedHigh = allocateHigh;
441 » 466
442 return err; 467 return err;
443 } 468 }
444 469
445 /******************************************************************************* 470 /*******************************************************************************
446 Implementation: Deallocates memory for a branch island. 471 Implementation: Deallocates memory for a branch island.
447 472
448 @param island -> The island to deallocate. 473 @param island -> The island to deallocate.
449 @result <- mach_error_t 474 @result <- mach_error_t
450 475
451 ************************************************************************ ***/ 476 ************************************************************************ ***/
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 ); 716 );
692 #elif defined(__x86_64__) 717 #elif defined(__x86_64__)
693 void atomic_mov64( 718 void atomic_mov64(
694 uint64_t *targetAddress, 719 uint64_t *targetAddress,
695 uint64_t value ) 720 uint64_t value )
696 { 721 {
697 *targetAddress = value; 722 *targetAddress = value;
698 } 723 }
699 #endif 724 #endif
700 #endif 725 #endif
OLDNEW
« no previous file with comments | « third_party/mach_override/chromium.patch ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698