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

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

Issue 61273002: Update mach_override to upstream 1a1bb352 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « third_party/mach_override/mach_override.h ('k') | third_party/mach_override/mach_override.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /******************************************************************************* 1 // mach_override.c semver:1.2.0
Mark Mentovai 2013/11/05 23:35:37 This patch set, patch set 1, contains the virgin u
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 <sys/mman.h> 15 #include <sys/mman.h>
16 16
17 #include <CoreServices/CoreServices.h> 17 #include <CoreServices/CoreServices.h>
18 18
19 /************************** 19 /**************************
20 * 20 *
21 * Constants 21 * Constants
22 * 22 *
23 **************************/ 23 **************************/
24 #pragma mark - 24 #pragma mark -
25 #pragma mark (Constants) 25 #pragma mark (Constants)
26 26
27 #define kPageSize 4096
28 #if defined(__ppc__) || defined(__POWERPC__) 27 #if defined(__ppc__) || defined(__POWERPC__)
29 28
30 long kIslandTemplate[] = { 29 long kIslandTemplate[] = {
31 0x9001FFFC, // stw r0,-4(SP) 30 0x9001FFFC, // stw r0,-4(SP)
32 0x3C00DEAD, // lis r0,0xDEAD 31 0x3C00DEAD, // lis r0,0xDEAD
33 0x6000BEEF, // ori r0,r0,0xBEEF 32 0x6000BEEF, // ori r0,r0,0xBEEF
34 0x7C0903A6, // mtctr r0 33 0x7C0903A6, // mtctr r0
35 0x8001FFFC, // lwz r0,-4(SP) 34 0x8001FFFC, // lwz r0,-4(SP)
36 0x60000000, // nop ; optionally replaced 35 0x60000000, // nop ; optionally replaced
37 0x4E800420 // bctr 36 0x4E800420 // bctr
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 70 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
72 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 71 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
73 // Now the real jump instruction 72 // Now the real jump instruction
74 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 73 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00 75 0x00, 0x00, 0x00, 0x00
77 }; 76 };
78 77
79 #endif 78 #endif
80 79
80 #define kAllocateHigh 1
81 #define kAllocateNormal 0
82
81 /************************** 83 /**************************
82 * 84 *
83 * Data Types 85 * Data Types
84 * 86 *
85 **************************/ 87 **************************/
86 #pragma mark - 88 #pragma mark -
87 #pragma mark (Data Types) 89 #pragma mark (Data Types)
88 90
89 typedef struct { 91 typedef struct {
90 char instructions[sizeof(kIslandTemplate)]; 92 char instructions[sizeof(kIslandTemplate)];
93 int allocatedHigh;
91 } BranchIsland; 94 } BranchIsland;
92 95
93 /************************** 96 /**************************
94 * 97 *
95 * Funky Protos 98 * Funky Protos
96 * 99 *
97 **************************/ 100 **************************/
98 #pragma mark - 101 #pragma mark -
99 #pragma mark (Funky Protos) 102 #pragma mark (Funky Protos)
100 103
101 mach_error_t 104 mach_error_t
102 allocateBranchIsland( 105 allocateBranchIsland(
103 BranchIsland **island, 106 BranchIsland **island,
107 int allocateHigh,
104 void *originalFunctionAddress); 108 void *originalFunctionAddress);
105 109
106 mach_error_t 110 mach_error_t
107 freeBranchIsland( 111 freeBranchIsland(
108 BranchIsland *island ); 112 BranchIsland *island );
109 113
110 #if defined(__ppc__) || defined(__POWERPC__) 114 #if defined(__ppc__) || defined(__POWERPC__)
111 mach_error_t 115 mach_error_t
112 setBranchIslandTarget( 116 setBranchIslandTarget(
113 BranchIsland *island, 117 BranchIsland *island,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 * 152 *
149 * Interface 153 * Interface
150 * 154 *
151 *******************************************************************************/ 155 *******************************************************************************/
152 #pragma mark - 156 #pragma mark -
153 #pragma mark (Interface) 157 #pragma mark (Interface)
154 158
155 #if defined(__i386__) || defined(__x86_64__) 159 #if defined(__i386__) || defined(__x86_64__)
156 mach_error_t makeIslandExecutable(void *address) { 160 mach_error_t makeIslandExecutable(void *address) {
157 mach_error_t err = err_none; 161 mach_error_t err = err_none;
158 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1); 162 vm_size_t pageSize;
163 host_page_size( mach_host_self(), &pageSize );
164 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1);
159 int e = err_none; 165 int e = err_none;
160 e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ); 166 e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
161 e |= msync((void *)page, kPageSize, MS_INVALIDATE ); 167 e |= msync((void *)page, pageSize, MS_INVALIDATE );
162 if (e) { 168 if (e) {
163 err = err_cannot_override; 169 err = err_cannot_override;
164 } 170 }
165 return err; 171 return err;
166 } 172 }
167 #endif 173 #endif
168 174
169 mach_error_t 175 mach_error_t
170 mach_override_ptr( 176 mach_override_ptr(
171 void *originalFunctionAddress, 177 void *originalFunctionAddress,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 if( err ) 235 if( err )
230 err = vm_protect( mach_task_self(), 236 err = vm_protect( mach_task_self(),
231 (vm_address_t) originalFunctionPtr, 8, f alse, 237 (vm_address_t) originalFunctionPtr, 8, f alse,
232 (VM_PROT_DEFAULT | VM_PROT_COPY) ); 238 (VM_PROT_DEFAULT | VM_PROT_COPY) );
233 } 239 }
234 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); 240 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
235 241
236 // Allocate and target the escape island to the overriding function . 242 // Allocate and target the escape island to the overriding function .
237 BranchIsland *escapeIsland = NULL; 243 BranchIsland *escapeIsland = NULL;
238 if( !err ) 244 if( !err )
239 » » err = allocateBranchIsland( &escapeIsland, originalFunctionAddre ss ); 245 » » err = allocateBranchIsland( &escapeIsland, kAllocateHigh, origin alFunctionAddress );
240 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LI NE__); 246 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LI NE__);
241 247
242 248
243 #if defined(__ppc__) || defined(__POWERPC__) 249 #if defined(__ppc__) || defined(__POWERPC__)
244 if( !err ) 250 if( !err )
245 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 ); 251 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 );
246 252
247 // Build the branch absolute instruction to the escape island. 253 // Build the branch absolute instruction to the escape island.
248 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng. 254 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng.
249 if( !err ) { 255 if( !err ) {
(...skipping 21 matching lines...) Expand all
271 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); 277 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction);
272 } 278 }
273 #endif 279 #endif
274 280
275 // Optionally allocate & return the reentry island. This may contai n relocated 281 // Optionally allocate & return the reentry island. This may contai n relocated
276 // jmp instructions and so has all the same addressing reachability req uirements 282 // 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 283 // the escape island has to the original function, except the escape is land is
278 // technically our original function. 284 // technically our original function.
279 BranchIsland *reentryIsland = NULL; 285 BranchIsland *reentryIsland = NULL;
280 if( !err && originalFunctionReentryIsland ) { 286 if( !err && originalFunctionReentryIsland ) {
281 » » err = allocateBranchIsland( &reentryIsland, escapeIsland); 287 » » err = allocateBranchIsland( &reentryIsland, kAllocateHigh, escap eIsland);
282 if( !err ) 288 if( !err )
283 *originalFunctionReentryIsland = reentryIsland; 289 *originalFunctionReentryIsland = reentryIsland;
284 } 290 }
285 291
286 #if defined(__ppc__) || defined(__POWERPC__) 292 #if defined(__ppc__) || defined(__POWERPC__)
287 // Atomically: 293 // Atomically:
288 // o If the reentry island was allocated: 294 // o If the reentry island was allocated:
289 // o Insert the original instruction into the reentry islan d. 295 // o Insert the original instruction into the reentry islan d.
290 // o Target the reentry island at the 2nd instruction of th e 296 // o Target the reentry island at the 2nd instruction of th e
291 // original function. 297 // original function.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions ); 335 (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions );
330 // try making islands executable before planting the jmp 336 // try making islands executable before planting the jmp
331 #if defined(__x86_64__) || defined(__i386__) 337 #if defined(__x86_64__) || defined(__i386__)
332 if( !err ) 338 if( !err )
333 err = makeIslandExecutable(escapeIsland); 339 err = makeIslandExecutable(escapeIsland);
334 if( !err && reentryIsland ) 340 if( !err && reentryIsland )
335 err = makeIslandExecutable(reentryIsland); 341 err = makeIslandExecutable(reentryIsland);
336 #endif 342 #endif
337 if ( !err ) 343 if ( !err )
338 atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelati veInstruction); 344 atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelati veInstruction);
339
340 mach_error_t prot_err = err_none;
341 prot_err = vm_protect( mach_task_self(),
342 (vm_address_t) originalFunctionPtr, 8, fa lse,
343 (VM_PROT_READ | VM_PROT_EXECUTE) );
344 if (prot_err) fprintf(stderr, "err = %x %s:%d\n", prot_err, __FI LE__, __LINE__);
345 } 345 }
346 #endif 346 #endif
347 347
348 // Clean up on error. 348 // Clean up on error.
349 if( err ) { 349 if( err ) {
350 if( reentryIsland ) 350 if( reentryIsland )
351 freeBranchIsland( reentryIsland ); 351 freeBranchIsland( reentryIsland );
352 if( escapeIsland ) 352 if( escapeIsland )
353 freeBranchIsland( escapeIsland ); 353 freeBranchIsland( escapeIsland );
354 } 354 }
355 355
356 return err; 356 return err;
357 } 357 }
358 358
359 /******************************************************************************* 359 /*******************************************************************************
360 * 360 *
361 * Implementation 361 * Implementation
362 * 362 *
363 *******************************************************************************/ 363 *******************************************************************************/
364 #pragma mark - 364 #pragma mark -
365 #pragma mark (Implementation) 365 #pragma mark (Implementation)
366 366
367 /***************************************************************************//** 367 /*******************************************************************************
368 Implementation: Allocates memory for a branch island. 368 Implementation: Allocates memory for a branch island.
369 369
370 @param island <- The allocated island. 370 @param island <- The allocated island.
371 @param allocateHigh -> Whether to allocate the island at the en d of the
372 address space (f or use with the branch absolute
373 instruction).
371 @result <- mach_error_t 374 @result <- mach_error_t
372 375
373 ************************************************************************ ***/ 376 ************************************************************************ ***/
374 377
375 mach_error_t 378 mach_error_t
376 allocateBranchIsland( 379 allocateBranchIsland(
377 BranchIsland **island, 380 BranchIsland **island,
381 int allocateHigh,
378 void *originalFunctionAddress) 382 void *originalFunctionAddress)
379 { 383 {
380 assert( island ); 384 assert( island );
381 385
382 » assert( sizeof( BranchIsland ) <= kPageSize ); 386 » mach_error_t» err = err_none;
383 #if defined(__i386__) 387 »
384 » vm_address_t page = 0; 388 » if( allocateHigh ) {
385 » mach_error_t err = vm_allocate( mach_task_self(), &page, kPageSize, VM_F LAGS_ANYWHERE ); 389 » » vm_size_t pageSize;
386 » if( err == err_none ) { 390 » » err = host_page_size( mach_host_self(), &pageSize );
387 » » *island = (BranchIsland*) page; 391 » » if( !err ) {
388 » » return err_none; 392 » » » assert( sizeof( BranchIsland ) <= pageSize );
389 » } 393 #if defined(__ppc__) || defined(__POWERPC__)
390 » return err; 394 » » » vm_address_t first = 0xfeffffff;
395 » » » vm_address_t last = 0xfe000000 + pageSize;
396 #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 m iddle of the page?
398 » » » vm_address_t last = 0x0;
391 #else 399 #else
392 400 » » » vm_address_t first = 0xffc00000;
393 #if defined(__ppc__) || defined(__POWERPC__) 401 » » » vm_address_t last = 0xfffe0000;
394 » vm_address_t first = 0xfeffffff;
395 » vm_address_t last = 0xfe000000 + kPageSize;
396 #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?
398 » vm_address_t last = 0x0;
399 #endif 402 #endif
400 403
401 » vm_address_t page = first; 404 » » » vm_address_t page = first;
402 » vm_map_t task_self = mach_task_self(); 405 » » » int allocated = 0;
406 » » » vm_map_t task_self = mach_task_self();
407 » » »
408 » » » while( !err && !allocated && page != last ) {
403 409
404 » while( page != last ) { 410 » » » » err = vm_allocate( task_self, &page, pageSize, 0 );
405 » » mach_error_t err = vm_allocate( task_self, &page, kPageSize, 0 ) ; 411 » » » » if( err == err_none )
406 » » if( err == err_none ) { 412 » » » » » allocated = 1;
407 » » » *island = (BranchIsland*) page; 413 » » » » 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__) 414 #if defined(__x86_64__)
413 » » page -= kPageSize; 415 » » » » » page -= pageSize;
414 #else 416 #else
415 » » page += kPageSize; 417 » » » » » page += pageSize;
416 #endif 418 #endif
417 » » err = err_none; 419 » » » » » err = err_none;
420 » » » » }
421 » » » }
422 » » » if( allocated )
423 » » » » *island = (BranchIsland*) page;
424 » » » else if( !allocated && !err )
425 » » » » err = KERN_NO_SPACE;
426 » » }
427 » } else {
428 » » void *block = malloc( sizeof( BranchIsland ) );
429 » » if( block )
430 » » » *island = block;
431 » » else
432 » » » err = KERN_NO_SPACE;
418 } 433 }
419 434 » if( !err )
420 » return KERN_NO_SPACE; 435 » » (**island).allocatedHigh = allocateHigh;
421 #endif 436 »
437 » return err;
422 } 438 }
423 439
424 /***************************************************************************//** 440 /*******************************************************************************
425 Implementation: Deallocates memory for a branch island. 441 Implementation: Deallocates memory for a branch island.
426 442
427 @param island -> The island to deallocate. 443 @param island -> The island to deallocate.
428 @result <- mach_error_t 444 @result <- mach_error_t
429 445
430 ************************************************************************ ***/ 446 ************************************************************************ ***/
431 447
432 mach_error_t 448 mach_error_t
433 freeBranchIsland( 449 freeBranchIsland(
434 BranchIsland *island ) 450 BranchIsland *island )
435 { 451 {
436 assert( island ); 452 assert( island );
437 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); 453 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] );
438 » assert( sizeof( BranchIsland ) <= kPageSize ); 454 » assert( island->allocatedHigh );
439 » return vm_deallocate( mach_task_self(), (vm_address_t) island, 455 »
440 » » » kPageSize ); 456 » mach_error_t» err = err_none;
457 »
458 » if( island->allocatedHigh ) {
459 » » vm_size_t pageSize;
460 » » err = host_page_size( mach_host_self(), &pageSize );
461 » » if( !err ) {
462 » » » assert( sizeof( BranchIsland ) <= pageSize );
463 » » » err = vm_deallocate(
464 » » » » » mach_task_self(),
465 » » » » » (vm_address_t) island, pageSize );
466 » » }
467 » } else {
468 » » free( island );
469 » }
470 »
471 » return err;
441 } 472 }
442 473
443 /***************************************************************************//** 474 /*******************************************************************************
444 Implementation: Sets the branch island's target, with an optional 475 Implementation: Sets the branch island's target, with an optional
445 instruction. 476 instruction.
446 477
447 @param island -> The branch island to insert target into. 478 @param island -> The branch island to insert target into.
448 @param branchTo -> The address of the target. 479 @param branchTo -> The address of the target.
449 @param instruction -> Optional instruction to execute prior to branch. Set 480 @param instruction -> Optional instruction to execute prior to branch. Set
450 to zero for nop. 481 to zero for nop.
451 @result <- mach_error_t 482 @result <- mach_error_t
452 483
453 ************************************************************************ ***/ 484 ************************************************************************ ***/
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 // Fill in the address. 554 // Fill in the address.
524 *((uint64_t *)(island->instructions + kJumpAddress)) = (uint64_t)branchTo; 555 *((uint64_t *)(island->instructions + kJumpAddress)) = (uint64_t)branchTo;
525 msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE ); 556 msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE );
526 557
527 return err_none; 558 return err_none;
528 } 559 }
529 #endif 560 #endif
530 561
531 562
532 #if defined(__i386__) || defined(__x86_64__) 563 #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 564 static Boolean
596 eatKnownInstructions( 565 eatKnownInstructions(
597 unsigned char *code, 566 unsigned char *code,
598 uint64_t *newInstruction, 567 uint64_t *newInstruction,
599 int *howManyEaten, 568 int *howManyEaten,
600 char *originalInstructions, 569 char *originalInstructions,
601 int *originalInstructionCount, 570 int *originalInstructionCount,
602 uint8_t *originalInstructionSizes ) 571 uint8_t *originalInstructionSizes )
603 { 572 {
604 Boolean allInstructionsKnown = true; 573 Boolean allInstructionsKnown = true;
605 int totalEaten = 0; 574 int totalEaten = 0;
606 unsigned char* ptr = code;
607 int remainsToEat = 5; // a JMP instruction takes 5 bytes 575 int remainsToEat = 5; // a JMP instruction takes 5 bytes
608 int instructionIndex = 0; 576 int instructionIndex = 0;
577 ud_t ud_obj;
609 578
610 if (howManyEaten) *howManyEaten = 0; 579 if (howManyEaten) *howManyEaten = 0;
611 if (originalInstructionCount) *originalInstructionCount = 0; 580 if (originalInstructionCount) *originalInstructionCount = 0;
581 ud_init(&ud_obj);
582 #if defined(__i386__)
583 ud_set_mode(&ud_obj, 32);
584 #else
585 ud_set_mode(&ud_obj, 64);
586 #endif
587 ud_set_input_buffer(&ud_obj, code, 64); // Assume that 'code' points to at least 64bytes of data.
612 while (remainsToEat > 0) { 588 while (remainsToEat > 0) {
613 » » Boolean curInstructionKnown = false; 589 » » if (!ud_disassemble(&ud_obj)) {
614 » » 590 » » allInstructionsKnown = false;
615 » » // See if instruction matches one we know 591 » » fprintf(stderr, "mach_override: some instructions unknown! N eed to update libudis86\n");
616 » » AsmInstructionMatch* curInstr = possibleInstructions; 592 » » 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 } 593 }
628 594
629 // At this point, we've matched curInstr 595 // At this point, we've matched curInstr
630 » » int eaten = curInstr->length; 596 » » int eaten = ud_insn_len(&ud_obj);
631 » » ptr += eaten;
632 remainsToEat -= eaten; 597 remainsToEat -= eaten;
633 totalEaten += eaten; 598 totalEaten += eaten;
634 599
635 if (originalInstructionSizes) originalInstructionSizes[instructi onIndex] = eaten; 600 if (originalInstructionSizes) originalInstructionSizes[instructi onIndex] = eaten;
636 instructionIndex += 1; 601 instructionIndex += 1;
637 if (originalInstructionCount) *originalInstructionCount = instru ctionIndex; 602 if (originalInstructionCount) *originalInstructionCount = instru ctionIndex;
638 } 603 }
639 604
640 605
641 if (howManyEaten) *howManyEaten = totalEaten; 606 if (howManyEaten) *howManyEaten = totalEaten;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 uint32_t offset = (uintptr_t)originalFunction - (uintptr _t)escapeIsland; 647 uint32_t offset = (uintptr_t)originalFunction - (uintptr _t)escapeIsland;
683 uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instruc tionsToFix + 1); 648 uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instruc tionsToFix + 1);
684 *jumpOffsetPtr += offset; 649 *jumpOffsetPtr += offset;
685 } 650 }
686 651
687 originalFunction = (void*)((uintptr_t)originalFunction + instruc tionSizes[index]); 652 originalFunction = (void*)((uintptr_t)originalFunction + instruc tionSizes[index]);
688 escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSize s[index]); 653 escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSize s[index]);
689 instructionsToFix = (void*)((uintptr_t)instructionsToFix + instr uctionSizes[index]); 654 instructionsToFix = (void*)((uintptr_t)instructionsToFix + instr uctionSizes[index]);
690 } 655 }
691 } 656 }
692 #endif
693 657
694 #if defined(__i386__) 658 #if defined(__i386__)
695 __asm( 659 __asm(
696 ".text;" 660 ".text;"
697 ".align 2, 0x90;" 661 ".align 2, 0x90;"
698 "_atomic_mov64:;" 662 "_atomic_mov64:;"
699 " pushl %ebp;" 663 " pushl %ebp;"
700 " movl %esp, %ebp;" 664 " movl %esp, %ebp;"
701 " pushl %esi;" 665 " pushl %esi;"
702 " pushl %ebx;" 666 " pushl %ebx;"
(...skipping 25 matching lines...) Expand all
728 ); 692 );
729 #elif defined(__x86_64__) 693 #elif defined(__x86_64__)
730 void atomic_mov64( 694 void atomic_mov64(
731 uint64_t *targetAddress, 695 uint64_t *targetAddress,
732 uint64_t value ) 696 uint64_t value )
733 { 697 {
734 *targetAddress = value; 698 *targetAddress = value;
735 } 699 }
736 #endif 700 #endif
737 #endif 701 #endif
OLDNEW
« no previous file with comments | « third_party/mach_override/mach_override.h ('k') | third_party/mach_override/mach_override.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698