Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /******************************************************************************* | 1 // mach_override.c semver:1.2.0 |
|
Mark Mentovai
2013/11/05 23:35:37
This patch set contains our local changes merged b
| |
| 2 » mach_override.c | 2 // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com |
| 3 » » Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzs ch.com> | 3 // Some rights reserved: http://opensource.org/licenses/mit |
| 4 » » Some rights reserved: <http://opensource.org/licenses/mit-licens e.php> | 4 // https://github.com/rentzsch/mach_override |
| 5 | 5 |
| 6 ************************************************************************ ***/ | |
| 7 | |
| 8 #include "mach_override.h" | 6 #include "mach_override.h" |
| 7 #if defined(__i386__) || defined(__x86_64__) | |
| 8 #include "udis86.h" | |
| 9 #endif | |
| 9 | 10 |
| 10 #include <mach-o/dyld.h> | 11 #include <mach-o/dyld.h> |
| 11 #include <mach/mach_host.h> | 12 #include <mach/mach_host.h> |
| 12 #include <mach/mach_init.h> | 13 #include <mach/mach_init.h> |
| 13 #include <mach/vm_map.h> | 14 #include <mach/vm_map.h> |
| 14 #include <mach/vm_statistics.h> | 15 #include <mach/vm_statistics.h> |
| 15 #include <sys/mman.h> | 16 #include <sys/mman.h> |
| 16 | 17 |
| 17 #include <CoreServices/CoreServices.h> | 18 #include <CoreServices/CoreServices.h> |
| 18 | 19 |
| 19 /************************** | 20 /************************** |
| 20 * | 21 * |
| 21 * Constants | 22 * Constants |
| 22 * | 23 * |
| 23 **************************/ | 24 **************************/ |
| 24 #pragma mark - | 25 #pragma mark - |
| 25 #pragma mark (Constants) | 26 #pragma mark (Constants) |
| 26 | 27 |
| 27 #define kPageSize 4096 | |
| 28 #if defined(__ppc__) || defined(__POWERPC__) | 28 #if defined(__ppc__) || defined(__POWERPC__) |
| 29 | 29 |
| 30 long kIslandTemplate[] = { | 30 long kIslandTemplate[] = { |
| 31 0x9001FFFC, // stw r0,-4(SP) | 31 0x9001FFFC, // stw r0,-4(SP) |
| 32 0x3C00DEAD, // lis r0,0xDEAD | 32 0x3C00DEAD, // lis r0,0xDEAD |
| 33 0x6000BEEF, // ori r0,r0,0xBEEF | 33 0x6000BEEF, // ori r0,r0,0xBEEF |
| 34 0x7C0903A6, // mtctr r0 | 34 0x7C0903A6, // mtctr r0 |
| 35 0x8001FFFC, // lwz r0,-4(SP) | 35 0x8001FFFC, // lwz r0,-4(SP) |
| 36 0x60000000, // nop ; optionally replaced | 36 0x60000000, // nop ; optionally replaced |
| 37 0x4E800420 // bctr | 37 0x4E800420 // bctr |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, |
| 73 // Now the real jump instruction | 73 // Now the real jump instruction |
| 74 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, | 74 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, |
| 75 0x00, 0x00, 0x00, 0x00, | 75 0x00, 0x00, 0x00, 0x00, |
| 76 0x00, 0x00, 0x00, 0x00 | 76 0x00, 0x00, 0x00, 0x00 |
| 77 }; | 77 }; |
| 78 | 78 |
| 79 #endif | 79 #endif |
| 80 | 80 |
| 81 #define kAllocateHigh 1 | |
| 82 #define kAllocateNormal 0 | |
| 83 | |
| 81 /************************** | 84 /************************** |
| 82 * | 85 * |
| 83 * Data Types | 86 * Data Types |
| 84 * | 87 * |
| 85 **************************/ | 88 **************************/ |
| 86 #pragma mark - | 89 #pragma mark - |
| 87 #pragma mark (Data Types) | 90 #pragma mark (Data Types) |
| 88 | 91 |
| 89 typedef struct { | 92 typedef struct { |
| 90 char instructions[sizeof(kIslandTemplate)]; | 93 char instructions[sizeof(kIslandTemplate)]; |
| 94 int allocatedHigh; | |
| 91 } BranchIsland; | 95 } BranchIsland; |
| 92 | 96 |
| 93 /************************** | 97 /************************** |
| 94 * | 98 * |
| 95 * Funky Protos | 99 * Funky Protos |
| 96 * | 100 * |
| 97 **************************/ | 101 **************************/ |
| 98 #pragma mark - | 102 #pragma mark - |
| 99 #pragma mark (Funky Protos) | 103 #pragma mark (Funky Protos) |
| 100 | 104 |
| 101 mach_error_t | 105 mach_error_t |
| 102 allocateBranchIsland( | 106 allocateBranchIsland( |
| 103 BranchIsland **island, | 107 BranchIsland **island, |
| 108 int allocateHigh, | |
| 104 void *originalFunctionAddress); | 109 void *originalFunctionAddress); |
| 105 | 110 |
| 106 mach_error_t | 111 mach_error_t |
| 107 freeBranchIsland( | 112 freeBranchIsland( |
| 108 BranchIsland *island ); | 113 BranchIsland *island ); |
| 109 | 114 |
| 110 #if defined(__ppc__) || defined(__POWERPC__) | 115 #if defined(__ppc__) || defined(__POWERPC__) |
| 111 mach_error_t | 116 mach_error_t |
| 112 setBranchIslandTarget( | 117 setBranchIslandTarget( |
| 113 BranchIsland *island, | 118 BranchIsland *island, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 148 * | 153 * |
| 149 * Interface | 154 * Interface |
| 150 * | 155 * |
| 151 *******************************************************************************/ | 156 *******************************************************************************/ |
| 152 #pragma mark - | 157 #pragma mark - |
| 153 #pragma mark (Interface) | 158 #pragma mark (Interface) |
| 154 | 159 |
| 155 #if defined(__i386__) || defined(__x86_64__) | 160 #if defined(__i386__) || defined(__x86_64__) |
| 156 mach_error_t makeIslandExecutable(void *address) { | 161 mach_error_t makeIslandExecutable(void *address) { |
| 157 mach_error_t err = err_none; | 162 mach_error_t err = err_none; |
| 158 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1); | 163 vm_size_t pageSize; |
| 164 host_page_size( mach_host_self(), &pageSize ); | |
| 165 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1); | |
| 159 int e = err_none; | 166 int e = err_none; |
| 160 e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ); | 167 e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ); |
| 161 e |= msync((void *)page, kPageSize, MS_INVALIDATE ); | 168 e |= msync((void *)page, pageSize, MS_INVALIDATE ); |
| 162 if (e) { | 169 if (e) { |
| 163 err = err_cannot_override; | 170 err = err_cannot_override; |
| 164 } | 171 } |
| 165 return err; | 172 return err; |
| 166 } | 173 } |
| 167 #endif | 174 #endif |
| 168 | 175 |
| 169 mach_error_t | 176 mach_error_t |
| 170 mach_override_ptr( | 177 mach_override_ptr( |
| 171 void *originalFunctionAddress, | 178 void *originalFunctionAddress, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 if( err ) | 236 if( err ) |
| 230 err = vm_protect( mach_task_self(), | 237 err = vm_protect( mach_task_self(), |
| 231 (vm_address_t) originalFunctionPtr, 8, f alse, | 238 (vm_address_t) originalFunctionPtr, 8, f alse, |
| 232 (VM_PROT_DEFAULT | VM_PROT_COPY) ); | 239 (VM_PROT_DEFAULT | VM_PROT_COPY) ); |
| 233 } | 240 } |
| 234 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); | 241 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); |
| 235 | 242 |
| 236 // Allocate and target the escape island to the overriding function . | 243 // Allocate and target the escape island to the overriding function . |
| 237 BranchIsland *escapeIsland = NULL; | 244 BranchIsland *escapeIsland = NULL; |
| 238 if( !err ) | 245 if( !err ) |
| 239 » » err = allocateBranchIsland( &escapeIsland, originalFunctionAddre ss ); | 246 » » err = allocateBranchIsland( &escapeIsland, kAllocateHigh, origin alFunctionAddress ); |
| 240 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LI NE__); | 247 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LI NE__); |
| 241 | 248 |
| 242 | 249 |
| 243 #if defined(__ppc__) || defined(__POWERPC__) | 250 #if defined(__ppc__) || defined(__POWERPC__) |
| 244 if( !err ) | 251 if( !err ) |
| 245 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 ); | 252 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 ); |
| 246 | 253 |
| 247 // Build the branch absolute instruction to the escape island. | 254 // Build the branch absolute instruction to the escape island. |
| 248 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng. | 255 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng. |
| 249 if( !err ) { | 256 if( !err ) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 271 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); | 278 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); |
| 272 } | 279 } |
| 273 #endif | 280 #endif |
| 274 | 281 |
| 275 // Optionally allocate & return the reentry island. This may contai n relocated | 282 // Optionally allocate & return the reentry island. This may contai n relocated |
| 276 // jmp instructions and so has all the same addressing reachability req uirements | 283 // jmp instructions and so has all the same addressing reachability req uirements |
| 277 // the escape island has to the original function, except the escape is land is | 284 // the escape island has to the original function, except the escape is land is |
| 278 // technically our original function. | 285 // technically our original function. |
| 279 BranchIsland *reentryIsland = NULL; | 286 BranchIsland *reentryIsland = NULL; |
| 280 if( !err && originalFunctionReentryIsland ) { | 287 if( !err && originalFunctionReentryIsland ) { |
| 281 » » err = allocateBranchIsland( &reentryIsland, escapeIsland); | 288 » » err = allocateBranchIsland( &reentryIsland, kAllocateHigh, escap eIsland); |
| 282 if( !err ) | 289 if( !err ) |
| 283 *originalFunctionReentryIsland = reentryIsland; | 290 *originalFunctionReentryIsland = reentryIsland; |
| 284 } | 291 } |
| 285 | 292 |
| 286 #if defined(__ppc__) || defined(__POWERPC__) | 293 #if defined(__ppc__) || defined(__POWERPC__) |
| 287 // Atomically: | 294 // Atomically: |
| 288 // o If the reentry island was allocated: | 295 // o If the reentry island was allocated: |
| 289 // o Insert the original instruction into the reentry islan d. | 296 // o Insert the original instruction into the reentry islan d. |
| 290 // o Target the reentry island at the 2nd instruction of th e | 297 // o Target the reentry island at the 2nd instruction of th e |
| 291 // original function. | 298 // original function. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 357 } | 364 } |
| 358 | 365 |
| 359 /******************************************************************************* | 366 /******************************************************************************* |
| 360 * | 367 * |
| 361 * Implementation | 368 * Implementation |
| 362 * | 369 * |
| 363 *******************************************************************************/ | 370 *******************************************************************************/ |
| 364 #pragma mark - | 371 #pragma mark - |
| 365 #pragma mark (Implementation) | 372 #pragma mark (Implementation) |
| 366 | 373 |
| 367 /***************************************************************************//** | 374 /******************************************************************************* |
| 368 Implementation: Allocates memory for a branch island. | 375 Implementation: Allocates memory for a branch island. |
| 369 | 376 |
| 370 @param island <- The allocated island. | 377 @param island <- The allocated island. |
| 378 @param allocateHigh -> Whether to allocate the island at the en d of the | |
| 379 address space (f or use with the branch absolute | |
| 380 instruction). | |
| 371 @result <- mach_error_t | 381 @result <- mach_error_t |
| 372 | 382 |
| 373 ************************************************************************ ***/ | 383 ************************************************************************ ***/ |
| 374 | 384 |
| 375 mach_error_t | 385 mach_error_t |
| 376 allocateBranchIsland( | 386 allocateBranchIsland( |
| 377 BranchIsland **island, | 387 BranchIsland **island, |
| 388 int allocateHigh, | |
| 378 void *originalFunctionAddress) | 389 void *originalFunctionAddress) |
| 379 { | 390 { |
| 380 assert( island ); | 391 assert( island ); |
| 381 | 392 |
| 382 » assert( sizeof( BranchIsland ) <= kPageSize ); | 393 » mach_error_t» err = err_none; |
| 394 » | |
| 395 » if( allocateHigh ) { | |
| 396 » » vm_size_t pageSize; | |
| 397 » » err = host_page_size( mach_host_self(), &pageSize ); | |
| 398 » » if( !err ) { | |
| 399 » » » assert( sizeof( BranchIsland ) <= pageSize ); | |
| 383 #if defined(__i386__) | 400 #if defined(__i386__) |
| 384 » vm_address_t page = 0; | 401 » » » vm_address_t page = 0; |
| 385 » mach_error_t err = vm_allocate( mach_task_self(), &page, kPageSize, VM_F LAGS_ANYWHERE ); | 402 » » » mach_error_t err = vm_allocate( mach_task_self(), &page, pageSize, VM_FLAGS_ANYWHERE ); |
| 386 » if( err == err_none ) { | 403 » » » if( err == err_none ) { |
| 387 » » *island = (BranchIsland*) page; | 404 » » » » *island = (BranchIsland*) page; |
| 388 » » return err_none; | 405 » » » » return err_none; |
| 389 » } | 406 » » » } |
| 390 » return err; | 407 » » » return err; |
| 391 #else | 408 #else |
| 392 | 409 |
| 393 #if defined(__ppc__) || defined(__POWERPC__) | 410 #if defined(__ppc__) || defined(__POWERPC__) |
| 394 » vm_address_t first = 0xfeffffff; | 411 » » » vm_address_t first = 0xfeffffff; |
| 395 » vm_address_t last = 0xfe000000 + kPageSize; | 412 » » » vm_address_t last = 0xfe000000 + pageSize; |
| 396 #elif defined(__x86_64__) | 413 #elif defined(__x86_64__) |
| 397 » vm_address_t first = ((uint64_t)originalFunctionAddress & ~(uint64_t)((( uint64_t)1 << 31) - 1)) | ((uint64_t)1 << 31); // start in the middle of the pag e? | 414 » » » vm_address_t first = ((uint64_t)originalFunctionAddress & ~(uint64_t)(((uint64_t)1 << 31) - 1)) | ((uint64_t)1 << 31); // start in the m iddle of the page? |
| 398 » vm_address_t last = 0x0; | 415 » » » vm_address_t last = 0x0; |
| 399 #endif | 416 #endif |
| 400 | 417 |
| 401 » vm_address_t page = first; | 418 » » » vm_address_t page = first; |
| 402 » vm_map_t task_self = mach_task_self(); | 419 » » » int allocated = 0; |
| 420 » » » vm_map_t task_self = mach_task_self(); | |
| 421 » » » | |
| 422 » » » while( !err && !allocated && page != last ) { | |
| 403 | 423 |
| 404 » while( page != last ) { | 424 » » » » err = vm_allocate( task_self, &page, pageSize, 0 ); |
| 405 » » mach_error_t err = vm_allocate( task_self, &page, kPageSize, 0 ) ; | 425 » » » » if( err == err_none ) |
| 406 » » if( err == err_none ) { | 426 » » » » » allocated = 1; |
| 407 » » » *island = (BranchIsland*) page; | 427 » » » » else if( err == KERN_NO_SPACE ) { |
| 408 » » » return err_none; | |
| 409 } | |
| 410 » » if( err != KERN_NO_SPACE ) | |
| 411 » » » return err; | |
| 412 #if defined(__x86_64__) | 428 #if defined(__x86_64__) |
| 413 » » page -= kPageSize; | 429 » » » » » page -= pageSize; |
| 414 #else | 430 #else |
| 415 » » page += kPageSize; | 431 » » » » » page += pageSize; |
| 416 #endif | 432 #endif |
| 417 » » err = err_none; | 433 » » » » » err = err_none; |
| 434 » » » » } | |
| 435 » » » } | |
| 436 » » » if( allocated ) | |
| 437 » » » » *island = (BranchIsland*) page; | |
| 438 » » » else if( !allocated && !err ) | |
| 439 » » » » err = KERN_NO_SPACE; | |
| 440 #endif | |
| 441 » » } | |
| 442 » } else { | |
| 443 » » void *block = malloc( sizeof( BranchIsland ) ); | |
| 444 » » if( block ) | |
| 445 » » » *island = block; | |
| 446 » » else | |
| 447 » » » err = KERN_NO_SPACE; | |
| 418 } | 448 } |
| 419 | 449 » if( !err ) |
| 420 » return KERN_NO_SPACE; | 450 » » (**island).allocatedHigh = allocateHigh; |
| 421 #endif | 451 » |
| 452 » return err; | |
| 422 } | 453 } |
| 423 | 454 |
| 424 /***************************************************************************//** | 455 /******************************************************************************* |
| 425 Implementation: Deallocates memory for a branch island. | 456 Implementation: Deallocates memory for a branch island. |
| 426 | 457 |
| 427 @param island -> The island to deallocate. | 458 @param island -> The island to deallocate. |
| 428 @result <- mach_error_t | 459 @result <- mach_error_t |
| 429 | 460 |
| 430 ************************************************************************ ***/ | 461 ************************************************************************ ***/ |
| 431 | 462 |
| 432 mach_error_t | 463 mach_error_t |
| 433 freeBranchIsland( | 464 freeBranchIsland( |
| 434 BranchIsland *island ) | 465 BranchIsland *island ) |
| 435 { | 466 { |
| 436 assert( island ); | 467 assert( island ); |
| 437 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); | 468 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); |
| 438 » assert( sizeof( BranchIsland ) <= kPageSize ); | 469 » assert( island->allocatedHigh ); |
| 439 » return vm_deallocate( mach_task_self(), (vm_address_t) island, | 470 » |
| 440 » » » kPageSize ); | 471 » mach_error_t» err = err_none; |
| 472 » | |
| 473 » if( island->allocatedHigh ) { | |
| 474 » » vm_size_t pageSize; | |
| 475 » » err = host_page_size( mach_host_self(), &pageSize ); | |
| 476 » » if( !err ) { | |
| 477 » » » assert( sizeof( BranchIsland ) <= pageSize ); | |
| 478 » » » err = vm_deallocate( | |
| 479 » » » » » mach_task_self(), | |
| 480 » » » » » (vm_address_t) island, pageSize ); | |
| 481 » » } | |
| 482 » } else { | |
| 483 » » free( island ); | |
| 484 » } | |
| 485 » | |
| 486 » return err; | |
| 441 } | 487 } |
| 442 | 488 |
| 443 /***************************************************************************//** | 489 /******************************************************************************* |
| 444 Implementation: Sets the branch island's target, with an optional | 490 Implementation: Sets the branch island's target, with an optional |
| 445 instruction. | 491 instruction. |
| 446 | 492 |
| 447 @param island -> The branch island to insert target into. | 493 @param island -> The branch island to insert target into. |
| 448 @param branchTo -> The address of the target. | 494 @param branchTo -> The address of the target. |
| 449 @param instruction -> Optional instruction to execute prior to branch. Set | 495 @param instruction -> Optional instruction to execute prior to branch. Set |
| 450 to zero for nop. | 496 to zero for nop. |
| 451 @result <- mach_error_t | 497 @result <- mach_error_t |
| 452 | 498 |
| 453 ************************************************************************ ***/ | 499 ************************************************************************ ***/ |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 523 // Fill in the address. | 569 // Fill in the address. |
| 524 *((uint64_t *)(island->instructions + kJumpAddress)) = (uint64_t)branchTo; | 570 *((uint64_t *)(island->instructions + kJumpAddress)) = (uint64_t)branchTo; |
| 525 msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE ); | 571 msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE ); |
| 526 | 572 |
| 527 return err_none; | 573 return err_none; |
| 528 } | 574 } |
| 529 #endif | 575 #endif |
| 530 | 576 |
| 531 | 577 |
| 532 #if defined(__i386__) || defined(__x86_64__) | 578 #if defined(__i386__) || defined(__x86_64__) |
| 533 // simplistic instruction matching | |
| 534 typedef struct { | |
| 535 unsigned int length; // max 15 | |
| 536 unsigned char mask[15]; // sequence of bytes in memory order | |
| 537 unsigned char constraint[15]; // sequence of bytes in memory order | |
| 538 } AsmInstructionMatch; | |
| 539 | |
| 540 #if defined(__i386__) | |
| 541 static AsmInstructionMatch possibleInstructions[] = { | |
| 542 { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x???????? | |
| 543 { 0x5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x55, 0x89, 0xe5, 0xc9, 0xc3} }, // push %ebp; mov %esp,%ebp; leave; ret | |
| 544 { 0x1, {0xFF}, {0x90} }, // nop | |
| 545 { 0x1, {0xFF}, {0x55} }, // push %esp | |
| 546 { 0x2, {0xFF, 0xFF}, {0x89, 0xE5} }, // mov %esp,%ebp | |
| 547 { 0x1, {0xFF}, {0x53} }, // push %ebx | |
| 548 { 0x3, {0xFF, 0xFF, 0x00}, {0x83, 0xEC, 0x00} }, // sub 0x??, %esp | |
| 549 { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x81, 0xEC, 0x00, 0x00, 0x 00, 0x00} }, // sub 0x??, %esp with 32bit immediate | |
| 550 { 0x1, {0xFF}, {0x57} }, // push %edi | |
| 551 { 0x1, {0xFF}, {0x56} }, // push %esi | |
| 552 { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax | |
| 553 { 0x3, {0xFF, 0x4F, 0x00}, {0x8B, 0x45, 0x00} }, // mov $imm(%ebp), %re g | |
| 554 { 0x3, {0xFF, 0x4C, 0x00}, {0x8B, 0x40, 0x00} }, // mov $imm(%eax-%edx) , %reg | |
| 555 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x8B, 0x4C, 0x24, 0x00} }, // mov $im m(%esp), %ecx | |
| 556 { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %eax | |
| 557 { 0x0 } | |
| 558 }; | |
| 559 #elif defined(__x86_64__) | |
| 560 static AsmInstructionMatch possibleInstructions[] = { | |
| 561 { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x???????? | |
| 562 { 0x1, {0xFF}, {0x90} }, // nop | |
| 563 { 0x1, {0xF8}, {0x50} }, // push %rX | |
| 564 { 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp | |
| 565 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp | |
| 566 { 0x4, {0xFB, 0xFF, 0x00, 0x00}, {0x48, 0x89, 0x00, 0x00} }, // move onto rbp | |
| 567 { 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX | |
| 568 { 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX | |
| 569 { 0x5, {0xF8, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %reg | |
| 570 { 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi) | |
| 571 { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax | |
| 572 { 0x2, {0xFF, 0xFF}, {0x89, 0xF8} }, // mov %edi, %ea x | |
| 573 { 0x0 } | |
| 574 }; | |
| 575 #endif | |
| 576 | |
| 577 static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch* instruction) | |
| 578 { | |
| 579 Boolean match = true; | |
| 580 | |
| 581 size_t i; | |
| 582 for (i=0; i<instruction->length; i++) { | |
| 583 unsigned char mask = instruction->mask[i]; | |
| 584 unsigned char constraint = instruction->constraint[i]; | |
| 585 unsigned char codeValue = code[i]; | |
| 586 | |
| 587 match = ((codeValue & mask) == constraint); | |
| 588 if (!match) break; | |
| 589 } | |
| 590 | |
| 591 return match; | |
| 592 } | |
| 593 | |
| 594 #if defined(__i386__) || defined(__x86_64__) | |
| 595 static Boolean | 579 static Boolean |
| 596 eatKnownInstructions( | 580 eatKnownInstructions( |
| 597 unsigned char *code, | 581 unsigned char *code, |
| 598 uint64_t *newInstruction, | 582 uint64_t *newInstruction, |
| 599 int *howManyEaten, | 583 int *howManyEaten, |
| 600 char *originalInstructions, | 584 char *originalInstructions, |
| 601 int *originalInstructionCount, | 585 int *originalInstructionCount, |
| 602 uint8_t *originalInstructionSizes ) | 586 uint8_t *originalInstructionSizes ) |
| 603 { | 587 { |
| 604 Boolean allInstructionsKnown = true; | 588 Boolean allInstructionsKnown = true; |
| 605 int totalEaten = 0; | 589 int totalEaten = 0; |
| 606 unsigned char* ptr = code; | |
| 607 int remainsToEat = 5; // a JMP instruction takes 5 bytes | 590 int remainsToEat = 5; // a JMP instruction takes 5 bytes |
| 608 int instructionIndex = 0; | 591 int instructionIndex = 0; |
| 592 ud_t ud_obj; | |
| 609 | 593 |
| 610 if (howManyEaten) *howManyEaten = 0; | 594 if (howManyEaten) *howManyEaten = 0; |
| 611 if (originalInstructionCount) *originalInstructionCount = 0; | 595 if (originalInstructionCount) *originalInstructionCount = 0; |
| 596 ud_init(&ud_obj); | |
| 597 #if defined(__i386__) | |
| 598 ud_set_mode(&ud_obj, 32); | |
| 599 #else | |
| 600 ud_set_mode(&ud_obj, 64); | |
| 601 #endif | |
| 602 ud_set_input_buffer(&ud_obj, code, 64); // Assume that 'code' points to at least 64bytes of data. | |
| 612 while (remainsToEat > 0) { | 603 while (remainsToEat > 0) { |
| 613 » » Boolean curInstructionKnown = false; | 604 » » if (!ud_disassemble(&ud_obj)) { |
| 614 » » | 605 » » allInstructionsKnown = false; |
| 615 » » // See if instruction matches one we know | 606 » » fprintf(stderr, "mach_override: some instructions unknown! N eed to update libudis86\n"); |
| 616 » » AsmInstructionMatch* curInstr = possibleInstructions; | 607 » » break; |
| 617 » » do { | |
| 618 » » » if ((curInstructionKnown = codeMatchesInstruction(ptr, c urInstr))) break; | |
| 619 » » » curInstr++; | |
| 620 » » } while (curInstr->length > 0); | |
| 621 » » | |
| 622 » » // if all instruction matches failed, we don't know current inst ruction then, stop here | |
| 623 » » if (!curInstructionKnown) { | |
| 624 » » » allInstructionsKnown = false; | |
| 625 » » » fprintf(stderr, "mach_override: some instructions unknow n! Need to update mach_override.c\n"); | |
| 626 » » » break; | |
| 627 } | 608 } |
| 628 | 609 |
| 629 // At this point, we've matched curInstr | 610 // At this point, we've matched curInstr |
| 630 » » int eaten = curInstr->length; | 611 » » int eaten = ud_insn_len(&ud_obj); |
| 631 » » ptr += eaten; | |
| 632 remainsToEat -= eaten; | 612 remainsToEat -= eaten; |
| 633 totalEaten += eaten; | 613 totalEaten += eaten; |
| 634 | 614 |
| 635 if (originalInstructionSizes) originalInstructionSizes[instructi onIndex] = eaten; | 615 if (originalInstructionSizes) originalInstructionSizes[instructi onIndex] = eaten; |
| 636 instructionIndex += 1; | 616 instructionIndex += 1; |
| 637 if (originalInstructionCount) *originalInstructionCount = instru ctionIndex; | 617 if (originalInstructionCount) *originalInstructionCount = instru ctionIndex; |
| 638 } | 618 } |
| 639 | 619 |
| 640 | 620 |
| 641 if (howManyEaten) *howManyEaten = totalEaten; | 621 if (howManyEaten) *howManyEaten = totalEaten; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 682 uint32_t offset = (uintptr_t)originalFunction - (uintptr _t)escapeIsland; | 662 uint32_t offset = (uintptr_t)originalFunction - (uintptr _t)escapeIsland; |
| 683 uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instruc tionsToFix + 1); | 663 uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instruc tionsToFix + 1); |
| 684 *jumpOffsetPtr += offset; | 664 *jumpOffsetPtr += offset; |
| 685 } | 665 } |
| 686 | 666 |
| 687 originalFunction = (void*)((uintptr_t)originalFunction + instruc tionSizes[index]); | 667 originalFunction = (void*)((uintptr_t)originalFunction + instruc tionSizes[index]); |
| 688 escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSize s[index]); | 668 escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSize s[index]); |
| 689 instructionsToFix = (void*)((uintptr_t)instructionsToFix + instr uctionSizes[index]); | 669 instructionsToFix = (void*)((uintptr_t)instructionsToFix + instr uctionSizes[index]); |
| 690 } | 670 } |
| 691 } | 671 } |
| 692 #endif | |
| 693 | 672 |
| 694 #if defined(__i386__) | 673 #if defined(__i386__) |
| 695 __asm( | 674 __asm( |
| 696 ".text;" | 675 ".text;" |
| 697 ".align 2, 0x90;" | 676 ".align 2, 0x90;" |
| 698 "_atomic_mov64:;" | 677 "_atomic_mov64:;" |
| 699 " pushl %ebp;" | 678 " pushl %ebp;" |
| 700 " movl %esp, %ebp;" | 679 " movl %esp, %ebp;" |
| 701 " pushl %esi;" | 680 " pushl %esi;" |
| 702 " pushl %ebx;" | 681 " pushl %ebx;" |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 728 ); | 707 ); |
| 729 #elif defined(__x86_64__) | 708 #elif defined(__x86_64__) |
| 730 void atomic_mov64( | 709 void atomic_mov64( |
| 731 uint64_t *targetAddress, | 710 uint64_t *targetAddress, |
| 732 uint64_t value ) | 711 uint64_t value ) |
| 733 { | 712 { |
| 734 *targetAddress = value; | 713 *targetAddress = value; |
| 735 } | 714 } |
| 736 #endif | 715 #endif |
| 737 #endif | 716 #endif |
| OLD | NEW |