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

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

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