1 | /*␊ |
2 | * Copyright 2010 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | * TODO: Zero out bss if needed␊ |
5 | */␊ |
6 | ␊ |
7 | #include "boot.h"␊ |
8 | #include "bootstruct.h"␊ |
9 | #include "multiboot.h"␊ |
10 | #include "modules.h"␊ |
11 | ␊ |
12 | #ifndef DEBUG_MODULES␊ |
13 | #define DEBUG_MODULES 1␊ |
14 | #endif␊ |
15 | ␊ |
16 | #if DEBUG_MODULES␊ |
17 | #define DBG(x...)␉verbose(x) //;getc()␊ |
18 | #else␊ |
19 | #define DBG(x...)␉//msglog(x)␊ |
20 | #endif␊ |
21 | ␊ |
22 | // NOTE: Global so that modules can link with this␊ |
23 | unsigned long long textAddress = 0;␊ |
24 | unsigned long long textSection = 0;␊ |
25 | ␊ |
26 | void* symbols_module_start = (void*)0xFFFFFFFF;␉// This will be modified post compile␊ |
27 | ␊ |
28 | /** Internal symbols, however there are accessor methods **/␊ |
29 | moduleHook_t* moduleCallbacks = NULL;␊ |
30 | moduleList_t* loadedModules = NULL;␊ |
31 | symbolList_t* moduleSymbols = NULL;␊ |
32 | unsigned int (*lookup_symbol)(const char*) = NULL;␊ |
33 | ␊ |
34 | ␊ |
35 | ␊ |
36 | ␊ |
37 | ␊ |
38 | #if DEBUG_MODULES␊ |
39 | void print_hook_list()␊ |
40 | {␊ |
41 | ␉DBG("---Hook Table---\n");␊ |
42 | ␊ |
43 | ␉moduleHook_t* hooks = moduleCallbacks;␊ |
44 | ␉while(hooks)␊ |
45 | ␉{␊ |
46 | ␉␉DBG("Hook: %s\n", hooks->name);␊ |
47 | ␉␉callbackList_t* callbacks = hooks->callbacks; ␊ |
48 | ␉␉while(callbacks->next != NULL)␊ |
49 | ␉␉{␊ |
50 | ␉␉␉DBG("\tcallbacks: %x\n", callbacks->callback);␊ |
51 | ␉␉␉callbacks = callbacks->next;␊ |
52 | ␉␉}␊ |
53 | ␉␉␊ |
54 | ␉␉hooks = hooks->next;␊ |
55 | ␉}␊ |
56 | }␊ |
57 | #endif␊ |
58 | ␊ |
59 | /*␊ |
60 | * Initialize the module system by loading the Symbols.dylib module.␊ |
61 | * Once loaded, locate the _lookup_symbol function so that internal␊ |
62 | * symbols can be resolved.␊ |
63 | */␊ |
64 | int init_module_system()␊ |
65 | {␊ |
66 | ␉void (*module_start)(void) = NULL;␊ |
67 | ␉char* module_data = symbols_module_start + BOOT2_ADDR;␊ |
68 | ␉// Intialize module system␊ |
69 | ␉if(symbols_module_start == (void*)0xFFFFFFFF)␊ |
70 | ␉{␊ |
71 | ␉␉DBG("Module system not compiled in\n");␊ |
72 | ␉␉load_module(SYMBOLS_MODULE);␊ |
73 | ␉␉␊ |
74 | ␉␉lookup_symbol = (void*)lookup_all_symbols(SYMBOL_LOOKUP_SYMBOL);␊ |
75 | ␉␉␊ |
76 | ␉␉if((UInt32)lookup_symbol != 0xFFFFFFFF)␊ |
77 | ␉␉{␊ |
78 | ␉␉␉return 1;␊ |
79 | ␉␉}␊ |
80 | ␉␉␊ |
81 | ␉␉return 0;␊ |
82 | ␉}␊ |
83 | ␊ |
84 | ␉module_start = parse_mach(module_data, &load_module, &add_symbol);␊ |
85 | ␉␊ |
86 | ␉if(module_start && module_start != (void*)0xFFFFFFFF)␊ |
87 | ␉{␊ |
88 | ␉␉// Notify the system that it was laoded␊ |
89 | ␉␉module_loaded(SYMBOLS_MODULE /*moduleName, moduleVersion, moduleCompat*/);␊ |
90 | ␉␉(*module_start)();␉// Start the module␊ |
91 | ␉␉DBG("Module %s Loaded.\n", SYMBOLS_MODULE);␊ |
92 | ␊ |
93 | ␉␉lookup_symbol = (void*)lookup_all_symbols(SYMBOL_LOOKUP_SYMBOL);␊ |
94 | ␉␉␊ |
95 | ␉␉if((UInt32)lookup_symbol != 0xFFFFFFFF)␊ |
96 | ␉␉{␊ |
97 | ␉␉␉return 1;␊ |
98 | ␉␉}␊ |
99 | ␉}␊ |
100 | ␉else {␊ |
101 | ␉␉// The module does not have a valid start function␊ |
102 | ␉␉verbose("Unable to start %s\n", SYMBOLS_MODULE);␊ |
103 | ␉␉//getc();␊ |
104 | ␉}␉␉␊ |
105 | ␉return 0;␊ |
106 | }␊ |
107 | ␊ |
108 | ␊ |
109 | /*␊ |
110 | * Load all modules in the /Extra/modules/ directory␊ |
111 | * Module depencdies will be loaded first␊ |
112 | * Modules will only be loaded once. When loaded a module must␊ |
113 | * setup apropriete function calls and hooks as required.␊ |
114 | * NOTE: To ensure a module loads after another you may ␊ |
115 | * link one module with the other. For dyld to allow this, you must␊ |
116 | * reference at least one symbol within the module.␊ |
117 | */␊ |
118 | void load_all_modules()␊ |
119 | {␊ |
120 | ␉char* name;␊ |
121 | ␉long flags;␊ |
122 | ␉long time;␊ |
123 | ␉DBG("Loading modules...\n");␊ |
124 | ␉struct dirstuff* moduleDir = opendir("/Extra/modules/");␊ |
125 | ␉while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)␊ |
126 | ␉{␊ |
127 | ␉␉if(strcmp(&name[strlen(name) - sizeof("dylib")], ".dylib") == 0)␊ |
128 | ␉␉{␊ |
129 | ␉␉␉char* tmp = malloc(strlen(name) + 1);␊ |
130 | ␉␉␉if (name[0] == '.') {␊ |
131 | ␉␉␉␉continue;␊ |
132 | ␉␉␉}␊ |
133 | ␉␉␉strcpy(tmp, name);␊ |
134 | ␉␉␉␊ |
135 | ␉␉␉DBG("Attempting to load %s\n", tmp);␉␉␉␊ |
136 | ␉␉␉if(!load_module(tmp))␊ |
137 | ␉␉␉{␊ |
138 | ␉␉␉␉// failed to load␊ |
139 | ␉␉␉␉// free(tmp);␊ |
140 | ␉␉␉␉DBG("...failed to load\n");␊ |
141 | ␉␉␉}␊ |
142 | ␉␉}␊ |
143 | ␉␉else ␊ |
144 | ␉␉{␊ |
145 | ␉␉␉DBG("Ignoring %s\n", name);␊ |
146 | ␉␉}␊ |
147 | ␊ |
148 | ␉}␊ |
149 | }␊ |
150 | ␊ |
151 | ␊ |
152 | /*␊ |
153 | * Load a module file in /Extra/modules␊ |
154 | * TODO: verify version number of module␊ |
155 | */␊ |
156 | int load_module(char* module)␊ |
157 | {␊ |
158 | ␉void (*module_start)(void) = NULL;␊ |
159 | ␊ |
160 | ␉␊ |
161 | ␉// Check to see if the module has already been loaded␊ |
162 | ␉if(is_module_loaded(module))␊ |
163 | ␉{␊ |
164 | ␉␉// NOTE: Symbols.dylib tries to load twice, this catches it as well␊ |
165 | ␉␉// as when a module links with an already loaded module␊ |
166 | ␉␉DBG("load_module: Module %s already loaded\n", module);␊ |
167 | ␉␉return 1;␊ |
168 | ␉}␊ |
169 | ␉␊ |
170 | ␉char modString[128];␊ |
171 | ␉int fh = -1;␊ |
172 | ␉sprintf(modString, "/Extra/modules/%s", module);␊ |
173 | ␉fh = open(modString, 0);␊ |
174 | ␉if(fh < 0)␊ |
175 | ␉{␊ |
176 | ␉␉DBG("load_module: Unable to locate module %s\n", modString);␊ |
177 | ␉␉//getc();␊ |
178 | ␉␉return 0;␊ |
179 | ␉}␊ |
180 | ␉␊ |
181 | ␉unsigned int moduleSize = file_size(fh);␊ |
182 | ␉char* module_base = (char*) malloc(moduleSize);␊ |
183 | ␉if (moduleSize && read(fh, module_base, moduleSize) == moduleSize)␊ |
184 | ␉{␊ |
185 | ␊ |
186 | ␉␉DBG("load_module: Module %s read in.\n", modString);␊ |
187 | ␊ |
188 | ␉␉// Module loaded into memory, parse it␊ |
189 | ␉␉module_start = parse_mach(module_base, &load_module, &add_symbol);␊ |
190 | ␊ |
191 | ␉␉if(module_start && module_start != (void*)0xFFFFFFFF)␊ |
192 | ␉␉{␊ |
193 | ␉␉␉// Notify the system that it was laoded␊ |
194 | ␉␉␉module_loaded(module/*moduleName, moduleVersion, moduleCompat*/);␊ |
195 | ␉␉␉(*module_start)();␉// Start the module␊ |
196 | ␉␉␉DBG("load_module: Module %s Loaded.\n", module);␊ |
197 | ␉␉}␊ |
198 | ␉␉else {␊ |
199 | ␉␉␉// The module does not have a valid start function␊ |
200 | ␉␉␉verbose("load_module: Unable to start %s\n", module);␊ |
201 | ␉␉␉getc();␊ |
202 | ␉␉}␉␉␊ |
203 | ␉}␊ |
204 | ␉else␊ |
205 | ␉{␊ |
206 | ␉␉DBG("load_module: Unable to read in module %s\n.", module);␊ |
207 | ␉␉//getc();␊ |
208 | ␉}␊ |
209 | ␉close(fh);␊ |
210 | ␉return 1;␊ |
211 | }␊ |
212 | ␊ |
213 | /*␊ |
214 | *␉execute_hook( const char* name )␊ |
215 | *␉␉name - Name of the module hook␊ |
216 | *␉␉␉If any callbacks have been registered for this hook␊ |
217 | *␉␉␉they will be executed now in the same order that the␊ |
218 | *␉␉␉hooks were added.␊ |
219 | */␊ |
220 | int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4)␊ |
221 | {␊ |
222 | ␉DBG("execute_hook: Attempting to execute hook '%s'\n", name);␊ |
223 | ␉moduleHook_t* hooks = moduleCallbacks;␊ |
224 | //Slice - dunno why it not works␊ |
225 | /*␉while(hooks && strcmp(name, hooks->name) < 0)␊ |
226 | ␉{␊ |
227 | ␉␉DBG("execute_hook: name=%s hook->name=%s cmp=%d try next\n", name, hooks->name, strcmp(name, hooks->name));␊ |
228 | ␉␉hooks = hooks->next;␊ |
229 | ␉␉␊ |
230 | ␉}*/␊ |
231 | ␉do {␊ |
232 | ␉␉␊ |
233 | ␉␉DBG("execute_hook: name=%s hook->name=%s cmp=%d try next\n", name, hooks->name, strcmp(name, hooks->name));␊ |
234 | ␉␉if (strcmp(name, hooks->name) == 0) {␊ |
235 | ␉␉␉break;␊ |
236 | ␉␉}␊ |
237 | ␉␉hooks = hooks->next;␊ |
238 | ␉} while (hooks);␊ |
239 | ␊ |
240 | ␉if(hooks) // && strcmp(name, hooks->name) == 0)␊ |
241 | ␉{␊ |
242 | ␉␉// Loop through all callbacks for this module␊ |
243 | ␉␉callbackList_t* callbacks = hooks->callbacks;␊ |
244 | ␉␉␊ |
245 | ␉␉while(callbacks)␊ |
246 | ␉␉{␊ |
247 | ␉␉␉DBG("execute_hook: Executing '%s' with callback 0x%X.\n", name, callbacks->callback);␊ |
248 | ␉␉␉// Execute callback␊ |
249 | ␉␉␉callbacks->callback(arg1, arg2, arg3, arg4);␊ |
250 | ␉␉␉callbacks = callbacks->next;␊ |
251 | //␉␉␉DBG("execute_hook: Hook '%s' callback executed, next is 0x%X.\n", name, callbacks);␊ |
252 | ␉␉␉␊ |
253 | ␉␉}␊ |
254 | ␉␉DBG("execute_hook: Hook '%s' executed.\n", name);␊ |
255 | ␉␉␊ |
256 | ␉␉return 1;␊ |
257 | ␉}␊ |
258 | ␉else␊ |
259 | ␉{␊ |
260 | ␉␉DBG("execute_hook: No callbacks for '%s' hook.\n", name);␊ |
261 | ␉␉␊ |
262 | ␉␉// Callback for this module doesn't exist;␊ |
263 | ␉␉//verbose("Unable execute hook '%s', no callbacks registered.\n", name);␊ |
264 | ␉␉//pause();␊ |
265 | ␉␉return 0;␊ |
266 | ␉}␊ |
267 | }␊ |
268 | ␊ |
269 | ␊ |
270 | ␊ |
271 | /*␊ |
272 | *␉register_hook_callback( const char* name, void(*callback)())␊ |
273 | *␉␉name - Name of the module hook to attach to.␊ |
274 | *␉␉callbacks - The function pointer that will be called when the␊ |
275 | *␉␉␉hook is executed. When registering a new callback name, the callback is added sorted.␊ |
276 | *␉␉␉NOTE: the hooks take four void* arguments.␊ |
277 | *␉␉␉TODO: refactor␊ |
278 | */␊ |
279 | void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*))␊ |
280 | {␉␊ |
281 | ␉DBG("register_hook_callback: Adding callback for '%s' hook.\n", name);␊ |
282 | ␊ |
283 | ␉moduleHook_t* newHook = malloc(sizeof(moduleHook_t));␊ |
284 | ␉if(!moduleCallbacks)␊ |
285 | ␉{␊ |
286 | ␉␉newHook->next = moduleCallbacks;␊ |
287 | ␉␉moduleCallbacks = newHook;␊ |
288 | ␉␉␊ |
289 | ␉␉newHook->name = name;␊ |
290 | ␉␉newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));␊ |
291 | ␉␉newHook->callbacks->callback = callback;␊ |
292 | ␉␉newHook->callbacks->next = NULL;␊ |
293 | ␉␉DBG("register_hook_callback: new moduleCallbacks with %s\n", name);␊ |
294 | ␉}␊ |
295 | ␉else␊ |
296 | ␉{␊ |
297 | ␉␉moduleHook_t* hooks = moduleCallbacks;␊ |
298 | //Slice␊ |
299 | // ignored␉first node where hooks->name == name ?!␊ |
300 | /*␉␉␊ |
301 | ␉␉while(hooks->next && strcmp(name, hooks->next->name) < 0)␊ |
302 | ␉␉{␊ |
303 | ␉␉␉hooks = hooks->next;␊ |
304 | ␉␉}␊ |
305 | */␉␉␊ |
306 | ␉␉moduleHook_t* backHook = moduleCallbacks; //I need to remember last node in chain if next=NULL␊ |
307 | ␉␉do {␊ |
308 | ␉␉␉DBG("register_hook_callback: found = %s\n", hooks->name);␊ |
309 | ␉␉␉if (strcmp(name, hooks->name) == 0) {␊ |
310 | ␉␉␉␉break;␊ |
311 | ␉␉␉}␊ |
312 | ␉␉␉backHook = hooks;␊ |
313 | ␉␉␉hooks = hooks->next;␊ |
314 | ␉␉} while (hooks);␊ |
315 | // There are only two variants: hooks found or not␊ |
316 | // if not found then hooks=NULL so remember backHook␉␉␊ |
317 | /*␉␉␊ |
318 | ␉␉if(!hooks->next)␊ |
319 | ␉␉{␊ |
320 | ␉␉␉// Appent to the end␊ |
321 | ␉␉␉newHook->next = NULL;␊ |
322 | ␉␉␉hooks->next = newHook;␊ |
323 | ␉␉␉newHook->name = name;␊ |
324 | ␉␉␉newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));␊ |
325 | ␉␉␉newHook->callbacks->callback = callback;␊ |
326 | ␉␉␉newHook->callbacks->next = NULL;␊ |
327 | ␉␉␉DBG("register_hook_callback: Appent to the end\n");␊ |
328 | ␉␉␉␊ |
329 | ␉␉}␊ |
330 | ␉␉else */␊ |
331 | //First␉check for hook found. So hooks != NULL␊ |
332 | ␉␉if(hooks) //&& strcmp(name, hooks->name) == 0)␊ |
333 | ␉␉{␊ |
334 | ␉␉␉// We found the hook␊ |
335 | ␉␉␉// Hook already exists, add a callback to this hook␊ |
336 | ␉␉␉callbackList_t* callbacks = hooks->callbacks; //hooks->next->callbacks␊ |
337 | ␉␉␉while(callbacks->next != NULL)␊ |
338 | ␉␉␉{␊ |
339 | ␉␉␉␉callbacks = callbacks->next;␊ |
340 | ␉␉␉}␊ |
341 | ␉␉␉// Add new entry to end of hook list.␊ |
342 | ␉␉␉callbacks->next = (callbackList_t*)malloc(sizeof(callbackList_t));␊ |
343 | ␉␉␉callbacks = callbacks->next;␊ |
344 | ␉␉␉callbacks->next = NULL;␊ |
345 | ␉␉␉callbacks->callback = callback;␊ |
346 | ␉␉␉DBG("register_hook_callback: existing hook with new callback\n");␊ |
347 | ␉␉}␊ |
348 | ␉␉else␊ |
349 | ␉␉{␊ |
350 | ␉␉␉hooks = backHook; //now hooks=NULL so remember last not NULL where hooks->next=NULL␉␉␊ |
351 | ␉␉␉newHook->next = NULL;␊ |
352 | ␉␉␉hooks->next = newHook;␊ |
353 | ␉␉␉newHook->name = name;␊ |
354 | ␉␉␉newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t));␊ |
355 | ␉␉␉newHook->callbacks->callback = callback;␊ |
356 | ␉␉␉newHook->callbacks->next = NULL;␊ |
357 | ␉␉␉DBG("register_hook_callback: add new hook %s\n", name);␊ |
358 | ␉␉}␊ |
359 | ␉}␊ |
360 | #if DEBUG_MODULES␊ |
361 | ␉print_hook_list();␊ |
362 | ␉//getc();␊ |
363 | #endif␊ |
364 | ␉␊ |
365 | }␊ |
366 | ␊ |
367 | ␊ |
368 | /*␊ |
369 | * Parse through a macho module. The module will be rebased and binded␊ |
370 | * as specified in the macho header. If the module is sucessfuly laoded␊ |
371 | * the module iinit address will be returned.␊ |
372 | * NOTE; all dependecies will be loaded before this module is started␊ |
373 | * NOTE: If the module is unable to load ot completeion, the modules␊ |
374 | * symbols will still be available (TODO: fix this). This should not␊ |
375 | * happen as all dependencies are verified before the symbols are read in.␊ |
376 | */␊ |
377 | void* parse_mach(void* binary, int(*dylib_loader)(char*), long long(*symbol_handler)(char*, long long, char))␉// TODO: add param to specify valid archs␊ |
378 | {␉␊ |
379 | ␉char is64 = false;␊ |
380 | ␉void (*module_start)(void) = NULL;␊ |
381 | ␉␊ |
382 | ␉// Module info␊ |
383 | ␉/*char* moduleName = NULL;␊ |
384 | ␉UInt32 moduleVersion = 0;␊ |
385 | ␉UInt32 moduleCompat = 0;␊ |
386 | ␉*/␊ |
387 | ␉// TODO convert all of the structs to a union␊ |
388 | ␉struct load_command *loadCommand = NULL;␊ |
389 | ␉struct dylib_command* dylibCommand = NULL;␊ |
390 | ␉struct dyld_info_command* dyldInfoCommand = NULL;␊ |
391 | ␉␊ |
392 | ␉struct symtab_command* symtabCommand = NULL;␊ |
393 | ␉struct segment_command *segCommand = NULL;␊ |
394 | ␉struct segment_command_64 *segCommand64 = NULL;␊ |
395 | ␊ |
396 | ␉//struct dysymtab_command* dysymtabCommand = NULL;␊ |
397 | ␉UInt32 binaryIndex = 0;␊ |
398 | ␉UInt16 cmd = 0;␊ |
399 | ␊ |
400 | ␉// Parse through the load commands␊ |
401 | ␉if(((struct mach_header*)binary)->magic == MH_MAGIC)␊ |
402 | ␉{␊ |
403 | ␉␉is64 = false;␊ |
404 | ␉␉binaryIndex += sizeof(struct mach_header);␊ |
405 | ␉}␊ |
406 | ␉else if(((struct mach_header_64*)binary)->magic == MH_MAGIC_64)␊ |
407 | ␉{␊ |
408 | ␉␉// NOTE: modules cannot be 64bit...␊ |
409 | ␉␉is64 = true;␊ |
410 | ␉␉binaryIndex += sizeof(struct mach_header_64);␊ |
411 | ␉}␊ |
412 | ␉else␊ |
413 | ␉{␊ |
414 | ␉␉verbose("Invalid mach magic 0x%X\n", ((struct mach_header*)binary)->magic);␊ |
415 | ␉␉getc();␊ |
416 | ␉␉return NULL;␊ |
417 | ␉}␊ |
418 | ␊ |
419 | ␊ |
420 | ␉␊ |
421 | ␉/*if(((struct mach_header*)binary)->filetype != MH_DYLIB)␊ |
422 | ␉{␊ |
423 | ␉␉verbose("Module is not a dylib. Unable to load.\n");␊ |
424 | ␉␉getc();␊ |
425 | ␉␉return NULL; // Module is in the incorrect format␊ |
426 | ␉}*/␊ |
427 | ␉␊ |
428 | ␉while(cmd < ((struct mach_header*)binary)->ncmds)␊ |
429 | ␉{␊ |
430 | ␉␉cmd++;␊ |
431 | ␉␉␊ |
432 | ␉␉loadCommand = binary + binaryIndex;␊ |
433 | ␉␉UInt32 cmdSize = loadCommand->cmdsize;␊ |
434 | ␊ |
435 | ␉␉␊ |
436 | ␉␉switch ((loadCommand->cmd & 0x7FFFFFFF))␊ |
437 | ␉␉{␊ |
438 | ␉␉␉␉// TODO: sepeare function to handel appropriate sections␊ |
439 | ␉␉␉case LC_SYMTAB:␊ |
440 | ␉␉␉␉symtabCommand = binary + binaryIndex;␊ |
441 | ␉␉␉␉break;␊ |
442 | ␉␉␉␉␊ |
443 | ␉␉␉case LC_SEGMENT: // 32bit macho␊ |
444 | ␉␉␉␉segCommand = binary + binaryIndex;␊ |
445 | ␉␉␉␉␊ |
446 | ␉␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
447 | ␉␉␉␉␊ |
448 | ␉␉␉␉if(strcmp("__TEXT", segCommand->segname) == 0)␊ |
449 | ␉␉␉␉{␊ |
450 | ␉␉␉␉␉UInt32 sectionIndex;␊ |
451 | ␉␉␉␉␉␊ |
452 | ␉␉␉␉␉sectionIndex = sizeof(struct segment_command);␊ |
453 | ␉␉␉␉␉␊ |
454 | ␉␉␉␉␉struct section *sect;␊ |
455 | ␉␉␉␉␉␊ |
456 | ␉␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
457 | ␉␉␉␉␉{␊ |
458 | ␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
459 | ␉␉␉␉␉␉␊ |
460 | ␉␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
461 | ␉␉␉␉␉␉␊ |
462 | ␉␉␉␉␉␉␊ |
463 | ␉␉␉␉␉␉if(strcmp("__text", sect->sectname) == 0)␊ |
464 | ␉␉␉␉␉␉{␊ |
465 | ␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
466 | ␉␉␉␉␉␉␉textSection = sect->offset;␊ |
467 | ␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
468 | ␉␉␉␉␉␉␉break;␊ |
469 | ␉␉␉␉␉␉}␉␉␉␉␉␊ |
470 | ␉␉␉␉␉}␊ |
471 | ␉␉␉␉}␊ |
472 | ␉␉␉␉else if(strcmp("__DATA", segCommand->segname) == 0)␊ |
473 | ␉␉␉␉{␊ |
474 | ␉␉␉␉␉UInt32 sectionIndex;␊ |
475 | ␉␉␉␉␉␊ |
476 | ␉␉␉␉␉sectionIndex = sizeof(struct segment_command);␊ |
477 | ␉␉␉␉␉␊ |
478 | ␉␉␉␉␉struct section *sect;␊ |
479 | ␉␉␉␉␉␊ |
480 | ␉␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
481 | ␉␉␉␉␉{␊ |
482 | ␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
483 | ␉␉␉␉␉␉␊ |
484 | ␉␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
485 | ␉␉␉␉␉␉␊ |
486 | ␉␉␉␉␉␉␊ |
487 | ␉␉␉␉␉␉if(strcmp("__bss", sect->sectname) == 0)␊ |
488 | ␉␉␉␉␉␉{␊ |
489 | ␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
490 | ␉␉␉␉␉␉␉//printf("__DATA,__bss found.\n"); getc();␊ |
491 | ␉␉␉␉␉␉␉break;␊ |
492 | ␉␉␉␉␉␉}␉␉␉␉␉␊ |
493 | ␉␉␉␉␉}␊ |
494 | ␉␉␉␉␉␊ |
495 | ␉␉␉␉}␊ |
496 | ␊ |
497 | ␉␉␉␉break;␊ |
498 | ␉␉␉case LC_SEGMENT_64:␉// 64bit macho's␊ |
499 | ␉␉␉␉segCommand64 = binary + binaryIndex;␊ |
500 | ␉␉␉␉␊ |
501 | ␉␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
502 | ␉␉␉␉␊ |
503 | ␉␉␉␉if(strcmp("__TEXT", segCommand64->segname) == 0)␊ |
504 | ␉␉␉␉{␊ |
505 | ␉␉␉␉␉UInt32 sectionIndex;␊ |
506 | ␉␉␉␉␉␊ |
507 | ␉␉␉␉␉sectionIndex = sizeof(struct segment_command_64);␊ |
508 | ␉␉␉␉␉␊ |
509 | ␉␉␉␉␉struct section_64 *sect;␊ |
510 | ␉␉␉␉␉␊ |
511 | ␉␉␉␉␉while(sectionIndex < segCommand64->cmdsize)␊ |
512 | ␉␉␉␉␉{␊ |
513 | ␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
514 | ␉␉␉␉␉␉␊ |
515 | ␉␉␉␉␉␉sectionIndex += sizeof(struct section_64);␊ |
516 | ␉␉␉␉␉␉␊ |
517 | ␉␉␉␉␉␉␊ |
518 | ␉␉␉␉␉␉if(strcmp("__text", sect->sectname) == 0)␊ |
519 | ␉␉␉␉␉␉{␊ |
520 | ␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
521 | ␉␉␉␉␉␉␉textSection = sect->offset;␊ |
522 | ␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
523 | ␉␉␉␉␉␉␉␊ |
524 | ␉␉␉␉␉␉␉break;␊ |
525 | ␉␉␉␉␉␉}␉␉␉␉␉␊ |
526 | ␉␉␉␉␉}␊ |
527 | ␉␉␉␉}␊ |
528 | ␉␉␉␉else if(strcmp("__DATA", segCommand->segname) == 0)␊ |
529 | ␉␉␉␉{␊ |
530 | ␉␉␉␉␉UInt32 sectionIndex;␊ |
531 | ␉␉␉␉␉␊ |
532 | ␉␉␉␉␉sectionIndex = sizeof(struct segment_command_64);␊ |
533 | ␉␉␉␉␉␊ |
534 | ␉␉␉␉␉struct section_64 *sect;␊ |
535 | ␉␉␉␉␉␊ |
536 | ␉␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
537 | ␉␉␉␉␉{␊ |
538 | ␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
539 | ␉␉␉␉␉␉␊ |
540 | ␉␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
541 | ␉␉␉␉␉␉␊ |
542 | ␉␉␉␉␉␉␊ |
543 | ␉␉␉␉␉␉if(strcmp("__bss", sect->sectname) == 0)␊ |
544 | ␉␉␉␉␉␉{␊ |
545 | ␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
546 | ␉␉␉␉␉␉␉//printf("__DATA,__bss found.\n"); getc();␊ |
547 | ␉␉␉␉␉␉␉break;␊ |
548 | ␉␉␉␉␉␉}␉␉␉␉␉␊ |
549 | ␉␉␉␉␉}␊ |
550 | ␉␉␉␉␉␊ |
551 | ␉␉␉␉}␊ |
552 | ␉␉␉␉␊ |
553 | ␉␉␉␉␊ |
554 | ␉␉␉␉break;␊ |
555 | ␉␉␉␉␊ |
556 | ␉␉␉case LC_DYSYMTAB:␊ |
557 | ␉␉␉␉break;␊ |
558 | ␉␉␉␉␊ |
559 | ␉␉␉case LC_LOAD_DYLIB:␊ |
560 | ␉␉␉case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:␊ |
561 | ␉␉␉␉dylibCommand = binary + binaryIndex;␊ |
562 | ␉␉␉␉char* module = binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));␊ |
563 | ␉␉␉␉// TODO: verify version␊ |
564 | ␉␉␉␉// =␉dylibCommand->dylib.current_version;␊ |
565 | ␉␉␉␉// =␉dylibCommand->dylib.compatibility_version;␊ |
566 | ␉␉␉␉if(dylib_loader)␊ |
567 | ␉␉␉␉{␊ |
568 | ␉␉␉␉␉char* name = malloc(strlen(module) + strlen(".dylib") + 1);␊ |
569 | ␉␉␉␉␉sprintf(name, "%s.dylib", module);␊ |
570 | ␊ |
571 | ␉␉␉␉␉if (!dylib_loader(name))␊ |
572 | ␉␉␉␉␉{␊ |
573 | ␉␉␉␉␉␉free(name);␊ |
574 | ␉␉␉␉␉␉verbose("Unable to load dependency...\n");␊ |
575 | ␉␉␉␉␉␉//return NULL;␊ |
576 | ␉␉␉␉␉}␊ |
577 | ␉␉␉␉}␊ |
578 | ␊ |
579 | ␉␉␉␉break;␊ |
580 | ␉␉␉␉␊ |
581 | ␉␉␉case LC_ID_DYLIB:␊ |
582 | ␉␉␉␉dylibCommand = binary + binaryIndex;␊ |
583 | ␉␉␉␉/*moduleName =␉binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));␊ |
584 | ␉␉␉␉moduleVersion =␉dylibCommand->dylib.current_version;␊ |
585 | ␉␉␉␉moduleCompat =␉dylibCommand->dylib.compatibility_version;␊ |
586 | ␉␉␉␉ */␊ |
587 | ␉␉␉␉break;␊ |
588 | ␊ |
589 | ␉␉␉case LC_DYLD_INFO:␊ |
590 | ␉␉␉␉// Bind and rebase info is stored here␊ |
591 | ␉␉␉␉dyldInfoCommand = binary + binaryIndex;␊ |
592 | ␉␉␉␉break;␊ |
593 | ␉␉␉␉␊ |
594 | ␉␉␉case LC_UUID:␊ |
595 | ␉␉␉␉break;␊ |
596 | ␉␉␉␉␊ |
597 | ␉␉␉case LC_UNIXTHREAD:␊ |
598 | ␉␉␉␉break;␊ |
599 | ␉␉␉␉␊ |
600 | ␉␉␉default:␊ |
601 | ␉␉␉␉DBG("parse_mach: Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);␊ |
602 | ␉␉␉␉break;␊ |
603 | ␉␉␊ |
604 | ␉␉}␊ |
605 | ␊ |
606 | ␉␉binaryIndex += cmdSize;␊ |
607 | ␉}␊ |
608 | ␉//if(!moduleName) return NULL;␊ |
609 | ␉␉␊ |
610 | ␊ |
611 | ␉// bind_macho uses the symbols.␊ |
612 | ␉module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbol_handler, is64);␊ |
613 | ␊ |
614 | ␉// Rebase the module before binding it.␊ |
615 | ␉if(dyldInfoCommand && dyldInfoCommand->rebase_off)␊ |
616 | ␉{␊ |
617 | ␉␉rebase_macho(binary, (char*)dyldInfoCommand->rebase_off, dyldInfoCommand->rebase_size);␊ |
618 | ␉}␊ |
619 | ␉␊ |
620 | ␉if(dyldInfoCommand && dyldInfoCommand->bind_off)␊ |
621 | ␉{␊ |
622 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->bind_off, dyldInfoCommand->bind_size);␊ |
623 | ␉}␊ |
624 | ␉␊ |
625 | ␉if(dyldInfoCommand && dyldInfoCommand->weak_bind_off)␊ |
626 | ␉{␊ |
627 | ␉␉// NOTE: this currently should never happen.␊ |
628 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->weak_bind_off, dyldInfoCommand->weak_bind_size);␊ |
629 | ␉}␊ |
630 | ␉␊ |
631 | ␉if(dyldInfoCommand && dyldInfoCommand->lazy_bind_off)␊ |
632 | ␉{␊ |
633 | ␉␉// NOTE: we are binding the lazy pointers as a module is laoded,␊ |
634 | ␉␉// This should be changed to bind when a symbol is referened at runtime instead.␊ |
635 | ␉␉bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size);␊ |
636 | ␉}␊ |
637 | ␊ |
638 | ␉return module_start;␊ |
639 | ␉␊ |
640 | }␊ |
641 | ␊ |
642 | ␊ |
643 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
644 | void rebase_macho(void* base, char* rebase_stream, UInt32 size)␊ |
645 | {␊ |
646 | ␉rebase_stream += (UInt32)base;␊ |
647 | ␉␊ |
648 | ␉UInt8 immediate = 0;␊ |
649 | ␉UInt8 opcode = 0;␊ |
650 | ␉UInt8 type = 0;␊ |
651 | ␉␊ |
652 | ␉UInt32 segmentAddress = 0;␊ |
653 | ␉␊ |
654 | ␉␊ |
655 | ␉␊ |
656 | ␉UInt32 tmp = 0;␊ |
657 | ␉UInt32 tmp2 = 0;␊ |
658 | ␉UInt8 bits = 0;␊ |
659 | ␉int index = 0;␊ |
660 | ␉␊ |
661 | ␉//int done = 0;␊ |
662 | ␉unsigned int i = 0;␊ |
663 | ␉␊ |
664 | ␉while(/*!done &&*/ i < size)␊ |
665 | ␉{␊ |
666 | ␉␉immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;␊ |
667 | ␉␉opcode = rebase_stream[i] & REBASE_OPCODE_MASK;␊ |
668 | ␊ |
669 | ␉␉␊ |
670 | ␉␉switch(opcode)␊ |
671 | ␉␉{␊ |
672 | ␉␉␉case REBASE_OPCODE_DONE:␊ |
673 | ␉␉␉␉// Rebase complete.␊ |
674 | ␉␉␉␉//done = 1;␊ |
675 | ␉␉␉default:␊ |
676 | ␉␉␉␉break;␊ |
677 | ␉␉␉␉␊ |
678 | ␉␉␉␉␊ |
679 | ␉␉␉case REBASE_OPCODE_SET_TYPE_IMM:␊ |
680 | ␉␉␉␉// Set rebase type (pointer, absolute32, pcrel32)␊ |
681 | ␉␉␉␉//DBG("Rebase type = 0x%X\n", immediate);␊ |
682 | ␉␉␉␉type = immediate;␊ |
683 | ␉␉␉␉break;␊ |
684 | ␉␉␉␉␊ |
685 | ␉␉␉␉␊ |
686 | ␉␉␉case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
687 | ␉␉␉␉// Locate address to begin rebasing␊ |
688 | ␉␉␉␉segmentAddress = 0;␊ |
689 | ␊ |
690 | ␉␉␉␉struct segment_command* segCommand = NULL; // NOTE: 32bit only␊ |
691 | ␉␉␉␉␊ |
692 | ␉␉␉␉unsigned int binIndex = 0;␊ |
693 | ␉␉␉␉index = 0;␊ |
694 | ␉␉␉␉do␊ |
695 | ␉␉␉␉{␊ |
696 | ␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
697 | ␉␉␉␉␉␊ |
698 | ␉␉␉␉␉␊ |
699 | ␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
700 | ␉␉␉␉␉index++;␊ |
701 | ␉␉␉␉}␊ |
702 | ␉␉␉␉while(index <= immediate);␊ |
703 | ␊ |
704 | ␊ |
705 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
706 | ␉␉␉␉␊ |
707 | ␉␉␉␉tmp = 0;␊ |
708 | ␉␉␉␉bits = 0;␊ |
709 | ␉␉␉␉do␊ |
710 | ␉␉␉␉{␊ |
711 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
712 | ␉␉␉␉␉bits += 7;␊ |
713 | ␉␉␉␉}␊ |
714 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
715 | ␉␉␉␉␊ |
716 | ␉␉␉␉segmentAddress += tmp;␊ |
717 | ␉␉␉␉break;␊ |
718 | ␉␉␉␉␊ |
719 | ␉␉␉␉␊ |
720 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_ULEB:␊ |
721 | ␉␉␉␉// Add value to rebase address␊ |
722 | ␉␉␉␉tmp = 0;␊ |
723 | ␉␉␉␉bits = 0;␊ |
724 | ␉␉␉␉do␊ |
725 | ␉␉␉␉{␊ |
726 | ␉␉␉␉␉tmp <<= bits;␊ |
727 | ␉␉␉␉␉tmp |= rebase_stream[++i] & 0x7f;␊ |
728 | ␉␉␉␉␉bits += 7;␊ |
729 | ␉␉␉␉}␊ |
730 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
731 | ␉␉␉␉␊ |
732 | ␉␉␉␉segmentAddress +=␉tmp; ␊ |
733 | ␉␉␉␉break;␊ |
734 | ␉␉␉␉␊ |
735 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:␊ |
736 | ␉␉␉␉segmentAddress += immediate * sizeof(void*);␊ |
737 | ␉␉␉␉break;␊ |
738 | ␉␉␉␉␊ |
739 | ␉␉␉␉␊ |
740 | ␉␉␉case REBASE_OPCODE_DO_REBASE_IMM_TIMES:␊ |
741 | ␉␉␉␉index = 0;␊ |
742 | ␉␉␉␉for (index = 0; index < immediate; ++index) {␊ |
743 | ␉␉␉␉␉rebase_location(base + segmentAddress, (char*)base, type);␊ |
744 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
745 | ␉␉␉␉}␊ |
746 | ␉␉␉␉break;␊ |
747 | ␉␉␉␊ |
748 | ␉␉␉␉␊ |
749 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:␊ |
750 | ␉␉␉␉tmp = 0;␊ |
751 | ␉␉␉␉bits = 0;␊ |
752 | ␉␉␉␉do␊ |
753 | ␉␉␉␉{␊ |
754 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
755 | ␉␉␉␉␉bits += 7;␊ |
756 | ␉␉␉␉}␊ |
757 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
758 | ␉␉␉␉␊ |
759 | ␉␉␉␉index = 0;␊ |
760 | ␉␉␉␉for (index = 0; index < tmp; ++index) {␊ |
761 | ␉␉␉␉␉//DBG("\tRebasing 0x%X\n", segmentAddress);␊ |
762 | ␉␉␉␉␉rebase_location(base + segmentAddress, (char*)base, type);␉␉␉␉␉␊ |
763 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
764 | ␉␉␉␉}␊ |
765 | ␉␉␉␉break;␊ |
766 | ␉␉␉␉␊ |
767 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:␊ |
768 | ␉␉␉␉tmp = 0;␊ |
769 | ␉␉␉␉bits = 0;␊ |
770 | ␉␉␉␉do␊ |
771 | ␉␉␉␉{␊ |
772 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
773 | ␉␉␉␉␉bits += 7;␊ |
774 | ␉␉␉␉}␊ |
775 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
776 | ␉␉␉␉␊ |
777 | ␉␉␉␉rebase_location(base + segmentAddress, (char*)base, type);␊ |
778 | ␉␉␉␉␊ |
779 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
780 | ␉␉␉␉break;␊ |
781 | ␉␉␉␉␊ |
782 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:␊ |
783 | ␉␉␉␉tmp = 0;␊ |
784 | ␉␉␉␉bits = 0;␊ |
785 | ␉␉␉␉do␊ |
786 | ␉␉␉␉{␊ |
787 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
788 | ␉␉␉␉␉bits += 7;␊ |
789 | ␉␉␉␉}␊ |
790 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
791 | ␉␉␉␉␊ |
792 | ␉␉␉␉␊ |
793 | ␉␉␉␉tmp2 = 0;␊ |
794 | ␉␉␉␉bits = 0;␊ |
795 | ␉␉␉␉do␊ |
796 | ␉␉␉␉{␊ |
797 | ␉␉␉␉␉tmp2 |= (rebase_stream[++i] & 0x7f) << bits;␊ |
798 | ␉␉␉␉␉bits += 7;␊ |
799 | ␉␉␉␉}␊ |
800 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
801 | ␉␉␉␉␊ |
802 | ␉␉␉␉index = 0;␊ |
803 | ␉␉␉␉for (index = 0; index < tmp; ++index) {␊ |
804 | ␊ |
805 | ␉␉␉␉␉rebase_location(base + segmentAddress, (char*)base, type);␊ |
806 | ␉␉␉␉␉␊ |
807 | ␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
808 | ␉␉␉␉}␊ |
809 | ␉␉␉␉break;␊ |
810 | ␉␉}␊ |
811 | ␉␉i++;␊ |
812 | ␉}␊ |
813 | }␊ |
814 | ␊ |
815 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
816 | // NOTE: this uses 32bit values, and not 64bit values. ␊ |
817 | // There is apossibility that this could cause issues,␊ |
818 | // however the macho file is 32 bit, so it shouldn't matter too much␊ |
819 | void bind_macho(void* base, char* bind_stream, UInt32 size)␊ |
820 | {␉␊ |
821 | ␉bind_stream += (UInt32)base;␊ |
822 | ␉␊ |
823 | ␉UInt8 immediate = 0;␊ |
824 | ␉UInt8 opcode = 0;␊ |
825 | ␉UInt8 type = 0;␊ |
826 | ␉␊ |
827 | ␉UInt32 segmentAddress = 0;␊ |
828 | ␉␊ |
829 | ␉UInt32 address = 0;␊ |
830 | ␉␊ |
831 | ␉SInt32 addend = 0;␉␉␉// TODO: handle this␊ |
832 | ␉SInt32 libraryOrdinal = 0;␊ |
833 | ␊ |
834 | ␉const char* symbolName = NULL;␊ |
835 | ␉UInt8 symboFlags = 0;␊ |
836 | ␉UInt32 symbolAddr = 0xFFFFFFFF;␊ |
837 | ␉␊ |
838 | ␉// Temperary variables␊ |
839 | ␉UInt8 bits = 0;␊ |
840 | ␉UInt32 tmp = 0;␊ |
841 | ␉UInt32 tmp2 = 0;␊ |
842 | ␉␊ |
843 | ␉UInt32 index = 0;␊ |
844 | ␉//int done = 0;␊ |
845 | ␉unsigned int i = 0;␊ |
846 | ␉␊ |
847 | ␉while(/*!done &&*/ i < size)␊ |
848 | ␉{␊ |
849 | ␉␉immediate = bind_stream[i] & BIND_IMMEDIATE_MASK;␊ |
850 | ␉␉opcode = bind_stream[i] & BIND_OPCODE_MASK;␊ |
851 | ␉␉␊ |
852 | ␉␉␊ |
853 | ␉␉switch(opcode)␊ |
854 | ␉␉{␊ |
855 | ␉␉␉case BIND_OPCODE_DONE:␊ |
856 | ␉␉␉␉//done = 1; ␊ |
857 | ␉␉␉default:␊ |
858 | ␉␉␉␉break;␊ |
859 | ␉␉␉␉␊ |
860 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:␊ |
861 | ␉␉␉␉libraryOrdinal = immediate;␊ |
862 | ␉␉␉␉//DBG("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);␊ |
863 | ␉␉␉␉break;␊ |
864 | ␉␉␉␉␊ |
865 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:␊ |
866 | ␉␉␉␉libraryOrdinal = 0;␊ |
867 | ␉␉␉␉bits = 0;␊ |
868 | ␉␉␉␉do␊ |
869 | ␉␉␉␉{␊ |
870 | ␉␉␉␉␉libraryOrdinal |= (bind_stream[++i] & 0x7f) << bits;␊ |
871 | ␉␉␉␉␉bits += 7;␊ |
872 | ␉␉␉␉}␊ |
873 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
874 | ␉␉␉␉␊ |
875 | ␉␉␉␉//DBG("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);␊ |
876 | ␊ |
877 | ␉␉␉␉break;␊ |
878 | ␉␉␉␉␊ |
879 | ␉␉␉case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:␊ |
880 | ␉␉␉␉// NOTE: this is wrong, fortunately we don't use it␊ |
881 | ␉␉␉␉libraryOrdinal = immediate ? (SInt8)(BIND_OPCODE_MASK | immediate) : immediate;␉␉␉␉␊ |
882 | ␉␉␉␉//DBG("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);␊ |
883 | ␊ |
884 | ␉␉␉␉break;␊ |
885 | ␉␉␉␉␊ |
886 | ␉␉␉case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:␊ |
887 | ␉␉␉␉symboFlags = immediate;␊ |
888 | ␉␉␉␉symbolName = (char*)&bind_stream[++i];␊ |
889 | ␉␉␉␉i += strlen((char*)&bind_stream[i]);␊ |
890 | ␉␉␉␉//DBG("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symboFlags);␊ |
891 | ␊ |
892 | ␉␉␉␉symbolAddr = lookup_all_symbols(symbolName);␊ |
893 | ␊ |
894 | ␉␉␉␉break;␊ |
895 | ␉␉␉␉␊ |
896 | ␉␉␉case BIND_OPCODE_SET_TYPE_IMM:␊ |
897 | ␉␉␉␉// Set bind type (pointer, absolute32, pcrel32)␊ |
898 | ␉␉␉␉type = immediate;␊ |
899 | ␉␉␉␉//DBG("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);␊ |
900 | ␊ |
901 | ␉␉␉␉break;␊ |
902 | ␉␉␉␉␊ |
903 | ␉␉␉case BIND_OPCODE_SET_ADDEND_SLEB:␊ |
904 | ␉␉␉␉addend = 0;␊ |
905 | ␉␉␉␉bits = 0;␊ |
906 | ␉␉␉␉do␊ |
907 | ␉␉␉␉{␊ |
908 | ␉␉␉␉␉addend |= (bind_stream[++i] & 0x7f) << bits;␊ |
909 | ␉␉␉␉␉bits += 7;␊ |
910 | ␉␉␉␉}␊ |
911 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
912 | ␉␉␉␉␊ |
913 | ␉␉␉␉if(!(bind_stream[i-1] & 0x40)) addend *= -1;␊ |
914 | ␉␉␉␉␊ |
915 | ␉␉␉␉//DBG("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);␊ |
916 | ␉␉␉␉break;␊ |
917 | ␉␉␉␉␊ |
918 | ␉␉␉case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
919 | ␉␉␉␉segmentAddress = 0;␊ |
920 | ␊ |
921 | ␉␉␉␉// Locate address␊ |
922 | ␉␉␉␉struct segment_command* segCommand = NULL;␉// NOTE: 32bit only␊ |
923 | ␉␉␉␉␊ |
924 | ␉␉␉␉unsigned int binIndex = 0;␊ |
925 | ␉␉␉␉index = 0;␊ |
926 | ␉␉␉␉do␊ |
927 | ␉␉␉␉{␊ |
928 | ␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
929 | ␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
930 | ␉␉␉␉␉index++;␊ |
931 | ␉␉␉␉}␊ |
932 | ␉␉␉␉while(index <= immediate);␊ |
933 | ␉␉␉␉␊ |
934 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
935 | ␉␉␉␉␊ |
936 | ␉␉␉␉// Read in offset␊ |
937 | ␉␉␉␉tmp = 0;␊ |
938 | ␉␉␉␉bits = 0;␊ |
939 | ␉␉␉␉do␊ |
940 | ␉␉␉␉{␊ |
941 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
942 | ␉␉␉␉␉bits += 7;␊ |
943 | ␉␉␉␉}␊ |
944 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
945 | ␉␉␉␉␊ |
946 | ␉␉␉␉segmentAddress += tmp;␊ |
947 | ␉␉␉␉␊ |
948 | ␉␉␉␉//DBG("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress);␊ |
949 | ␉␉␉␉break;␊ |
950 | ␉␉␉␉␊ |
951 | ␉␉␉case BIND_OPCODE_ADD_ADDR_ULEB:␊ |
952 | ␉␉␉␉// Read in offset␊ |
953 | ␉␉␉␉tmp = 0;␊ |
954 | ␉␉␉␉bits = 0;␊ |
955 | ␉␉␉␉do␊ |
956 | ␉␉␉␉{␊ |
957 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
958 | ␉␉␉␉␉bits += 7;␊ |
959 | ␉␉␉␉}␊ |
960 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
961 | ␉␉␉␉␊ |
962 | ␉␉␉␉segmentAddress += tmp;␊ |
963 | ␉␉␉␉//DBG("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);␊ |
964 | ␉␉␉␉break;␊ |
965 | ␉␉␉␉␊ |
966 | ␉␉␉case BIND_OPCODE_DO_BIND:␊ |
967 | ␉␉␉␉//DBG("BIND_OPCODE_DO_BIND\n");␊ |
968 | ␉␉␉␉if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)␊ |
969 | ␉␉␉␉{␊ |
970 | ␉␉␉␉␉// HACK(ish)␊ |
971 | ␉␉␉␉␉// Internal symbol, don't bind␊ |
972 | ␉␉␉␉}␊ |
973 | ␉␉␉␉else␊ |
974 | ␉␉␉␉{␊ |
975 | ␉␉␉␉␉//printf("Binding symbol %s, libraryOrdinal = %d, symboFlags = %d, type = %d\n", symbolName, libraryOrdinal, symboFlags, type);␊ |
976 | ␉␉␉␉␉␊ |
977 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
978 | ␉␉␉␉{␊ |
979 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
980 | ␊ |
981 | ␉␉␉␉␉bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);␊ |
982 | ␉␉␉␉}␊ |
983 | ␉␉␉␉else //if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
984 | ␉␉␉␉{␊ |
985 | ␉␉␉␉␉verbose("Unable to bind symbol %s, libraryOrdinal = %d, symboFlags = %d, type = %d\n", symbolName, libraryOrdinal, symboFlags, type);␊ |
986 | ␉␉␉␉␉getc();␊ |
987 | ␉␉␉␉}␊ |
988 | ␉␉␉␉}␊ |
989 | ␉␉␉␉␊ |
990 | ␉␉␉␉segmentAddress += sizeof(void*);␊ |
991 | ␉␉␉␉break;␊ |
992 | ␉␉␉␉␊ |
993 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:␊ |
994 | ␉␉␉␉//DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");␊ |
995 | ␉␉␉␉␊ |
996 | ␉␉␉␉␊ |
997 | ␉␉␉␉// Read in offset␊ |
998 | ␉␉␉␉tmp = 0;␊ |
999 | ␉␉␉␉bits = 0;␊ |
1000 | ␉␉␉␉do␊ |
1001 | ␉␉␉␉{␊ |
1002 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
1003 | ␉␉␉␉␉bits += 7;␊ |
1004 | ␉␉␉␉}␊ |
1005 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
1006 | ␉␉␉␉␊ |
1007 | ␉␉␉␉␊ |
1008 | ␉␉␉␉if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)␊ |
1009 | ␉␉␉␉{␊ |
1010 | ␉␉␉␉␉// Internal symbol, don't bind␊ |
1011 | ␉␉␉␉}␊ |
1012 | ␉␉␉␉else␊ |
1013 | ␉␉␉␉{␊ |
1014 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
1015 | ␉␉␉␉{␊ |
1016 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
1017 | ␊ |
1018 | ␉␉␉␉␉bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);␊ |
1019 | ␉␉␉␉}␊ |
1020 | ␉␉␉␉else //if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
1021 | ␉␉␉␉{␊ |
1022 | ␉␉␉␉␉verbose("Unable to bind symbol %s\n", symbolName);␊ |
1023 | ␉␉␉␉␉getc();␊ |
1024 | ␉␉␉␉}␊ |
1025 | ␉␉␉␉}␊ |
1026 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
1027 | ␊ |
1028 | ␉␉␉␉␊ |
1029 | ␉␉␉␉break;␊ |
1030 | ␉␉␉␉␊ |
1031 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:␊ |
1032 | ␉␉␉␉//DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");␊ |
1033 | ␉␉␉␉if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)␊ |
1034 | ␉␉␉␉{␊ |
1035 | ␉␉␉␉␉// Internal symbol, don't bind␊ |
1036 | ␉␉␉␉}␊ |
1037 | ␉␉␉␉else␊ |
1038 | ␉␉␉␉{␊ |
1039 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
1040 | ␉␉␉␉{␊ |
1041 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
1042 | ␊ |
1043 | ␉␉␉␉␉bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);␊ |
1044 | ␉␉␉␉}␊ |
1045 | ␉␉␉␉else //if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)␊ |
1046 | ␉␉␉␉{␊ |
1047 | ␉␉␉␉␉verbose("Unable to bind symbol %s\n", symbolName);␊ |
1048 | ␉␉␉␉␉getc();␊ |
1049 | ␉␉␉␉}␊ |
1050 | ␉␉␉␉}␊ |
1051 | ␉␉␉␉segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);␊ |
1052 | ␊ |
1053 | ␉␉␉␉␊ |
1054 | ␉␉␉␉break;␊ |
1055 | ␉␉␉␉␊ |
1056 | ␉␉␉case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:␊ |
1057 | ␊ |
1058 | ␉␉␉␉tmp = 0;␊ |
1059 | ␉␉␉␉bits = 0;␊ |
1060 | ␉␉␉␉do␊ |
1061 | ␉␉␉␉{␊ |
1062 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
1063 | ␉␉␉␉␉bits += 7;␊ |
1064 | ␉␉␉␉}␊ |
1065 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
1066 | ␊ |
1067 | ␉␉␉␉␊ |
1068 | ␉␉␉␉tmp2 = 0;␊ |
1069 | ␉␉␉␉bits = 0;␊ |
1070 | ␉␉␉␉do␊ |
1071 | ␉␉␉␉{␊ |
1072 | ␉␉␉␉␉tmp2 |= (bind_stream[++i] & 0x7f) << bits;␊ |
1073 | ␉␉␉␉␉bits += 7;␊ |
1074 | ␉␉␉␉}␊ |
1075 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
1076 | ␉␉␉␉␊ |
1077 | ␉␉␉␉␊ |
1078 | ␉␉␉␉//DBG("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);␊ |
1079 | ␊ |
1080 | ␉␉␉␉␊ |
1081 | ␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
1082 | ␉␉␉␉{␊ |
1083 | ␉␉␉␉␉for(index = 0; index < tmp; index++)␊ |
1084 | ␉␉␉␉␉{␊ |
1085 | ␉␉␉␉␉␉␊ |
1086 | ␉␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
1087 | ␉␉␉␉␉␉if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)␊ |
1088 | ␉␉␉␉␉␉{␊ |
1089 | ␉␉␉␉␉␉␉// Internal symbol, don't bind␊ |
1090 | ␉␉␉␉␉␉}␊ |
1091 | ␉␉␉␉␉␉else␊ |
1092 | ␉␉␉␉␉␉{␊ |
1093 | ␊ |
1094 | ␉␉␉␉␉␉bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);␊ |
1095 | ␉␉␉␉␉␉}␉␉␉␉␉␉␊ |
1096 | ␉␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
1097 | ␉␉␉␉␉}␊ |
1098 | ␉␉␉␉}␊ |
1099 | ␉␉␉␉else␊ |
1100 | ␉␉␉␉{␊ |
1101 | ␉␉␉␉␉if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER)␊ |
1102 | ␉␉␉␉␉{␊ |
1103 | ␉␉␉␉␉␉// Internal symbol, don't bind␊ |
1104 | ␉␉␉␉␉}␊ |
1105 | ␉␉␉␉␉else␊ |
1106 | ␉␉␉␉␉{␉␉␉␉␉␉␊ |
1107 | ␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
1108 | ␉␉␉␉␉getc();␊ |
1109 | ␉␉␉␉}␊ |
1110 | ␉␉␉␉}␊ |
1111 | ␉␉␉␉␊ |
1112 | ␉␉␉␉␊ |
1113 | ␉␉␉␉break;␊ |
1114 | ␉␉␉␉␊ |
1115 | ␉␉}␊ |
1116 | ␉␉i++;␊ |
1117 | ␉}␊ |
1118 | }␊ |
1119 | ␊ |
1120 | inline void rebase_location(UInt32* location, char* base, int type)␊ |
1121 | {␉␊ |
1122 | ␉switch(type)␊ |
1123 | ␉{␊ |
1124 | ␉␉case REBASE_TYPE_POINTER:␊ |
1125 | ␉␉case REBASE_TYPE_TEXT_ABSOLUTE32:␊ |
1126 | ␉␉␉*location += (UInt32)base;␊ |
1127 | ␉␉␉break;␊ |
1128 | ␉␉␉␊ |
1129 | ␉␉default:␊ |
1130 | ␉␉␉break;␊ |
1131 | ␉}␊ |
1132 | }␊ |
1133 | ␊ |
1134 | inline void bind_location(UInt32* location, char* value, UInt32 addend, int type)␊ |
1135 | {␉␊ |
1136 | ␉// do actual update␊ |
1137 | ␉char* newValue = value + addend;␊ |
1138 | ␊ |
1139 | ␉switch (type) {␊ |
1140 | ␉␉case BIND_TYPE_POINTER:␊ |
1141 | ␉␉case BIND_TYPE_TEXT_ABSOLUTE32:␊ |
1142 | ␉␉␉break;␊ |
1143 | ␊ |
1144 | ␉␉case BIND_TYPE_TEXT_PCREL32:␊ |
1145 | ␉␉␉newValue -= ((UInt32)location + 4);␊ |
1146 | ␊ |
1147 | ␉␉␉break;␊ |
1148 | ␉␉default:␊ |
1149 | ␉␉␉return;␊ |
1150 | ␉}␊ |
1151 | ␉␊ |
1152 | ␉*location = (UInt32)newValue;␊ |
1153 | }␊ |
1154 | ␊ |
1155 | ␊ |
1156 | /*␊ |
1157 | * add_symbol␊ |
1158 | * This function adds a symbol from a module to the list of known symbols ␊ |
1159 | * possibly change to a pointer and add this to the Symbol module so that it can␊ |
1160 | * adjust it's internal symbol list (sort) to optimize locating new symbols␊ |
1161 | * NOTE: returns the address if the symbol is "start", else returns 0xFFFFFFFF␊ |
1162 | */␊ |
1163 | long long add_symbol(char* symbol, long long addr, char is64)␊ |
1164 | {␊ |
1165 | ␉if(is64) return 0xFFFFFFFF; // Fixme␊ |
1166 | ␊ |
1167 | ␉// This only can handle 32bit symbols ␊ |
1168 | ␉symbolList_t* entry;␊ |
1169 | ␉//DBG("Adding symbol %s at 0x%X\n", symbol, addr);␊ |
1170 | ␉␊ |
1171 | ␉if(!moduleSymbols)␊ |
1172 | ␉{␊ |
1173 | ␉␉moduleSymbols = entry = malloc(sizeof(symbolList_t));␊ |
1174 | ␊ |
1175 | ␉}␊ |
1176 | ␉else␊ |
1177 | ␉{␊ |
1178 | ␉␉entry = moduleSymbols;␊ |
1179 | ␉␉while(entry->next)␊ |
1180 | ␉␉{␊ |
1181 | ␉␉␉entry = entry->next;␊ |
1182 | ␉␉}␊ |
1183 | ␉␉␊ |
1184 | ␉␉entry->next = malloc(sizeof(symbolList_t));␊ |
1185 | ␉␉entry = entry->next;␊ |
1186 | ␉}␊ |
1187 | ␊ |
1188 | ␉entry->next = NULL;␊ |
1189 | ␉entry->addr = (UInt32)addr;␊ |
1190 | ␉entry->symbol = symbol;␊ |
1191 | ␉␊ |
1192 | ␉if(strcmp(symbol, "start") == 0)␊ |
1193 | ␉{␊ |
1194 | ␉␉return addr;␊ |
1195 | ␉}␊ |
1196 | ␉else␊ |
1197 | ␉{␊ |
1198 | ␉␉return 0xFFFFFFFF; // fixme␊ |
1199 | ␉}␊ |
1200 | }␊ |
1201 | ␊ |
1202 | ␊ |
1203 | /*␊ |
1204 | * print out the information about the loaded module␊ |
1205 | ␊ |
1206 | */␊ |
1207 | void module_loaded(const char* name/*, UInt32 version, UInt32 compat*/)␊ |
1208 | {␊ |
1209 | ␉// TODO: insert sorted␊ |
1210 | ␉moduleList_t* new_entry = malloc(sizeof(moduleList_t));␊ |
1211 | //␉DBG("module_loaded: %s\n", name);␊ |
1212 | ␉new_entry->next = loadedModules;␊ |
1213 | ␉loadedModules = new_entry;␊ |
1214 | ␉␊ |
1215 | ␉new_entry->module = (char*)name;␊ |
1216 | ␉new_entry->version = 0; //version;␊ |
1217 | ␉new_entry->compat = 0; //compat;␊ |
1218 | }␊ |
1219 | ␊ |
1220 | int is_module_loaded(const char* name)␊ |
1221 | {␊ |
1222 | ␉// todo sorted search␊ |
1223 | ␉moduleList_t* entry = loadedModules;␊ |
1224 | ␉while(entry)␊ |
1225 | ␉{␊ |
1226 | //␉␉DBG("\tis_module_loaded:Comparing %s with %s\n", name, entry->module);␊ |
1227 | ␉␉if(strcmp(entry->module, name) == 0)␊ |
1228 | ␉␉{␊ |
1229 | //␉␉␉DBG("\tis_module_loaded:Located module %s\n", name);␊ |
1230 | ␉␉␉return 1;␊ |
1231 | ␉␉}␊ |
1232 | ␉␉else␊ |
1233 | ␉␉{␊ |
1234 | ␉␉␉entry = entry->next;␊ |
1235 | ␉␉}␊ |
1236 | ␊ |
1237 | ␉}␊ |
1238 | //␉DBG("\tis_module_loaded:Module %s not found in list\n", name);␊ |
1239 | ␊ |
1240 | ␉return 0;␊ |
1241 | }␊ |
1242 | ␊ |
1243 | // Look for symbols using the Symbols module function.␊ |
1244 | // If non are found, look through the list of module symbols␊ |
1245 | unsigned int lookup_all_symbols(const char* name)␊ |
1246 | {␊ |
1247 | ␉unsigned int addr = 0xFFFFFFFF;␊ |
1248 | ␉symbolList_t* entry = moduleSymbols;␊ |
1249 | ␉while(entry)␊ |
1250 | ␉{␊ |
1251 | ␉␉if(strcmp(entry->symbol, name) == 0)␊ |
1252 | ␉␉{␊ |
1253 | ␉␉␉//DBG("External symbol %s located at 0x%X\n", name, entry->addr);␊ |
1254 | ␉␉␉return entry->addr;␊ |
1255 | ␉␉}␊ |
1256 | ␉␉else␊ |
1257 | ␉␉{␊ |
1258 | ␉␉␉entry = entry->next;␊ |
1259 | ␉␉}␊ |
1260 | ␊ |
1261 | ␉}␊ |
1262 | ␉␊ |
1263 | ␉if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF)␊ |
1264 | ␉{␊ |
1265 | ␉␉addr = lookup_symbol(name);␊ |
1266 | ␉␉if(addr != 0xFFFFFFFF)␊ |
1267 | ␉␉{␊ |
1268 | ␉␉␉//DBG("Internal symbol %s located at 0x%X\n", name, addr);␊ |
1269 | ␉␉␉return addr;␊ |
1270 | ␉␉}␊ |
1271 | ␉}␊ |
1272 | ␉␊ |
1273 | ␊ |
1274 | #if DEBUG_MODULES␊ |
1275 | ␉␉verbose("Unable to locate symbol %s\n", name);␊ |
1276 | ␉␉getc();␊ |
1277 | #endif␊ |
1278 | ␉return 0xFFFFFFFF;␊ |
1279 | }␊ |
1280 | ␊ |
1281 | ␊ |
1282 | /*␊ |
1283 | * parse the symbol table␊ |
1284 | * Lookup any undefined symbols␊ |
1285 | */␊ |
1286 | ␊ |
1287 | unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, long long, char), char is64)␊ |
1288 | {␊ |
1289 | ␉// TODO: verify that the _TEXT,_text segment starts at the same locaiton in the file. If not␊ |
1290 | ␉//␉␉␉subtract the vmaddress and add the actual file address back on. (NOTE: if compiled properly, not needed)␊ |
1291 | ␉␊ |
1292 | ␉unsigned int module_start = 0xFFFFFFFF;␊ |
1293 | ␉␊ |
1294 | ␉UInt32 symbolIndex = 0;␊ |
1295 | ␉char* symbolString = base + (char*)symtabCommand->stroff;␊ |
1296 | ␉//char* symbolTable = base + symtabCommand->symoff;␊ |
1297 | ␉if(!is64)␊ |
1298 | ␉{␊ |
1299 | ␉␉struct nlist* symbolEntry = (void*)base + symtabCommand->symoff;␊ |
1300 | ␉␉while(symbolIndex < symtabCommand->nsyms)␊ |
1301 | ␉␉{␊ |
1302 | ␉␉␉// If the symbol is exported by this module␊ |
1303 | ␉␉␉if(symbolEntry->n_value &&␊ |
1304 | ␉␉␉ symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF)␊ |
1305 | ␉␉␉{␊ |
1306 | ␉␉␉␉␊ |
1307 | ␉␉␉␉// Module start located. Start is an alias so don't register it␊ |
1308 | ␉␉␉␉module_start = base + symbolEntry->n_value;␊ |
1309 | ␉␉␉}␊ |
1310 | ␉␉␉␊ |
1311 | ␉␉␉symbolEntry++;␊ |
1312 | ␉␉␉symbolIndex++;␉// TODO remove␊ |
1313 | ␉␉}␊ |
1314 | ␉}␊ |
1315 | ␉else␊ |
1316 | ␉{␊ |
1317 | ␉␉struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff;␊ |
1318 | ␉␉// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now)␉␊ |
1319 | ␉␉while(symbolIndex < symtabCommand->nsyms)␊ |
1320 | ␉␉{␊ |
1321 | ␉␉␉␊ |
1322 | ␉␉␉␊ |
1323 | ␉␉␉// If the symbol is exported by this module␊ |
1324 | ␉␉␉if(symbolEntry->n_value &&␊ |
1325 | ␉␉␉ symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF)␊ |
1326 | ␉␉␉{␊ |
1327 | ␉␉␉␉␊ |
1328 | ␉␉␉␉// Module start located. Start is an alias so don't register it␊ |
1329 | ␉␉␉␉module_start = base + symbolEntry->n_value;␊ |
1330 | ␉␉␉}␊ |
1331 | ␉␉␉␊ |
1332 | ␉␉␉symbolEntry++;␊ |
1333 | ␉␉␉symbolIndex++;␉// TODO remove␊ |
1334 | ␉␉}␊ |
1335 | ␉}␊ |
1336 | ␉␉␊ |
1337 | ␉return module_start;␊ |
1338 | ␉␊ |
1339 | }␊ |
1340 | ␊ |
1341 | ␊ |
1342 | /*␊ |
1343 | * Locate the symbol for an already loaded function and modify the beginning of␊ |
1344 | * the function to jump directly to the new one␊ |
1345 | * example: replace_function("_HelloWorld_start", &replacement_start);␊ |
1346 | */␊ |
1347 | int replace_function(const char* symbol, void* newAddress)␊ |
1348 | {␊ |
1349 | ␉UInt32* jumpPointer = malloc(sizeof(UInt32*));␉ ␊ |
1350 | ␉// TODO: look into using the next four bytes of the function instead␊ |
1351 | ␉// Most functions should support this, as they probably will be at ␊ |
1352 | ␉// least 10 bytes long, but you never know, this is sligtly safer as␊ |
1353 | ␉// function can be as small as 6 bytes.␊ |
1354 | ␉UInt32 addr = lookup_all_symbols(symbol);␊ |
1355 | ␉␊ |
1356 | ␉char* binary = (char*)addr;␊ |
1357 | ␉if(addr != 0xFFFFFFFF)␊ |
1358 | ␉{␊ |
1359 | ␉␉DBG("Replacing %s to point to 0x%x\n", symbol, newAddress);␊ |
1360 | ␉␉*binary++ = 0xFF;␉// Jump␊ |
1361 | ␉␉*binary++ = 0x25;␉// Long Jump␊ |
1362 | ␉␉*((UInt32*)binary) = (UInt32)jumpPointer;␊ |
1363 | ␉␉␊ |
1364 | ␉␉*jumpPointer = (UInt32)newAddress;␊ |
1365 | ␉␉␊ |
1366 | ␉␉return 1;␊ |
1367 | ␉}␊ |
1368 | ␉else ␊ |
1369 | ␉{␊ |
1370 | ␉␉return 0;␊ |
1371 | ␉}␊ |
1372 | ␊ |
1373 | }␊ |
1374 | ␊ |
1375 | void dyld_stub_binder()␊ |
1376 | {␊ |
1377 | ␉// TODO: actualy impliment this function (asm)␊ |
1378 | ␉stop("ERROR: dyld_stub_binder was called, should have been take care of by the linker.\n");␊ |
1379 | } |