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

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

Issue 10834127: Update third_party/mach_override to include the fix for building Chromium on 64 bits (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Local Modifications: None in README.chromium. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/mach_override/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>
11 #include <mach/mach_host.h> 11 #include <mach/mach_host.h>
12 #include <mach/mach_init.h> 12 #include <mach/mach_init.h>
13 #include <mach/vm_map.h> 13 #include <mach/vm_map.h>
14 #include <sys/mman.h> 14 #include <sys/mman.h>
15 15
16 #include <CoreServices/CoreServices.h> 16 #include <CoreServices/CoreServices.h>
17 17
18 /************************** 18 /**************************
19 * 19 *
20 * Constants 20 * Constants
21 * 21 *
22 **************************/ 22 **************************/
23 #pragma mark - 23 #pragma mark -
24 #pragma mark (Constants) 24 #pragma mark (Constants)
25 25
26 #define kPageSize 4096
26 #if defined(__ppc__) || defined(__POWERPC__) 27 #if defined(__ppc__) || defined(__POWERPC__)
27 28
28 long kIslandTemplate[] = { 29 long kIslandTemplate[] = {
29 0x9001FFFC, // stw r0,-4(SP) 30 0x9001FFFC, // stw r0,-4(SP)
30 0x3C00DEAD, // lis r0,0xDEAD 31 0x3C00DEAD, // lis r0,0xDEAD
31 0x6000BEEF, // ori r0,r0,0xBEEF 32 0x6000BEEF, // ori r0,r0,0xBEEF
32 0x7C0903A6, // mtctr r0 33 0x7C0903A6, // mtctr r0
33 0x8001FFFC, // lwz r0,-4(SP) 34 0x8001FFFC, // lwz r0,-4(SP)
34 0x60000000, // nop ; optionally replaced 35 0x60000000, // nop ; optionally replaced
35 0x4E800420 // bctr 36 0x4E800420 // bctr
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 70 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
70 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 71 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
71 // Now the real jump instruction 72 // Now the real jump instruction
72 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 73 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00 75 0x00, 0x00, 0x00, 0x00
75 }; 76 };
76 77
77 #endif 78 #endif
78 79
79 #define kAllocateHigh 1
80 #define kAllocateNormal 0
81
82 /************************** 80 /**************************
83 * 81 *
84 * Data Types 82 * Data Types
85 * 83 *
86 **************************/ 84 **************************/
87 #pragma mark - 85 #pragma mark -
88 #pragma mark (Data Types) 86 #pragma mark (Data Types)
89 87
90 typedef struct { 88 typedef struct {
91 char instructions[sizeof(kIslandTemplate)]; 89 char instructions[sizeof(kIslandTemplate)];
92 int allocatedHigh;
93 } BranchIsland; 90 } BranchIsland;
94 91
95 /************************** 92 /**************************
96 * 93 *
97 * Funky Protos 94 * Funky Protos
98 * 95 *
99 **************************/ 96 **************************/
100 #pragma mark - 97 #pragma mark -
101 #pragma mark (Funky Protos) 98 #pragma mark (Funky Protos)
102 99
103 mach_error_t 100 mach_error_t
104 allocateBranchIsland( 101 allocateBranchIsland(
105 BranchIsland **island, 102 BranchIsland **island,
106 int allocateHigh,
107 void *originalFunctionAddress); 103 void *originalFunctionAddress);
108 104
109 mach_error_t 105 mach_error_t
110 freeBranchIsland( 106 freeBranchIsland(
111 BranchIsland *island ); 107 BranchIsland *island );
112 108
113 #if defined(__ppc__) || defined(__POWERPC__) 109 #if defined(__ppc__) || defined(__POWERPC__)
114 mach_error_t 110 mach_error_t
115 setBranchIslandTarget( 111 setBranchIslandTarget(
116 BranchIsland *island, 112 BranchIsland *island,
(...skipping 10 matching lines...) Expand all
127 void 123 void
128 atomic_mov64( 124 atomic_mov64(
129 uint64_t *targetAddress, 125 uint64_t *targetAddress,
130 uint64_t value ); 126 uint64_t value );
131 127
132 static Boolean 128 static Boolean
133 eatKnownInstructions( 129 eatKnownInstructions(
134 unsigned char *code, 130 unsigned char *code,
135 uint64_t *newInstruction, 131 uint64_t *newInstruction,
136 int *howManyEaten, 132 int *howManyEaten,
137 » char» » » *originalInstructions ); 133 » char» » » *originalInstructions,
134 » int» » » » *originalInstructionCount,
135 » uint8_t»» » *originalInstructionSizes );
136
137 » static void
138 fixupInstructions(
139 void» » *originalFunction,
140 void» » *escapeIsland,
141 void» » *instructionsToFix,
142 » int» » » instructionCount,
143 » uint8_t»» *instructionSizes );
138 #endif 144 #endif
139 145
140 /******************************************************************************* 146 /*******************************************************************************
141 * 147 *
142 * Interface 148 * Interface
143 * 149 *
144 *******************************************************************************/ 150 *******************************************************************************/
145 #pragma mark - 151 #pragma mark -
146 #pragma mark (Interface) 152 #pragma mark (Interface)
147 153
148 #if defined(__i386__) || defined(__x86_64__) 154 #if defined(__i386__) || defined(__x86_64__)
149 mach_error_t makeIslandExecutable(void *address) { 155 mach_error_t makeIslandExecutable(void *address) {
150 mach_error_t err = err_none; 156 mach_error_t err = err_none;
151 vm_size_t pageSize; 157 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1);
152 host_page_size( mach_host_self(), &pageSize );
153 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1);
154 int e = err_none; 158 int e = err_none;
155 e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ | PROT_WRITE); 159 e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
156 e |= msync((void *)page, pageSize, MS_INVALIDATE ); 160 e |= msync((void *)page, kPageSize, MS_INVALIDATE );
157 if (e) { 161 if (e) {
158 err = err_cannot_override; 162 err = err_cannot_override;
159 } 163 }
160 return err; 164 return err;
161 } 165 }
162 #endif 166 #endif
163 167
164 mach_error_t 168 mach_error_t
165 mach_override_ptr( 169 mach_override_ptr(
166 void *originalFunctionAddress, 170 void *originalFunctionAddress,
167 const void *overrideFunctionAddress, 171 const void *overrideFunctionAddress,
168 void **originalFunctionReentryIsland ) 172 void **originalFunctionReentryIsland )
169 { 173 {
170 assert( originalFunctionAddress ); 174 assert( originalFunctionAddress );
171 assert( overrideFunctionAddress ); 175 assert( overrideFunctionAddress );
172 176
173 // this addresses overriding such functions as AudioOutputUnitStart() 177 // this addresses overriding such functions as AudioOutputUnitStart()
174 // test with modified DefaultOutputUnit project 178 // test with modified DefaultOutputUnit project
175 #if defined(__x86_64__) || defined(__i386__) 179 #if defined(__x86_64__)
176 for(;;){ 180 for(;;){
177 if(*(unsigned char*)originalFunctionAddress==0xE9) // jmp .+0x????? ??? 181 if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp qword near [ri p+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 originalFunctionAddress=*(void**)((char*)originalFunctionAddress+6+* (int32_t *)((uint16_t*)originalFunctionAddress+1));
183 else break;
184 }
182 #elif defined(__i386__) 185 #elif defined(__i386__)
183 else if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp *0x?????? ?? 186 for(;;){
187 if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp *0x????????
184 originalFunctionAddress=**(void***)((uint16_t*)originalFunctionAddre ss+1); 188 originalFunctionAddress=**(void***)((uint16_t*)originalFunctionAddre ss+1);
185 #endif
186 else break; 189 else break;
187 } 190 }
188 #endif 191 #endif
189 192
190 long *originalFunctionPtr = (long*) originalFunctionAddress; 193 long *originalFunctionPtr = (long*) originalFunctionAddress;
191 mach_error_t err = err_none; 194 mach_error_t err = err_none;
192 195
193 #if defined(__ppc__) || defined(__POWERPC__) 196 #if defined(__ppc__) || defined(__POWERPC__)
194 // Ensure first instruction isn't 'mfctr'. 197 // Ensure first instruction isn't 'mfctr'.
195 #define kMFCTRMask 0xfc1fffff 198 #define kMFCTRMask 0xfc1fffff
196 #define kMFCTRInstruction 0x7c0903a6 199 #define kMFCTRInstruction 0x7c0903a6
197 200
198 long originalInstruction = *originalFunctionPtr; 201 long originalInstruction = *originalFunctionPtr;
199 if( !err && ((originalInstruction & kMFCTRMask) == kMFCTRInstruction) ) 202 if( !err && ((originalInstruction & kMFCTRMask) == kMFCTRInstruction) )
200 err = err_cannot_override; 203 err = err_cannot_override;
201 #elif defined(__i386__) || defined(__x86_64__) 204 #elif defined(__i386__) || defined(__x86_64__)
202 int eatenCount = 0; 205 int eatenCount = 0;
206 int originalInstructionCount = 0;
203 char originalInstructions[kOriginalInstructionsSize]; 207 char originalInstructions[kOriginalInstructionsSize];
208 uint8_t originalInstructionSizes[kOriginalInstructionsSize];
204 uint64_t jumpRelativeInstruction = 0; // JMP 209 uint64_t jumpRelativeInstruction = 0; // JMP
205 210
206 Boolean overridePossible = eatKnownInstructions ((unsigned char *)origin alFunctionPtr, 211 Boolean overridePossible = eatKnownInstructions ((unsigned char *)origin alFunctionPtr,
207 » » » » » » » » » » &jumpRelativeInstruction, &eatenCount, originalInstructions); 212 » » » » » » » » » » &jumpRelativeInstruction, &eatenCount,
213 » » » » » » » » » » originalInstructions, &originalInstructionCount,
214 » » » » » » » » » » originalInstructionSizes );
208 if (eatenCount > kOriginalInstructionsSize) { 215 if (eatenCount > kOriginalInstructionsSize) {
209 //printf ("Too many instructions eaten\n"); 216 //printf ("Too many instructions eaten\n");
210 overridePossible = false; 217 overridePossible = false;
211 } 218 }
212 if (!overridePossible) err = err_cannot_override; 219 if (!overridePossible) err = err_cannot_override;
213 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); 220 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
214 #endif 221 #endif
215 222
216 // Make the original function implementation writable. 223 // Make the original function implementation writable.
217 if( !err ) { 224 if( !err ) {
218 err = vm_protect( mach_task_self(), 225 err = vm_protect( mach_task_self(),
219 (vm_address_t) originalFunctionPtr, 8, false, 226 (vm_address_t) originalFunctionPtr, 8, false,
220 (VM_PROT_ALL | VM_PROT_COPY) ); 227 (VM_PROT_ALL | VM_PROT_COPY) );
221 if( err ) 228 if( err )
222 err = vm_protect( mach_task_self(), 229 err = vm_protect( mach_task_self(),
223 (vm_address_t) originalFunctionPtr, 8, f alse, 230 (vm_address_t) originalFunctionPtr, 8, f alse,
224 (VM_PROT_DEFAULT | VM_PROT_COPY) ); 231 (VM_PROT_DEFAULT | VM_PROT_COPY) );
225 } 232 }
226 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); 233 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
227 234
228 // Allocate and target the escape island to the overriding function . 235 // Allocate and target the escape island to the overriding function .
229 BranchIsland *escapeIsland = NULL; 236 BranchIsland *escapeIsland = NULL;
230 if( !err ) 237 if( !err )
231 » » err = allocateBranchIsland( &escapeIsland, kAllocateHigh, origin alFunctionAddress ); 238 » » err = allocateBranchIsland( &escapeIsland, originalFunctionAddre ss );
232 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LI NE__); 239 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LI NE__);
233 240
234 241
235 #if defined(__ppc__) || defined(__POWERPC__) 242 #if defined(__ppc__) || defined(__POWERPC__)
236 if( !err ) 243 if( !err )
237 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 ); 244 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 );
238 245
239 // Build the branch absolute instruction to the escape island. 246 // Build the branch absolute instruction to the escape island.
240 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng. 247 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng.
241 if( !err ) { 248 if( !err ) {
(...skipping 15 matching lines...) Expand all
257 if (!err) { 264 if (!err) {
258 uint32_t addressOffset = ((char*)escapeIsland - (char*)originalF unctionPtr - 5); 265 uint32_t addressOffset = ((char*)escapeIsland - (char*)originalF unctionPtr - 5);
259 addressOffset = OSSwapInt32(addressOffset); 266 addressOffset = OSSwapInt32(addressOffset);
260 267
261 jumpRelativeInstruction |= 0xE900000000000000LL; 268 jumpRelativeInstruction |= 0xE900000000000000LL;
262 jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff ) << 24; 269 jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff ) << 24;
263 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); 270 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction);
264 } 271 }
265 #endif 272 #endif
266 273
267 » //» Optionally allocate & return the reentry island. 274 » //» Optionally allocate & return the reentry island. This may contai n relocated
275 » // jmp instructions and so has all the same addressing reachability req uirements
276 » // the escape island has to the original function, except the escape is land is
277 » // technically our original function.
268 BranchIsland *reentryIsland = NULL; 278 BranchIsland *reentryIsland = NULL;
269 if( !err && originalFunctionReentryIsland ) { 279 if( !err && originalFunctionReentryIsland ) {
270 » » err = allocateBranchIsland( &reentryIsland, kAllocateHigh, NULL) ; 280 » » err = allocateBranchIsland( &reentryIsland, escapeIsland);
271 if( !err ) 281 if( !err )
272 *originalFunctionReentryIsland = reentryIsland; 282 *originalFunctionReentryIsland = reentryIsland;
273 } 283 }
274 284
275 #if defined(__ppc__) || defined(__POWERPC__) 285 #if defined(__ppc__) || defined(__POWERPC__)
276 // Atomically: 286 // Atomically:
277 // o If the reentry island was allocated: 287 // o If the reentry island was allocated:
278 // o Insert the original instruction into the reentry islan d. 288 // o Insert the original instruction into the reentry islan d.
279 // o Target the reentry island at the 2nd instruction of th e 289 // o Target the reentry island at the 2nd instruction of th e
280 // original function. 290 // original function.
(...skipping 22 matching lines...) Expand all
303 #elif defined(__i386__) || defined(__x86_64__) 313 #elif defined(__i386__) || defined(__x86_64__)
304 // Atomically: 314 // Atomically:
305 // o If the reentry island was allocated: 315 // o If the reentry island was allocated:
306 // o Insert the original instructions into the reentry isla nd. 316 // o Insert the original instructions into the reentry isla nd.
307 // o Target the reentry island at the first non-replaced 317 // o Target the reentry island at the first non-replaced
308 // instruction of the original function. 318 // instruction of the original function.
309 // o Replace the original first instructions with the jump relative . 319 // o Replace the original first instructions with the jump relative .
310 // 320 //
311 // Note that on i386, we do not support someone else changing the code u nder our feet 321 // Note that on i386, we do not support someone else changing the code u nder our feet
312 if ( !err ) { 322 if ( !err ) {
323 fixupInstructions(originalFunctionPtr, reentryIsland, originalIn structions,
324 originalInstructionCount, originalInstru ctionSizes );
325
313 if( reentryIsland ) 326 if( reentryIsland )
314 err = setBranchIslandTarget_i386( reentryIsland, 327 err = setBranchIslandTarget_i386( reentryIsland,
315 (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions ); 328 (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions );
316 // try making islands executable before planting the jmp 329 // try making islands executable before planting the jmp
317 #if defined(__x86_64__) || defined(__i386__) 330 #if defined(__x86_64__) || defined(__i386__)
318 if( !err ) 331 if( !err )
319 err = makeIslandExecutable(escapeIsland); 332 err = makeIslandExecutable(escapeIsland);
320 if( !err && reentryIsland ) 333 if( !err && reentryIsland )
321 err = makeIslandExecutable(reentryIsland); 334 err = makeIslandExecutable(reentryIsland);
322 #endif 335 #endif
(...skipping 18 matching lines...) Expand all
341 * Implementation 354 * Implementation
342 * 355 *
343 *******************************************************************************/ 356 *******************************************************************************/
344 #pragma mark - 357 #pragma mark -
345 #pragma mark (Implementation) 358 #pragma mark (Implementation)
346 359
347 /***************************************************************************//** 360 /***************************************************************************//**
348 Implementation: Allocates memory for a branch island. 361 Implementation: Allocates memory for a branch island.
349 362
350 @param island <- The allocated island. 363 @param island <- The allocated island.
351 @param allocateHigh -> Whether to allocate the island at the en d of the
352 address space (f or use with the branch absolute
353 instruction).
354 @result <- mach_error_t 364 @result <- mach_error_t
355 365
356 ************************************************************************ ***/ 366 ************************************************************************ ***/
357 367
358 mach_error_t 368 mach_error_t
359 allocateBranchIsland( 369 allocateBranchIsland(
360 BranchIsland **island, 370 BranchIsland **island,
361 int allocateHigh,
362 void *originalFunctionAddress) 371 void *originalFunctionAddress)
363 { 372 {
364 assert( island ); 373 assert( island );
365 » 374 » assert( sizeof( BranchIsland ) <= kPageSize );
366 » mach_error_t» err = err_none; 375
367 » 376 » vm_map_t task_self = mach_task_self();
368 » if( allocateHigh ) { 377 » vm_address_t original_address = (vm_address_t) originalFunctionAddress;
369 » » vm_size_t pageSize; 378 » static vm_address_t last_allocated = 0;
370 » » err = host_page_size( mach_host_self(), &pageSize ); 379 » vm_address_t address =
371 » » if( !err ) { 380 » » last_allocated ? last_allocated : original_address;
372 » » » assert( sizeof( BranchIsland ) <= pageSize ); 381
373 #if defined(__x86_64__) 382 » for (;;) {
374 » » » vm_address_t first = (uint64_t)originalFunctionAddress & ~(uint64_t)(((uint64_t)1 << 31) - 1) | ((uint64_t)1 << 31); // start in the mid dle of the page? 383 » » vm_size_t vmsize = 0;
375 » » » vm_address_t last = 0x0; 384 » » memory_object_name_t object = 0;
385 » » kern_return_t kr = 0;
386 » » vm_region_flavor_t flavor = VM_REGION_BASIC_INFO;
387 » » // Find the page the address is in.
388 #if __WORDSIZE == 32
389 » » vm_region_basic_info_data_t info;
390 » » mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
391 » » kr = vm_region(task_self, &address, &vmsize, flavor,
392 » » » (vm_region_info_t)&info, &info_count, &object);
376 #else 393 #else
377 » » » vm_address_t first = 0xffc00000; 394 » » vm_region_basic_info_data_64_t info;
378 » » » vm_address_t last = 0xfffe0000; 395 » » mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_6 4;
396 » » kr = vm_region_64(task_self, &address, &vmsize, flavor,
397 » » » » (vm_region_info_t)&info, &info_count, &object) ;
379 #endif 398 #endif
399 if (kr != KERN_SUCCESS)
400 return kr;
380 401
381 » » » vm_address_t page = first; 402 » » // Don't underflow. This could be made to work, but this is a
382 » » » int allocated = 0; 403 » » // convenient place to give up.
383 » » » vm_map_t task_self = mach_task_self(); 404 » » assert((address & (kPageSize - 1)) == 0);
384 » » » 405 » » if (address == 0)
385 » » » while( !err && !allocated && page != last ) { 406 » » » break;
386 407
387 » » » » err = vm_allocate( task_self, &page, pageSize, 0 ); 408 » » // Go back one page.
388 » » » » if( err == err_none ) 409 » » vm_address_t new_address = address - kPageSize;
389 » » » » » allocated = 1; 410 #if __WORDSIZE == 64
390 » » » » else if( err == KERN_NO_SPACE ) { 411 » » if(original_address - new_address - 5 > INT32_MAX)
391 #if defined(__x86_64__) 412 » » » break;
392 » » » » » page -= pageSize;
393 #else
394 » » » » » page += pageSize;
395 #endif 413 #endif
396 » » » » » err = err_none; 414 » » address = new_address;
397 » » » » } 415
398 » » » } 416 » » // Try to allocate this page.
399 » » » if( allocated ) 417 » » kr = vm_allocate(task_self, &address, kPageSize, 0);
400 » » » » *island = (BranchIsland*) page; 418 » » if (kr == KERN_SUCCESS) {
401 » » » else if( !allocated && !err ) 419 » » » *island = (BranchIsland*) address;
402 » » » » err = KERN_NO_SPACE; 420 » » » last_allocated = address;
421 » » » return err_none;
403 } 422 }
404 » } else { 423 » » if (kr != KERN_NO_SPACE)
405 » » void *block = malloc( sizeof( BranchIsland ) ); 424 » » » return kr;
406 » » if( block )
407 » » » *island = block;
408 » » else
409 » » » err = KERN_NO_SPACE;
410 } 425 }
411 » if( !err ) 426
412 » » (**island).allocatedHigh = allocateHigh; 427 » return KERN_NO_SPACE;
413 »
414 » return err;
415 } 428 }
416 429
417 /***************************************************************************//** 430 /***************************************************************************//**
418 Implementation: Deallocates memory for a branch island. 431 Implementation: Deallocates memory for a branch island.
419 432
420 @param island -> The island to deallocate. 433 @param island -> The island to deallocate.
421 @result <- mach_error_t 434 @result <- mach_error_t
422 435
423 ************************************************************************ ***/ 436 ************************************************************************ ***/
424 437
425 mach_error_t 438 mach_error_t
426 freeBranchIsland( 439 freeBranchIsland(
427 BranchIsland *island ) 440 BranchIsland *island )
428 { 441 {
429 assert( island ); 442 assert( island );
430 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); 443 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] );
431 » assert( island->allocatedHigh ); 444 » assert( sizeof( BranchIsland ) <= kPageSize );
432 » 445 » return vm_deallocate( mach_task_self(), (vm_address_t) island,
433 » mach_error_t» err = err_none; 446 » » » kPageSize );
434 »
435 » if( island->allocatedHigh ) {
436 » » vm_size_t pageSize;
437 » » err = host_page_size( mach_host_self(), &pageSize );
438 » » if( !err ) {
439 » » » assert( sizeof( BranchIsland ) <= pageSize );
440 » » » err = vm_deallocate(
441 » » » » » mach_task_self(),
442 » » » » » (vm_address_t) island, pageSize );
443 » » }
444 » } else {
445 » » free( island );
446 » }
447 »
448 » return err;
449 } 447 }
450 448
451 /***************************************************************************//** 449 /***************************************************************************//**
452 Implementation: Sets the branch island's target, with an optional 450 Implementation: Sets the branch island's target, with an optional
453 instruction. 451 instruction.
454 452
455 @param island -> The branch island to insert target into. 453 @param island -> The branch island to insert target into.
456 @param branchTo -> The address of the target. 454 @param branchTo -> The address of the target.
457 @param instruction -> Optional instruction to execute prior to branch. Set 455 @param instruction -> Optional instruction to execute prior to branch. Set
458 to zero for nop. 456 to zero for nop.
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 #if defined(__i386__) || defined(__x86_64__) 538 #if defined(__i386__) || defined(__x86_64__)
541 // simplistic instruction matching 539 // simplistic instruction matching
542 typedef struct { 540 typedef struct {
543 unsigned int length; // max 15 541 unsigned int length; // max 15
544 unsigned char mask[15]; // sequence of bytes in memory order 542 unsigned char mask[15]; // sequence of bytes in memory order
545 unsigned char constraint[15]; // sequence of bytes in memory order 543 unsigned char constraint[15]; // sequence of bytes in memory order
546 } AsmInstructionMatch; 544 } AsmInstructionMatch;
547 545
548 #if defined(__i386__) 546 #if defined(__i386__)
549 static AsmInstructionMatch possibleInstructions[] = { 547 static AsmInstructionMatch possibleInstructions[] = {
548 { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x????????
550 { 0x5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x55, 0x89, 0xe5, 0xc9, 0xc3} }, // push %ebp; mov %esp,%ebp; leave; ret 549 { 0x5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x55, 0x89, 0xe5, 0xc9, 0xc3} }, // push %ebp; mov %esp,%ebp; leave; ret
551 { 0x1, {0xFF}, {0x90} }, // nop 550 { 0x1, {0xFF}, {0x90} }, // nop
552 { 0x1, {0xFF}, {0x55} }, // push %esp 551 { 0x1, {0xFF}, {0x55} }, // push %esp
553 { 0x2, {0xFF, 0xFF}, {0x89, 0xE5} }, // mov %esp,%ebp 552 { 0x2, {0xFF, 0xFF}, {0x89, 0xE5} }, // mov %esp,%ebp
554 { 0x1, {0xFF}, {0x53} }, // push %ebx 553 { 0x1, {0xFF}, {0x53} }, // push %ebx
555 { 0x3, {0xFF, 0xFF, 0x00}, {0x83, 0xEC, 0x00} }, // sub 0x??, %esp 554 { 0x3, {0xFF, 0xFF, 0x00}, {0x83, 0xEC, 0x00} }, // sub 0x??, %esp
556 { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x81, 0xEC, 0x00, 0x00, 0x 00, 0x00} }, // sub 0x??, %esp with 32bit immediate 555 { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x81, 0xEC, 0x00, 0x00, 0x 00, 0x00} }, // sub 0x??, %esp with 32bit immediate
557 { 0x1, {0xFF}, {0x57} }, // push %edi 556 { 0x1, {0xFF}, {0x57} }, // push %edi
558 { 0x1, {0xFF}, {0x56} }, // push %esi 557 { 0x1, {0xFF}, {0x56} }, // push %esi
559 { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax 558 { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax
560 { 0x3, {0xFF, 0x4F, 0x00}, {0x8B, 0x45, 0x00} }, // mov $imm(%ebp), %re g 559 { 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 560 { 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 561 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x8B, 0x4C, 0x24, 0x00} }, // mov $im m(%esp), %ecx
562 { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %eax
563 { 0x0 } 563 { 0x0 }
564 }; 564 };
565 #elif defined(__x86_64__) 565 #elif defined(__x86_64__)
566 static AsmInstructionMatch possibleInstructions[] = { 566 static AsmInstructionMatch possibleInstructions[] = {
567 { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x????????
567 { 0x1, {0xFF}, {0x90} }, // nop 568 { 0x1, {0xFF}, {0x90} }, // nop
568 { 0x1, {0xF8}, {0x50} }, // push %rX 569 { 0x1, {0xF8}, {0x50} }, // push %rX
569 { 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp 570 { 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp
570 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp 571 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp
571 { 0x4, {0xFB, 0xFF, 0x00, 0x00}, {0x48, 0x89, 0x00, 0x00} }, // move onto rbp 572 { 0x4, {0xFB, 0xFF, 0x00, 0x00}, {0x48, 0x89, 0x00, 0x00} }, // move onto rbp
573 { 0x4, {0xFF, 0xFF, 0xFF, 0xFF}, {0x40, 0x0f, 0xbe, 0xce} }, // movsbl %sil, %ecx
572 { 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX 574 { 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX
573 { 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX 575 { 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX
574 { 0x5, {0xF8, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %reg 576 { 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) 577 { 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi)
578 { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax
579 { 0x2, {0xFF, 0xFF}, {0x89, 0xF8} }, // mov %edi, %ea x
576 { 0x0 } 580 { 0x0 }
577 }; 581 };
578 #endif 582 #endif
579 583
580 static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch* instruction) 584 static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch* instruction)
581 { 585 {
582 Boolean match = true; 586 Boolean match = true;
583 587
584 size_t i; 588 size_t i;
585 for (i=0; i<instruction->length; i++) { 589 for (i=0; i<instruction->length; i++) {
586 unsigned char mask = instruction->mask[i]; 590 unsigned char mask = instruction->mask[i];
587 unsigned char constraint = instruction->constraint[i]; 591 unsigned char constraint = instruction->constraint[i];
588 unsigned char codeValue = code[i]; 592 unsigned char codeValue = code[i];
589 593
590 match = ((codeValue & mask) == constraint); 594 match = ((codeValue & mask) == constraint);
591 if (!match) break; 595 if (!match) break;
592 } 596 }
593 597
594 return match; 598 return match;
595 } 599 }
596 600
597 #if defined(__i386__) || defined(__x86_64__) 601 #if defined(__i386__) || defined(__x86_64__)
598 static Boolean 602 static Boolean
599 eatKnownInstructions( 603 eatKnownInstructions(
600 » unsigned char *code, 604 » unsigned char» *code,
601 » uint64_t* newInstruction, 605 » uint64_t» » *newInstruction,
602 » int* howManyEaten, 606 » int» » » » *howManyEaten,
603 » char* originalInstructions ) 607 » char» » » *originalInstructions,
608 » int» » » » *originalInstructionCount,
609 » uint8_t»» » *originalInstructionSizes )
604 { 610 {
605 Boolean allInstructionsKnown = true; 611 Boolean allInstructionsKnown = true;
606 int totalEaten = 0; 612 int totalEaten = 0;
607 unsigned char* ptr = code; 613 unsigned char* ptr = code;
608 int remainsToEat = 5; // a JMP instruction takes 5 bytes 614 int remainsToEat = 5; // a JMP instruction takes 5 bytes
615 int instructionIndex = 0;
609 616
610 if (howManyEaten) *howManyEaten = 0; 617 if (howManyEaten) *howManyEaten = 0;
618 if (originalInstructionCount) *originalInstructionCount = 0;
611 while (remainsToEat > 0) { 619 while (remainsToEat > 0) {
612 Boolean curInstructionKnown = false; 620 Boolean curInstructionKnown = false;
613 621
614 // See if instruction matches one we know 622 // See if instruction matches one we know
615 AsmInstructionMatch* curInstr = possibleInstructions; 623 AsmInstructionMatch* curInstr = possibleInstructions;
616 do { 624 do {
617 if ((curInstructionKnown = codeMatchesInstruction(ptr, c urInstr))) break; 625 if ((curInstructionKnown = codeMatchesInstruction(ptr, c urInstr))) break;
618 curInstr++; 626 curInstr++;
619 } while (curInstr->length > 0); 627 } while (curInstr->length > 0);
620 628
621 // if all instruction matches failed, we don't know current inst ruction then, stop here 629 // if all instruction matches failed, we don't know current inst ruction then, stop here
622 if (!curInstructionKnown) { 630 if (!curInstructionKnown) {
623 allInstructionsKnown = false; 631 allInstructionsKnown = false;
624 fprintf(stderr, "mach_override: some instructions unknow n! Need to update mach_override.c\n"); 632 fprintf(stderr, "mach_override: some instructions unknow n! Need to update mach_override.c\n");
625 break; 633 break;
626 } 634 }
627 635
628 // At this point, we've matched curInstr 636 // At this point, we've matched curInstr
629 int eaten = curInstr->length; 637 int eaten = curInstr->length;
630 ptr += eaten; 638 ptr += eaten;
631 remainsToEat -= eaten; 639 remainsToEat -= eaten;
632 totalEaten += eaten; 640 totalEaten += eaten;
641
642 if (originalInstructionSizes) originalInstructionSizes[instructi onIndex] = eaten;
643 instructionIndex += 1;
644 if (originalInstructionCount) *originalInstructionCount = instru ctionIndex;
633 } 645 }
634 646
635 647
636 if (howManyEaten) *howManyEaten = totalEaten; 648 if (howManyEaten) *howManyEaten = totalEaten;
637 649
638 if (originalInstructions) { 650 if (originalInstructions) {
639 Boolean enoughSpaceForOriginalInstructions = (totalEaten < kOrig inalInstructionsSize); 651 Boolean enoughSpaceForOriginalInstructions = (totalEaten < kOrig inalInstructionsSize);
640 652
641 if (enoughSpaceForOriginalInstructions) { 653 if (enoughSpaceForOriginalInstructions) {
642 memset(originalInstructions, 0x90 /* NOP */, kOriginalIn structionsSize); // fill instructions with NOP 654 memset(originalInstructions, 0x90 /* NOP */, kOriginalIn structionsSize); // fill instructions with NOP
(...skipping 10 matching lines...) Expand all
653 currentFirst64BitsOfCode = OSSwapInt64(currentFirst64BitsOfCode) ; // back to memory representation 665 currentFirst64BitsOfCode = OSSwapInt64(currentFirst64BitsOfCode) ; // back to memory representation
654 currentFirst64BitsOfCode &= 0x0000000000FFFFFFLL; 666 currentFirst64BitsOfCode &= 0x0000000000FFFFFFLL;
655 667
656 // keep only last 3 instructions bytes, first 5 will be replaced by JMP instr 668 // keep only last 3 instructions bytes, first 5 will be replaced by JMP instr
657 *newInstruction &= 0xFFFFFFFFFF000000LL; // clear last 3 bytes 669 *newInstruction &= 0xFFFFFFFFFF000000LL; // clear last 3 bytes
658 *newInstruction |= (currentFirst64BitsOfCode & 0x0000000000FFFFF FLL); // set last 3 bytes 670 *newInstruction |= (currentFirst64BitsOfCode & 0x0000000000FFFFF FLL); // set last 3 bytes
659 } 671 }
660 672
661 return allInstructionsKnown; 673 return allInstructionsKnown;
662 } 674 }
675
676 static void
677 fixupInstructions(
678 void *originalFunction,
679 void *escapeIsland,
680 void *instructionsToFix,
681 int instructionCount,
682 uint8_t *instructionSizes )
683 {
684 int index;
685 for (index = 0;index < instructionCount;index += 1)
686 {
687 if (*(uint8_t*)instructionsToFix == 0xE9) // 32-bit jump relativ e
688 {
689 uint32_t offset = (uintptr_t)originalFunction - (uintptr _t)escapeIsland;
690 uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instruc tionsToFix + 1);
691 *jumpOffsetPtr += offset;
692 }
693
694 originalFunction = (void*)((uintptr_t)originalFunction + instruc tionSizes[index]);
695 escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSize s[index]);
696 instructionsToFix = (void*)((uintptr_t)instructionsToFix + instr uctionSizes[index]);
697 }
698 }
663 #endif 699 #endif
664 700
665 #if defined(__i386__) 701 #if defined(__i386__)
666 __asm( 702 __asm(
667 ".text;" 703 ".text;"
668 ".align 2, 0x90;" 704 ".align 2, 0x90;"
669 "_atomic_mov64:;" 705 "_atomic_mov64:;"
670 " pushl %ebp;" 706 " pushl %ebp;"
671 " movl %esp, %ebp;" 707 " movl %esp, %ebp;"
672 " pushl %esi;" 708 " pushl %esi;"
(...skipping 26 matching lines...) Expand all
699 ); 735 );
700 #elif defined(__x86_64__) 736 #elif defined(__x86_64__)
701 void atomic_mov64( 737 void atomic_mov64(
702 uint64_t *targetAddress, 738 uint64_t *targetAddress,
703 uint64_t value ) 739 uint64_t value )
704 { 740 {
705 *targetAddress = value; 741 *targetAddress = value;
706 } 742 }
707 #endif 743 #endif
708 #endif 744 #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