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 |