Root/
Source at commit 429 created 13 years 7 months ago. By meklort, Updated module system. Hooks can now be used within modules when cetaion functions are called in chameleon. Note that onle two hooks currently exist, more need to be added. I also updated the HelloWorld module to use a hook instead of print out right away. | |
---|---|
1 | /*␊ |
2 | * Copyright 2010 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | */␊ |
5 | ␊ |
6 | #include "boot.h"␊ |
7 | #include "bootstruct.h"␊ |
8 | #include "multiboot.h"␊ |
9 | #include "modules.h"␊ |
10 | ␊ |
11 | #ifndef DEBUG_MODULES␊ |
12 | #define DEBUG_MODULES 0␊ |
13 | #endif␊ |
14 | ␊ |
15 | #if DEBUG_MODULES␊ |
16 | #define DBG(x...)␉printf(x); getc()␊ |
17 | #else␊ |
18 | #define DBG(x...)␊ |
19 | #endif␊ |
20 | ␊ |
21 | ␊ |
22 | moduleHook_t* moduleCallbacks = NULL;␊ |
23 | moduleList_t* loadedModules = NULL;␊ |
24 | symbolList_t* moduleSymbols = NULL;␊ |
25 | unsigned int (*lookup_symbol)(const char*) = NULL;␊ |
26 | ␊ |
27 | ␊ |
28 | void rebase_macho(void* base, char* rebase_stream, UInt32 size);␊ |
29 | void bind_macho(void* base, char* bind_stream, UInt32 size);␊ |
30 | ␊ |
31 | ␊ |
32 | /*␊ |
33 | * Initialize the module system by loading the Symbols.dylib module.␊ |
34 | * Once laoded, locate the _lookup_symbol function so that internal␊ |
35 | * symbols can be resolved.␊ |
36 | */␊ |
37 | int init_module_system()␊ |
38 | {␊ |
39 | ␉// Intialize module system␊ |
40 | ␉if(load_module(SYMBOLS_MODULE))␊ |
41 | ␉{␊ |
42 | ␉␉lookup_symbol = (void*)lookup_all_symbols("_lookup_symbol");␊ |
43 | ␉␉␊ |
44 | ␉␉if((UInt32)lookup_symbol != 0xFFFFFFFF)␊ |
45 | ␉␉{␊ |
46 | ␉␉␉return 1;␊ |
47 | ␉␉}␊ |
48 | ␉␉␊ |
49 | ␉}␊ |
50 | ␉␊ |
51 | ␉return 0;␊ |
52 | }␊ |
53 | ␊ |
54 | ␊ |
55 | /*␊ |
56 | * Load all modules in the /Extra/modules/ directory␊ |
57 | * Module depencdies will be loaded first␊ |
58 | * MOdules will only be loaded once. When loaded a module must␊ |
59 | * setup apropriete function calls and hooks as required.␊ |
60 | * NOTE: To ensure a module loads after another you may ␊ |
61 | * link one module with the other. For dyld to allow this, you must␊ |
62 | * reference at least one symbol within the module.␊ |
63 | */␊ |
64 | void load_all_modules()␊ |
65 | {␊ |
66 | ␉char* name;␊ |
67 | ␉long flags;␊ |
68 | ␉long time;␊ |
69 | ␉struct dirstuff* moduleDir = opendir("/Extra/modules/");␊ |
70 | ␉while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)␊ |
71 | ␉{␊ |
72 | ␉␉if(strcmp(&name[strlen(name) - sizeof("dylib")], ".dylib") == 0)␊ |
73 | ␉␉{␊ |
74 | ␉␉␉name[strlen(name) - sizeof("dylib")] = 0;␊ |
75 | ␉␉␉load_module(name);␊ |
76 | ␉␉}␊ |
77 | ␉}␊ |
78 | }␊ |
79 | ␊ |
80 | ␊ |
81 | /*␊ |
82 | * Load a module file in /Extra/modules␊ |
83 | * TODO: verify version number of module␊ |
84 | */␊ |
85 | int load_module(const char* module)␊ |
86 | {␊ |
87 | ␉// Check to see if the module has already been loaded␊ |
88 | ␉if(is_module_laoded(module))␊ |
89 | ␉{␊ |
90 | ␉␉return 1;␊ |
91 | ␉}␊ |
92 | ␉␊ |
93 | ␉char modString[128];␊ |
94 | ␉int fh = -1;␊ |
95 | ␉sprintf(modString, "/Extra/modules/%s.dylib", module);␊ |
96 | ␉fh = open(modString, 0);␊ |
97 | ␉if(fh < 0)␊ |
98 | ␉{␊ |
99 | ␉␉printf("Unable to locate module %s\n", modString);␊ |
100 | ␉␉getc();␊ |
101 | ␉␉return 0;␊ |
102 | ␉}␊ |
103 | ␉␊ |
104 | ␉unsigned int moduleSize = file_size(fh);␊ |
105 | ␉char* module_base = (char*) malloc(moduleSize);␊ |
106 | ␉if (read(fh, module_base, moduleSize) == moduleSize)␊ |
107 | ␉{␊ |
108 | ␉␉void (*module_start)(void) = NULL;␊ |
109 | ␊ |
110 | ␉␉//printf("Module %s read in.\n", modString);␊ |
111 | ␊ |
112 | ␉␉// Module loaded into memory, parse it␊ |
113 | ␉␉module_start = parse_mach(module_base);␊ |
114 | ␊ |
115 | ␉␉if(module_start)␊ |
116 | ␉␉{␊ |
117 | ␉␉␉(*module_start)();␉// Start the module␊ |
118 | ␉␉␉DBG("Module %s.dylib Loaded.\n", module);␊ |
119 | ␉␉}␊ |
120 | ␉␉else {␊ |
121 | ␉␉␉printf("Unabel to start %s.dylib\n", module);␊ |
122 | ␉␉␉getc();␊ |
123 | ␉␉}␊ |
124 | ␉␉// TODO: Add module to loaded list if loaded successfuly␊ |
125 | ␉␉␊ |
126 | ␉}␊ |
127 | ␉else␊ |
128 | ␉{␊ |
129 | ␉␉printf("Unable to read in module %s.dylib\n.", module);␊ |
130 | ␉␉getc();␊ |
131 | ␉}␊ |
132 | ␉return 1;␊ |
133 | }␊ |
134 | ␊ |
135 | ␊ |
136 | /*␊ |
137 | * register_hook( const char* name )␊ |
138 | *␉␉name - Name of the module Hook.␊ |
139 | *␉␉␉ NOTE: If the name already exists in the list, it'll␊ |
140 | *␉␉␉ still be added, however the entry will not be used, the first one␊ |
141 | *␉␉␉ will instead. That also means the the hook will most likely be␊ |
142 | *␉␉␉ called twice.␊ |
143 | *␊ |
144 | * Registers a hook with the module system, This allows modules to␊ |
145 | * register a callback when the hook is executed.␊ |
146 | */␊ |
147 | ␊ |
148 | inline void register_hook(const char* name)␊ |
149 | {␊ |
150 | ␉moduleHook_t* hooks;␊ |
151 | ␉if(moduleCallbacks == NULL)␊ |
152 | ␉{␊ |
153 | ␉␉moduleCallbacks = malloc(sizeof(moduleHook_t));␊ |
154 | ␉␉moduleCallbacks->next = NULL;␊ |
155 | ␉}␊ |
156 | ␉␊ |
157 | ␉hooks = moduleCallbacks;␊ |
158 | ␉while(hooks->next != NULL)␊ |
159 | ␉{␊ |
160 | ␉␉hooks = hooks->next;␊ |
161 | ␉}␊ |
162 | ␉␊ |
163 | ␉␊ |
164 | ␉hooks->name = name;␊ |
165 | ␉hooks->callbacks = NULL;␊ |
166 | }␊ |
167 | ␊ |
168 | ␊ |
169 | /*␊ |
170 | *␉execute_hook( const char* name )␊ |
171 | *␉␉name - Name of the module hook␊ |
172 | *␉␉␉If any callbacks have been registered for this hook␊ |
173 | *␉␉␉they will be executed now in the same order that the␊ |
174 | *␉␉␉hooks were added.␊ |
175 | */␊ |
176 | int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4)␊ |
177 | {␊ |
178 | ␉DBG("Attempting to execute hook '%s'\n", name);␊ |
179 | ␊ |
180 | ␉if(moduleCallbacks != NULL)␊ |
181 | ␉{␊ |
182 | ␉␉moduleHook_t* hooks = moduleCallbacks;␊ |
183 | ␉␉␊ |
184 | ␉␉while(hooks != NULL && strcmp(name, hooks->name) != 0)␊ |
185 | ␉␉{␊ |
186 | ␉␉␉hooks = hooks->next;␊ |
187 | ␉␉}␊ |
188 | ␉␉␊ |
189 | ␉␉if(hooks != NULL)␊ |
190 | ␉␉{␊ |
191 | ␉␉␉// Loop through all callbacks for this module␊ |
192 | ␉␉␉callbackList_t* callbacks = hooks->callbacks;␊ |
193 | ␉␉␉␊ |
194 | ␉␉␉while(callbacks)␊ |
195 | ␉␉␉{␊ |
196 | ␉␉␉␉// Execute callback␊ |
197 | ␉␉␉␉callbacks->callback(arg1, arg2, arg3, arg4);␊ |
198 | ␉␉␉␉callbacks = callbacks->next;␊ |
199 | ␉␉␉}␊ |
200 | ␉␉␉DBG("Hook '%s' executed.\n", name);␊ |
201 | ␊ |
202 | ␉␉␉return 1;␊ |
203 | ␉␉}␊ |
204 | ␉␉else␊ |
205 | ␉␉{␊ |
206 | ␉␉␉DBG("No callbacks for '%s' hook.\n", name);␊ |
207 | ␊ |
208 | ␉␉␉// Callbaack for this module doesn't exist;␊ |
209 | ␉␉␉//verbose("Unable execute hook '%s', no callbacks registered.\n", name);␊ |
210 | ␉␉␉//pause();␊ |
211 | ␉␉␉return 0;␊ |
212 | ␉␉}␊ |
213 | ␊ |
214 | ␊ |
215 | ␉}␉␊ |
216 | ␉DBG("No hooks have been registered.\n", name);␊ |
217 | ␉return 0;␊ |
218 | }␊ |
219 | ␊ |
220 | ␊ |
221 | ␊ |
222 | /*␊ |
223 | *␉register_hook_callback( const char* name, void(*callback)())␊ |
224 | *␉␉name - Name of the module hook to attach to.␊ |
225 | *␉␉callbacks - The funciton pointer that will be called when the␊ |
226 | *␉␉␉hook is executed.␊ |
227 | *␉␉␉NOTE: the hooks take four void* arguments.␊ |
228 | */␊ |
229 | /*␊ |
230 | void register_hook_callback(const char* name,␊ |
231 | ␉␉␉␉␉␉␉void(*callback)(void*, void*, void*, void*),␊ |
232 | ␉␉␉␉␉␉␉)*/␊ |
233 | void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*))␊ |
234 | {␊ |
235 | ␉// Locate Module hook␊ |
236 | ␉if(moduleCallbacks == NULL)␊ |
237 | ␉{␊ |
238 | ␉␉register_hook(name);␊ |
239 | ␉}␊ |
240 | ␉volatile moduleHook_t* hooks = moduleCallbacks;␊ |
241 | ␉␊ |
242 | ␉while(hooks != NULL && strcmp(name, hooks->name) != 0)␊ |
243 | ␉{␊ |
244 | ␉␉hooks = hooks->next;␊ |
245 | ␉}␊ |
246 | ␉␊ |
247 | ␉if(hooks == NULL)␊ |
248 | ␉{␊ |
249 | ␉␉// Hook doesn't exist, add it.␊ |
250 | ␉␉register_hook(name);␊ |
251 | ␉␉␊ |
252 | ␉␉// This is just a pointer, the data was modified in the register_hook function.␊ |
253 | ␉␉hooks = hooks->next;␊ |
254 | ␉}␊ |
255 | ␉␊ |
256 | ␉// Module Hooks located␊ |
257 | ␉if(hooks->callbacks == NULL)␊ |
258 | ␉{␊ |
259 | ␉␉// Initialize hook list␊ |
260 | ␉␉hooks->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));␊ |
261 | ␉␉hooks->callbacks->callback = callback;␊ |
262 | ␉␉hooks->callbacks->next = NULL;␊ |
263 | ␉}␊ |
264 | ␉else␊ |
265 | ␉{␊ |
266 | ␉␉callbackList_t* callbacks = hooks->callbacks;␊ |
267 | ␉␉while(callbacks->next != NULL)␊ |
268 | ␉␉{␊ |
269 | ␉␉␉callbacks = callbacks->next;␊ |
270 | ␉␉}␊ |
271 | ␉␉// Add new entry to end of hook list.␊ |
272 | ␉␉callbacks->next = (callbackList_t*)malloc(sizeof(callbackList_t));␊ |
273 | ␉␉callbacks = callbacks->next;␊ |
274 | ␉␉callbacks->next = NULL;␊ |
275 | ␉␉callbacks->callback = callback;␊ |
276 | ␉}␊ |
277 | }␊ |
278 | ␊ |
279 | ␊ |
280 | ␊ |
281 | /*␊ |
282 | * Parse through a macho module. The module will be rebased and binded␊ |
283 | * as specified in the macho header. If the module is sucessfuly laoded␊ |
284 | * the module iinit address will be returned.␊ |
285 | * NOTE; all dependecies will be loaded before this module is started␊ |
286 | * NOTE: If the module is unable to load ot completeion, the modules␊ |
287 | * symbols will still be available (TODO: fix this). This should not␊ |
288 | * happen as all dependencies are verified before the sybols are read in.␊ |
289 | */␊ |
290 | void* parse_mach(void* binary)␊ |
291 | {␉␊ |
292 | ␉void (*module_start)(void) = NULL;␊ |
293 | ␊ |
294 | ␉// Module info␊ |
295 | ␉char* moduleName = NULL;␊ |
296 | ␉UInt32 moduleVersion = 0;␊ |
297 | ␉UInt32 moduleCompat = 0;␊ |
298 | ␉␊ |
299 | ␉char* symbolStub = NULL;␊ |
300 | ␉char* nonlazy = NULL;␊ |
301 | ␉//char* nonlazy_variables = NULL;␊ |
302 | ␊ |
303 | ␉// TODO convert all of the structs to a union␊ |
304 | ␉struct load_command *loadCommand = NULL;␊ |
305 | ␉struct dylib_command* dylibCommand = NULL;␊ |
306 | ␉struct dyld_info_command* dyldInfoCommand = NULL;␊ |
307 | ␉struct symtab_command* symtabCommand = NULL;␊ |
308 | ␉struct segment_command* segmentCommand = NULL;␊ |
309 | ␉//struct dysymtab_command* dysymtabCommand = NULL;␊ |
310 | ␉struct section* section = NULL;␊ |
311 | ␉UInt32 binaryIndex = sizeof(struct mach_header);␊ |
312 | ␉UInt16 cmd = 0;␊ |
313 | ␊ |
314 | ␉// Parse through the load commands␊ |
315 | ␉if(((struct mach_header*)binary)->magic != MH_MAGIC)␊ |
316 | ␉{␊ |
317 | ␉␉printf("Module is not 32bit\n");␊ |
318 | ␉␉getc();␊ |
319 | ␉␉return NULL;␉// 32bit only␊ |
320 | ␉}␊ |
321 | ␉␊ |
322 | ␉if(((struct mach_header*)binary)->filetype != MH_DYLIB)␊ |
323 | ␉{␊ |
324 | ␉␉printf("Module is not a dylib. Unable to load.\n");␊ |
325 | ␉␉getc();␊ |
326 | ␉␉return NULL; // Module is in the incorrect format␊ |
327 | ␉}␊ |
328 | ␉␊ |
329 | ␉while(cmd < ((struct mach_header*)binary)->ncmds)␉// TODO: for loop instead␊ |
330 | ␉{␊ |
331 | ␉␉cmd++;␊ |
332 | ␉␉␊ |
333 | ␉␉loadCommand = binary + binaryIndex;␊ |
334 | ␉␉UInt32 cmdSize = loadCommand->cmdsize;␊ |
335 | ␊ |
336 | ␉␉␊ |
337 | ␉␉switch ((loadCommand->cmd & 0x7FFFFFFF))␊ |
338 | ␉␉{␊ |
339 | ␉␉␉case LC_SYMTAB:␊ |
340 | ␉␉␉␉symtabCommand = binary + binaryIndex;␊ |
341 | ␉␉␉␉break;␊ |
342 | ␉␉␉case LC_SEGMENT:␊ |
343 | ␉␉␉␉segmentCommand = binary + binaryIndex;␊ |
344 | ␊ |
345 | ␉␉␉␉UInt32 sections = segmentCommand->nsects;␊ |
346 | ␉␉␉␉section = binary + binaryIndex + sizeof(struct segment_command);␊ |
347 | ␉␉␉␉␊ |
348 | ␉␉␉␉// Loop untill needed variables are found␊ |
349 | ␉␉␉␉while(!(nonlazy && symbolStub) && sections)␉␊ |
350 | ␉␉␉␉{␊ |
351 | ␉␉␉␉␉// Look for some sections and save the addresses␊ |
352 | ␉␉␉␉␉if(strcmp(section->sectname, SECT_NON_LAZY_SYMBOL_PTR) == 0)␊ |
353 | ␉␉␉␉␉{␊ |
354 | ␉␉␉␉␉␉/*printf("\tSection non lazy pointers at 0x%X, %d symbols\n",␊ |
355 | ␉␉␉␉␉␉␉ section->offset, ␊ |
356 | ␉␉␉␉␉␉␉ section->size / 4);␊ |
357 | ␉␉␉␉␉␉*/␊ |
358 | ␉␉␉␉␉␉switch(section->flags)␊ |
359 | ␉␉␉␉␉␉{␊ |
360 | ␉␉␉␉␉␉␉case S_NON_LAZY_SYMBOL_POINTERS:␊ |
361 | ␉␉␉␉␉␉␉␉//printf("%s S_NON_LAZY_SYMBOL_POINTERS section\n", SECT_NON_LAZY_SYMBOL_PTR);␊ |
362 | ␊ |
363 | ␉␉␉␉␉␉␉␉//nonlazy_variables = binary + section->offset;␊ |
364 | ␉␉␉␉␉␉␉␉nonlazy = binary + section->offset;␊ |
365 | ␉␉␉␉␉␉␉␉break;␊ |
366 | ␉␉␉␉␉␉␉␉␊ |
367 | ␉␉␉␉␉␉␉case S_LAZY_SYMBOL_POINTERS:␊ |
368 | ␉␉␉␉␉␉␉␉// NOTE: Theses currently are not handled.␊ |
369 | ␉␉␉␉␉␉␉␉//nonlazy = binary + section->offset;␊ |
370 | ␉␉␉␉␉␉␉␉//printf("%s S_LAZY_SYMBOL_POINTERS section, 0x%X\n", SECT_NON_LAZY_SYMBOL_PTR, nonlazy);␊ |
371 | ␉␉␉␉␉␉␉␉// Fucntions␊ |
372 | ␉␉␉␉␉␉␉␉break;␊ |
373 | ␉␉␉␉␉␉␉␉␊ |
374 | ␉␉␉␉␉␉␉default:␊ |
375 | ␉␉␉␉␉␉␉␉//printf("Unhandled %s section\n", SECT_NON_LAZY_SYMBOL_PTR);␊ |
376 | ␉␉␉␉␉␉␉␉//getc();␊ |
377 | ␉␉␉␉␉␉␉␉break;␊ |
378 | ␉␉␉␉␉␉}␊ |
379 | ␉␉␉␉␉␉//getc();␊ |
380 | ␉␉␉␉␉}␊ |
381 | ␉␉␉␉␉else if(strcmp(section->sectname, SECT_SYMBOL_STUBS) == 0)␊ |
382 | ␉␉␉␉␉{␊ |
383 | ␉␉␉␉␉␉symbolStub = binary + section->offset;␊ |
384 | ␉␉␉␉␉}␊ |
385 | ␉␉␉␉␉/*␊ |
386 | ␉␉␉␉␉else ␊ |
387 | ␉␉␉␉␉{␊ |
388 | ␉␉␉␉␉␉printf("Unhandled section %s\n", section->sectname);␊ |
389 | ␉␉␉␉␉}␊ |
390 | ␉␉␉␉␉*/␊ |
391 | ␉␉␉␉␉sections--;␊ |
392 | ␉␉␉␉␉section++;␊ |
393 | ␉␉␉␉}␊ |
394 | ␉␉␉␉␉␉ ␊ |
395 | ␉␉␉␉␊ |
396 | ␉␉␉␉break;␊ |
397 | ␉␉␉␉␊ |
398 | ␉␉␉case LC_DYSYMTAB:␊ |
399 | ␉␉␉␉//dysymtabCommand = binary + binaryIndex;␊ |
400 | ␉␉␉␉//printf("Unhandled loadcommand LC_DYSYMTAB\n");␊ |
401 | ␉␉␉␉break;␊ |
402 | ␉␉␉␉␊ |
403 | ␉␉␉case LC_LOAD_DYLIB:␊ |
404 | ␉␉␉case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:␊ |
405 | ␉␉␉␉dylibCommand = binary + binaryIndex;␊ |
406 | ␉␉␉␉char* module = binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));␊ |
407 | ␉␉␉␉// TODO: verify version␊ |
408 | ␉␉␉␉// =␉dylibCommand->dylib.current_version;␊ |
409 | ␉␉␉␉// =␉dylibCommand->dylib.compatibility_version;␊ |
410 | ␊ |
411 | ␉␉␉␉if(!load_module(module))␊ |
412 | ␉␉␉␉{␊ |
413 | ␉␉␉␉␉// Unable to load dependancy␊ |
414 | ␉␉␉␉␉return NULL;␊ |
415 | ␉␉␉␉}␊ |
416 | ␉␉␉␉break;␊ |
417 | ␉␉␉␉␊ |
418 | ␉␉␉case LC_ID_DYLIB:␊ |
419 | ␉␉␉␉dylibCommand = binary + binaryIndex;␊ |
420 | ␉␉␉␉moduleName =␉binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));␊ |
421 | ␉␉␉␉moduleVersion =␉dylibCommand->dylib.current_version;␊ |
422 | ␉␉␉␉moduleCompat =␉dylibCommand->dylib.compatibility_version;␊ |
423 | ␉␉␉␉break;␊ |
424 | ␊ |
425 | ␉␉␉case LC_DYLD_INFO:␊ |
426 | ␉␉␉␉// Bind and rebase info is stored here␊ |
427 | ␉␉␉␉dyldInfoCommand = binary + binaryIndex;␊ |
428 | ␉␉␉␉break;␊ |
429 | ␉␉␉␉␊ |
430 | ␉␉␉case LC_UUID:␊ |
431 | ␉␉␉␉break;␊ |
432 | ␉␉␉␉␊ |
433 | ␉␉␉default:␊ |
434 | ␉␉␉␉DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);␊ |
435 | ␉␉␉␉break;␊ |
436 | ␉␉␊ |
437 | ␉␉}␊ |
438 | ␊ |
439 | ␉␉binaryIndex += cmdSize;␊ |
440 | ␉}␊ |
441 | ␉if(!moduleName) return NULL;␊ |
442 | ␉␉␊ |
443 | ␊ |
444 | ␉// bind_macho uses the symbols added in for some reason...␊ |
445 | ␉module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbolStub, (UInt32)nonlazy);␊ |
446 | ␊ |
447 | ␉// REbase the module before binding it.␊ |
448 | ␉if(dyldInfoCommand && dyldInfoCommand->rebase_off)␊ |
449 | ␉{␊ |
450 | ␉␉rebase_macho(binary, (char*)dyldInfoCommand->rebase_off, dyldInfoCommand->rebase_size);␊ |
451 | ␉}␊ |
452 | ␉␊ |
453 | ␉if(dyldInfoCommand && dyldInfoCommand->bind_off)␊ |
454 | ␉{␊ |
455 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->bind_off, dyldInfoCommand->bind_size);␊ |
456 | ␉}␊ |
457 | ␉␊ |
458 | ␉if(dyldInfoCommand && dyldInfoCommand->weak_bind_off)␊ |
459 | ␉{␊ |
460 | ␉␉// NOTE: this currently should never happen.␊ |
461 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->weak_bind_off, dyldInfoCommand->weak_bind_size);␊ |
462 | ␉}␊ |
463 | ␉␊ |
464 | ␉if(dyldInfoCommand && dyldInfoCommand->lazy_bind_off)␊ |
465 | ␉{␊ |
466 | ␉␉// NOTE: we are binding the lazy pointers as a module is laoded,␊ |
467 | ␉␉// This should be cahnged to bund when a symbol is referened at runtime.␊ |
468 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size);␊ |
469 | ␉}␊ |
470 | ␉␊ |
471 | ␊ |
472 | ␉␊ |
473 | ␊ |
474 | ␉// Notify the system that it was laoded␊ |
475 | ␉module_loaded(moduleName, moduleVersion, moduleCompat);␊ |
476 | ␉␊ |
477 | ␉return module_start;␊ |
478 | ␉␊ |
479 | }␊ |
480 | ␊ |
481 | ␊ |
482 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
483 | void rebase_macho(void* base, char* rebase_stream, UInt32 size)␊ |
484 | {␊ |
485 | ␉rebase_stream += (UInt32)base;␊ |
486 | ␉␊ |
487 | ␉UInt8 immediate = 0;␊ |
488 | ␉UInt8 opcode = 0;␊ |
489 | ␉UInt8 type = 0;␊ |
490 | ␉␊ |
491 | ␉UInt32 segmentAddress = 0;␊ |
492 | ␉␊ |
493 | ␉␊ |
494 | ␉␊ |
495 | ␉UInt32 tmp = 0;␊ |
496 | ␉UInt32 tmp2 = 0;␊ |
497 | ␉UInt8 bits = 0;␊ |
498 | ␉int index = 0;␊ |
499 | ␉␊ |
500 | ␉int done = 0;␊ |
501 | ␉unsigned int i = 0;␊ |
502 | ␉␊ |
503 | ␉while(/*!done &&*/ i < size)␊ |
504 | ␉{␊ |
505 | ␉␉immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;␊ |
506 | ␉␉opcode = rebase_stream[i] & REBASE_OPCODE_MASK;␊ |
507 | ␊ |
508 | ␉␉␊ |
509 | ␉␉switch(opcode)␊ |
510 | ␉␉{␊ |
511 | ␉␉␉case REBASE_OPCODE_DONE:␊ |
512 | ␉␉␉␉// Rebase complete.␊ |
513 | ␉␉␉␉done = 1;␊ |
514 | ␉␉␉␉break;␊ |
515 | ␉␉␉␉␊ |
516 | ␉␉␉␉␊ |
517 | ␉␉␉case REBASE_OPCODE_SET_TYPE_IMM:␊ |
518 | ␉␉␉␉// Set rebase type (pointer, absolute32, pcrel32)␊ |
519 | ␉␉␉␉//printf("Rebase type = 0x%X\n", immediate);␊ |
520 | ␉␉␉␉// NOTE: This is currently NOT used␊ |
521 | ␉␉␉␉type = immediate;␊ |
522 | ␉␉␉␉break;␊ |
523 | ␉␉␉␉␊ |
524 | ␉␉␉␉␊ |
525 | ␉␉␉case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
526 | ␉␉␉␉// Locate address to begin rebasing␊ |
527 | ␉␉␉␉segmentAddress = 0;␊ |
528 | ␊ |
529 | ␉␉␉␉struct segment_command* segCommand = NULL;␊ |
530 | ␉␉␉␉␊ |
531 | ␉␉␉␉unsigned int binIndex = 0;␊ |
532 | ␉␉␉␉index = 0;␊ |
533 | ␉␉␉␉do␊ |
534 | ␉␉␉␉{␊ |
535 | ␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
536 | ␉␉␉␉␉␊ |
537 | ␉␉␉␉␉␊ |
538 | ␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
539 | ␉␉␉␉␉index++;␊ |
540 | ␉␉␉␉}␊ |
541 | ␉␉␉␉while(index <= immediate);␊ |
542 | ␊ |
543 | ␊ |
544 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
545 | ␉␉␉␉␊ |
546 | ␉␉␉␉tmp = 0;␊ |
547 | ␉␉␉␉bits = 0;␊ |
548 | ␉␉␉␉do␊ |
549 | ␉␉␉␉{␊ |
550 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
551 | ␉␉␉␉␉bits += 7;␊ |
552 | ␉␉␉␉}␊ |
553 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
554 | ␉␉␉␉␊ |
555 | ␉␉␉␉segmentAddress += tmp;␊ |
556 | ␉␉␉␉break;␊ |
557 | ␉␉␉␉␊ |
558 | ␉␉␉␉␊ |
559 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_ULEB:␊ |
560 | ␉␉␉␉// Add value to rebase address␊ |
561 | ␉␉␉␉tmp = 0;␊ |
562 | ␉␉␉␉bits = 0;␊ |
563 | ␉␉␉␉do␊ |
564 | ␉␉␉␉{␊ |
565 | ␉␉␉␉␉tmp <<= bits;␊ |
566 | ␉␉␉␉␉tmp |= rebase_stream[++i] & 0x7f;␊ |
567 | ␉␉␉␉␉bits += 7;␊ |
568 | ␉␉␉␉}␊ |
569 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
570 | ␉␉␉␉␊ |
571 | ␉␉␉␉segmentAddress +=␉tmp; ␊ |
572 | ␉␉␉␉break;␊ |
573 | ␉␉␉␉␊ |
574 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:␊ |
575 | ␉␉␉␉segmentAddress += immediate * sizeof(void*);␊ |
576 | ␉␉␉␉break;␊ |
577 | ␉␉␉␉␊ |
578 | ␉␉␉␉␊ |
579 | ␉␉␉case REBASE_OPCODE_DO_REBASE_IMM_TIMES:␊ |
580 | ␉␉␉␉index = 0;␊ |
581 | ␉␉␉␉for (index = 0; index < immediate; ++index) {␊ |
582 | ␉␉␉␉␉rebase_location(base + segmentAddress, (char*)base);␊ |
583 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
584 | ␉␉␉␉}␊ |
585 | ␉␉␉␉break;␊ |
586 | ␉␉␉␊ |
587 | ␉␉␉␉␊ |
588 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:␊ |
589 | ␉␉␉␉tmp = 0;␊ |
590 | ␉␉␉␉bits = 0;␊ |
591 | ␉␉␉␉do␊ |
592 | ␉␉␉␉{␊ |
593 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
594 | ␉␉␉␉␉bits += 7;␊ |
595 | ␉␉␉␉}␊ |
596 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
597 | ␉␉␉␉␊ |
598 | ␉␉␉␉index = 0;␊ |
599 | ␉␉␉␉for (index = 0; index < tmp; ++index) {␊ |
600 | ␉␉␉␉␉//printf("\tRebasing 0x%X\n", segmentAddress);␊ |
601 | ␉␉␉␉␉rebase_location(base + segmentAddress, (char*)base);␉␉␉␉␉␊ |
602 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
603 | ␉␉␉␉}␊ |
604 | ␉␉␉␉break;␊ |
605 | ␉␉␉␉␊ |
606 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:␊ |
607 | ␉␉␉␉tmp = 0;␊ |
608 | ␉␉␉␉bits = 0;␊ |
609 | ␉␉␉␉do␊ |
610 | ␉␉␉␉{␊ |
611 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
612 | ␉␉␉␉␉bits += 7;␊ |
613 | ␉␉␉␉}␊ |
614 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
615 | ␉␉␉␉␊ |
616 | ␉␉␉␉rebase_location(base + segmentAddress, (char*)base);␊ |
617 | ␉␉␉␉␊ |
618 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
619 | ␉␉␉␉break;␊ |
620 | ␉␉␉␉␊ |
621 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:␊ |
622 | ␉␉␉␉tmp = 0;␊ |
623 | ␉␉␉␉bits = 0;␊ |
624 | ␉␉␉␉do␊ |
625 | ␉␉␉␉{␊ |
626 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
627 | ␉␉␉␉␉bits += 7;␊ |
628 | ␉␉␉␉}␊ |
629 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
630 | ␉␉␉␉␊ |
631 | ␉␉␉␉␊ |
632 | ␉␉␉␉tmp2 = 0;␊ |
633 | ␉␉␉␉bits = 0;␊ |
634 | ␉␉␉␉do␊ |
635 | ␉␉␉␉{␊ |
636 | ␉␉␉␉␉tmp2 |= (rebase_stream[++i] & 0x7f) << bits;␊ |
637 | ␉␉␉␉␉bits += 7;␊ |
638 | ␉␉␉␉}␊ |
639 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
640 | ␉␉␉␉␊ |
641 | ␉␉␉␉index = 0;␊ |
642 | ␉␉␉␉for (index = 0; index < tmp; ++index) {␊ |
643 | ␉␉␉␉␉rebase_location(base + segmentAddress, (char*)base);␊ |
644 | ␉␉␉␉␉␊ |
645 | ␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
646 | ␉␉␉␉}␊ |
647 | ␉␉␉␉break;␊ |
648 | ␉␉}␊ |
649 | ␉␉i++;␊ |
650 | ␉}␊ |
651 | }␊ |
652 | ␊ |
653 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
654 | // NOTE: this uses 32bit values, and not 64bit values. ␊ |
655 | // There is apossibility that this could cause issues,␊ |
656 | // however the macho file is 32 bit, so it shouldn't matter too much␊ |
657 | void bind_macho(void* base, char* bind_stream, UInt32 size)␊ |
658 | {␉␊ |
659 | ␉bind_stream += (UInt32)base;␊ |
660 | ␉␊ |
661 | ␉UInt8 immediate = 0;␊ |
662 | ␉UInt8 opcode = 0;␊ |
663 | ␉UInt8 type = 0;␊ |
664 | ␉␊ |
665 | ␉UInt32 segmentAddress = 0;␊ |
666 | ␉␊ |
667 | ␉UInt32 address = 0;␊ |
668 | ␉␊ |
669 | ␉SInt32 addend = 0;␉␉␉// TODO: handle this␊ |
670 | ␉SInt32 libraryOrdinal = 0;␊ |
671 | ␊ |
672 | ␉const char* symbolName = NULL;␊ |
673 | ␉UInt8 symboFlags = 0;␊ |
674 | ␉UInt32 symbolAddr = 0xFFFFFFFF;␊ |
675 | ␉␊ |
676 | ␉// Temperary variables␊ |
677 | ␉UInt8 bits = 0;␊ |
678 | ␉UInt32 tmp = 0;␊ |
679 | ␉UInt32 tmp2 = 0;␊ |
680 | ␉␊ |
681 | ␉UInt32 index = 0;␊ |
682 | ␉int done = 0;␊ |
683 | ␉unsigned int i = 0;␊ |
684 | ␉␊ |
685 | ␉while(/*!done &&*/ i < size)␊ |
686 | ␉{␊ |
687 | ␉␉immediate = bind_stream[i] & BIND_IMMEDIATE_MASK;␊ |
688 | ␉␉opcode = bind_stream[i] & BIND_OPCODE_MASK;␊ |
689 | ␉␉␊ |
690 | ␉␉␊ |
691 | ␉␉switch(opcode)␊ |
692 | ␉␉{␊ |
693 | ␉␉␉case BIND_OPCODE_DONE:␊ |
694 | ␉␉␉␉done = 1; ␊ |
695 | ␉␉␉␉break;␊ |
696 | ␉␉␉␉␊ |
697 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:␊ |
698 | ␉␉␉␉libraryOrdinal = immediate;␊ |
699 | ␉␉␉␉//DBG("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);␊ |
700 | ␉␉␉␉break;␊ |
701 | ␉␉␉␉␊ |
702 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:␊ |
703 | ␉␉␉␉libraryOrdinal = 0;␊ |
704 | ␉␉␉␉bits = 0;␊ |
705 | ␉␉␉␉do␊ |
706 | ␉␉␉␉{␊ |
707 | ␉␉␉␉␉libraryOrdinal |= (bind_stream[++i] & 0x7f) << bits;␊ |
708 | ␉␉␉␉␉bits += 7;␊ |
709 | ␉␉␉␉}␊ |
710 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
711 | ␉␉␉␉␊ |
712 | ␉␉␉␉//DBG("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);␊ |
713 | ␊ |
714 | ␉␉␉␉break;␊ |
715 | ␉␉␉␉␊ |
716 | ␉␉␉case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:␊ |
717 | ␉␉␉␉// NOTE: this is wrong, fortunately we don't use it␊ |
718 | ␉␉␉␉libraryOrdinal = -immediate;␊ |
719 | ␉␉␉␉//DBG("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);␊ |
720 | ␊ |
721 | ␉␉␉␉break;␊ |
722 | ␉␉␉␉␊ |
723 | ␉␉␉case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:␊ |
724 | ␉␉␉␉symboFlags = immediate;␊ |
725 | ␉␉␉␉symbolName = (char*)&bind_stream[++i];␊ |
726 | ␉␉␉␉i += strlen((char*)&bind_stream[i]);␊ |
727 | ␉␉␉␉//DBG("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symboFlags);␊ |
728 | ␊ |
729 | ␉␉␉␉symbolAddr = lookup_all_symbols(symbolName);␊ |
730 | ␊ |
731 | ␉␉␉␉break;␊ |
732 | ␉␉␉␉␊ |
733 | ␉␉␉case BIND_OPCODE_SET_TYPE_IMM:␊ |
734 | ␉␉␉␉// Set bind type (pointer, absolute32, pcrel32)␊ |
735 | ␉␉␉␉type = immediate;␊ |
736 | ␉␉␉␉//DBG("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);␊ |
737 | ␊ |
738 | ␉␉␉␉break;␊ |
739 | ␉␉␉␉␊ |
740 | ␉␉␉case BIND_OPCODE_SET_ADDEND_SLEB:␊ |
741 | ␉␉␉␉addend = 0;␊ |
742 | ␉␉␉␉bits = 0;␊ |
743 | ␉␉␉␉do␊ |
744 | ␉␉␉␉{␊ |
745 | ␉␉␉␉␉addend |= (bind_stream[++i] & 0x7f) << bits;␊ |
746 | ␉␉␉␉␉bits += 7;␊ |
747 | ␉␉␉␉}␊ |
748 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
749 | ␉␉␉␉␊ |
750 | ␉␉␉␉if(!(bind_stream[i-1] & 0x40)) addend *= -1;␊ |
751 | ␉␉␉␉␊ |
752 | ␉␉␉␉//DBG("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);␊ |
753 | ␉␉␉␉break;␊ |
754 | ␉␉␉␉␊ |
755 | ␉␉␉case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
756 | ␉␉␉␉segmentAddress = 0;␊ |
757 | ␊ |
758 | ␉␉␉␉// Locate address␊ |
759 | ␉␉␉␉struct segment_command* segCommand = NULL;␊ |
760 | ␉␉␉␉␊ |
761 | ␉␉␉␉unsigned int binIndex = 0;␊ |
762 | ␉␉␉␉index = 0;␊ |
763 | ␉␉␉␉do␊ |
764 | ␉␉␉␉{␊ |
765 | ␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
766 | ␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
767 | ␉␉␉␉␉index++;␊ |
768 | ␉␉␉␉}␊ |
769 | ␉␉␉␉while(index <= immediate);␊ |
770 | ␉␉␉␉␊ |
771 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
772 | ␉␉␉␉␊ |
773 | ␉␉␉␉// Read in offset␊ |
774 | ␉␉␉␉tmp = 0;␊ |
775 | ␉␉␉␉bits = 0;␊ |
776 | ␉␉␉␉do␊ |
777 | ␉␉␉␉{␊ |
778 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
779 | ␉␉␉␉␉bits += 7;␊ |
780 | ␉␉␉␉}␊ |
781 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
782 | ␉␉␉␉␊ |
783 | ␉␉␉␉segmentAddress += tmp;␊ |
784 | ␉␉␉␉␊ |
785 | ␉␉␉␉//DBG("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress);␊ |
786 | ␉␉␉␉break;␊ |
787 | ␉␉␉␉␊ |
788 | ␉␉␉case BIND_OPCODE_ADD_ADDR_ULEB:␊ |
789 | ␉␉␉␉// Read in offset␊ |
790 | ␉␉␉␉tmp = 0;␊ |
791 | ␉␉␉␉bits = 0;␊ |
792 | ␉␉␉␉do␊ |
793 | ␉␉␉␉{␊ |
794 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
795 | ␉␉␉␉␉bits += 7;␊ |
796 | ␉␉␉␉}␊ |
797 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
798 | ␉␉␉␉␊ |
799 | ␉␉␉␉segmentAddress += tmp;␊ |
800 | ␉␉␉␉//DBG("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);␊ |
801 | ␉␉␉␉break;␊ |
802 | ␉␉␉␉␊ |
803 | ␉␉␉case BIND_OPCODE_DO_BIND:␊ |
804 | ␉␉␉␉//DBG("BIND_OPCODE_DO_BIND\n");␊ |
805 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
806 | ␉␉␉␉{␊ |
807 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
808 | ␊ |
809 | ␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
810 | ␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
811 | ␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
812 | ␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
813 | ␉␉␉␉}␊ |
814 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
815 | ␉␉␉␉{␊ |
816 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
817 | ␉␉␉␉}␊ |
818 | ␉␉␉␉␊ |
819 | ␉␉␉␉segmentAddress += sizeof(void*);␊ |
820 | ␉␉␉␉break;␊ |
821 | ␉␉␉␉␊ |
822 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:␊ |
823 | ␉␉␉␉//DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");␊ |
824 | ␉␉␉␉␊ |
825 | ␉␉␉␉␊ |
826 | ␉␉␉␉// Read in offset␊ |
827 | ␉␉␉␉tmp = 0;␊ |
828 | ␉␉␉␉bits = 0;␊ |
829 | ␉␉␉␉do␊ |
830 | ␉␉␉␉{␊ |
831 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
832 | ␉␉␉␉␉bits += 7;␊ |
833 | ␉␉␉␉}␊ |
834 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
835 | ␉␉␉␉␊ |
836 | ␉␉␉␉␊ |
837 | ␉␉␉␉␊ |
838 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
839 | ␉␉␉␉{␊ |
840 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
841 | ␉␉␉␉␉␊ |
842 | ␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
843 | ␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
844 | ␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
845 | ␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
846 | ␉␉␉␉}␊ |
847 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
848 | ␉␉␉␉{␊ |
849 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
850 | ␉␉␉␉}␊ |
851 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
852 | ␊ |
853 | ␉␉␉␉␊ |
854 | ␉␉␉␉break;␊ |
855 | ␉␉␉␉␊ |
856 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:␊ |
857 | ␉␉␉␉//DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");␊ |
858 | ␉␉␉␉␊ |
859 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
860 | ␉␉␉␉{␊ |
861 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
862 | ␉␉␉␉␉␊ |
863 | ␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
864 | ␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
865 | ␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
866 | ␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
867 | ␉␉␉␉}␊ |
868 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
869 | ␉␉␉␉{␊ |
870 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
871 | ␉␉␉␉}␊ |
872 | ␉␉␉␉segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);␊ |
873 | ␊ |
874 | ␉␉␉␉␊ |
875 | ␉␉␉␉break;␊ |
876 | ␉␉␉␉␊ |
877 | ␉␉␉case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:␊ |
878 | ␊ |
879 | ␉␉␉␉tmp = 0;␊ |
880 | ␉␉␉␉bits = 0;␊ |
881 | ␉␉␉␉do␊ |
882 | ␉␉␉␉{␊ |
883 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
884 | ␉␉␉␉␉bits += 7;␊ |
885 | ␉␉␉␉}␊ |
886 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
887 | ␊ |
888 | ␉␉␉␉␊ |
889 | ␉␉␉␉tmp2 = 0;␊ |
890 | ␉␉␉␉bits = 0;␊ |
891 | ␉␉␉␉do␊ |
892 | ␉␉␉␉{␊ |
893 | ␉␉␉␉␉tmp2 |= (bind_stream[++i] & 0x7f) << bits;␊ |
894 | ␉␉␉␉␉bits += 7;␊ |
895 | ␉␉␉␉}␊ |
896 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
897 | ␉␉␉␉␊ |
898 | ␉␉␉␉␊ |
899 | ␉␉␉␉//DBG("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);␊ |
900 | ␊ |
901 | ␉␉␉␉␊ |
902 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
903 | ␉␉␉␉{␊ |
904 | ␉␉␉␉␉for(index = 0; index < tmp; index++)␊ |
905 | ␉␉␉␉␉{␊ |
906 | ␉␉␉␉␉␉␊ |
907 | ␉␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
908 | ␉␉␉␉␉␉␊ |
909 | ␉␉␉␉␉␉((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;␊ |
910 | ␉␉␉␉␉␉((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;␊ |
911 | ␉␉␉␉␉␉((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;␊ |
912 | ␉␉␉␉␉␉((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;␊ |
913 | ␉␉␉␉␉␉␊ |
914 | ␉␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
915 | ␉␉␉␉␉}␊ |
916 | ␉␉␉␉}␊ |
917 | ␉␉␉␉else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
918 | ␉␉␉␉{␊ |
919 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
920 | ␉␉␉␉}␊ |
921 | ␉␉␉␉␊ |
922 | ␉␉␉␉␊ |
923 | ␉␉␉␉break;␊ |
924 | ␉␉␉␉␊ |
925 | ␉␉}␊ |
926 | ␉␉i++;␊ |
927 | ␉}␊ |
928 | }␊ |
929 | ␊ |
930 | inline void rebase_location(UInt32* location, char* base)␊ |
931 | {␊ |
932 | ␉*location += (UInt32)base;␊ |
933 | }␊ |
934 | ␊ |
935 | /*␊ |
936 | * add_symbol␊ |
937 | * This function adds a symbol from a module to the list of known symbols ␊ |
938 | * possibly change to a pointer and add this to the Symbol module so that it can␊ |
939 | * adjust it's internal symbol list (sort) to optimize locating new symbols␊ |
940 | */␊ |
941 | void add_symbol(char* symbol, void* addr)␊ |
942 | {␊ |
943 | ␉symbolList_t* entry;␊ |
944 | ␉//DBG("Adding symbol %s at 0x%X\n", symbol, addr);␊ |
945 | ␉␊ |
946 | ␉if(!moduleSymbols)␊ |
947 | ␉{␊ |
948 | ␉␉moduleSymbols = entry = malloc(sizeof(symbolList_t));␊ |
949 | ␊ |
950 | ␉}␊ |
951 | ␉else␊ |
952 | ␉{␊ |
953 | ␉␉entry = moduleSymbols;␊ |
954 | ␉␉while(entry->next)␊ |
955 | ␉␉{␊ |
956 | ␉␉␉entry = entry->next;␊ |
957 | ␉␉}␊ |
958 | ␉␉␊ |
959 | ␉␉entry->next = malloc(sizeof(symbolList_t));␊ |
960 | ␉␉entry = entry->next;␊ |
961 | ␉}␊ |
962 | ␊ |
963 | ␉entry->next = NULL;␊ |
964 | ␉entry->addr = (unsigned int)addr;␊ |
965 | ␉entry->symbol = symbol;␊ |
966 | }␊ |
967 | ␊ |
968 | ␊ |
969 | /*␊ |
970 | * print out the information about the loaded module␊ |
971 | ␊ |
972 | */␊ |
973 | void module_loaded(char* name, UInt32 version, UInt32 compat)␊ |
974 | {␊ |
975 | ␉moduleList_t* entry;␊ |
976 | ␉/*␊ |
977 | ␉DBG("\%s.dylib Version %d.%d.%d loaded\n"␊ |
978 | ␉␉ "\tCompatibility Version: %d.%d.%d\n",␊ |
979 | ␉␉ name,␊ |
980 | ␉␉ (version >> 16) & 0xFFFF,␊ |
981 | ␉␉ (version >> 8) & 0x00FF,␊ |
982 | ␉␉ (version >> 0) & 0x00FF,␊ |
983 | ␉␉ (compat >> 16) & 0xFFFF,␊ |
984 | ␉␉ (compat >> 8) & 0x00FF,␊ |
985 | ␉␉ (compat >> 0) & 0x00FF);␉␊ |
986 | ␉*/␊ |
987 | ␉if(loadedModules == NULL)␊ |
988 | ␉{␊ |
989 | ␉␉loadedModules = entry = malloc(sizeof(moduleList_t));␊ |
990 | ␉}␊ |
991 | ␉else␊ |
992 | ␉{␊ |
993 | ␉␉entry = loadedModules;␊ |
994 | ␉␉while(entry->next)␊ |
995 | ␉␉{␊ |
996 | ␉␉␉entry = entry->next;␊ |
997 | ␉␉}␊ |
998 | ␉␉entry->next = malloc(sizeof(moduleList_t));␊ |
999 | ␉␉entry = entry->next;␊ |
1000 | ␉}␊ |
1001 | ␉␊ |
1002 | ␉entry->next = NULL;␊ |
1003 | ␉entry->module = name;␊ |
1004 | ␉entry->version = version;␊ |
1005 | ␉entry->compat = compat;␊ |
1006 | ␉␊ |
1007 | ␉␊ |
1008 | }␊ |
1009 | ␊ |
1010 | int is_module_laoded(const char* name)␊ |
1011 | {␊ |
1012 | ␉moduleList_t* entry = loadedModules;␊ |
1013 | ␉while(entry)␊ |
1014 | ␉{␊ |
1015 | ␉␉if(strcmp(entry->module, name) == 0)␊ |
1016 | ␉␉{␊ |
1017 | ␉␉␉return 1;␊ |
1018 | ␉␉}␊ |
1019 | ␉␉else␊ |
1020 | ␉␉{␊ |
1021 | ␉␉␉entry = entry->next;␊ |
1022 | ␉␉}␊ |
1023 | ␊ |
1024 | ␉}␊ |
1025 | ␉return 0;␊ |
1026 | }␊ |
1027 | ␊ |
1028 | // Look for symbols using the Smbols moduel function.␊ |
1029 | // If non are found, look through the list of module symbols␊ |
1030 | unsigned int lookup_all_symbols(const char* name)␊ |
1031 | {␊ |
1032 | ␉unsigned int addr = 0xFFFFFFFF;␊ |
1033 | ␉if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF)␊ |
1034 | ␉{␊ |
1035 | ␉␉addr = lookup_symbol(name);␊ |
1036 | ␉␉if(addr != 0xFFFFFFFF)␊ |
1037 | ␉␉{␊ |
1038 | ␉␉␉//DBG("Internal symbol %s located at 0x%X\n", name, addr);␊ |
1039 | ␉␉␉return addr;␊ |
1040 | ␉␉}␊ |
1041 | ␉}␊ |
1042 | ␊ |
1043 | ␉␊ |
1044 | ␉symbolList_t* entry = moduleSymbols;␊ |
1045 | ␉while(entry)␊ |
1046 | ␉{␊ |
1047 | ␉␉if(strcmp(entry->symbol, name) == 0)␊ |
1048 | ␉␉{␊ |
1049 | ␉␉␉//DBG("External symbol %s located at 0x%X\n", name, entry->addr);␊ |
1050 | ␉␉␉return entry->addr;␊ |
1051 | ␉␉}␊ |
1052 | ␉␉else␊ |
1053 | ␉␉{␊ |
1054 | ␉␉␉entry = entry->next;␊ |
1055 | ␉␉}␊ |
1056 | ␊ |
1057 | ␉}␊ |
1058 | ␉if(strcmp(name, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
1059 | ␉{␊ |
1060 | ␉␉printf("Unable to locate symbol %s\n", name);␊ |
1061 | ␉}␊ |
1062 | ␉return 0xFFFFFFFF;␊ |
1063 | }␊ |
1064 | ␊ |
1065 | ␊ |
1066 | /*␊ |
1067 | * parse the symbol table␊ |
1068 | * Lookup any undefined symbols␊ |
1069 | */␊ |
1070 | ␊ |
1071 | unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, char* symbolStub, UInt32 nonlazy)␊ |
1072 | {␊ |
1073 | ␉unsigned int module_start = 0xFFFFFFFF;␊ |
1074 | ␉␊ |
1075 | ␉UInt32 symbolIndex = 0;␊ |
1076 | ␉char* symbolString = base + (char*)symtabCommand->stroff;␊ |
1077 | ␉//char* symbolTable = base + symtabCommand->symoff;␊ |
1078 | ␉␊ |
1079 | ␉while(symbolIndex < symtabCommand->nsyms)␊ |
1080 | ␉{␊ |
1081 | ␉␉␊ |
1082 | ␉␉struct nlist* symbolEntry = (void*)base + symtabCommand->symoff + (symbolIndex * sizeof(struct nlist));␊ |
1083 | ␉␉␊ |
1084 | ␉␉// If the symbol is exported by this module␊ |
1085 | ␉␉if(symbolEntry->n_value)␊ |
1086 | ␉␉{␊ |
1087 | ␉␉␉if(strcmp(symbolString + symbolEntry->n_un.n_strx, "start") == 0)␊ |
1088 | ␉␉␉{␊ |
1089 | ␉␉␉␉// Module start located. Start is an alias so don't register it␊ |
1090 | ␉␉␉␉module_start = base + symbolEntry->n_value;␊ |
1091 | ␉␉␉}␊ |
1092 | ␉␉␉else␊ |
1093 | ␉␉␉{␊ |
1094 | ␉␉␉␉add_symbol(symbolString + symbolEntry->n_un.n_strx, (void*)base + symbolEntry->n_value); ␊ |
1095 | ␉␉␉}␊ |
1096 | ␉␉}␊ |
1097 | ␉␉␊ |
1098 | ␉␉symbolEntry+= sizeof(struct nlist);␊ |
1099 | ␉␉symbolIndex++;␉// TODO remove␊ |
1100 | ␉}␊ |
1101 | ␉␊ |
1102 | ␉return module_start;␊ |
1103 | ␉␊ |
1104 | }␊ |
1105 | ␊ |
1106 | ␊ |
1107 | /*␊ |
1108 | * Locate the symbol for an already loaded function and modify the beginning of␊ |
1109 | * the function to jump directly to the new one␊ |
1110 | * example: replace_function("_HelloWorld_start", &replacement_start);␊ |
1111 | */␊ |
1112 | int replace_function(const char* symbol, void* newAddress)␊ |
1113 | {␊ |
1114 | ␉UInt32* jumpPointer = malloc(sizeof(UInt32*));␉ ␊ |
1115 | ␉// TODO: look into using the next four bytes of the function instead␊ |
1116 | ␉// Most functions should support this, as they probably will be at ␊ |
1117 | ␉// least 10 bytes long, but you never know, this is sligtly safer as␊ |
1118 | ␉// function can be as small as 6 bytes.␊ |
1119 | ␉UInt32 addr = lookup_all_symbols(symbol);␊ |
1120 | ␉␊ |
1121 | ␉char* binary = (char*)addr;␊ |
1122 | ␉if(addr != 0xFFFFFFFF)␊ |
1123 | ␉{␊ |
1124 | ␉␉*binary++ = 0xFF;␉// Jump␊ |
1125 | ␉␉*binary++ = 0x25;␉// Long Jump␊ |
1126 | ␉␉*((UInt32*)binary) = (UInt32)jumpPointer;␊ |
1127 | ␉␉␊ |
1128 | ␉␉*jumpPointer = (UInt32)newAddress;␊ |
1129 | ␉␉␊ |
1130 | ␉␉return 1;␊ |
1131 | ␉}␊ |
1132 | ␉else ␊ |
1133 | ␉{␊ |
1134 | ␉␉return 0;␊ |
1135 | ␉}␊ |
1136 | ␊ |
1137 | } |