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

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

Issue 7748042: Merge trunk r97497 and its many dependents to the 14.0.835 branch. (Closed) Base URL: svn://svn.chromium.org/chrome/branches/835/src/
Patch Set: Created 9 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « third_party/mach_override/README.chromium ('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 /******************************************************************************* 1 /*******************************************************************************
2 mach_override.c 2 mach_override.c
3 Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzs ch.com> 3 Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzs ch.com>
4 Some rights reserved: <http://opensource.org/licenses/mit-licens e.php> 4 Some rights reserved: <http://opensource.org/licenses/mit-licens e.php>
5 5
6 ************************************************************************ ***/ 6 ************************************************************************ ***/
7 7
8 #include "mach_override.h" 8 #include "mach_override.h"
9 9
10 #include <mach-o/dyld.h> 10 #include <mach-o/dyld.h>
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 163
164 mach_error_t 164 mach_error_t
165 mach_override_ptr( 165 mach_override_ptr(
166 void *originalFunctionAddress, 166 void *originalFunctionAddress,
167 const void *overrideFunctionAddress, 167 const void *overrideFunctionAddress,
168 void **originalFunctionReentryIsland ) 168 void **originalFunctionReentryIsland )
169 { 169 {
170 assert( originalFunctionAddress ); 170 assert( originalFunctionAddress );
171 assert( overrideFunctionAddress ); 171 assert( overrideFunctionAddress );
172 172
173 // this addresses overriding such functions as AudioOutputUnitStart()
174 // test with modified DefaultOutputUnit project
175 #if defined(__x86_64__) || defined(__i386__)
176 for(;;){
177 if(*(unsigned char*)originalFunctionAddress==0xE9) // jmp .+0x????? ???
178 originalFunctionAddress=(void*)((char*)originalFunctionAddress+5+*(i nt32_t *)((char*)originalFunctionAddress+1));
179 #if defined(__x86_64__)
180 else if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp qword nea r [rip+0x????????]
181 originalFunctionAddress=*(void**)((char*)originalFunctionAddress+6+* (int32_t *)((uint16_t*)originalFunctionAddress+1));
182 #elif defined(__i386__)
183 else if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp *0x?????? ??
184 originalFunctionAddress=**(void***)((uint16_t*)originalFunctionAddre ss+1);
185 #endif
186 else break;
187 }
188 #endif
189
173 long *originalFunctionPtr = (long*) originalFunctionAddress; 190 long *originalFunctionPtr = (long*) originalFunctionAddress;
174 mach_error_t err = err_none; 191 mach_error_t err = err_none;
175 192
176 #if defined(__ppc__) || defined(__POWERPC__) 193 #if defined(__ppc__) || defined(__POWERPC__)
177 // Ensure first instruction isn't 'mfctr'. 194 // Ensure first instruction isn't 'mfctr'.
178 #define kMFCTRMask 0xfc1fffff 195 #define kMFCTRMask 0xfc1fffff
179 #define kMFCTRInstruction 0x7c0903a6 196 #define kMFCTRInstruction 0x7c0903a6
180 197
181 long originalInstruction = *originalFunctionPtr; 198 long originalInstruction = *originalFunctionPtr;
182 if( !err && ((originalInstruction & kMFCTRMask) == kMFCTRInstruction) ) 199 if( !err && ((originalInstruction & kMFCTRMask) == kMFCTRInstruction) )
183 err = err_cannot_override; 200 err = err_cannot_override;
184 #elif defined(__i386__) || defined(__x86_64__) 201 #elif defined(__i386__) || defined(__x86_64__)
185 int eatenCount = 0; 202 int eatenCount = 0;
186 char originalInstructions[kOriginalInstructionsSize]; 203 char originalInstructions[kOriginalInstructionsSize];
187 uint64_t jumpRelativeInstruction = 0; // JMP 204 uint64_t jumpRelativeInstruction = 0; // JMP
188 205
189 Boolean overridePossible = eatKnownInstructions ((unsigned char *)origin alFunctionPtr, 206 Boolean overridePossible = eatKnownInstructions ((unsigned char *)origin alFunctionPtr,
190 &jumpRelativeInstruction, &eatenCount, originalInstructions); 207 &jumpRelativeInstruction, &eatenCount, originalInstructions);
191 if (eatenCount > kOriginalInstructionsSize) { 208 if (eatenCount > kOriginalInstructionsSize) {
192 //printf ("Too many instructions eaten\n"); 209 //printf ("Too many instructions eaten\n");
193 overridePossible = false; 210 overridePossible = false;
194 } 211 }
195 if (!overridePossible) err = err_cannot_override; 212 if (!overridePossible) err = err_cannot_override;
196 » if (err) printf("err = %x %d\n", err, __LINE__); 213 » if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
197 #endif 214 #endif
198 215
199 // Make the original function implementation writable. 216 // Make the original function implementation writable.
200 if( !err ) { 217 if( !err ) {
201 err = vm_protect( mach_task_self(), 218 err = vm_protect( mach_task_self(),
202 » » » » (vm_address_t) originalFunctionPtr, 219 » » » » (vm_address_t) originalFunctionPtr, 8, false,
203 » » » » sizeof(long), false, (VM_PROT_ALL | VM_PROT_COPY ) ); 220 » » » » (VM_PROT_ALL | VM_PROT_COPY) );
204 if( err ) 221 if( err )
205 err = vm_protect( mach_task_self(), 222 err = vm_protect( mach_task_self(),
206 » » » » » (vm_address_t) originalFunctionPtr, size of(long), false, 223 » » » » » (vm_address_t) originalFunctionPtr, 8, f alse,
207 (VM_PROT_DEFAULT | VM_PROT_COPY) ); 224 (VM_PROT_DEFAULT | VM_PROT_COPY) );
208 } 225 }
209 » if (err) printf("err = %x %d\n", err, __LINE__); 226 » if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
210 227
211 // Allocate and target the escape island to the overriding function . 228 // Allocate and target the escape island to the overriding function .
212 BranchIsland *escapeIsland = NULL; 229 BranchIsland *escapeIsland = NULL;
213 if( !err ) 230 if( !err )
214 err = allocateBranchIsland( &escapeIsland, kAllocateHigh, origin alFunctionAddress ); 231 err = allocateBranchIsland( &escapeIsland, kAllocateHigh, origin alFunctionAddress );
215 » » if (err) printf("err = %x %d\n", err, __LINE__); 232 » » if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LI NE__);
216 233
217 234
218 #if defined(__ppc__) || defined(__POWERPC__) 235 #if defined(__ppc__) || defined(__POWERPC__)
219 if( !err ) 236 if( !err )
220 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 ); 237 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 );
221 238
222 // Build the branch absolute instruction to the escape island. 239 // Build the branch absolute instruction to the escape island.
223 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng. 240 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng.
224 if( !err ) { 241 if( !err ) {
225 long escapeIslandAddress = ((long) escapeIsland) & 0x3FFFFFF; 242 long escapeIslandAddress = ((long) escapeIsland) & 0x3FFFFFF;
226 branchAbsoluteInstruction = 0x48000002 | escapeIslandAddress; 243 branchAbsoluteInstruction = 0x48000002 | escapeIslandAddress;
227 } 244 }
228 #elif defined(__i386__) || defined(__x86_64__) 245 #elif defined(__i386__) || defined(__x86_64__)
229 if (err) printf("err = %x %d\n", err, __LINE__); 246 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
230 247
231 if( !err ) 248 if( !err )
232 err = setBranchIslandTarget_i386( escapeIsland, overrideFunction Address, 0 ); 249 err = setBranchIslandTarget_i386( escapeIsland, overrideFunction Address, 0 );
233 250
234 » if (err) printf("err = %x %d\n", err, __LINE__); 251 » if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
235 // Build the jump relative instruction to the escape island 252 // Build the jump relative instruction to the escape island
236 #endif 253 #endif
237 254
238 255
239 #if defined(__i386__) || defined(__x86_64__) 256 #if defined(__i386__) || defined(__x86_64__)
240 if (!err) { 257 if (!err) {
241 » » uint32_t addressOffset = ((void*)escapeIsland - (void*)originalF unctionPtr - 5); 258 » » uint32_t addressOffset = ((char*)escapeIsland - (char*)originalF unctionPtr - 5);
242 addressOffset = OSSwapInt32(addressOffset); 259 addressOffset = OSSwapInt32(addressOffset);
243 260
244 jumpRelativeInstruction |= 0xE900000000000000LL; 261 jumpRelativeInstruction |= 0xE900000000000000LL;
245 jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff ) << 24; 262 jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff ) << 24;
246 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); 263 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction);
247 } 264 }
248 #endif 265 #endif
249 266
250 // Optionally allocate & return the reentry island. 267 // Optionally allocate & return the reentry island.
251 BranchIsland *reentryIsland = NULL; 268 BranchIsland *reentryIsland = NULL;
252 if( !err && originalFunctionReentryIsland ) { 269 if( !err && originalFunctionReentryIsland ) {
253 » » err = allocateBranchIsland( &reentryIsland, kAllocateNormal, NUL L); 270 » » err = allocateBranchIsland( &reentryIsland, kAllocateHigh, NULL) ;
254 if( !err ) 271 if( !err )
255 *originalFunctionReentryIsland = reentryIsland; 272 *originalFunctionReentryIsland = reentryIsland;
256 } 273 }
257 274
258 #if defined(__ppc__) || defined(__POWERPC__) 275 #if defined(__ppc__) || defined(__POWERPC__)
259 // Atomically: 276 // Atomically:
260 // o If the reentry island was allocated: 277 // o If the reentry island was allocated:
261 // o Insert the original instruction into the reentry islan d. 278 // o Insert the original instruction into the reentry islan d.
262 // o Target the reentry island at the 2nd instruction of th e 279 // o Target the reentry island at the 2nd instruction of th e
263 // original function. 280 // original function.
(...skipping 25 matching lines...) Expand all
289 // o Insert the original instructions into the reentry isla nd. 306 // o Insert the original instructions into the reentry isla nd.
290 // o Target the reentry island at the first non-replaced 307 // o Target the reentry island at the first non-replaced
291 // instruction of the original function. 308 // instruction of the original function.
292 // o Replace the original first instructions with the jump relative . 309 // o Replace the original first instructions with the jump relative .
293 // 310 //
294 // Note that on i386, we do not support someone else changing the code u nder our feet 311 // Note that on i386, we do not support someone else changing the code u nder our feet
295 if ( !err ) { 312 if ( !err ) {
296 if( reentryIsland ) 313 if( reentryIsland )
297 err = setBranchIslandTarget_i386( reentryIsland, 314 err = setBranchIslandTarget_i386( reentryIsland,
298 (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions ); 315 (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions );
316 // try making islands executable before planting the jmp
317 #if defined(__x86_64__) || defined(__i386__)
318 if( !err )
319 err = makeIslandExecutable(escapeIsland);
320 if( !err && reentryIsland )
321 err = makeIslandExecutable(reentryIsland);
322 #endif
299 if ( !err ) 323 if ( !err )
300 atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelati veInstruction); 324 atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelati veInstruction);
301 } 325 }
302 #endif 326 #endif
303 327
304 #if defined(__i386__) || defined(__x86_64__)
305 if ( !err )
306 err = makeIslandExecutable( escapeIsland );
307 if ( !err && reentryIsland )
308 err = makeIslandExecutable( reentryIsland );
309 #endif
310
311 // Clean up on error. 328 // Clean up on error.
312 if( err ) { 329 if( err ) {
313 if( reentryIsland ) 330 if( reentryIsland )
314 freeBranchIsland( reentryIsland ); 331 freeBranchIsland( reentryIsland );
315 if( escapeIsland ) 332 if( escapeIsland )
316 freeBranchIsland( escapeIsland ); 333 freeBranchIsland( escapeIsland );
317 } 334 }
318 335
319 return err; 336 return err;
320 } 337 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 else if( err == KERN_NO_SPACE ) { 390 else if( err == KERN_NO_SPACE ) {
374 #if defined(__x86_64__) 391 #if defined(__x86_64__)
375 page -= pageSize; 392 page -= pageSize;
376 #else 393 #else
377 page += pageSize; 394 page += pageSize;
378 #endif 395 #endif
379 err = err_none; 396 err = err_none;
380 } 397 }
381 } 398 }
382 if( allocated ) 399 if( allocated )
383 » » » » *island = (void*) page; 400 » » » » *island = (BranchIsland*) page;
384 else if( !allocated && !err ) 401 else if( !allocated && !err )
385 err = KERN_NO_SPACE; 402 err = KERN_NO_SPACE;
386 } 403 }
387 } else { 404 } else {
388 void *block = malloc( sizeof( BranchIsland ) ); 405 void *block = malloc( sizeof( BranchIsland ) );
389 if( block ) 406 if( block )
390 *island = block; 407 *island = block;
391 else 408 else
392 err = KERN_NO_SPACE; 409 err = KERN_NO_SPACE;
393 } 410 }
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 #if defined(__i386__) || defined(__x86_64__) 540 #if defined(__i386__) || defined(__x86_64__)
524 // simplistic instruction matching 541 // simplistic instruction matching
525 typedef struct { 542 typedef struct {
526 unsigned int length; // max 15 543 unsigned int length; // max 15
527 unsigned char mask[15]; // sequence of bytes in memory order 544 unsigned char mask[15]; // sequence of bytes in memory order
528 unsigned char constraint[15]; // sequence of bytes in memory order 545 unsigned char constraint[15]; // sequence of bytes in memory order
529 } AsmInstructionMatch; 546 } AsmInstructionMatch;
530 547
531 #if defined(__i386__) 548 #if defined(__i386__)
532 static AsmInstructionMatch possibleInstructions[] = { 549 static AsmInstructionMatch possibleInstructions[] = {
550 { 0x5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x55, 0x89, 0xe5, 0xc9, 0xc3} }, // push %ebp; mov %esp,%ebp; leave; ret
533 { 0x1, {0xFF}, {0x90} }, // nop 551 { 0x1, {0xFF}, {0x90} }, // nop
534 { 0x1, {0xFF}, {0x55} }, // push %esp 552 { 0x1, {0xFF}, {0x55} }, // push %esp
535 { 0x2, {0xFF, 0xFF}, {0x89, 0xE5} }, // mov %esp,%ebp 553 { 0x2, {0xFF, 0xFF}, {0x89, 0xE5} }, // mov %esp,%ebp
536 { 0x1, {0xFF}, {0x53} }, // push %ebx 554 { 0x1, {0xFF}, {0x53} }, // push %ebx
537 { 0x3, {0xFF, 0xFF, 0x00}, {0x83, 0xEC, 0x00} }, // sub 0x??, %esp 555 { 0x3, {0xFF, 0xFF, 0x00}, {0x83, 0xEC, 0x00} }, // sub 0x??, %esp
538 { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x81, 0xEC, 0x00, 0x00, 0x 00, 0x00} }, // sub 0x??, %esp with 32bit immediate 556 { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x81, 0xEC, 0x00, 0x00, 0x 00, 0x00} }, // sub 0x??, %esp with 32bit immediate
539 { 0x1, {0xFF}, {0x57} }, // push %edi 557 { 0x1, {0xFF}, {0x57} }, // push %edi
540 { 0x1, {0xFF}, {0x56} }, // push %esi 558 { 0x1, {0xFF}, {0x56} }, // push %esi
541 { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax 559 { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax
560 { 0x3, {0xFF, 0x4F, 0x00}, {0x8B, 0x45, 0x00} }, // mov $imm(%ebp), %re g
561 { 0x3, {0xFF, 0x4C, 0x00}, {0x8B, 0x40, 0x00} }, // mov $imm(%eax-%edx) , %reg
562 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x8B, 0x4C, 0x24, 0x00} }, // mov $im m(%esp), %ecx
542 { 0x0 } 563 { 0x0 }
543 }; 564 };
544 #elif defined(__x86_64__) 565 #elif defined(__x86_64__)
545 static AsmInstructionMatch possibleInstructions[] = { 566 static AsmInstructionMatch possibleInstructions[] = {
546 { 0x1, {0xFF}, {0x90} }, // nop 567 { 0x1, {0xFF}, {0x90} }, // nop
547 { 0x1, {0xF8}, {0x50} }, // push %rX 568 { 0x1, {0xF8}, {0x50} }, // push %rX
548 { 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp 569 { 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp
549 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp 570 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp
550 { 0x4, {0xFB, 0xFF, 0x00, 0x00}, {0x48, 0x89, 0x00, 0x00} }, // move onto rbp 571 { 0x4, {0xFB, 0xFF, 0x00, 0x00}, {0x48, 0x89, 0x00, 0x00} }, // move onto rbp
551 { 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX 572 { 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX
552 { 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX 573 { 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX
574 { 0x5, {0xF8, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %reg
575 { 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi)
553 { 0x0 } 576 { 0x0 }
554 }; 577 };
555 #endif 578 #endif
556 579
557 static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch* instruction) 580 static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch* instruction)
558 { 581 {
559 Boolean match = true; 582 Boolean match = true;
560 583
561 size_t i; 584 size_t i;
562 for (i=0; i<instruction->length; i++) { 585 for (i=0; i<instruction->length; i++) {
(...skipping 28 matching lines...) Expand all
591 // See if instruction matches one we know 614 // See if instruction matches one we know
592 AsmInstructionMatch* curInstr = possibleInstructions; 615 AsmInstructionMatch* curInstr = possibleInstructions;
593 do { 616 do {
594 if ((curInstructionKnown = codeMatchesInstruction(ptr, c urInstr))) break; 617 if ((curInstructionKnown = codeMatchesInstruction(ptr, c urInstr))) break;
595 curInstr++; 618 curInstr++;
596 } while (curInstr->length > 0); 619 } while (curInstr->length > 0);
597 620
598 // if all instruction matches failed, we don't know current inst ruction then, stop here 621 // if all instruction matches failed, we don't know current inst ruction then, stop here
599 if (!curInstructionKnown) { 622 if (!curInstructionKnown) {
600 allInstructionsKnown = false; 623 allInstructionsKnown = false;
624 fprintf(stderr, "mach_override: some instructions unknow n! Need to update mach_override.c\n");
601 break; 625 break;
602 } 626 }
603 627
604 // At this point, we've matched curInstr 628 // At this point, we've matched curInstr
605 int eaten = curInstr->length; 629 int eaten = curInstr->length;
606 ptr += eaten; 630 ptr += eaten;
607 remainsToEat -= eaten; 631 remainsToEat -= eaten;
608 totalEaten += eaten; 632 totalEaten += eaten;
609 } 633 }
610 634
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 ); 699 );
676 #elif defined(__x86_64__) 700 #elif defined(__x86_64__)
677 void atomic_mov64( 701 void atomic_mov64(
678 uint64_t *targetAddress, 702 uint64_t *targetAddress,
679 uint64_t value ) 703 uint64_t value )
680 { 704 {
681 *targetAddress = value; 705 *targetAddress = value;
682 } 706 }
683 #endif 707 #endif
684 #endif 708 #endif
OLDNEW
« no previous file with comments | « third_party/mach_override/README.chromium ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698