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