1 | /*␊ |
2 | * Copyright 2010 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | */␊ |
5 | ␊ |
6 | /*␊ |
7 | * Copyright 2012 Cadet-petit Armel <armelcadetpetit@gmail.com>. All rights reserved.␊ |
8 | *␊ |
9 | * Cleaned, Added (runtime) bundles module support, based on a dylib environement.␊ |
10 | *␊ |
11 | */␊ |
12 | #include "libsaio.h"␊ |
13 | #include "bootstruct.h"␊ |
14 | #include "modules.h"␊ |
15 | ␊ |
16 | #include "sl.h"␊ |
17 | #include "xml.h"␊ |
18 | ␊ |
19 | #ifndef DEBUG_MODULES␊ |
20 | #define DEBUG_MODULES 0␊ |
21 | #endif␊ |
22 | ␊ |
23 | #if DEBUG_MODULES␊ |
24 | #define DBG(x...)␉printf(x)␊ |
25 | #else␊ |
26 | #define DBG(x...)␊ |
27 | #endif␊ |
28 | ␊ |
29 | struct Bundle { ␊ |
30 | ␉struct Bundle *nextBundle;␊ |
31 | ␉long willLoad;␊ |
32 | ␉TagPtr dict;␊ |
33 | TagPtr personalities;␊ |
34 | #if 0␊ |
35 | ␉config_file_t *LanguageConfig; // we will use an xml file instead of pure txt file ... it's easier to parse␊ |
36 | #endif␊ |
37 | ␉//pool_t workspace;␊ |
38 | ␉char *plistAddr;␊ |
39 | ␉long plistLength;␊ |
40 | ␉char *executablePath;␊ |
41 | ␉char *bundlePath;␊ |
42 | ␉long bundlePathLength;␊ |
43 | };␊ |
44 | typedef struct Bundle Bundle, *BundlePtr;␊ |
45 | ␊ |
46 | // NOTE: Global so that modules can link with this␊ |
47 | unsigned long long textAddress = 0;␊ |
48 | unsigned long long textSection = 0;␊ |
49 | ␊ |
50 | moduleHook_t* moduleCallbacks = NULL;␊ |
51 | symbolList_t* moduleSymbols = NULL;␊ |
52 | unsigned int (*lookup_symbol)(const char*, int(*strcmp_callback)(const char*, const char*)) = NULL;␊ |
53 | moduleHook_t* get_callback(const char* name);␊ |
54 | static unsigned int load_module(char * name, char* module, BundlePtr bundle);␊ |
55 | static EFI_STATUS _bind_macho(char* module, void* base, char* bind_stream, UInt32 size, BundlePtr bundle);␊ |
56 | ␊ |
57 | #if macho_64␊ |
58 | static unsigned int parse_mach(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long, char), BundlePtr bundle);␊ |
59 | #else␊ |
60 | static unsigned int parse_mach(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long), BundlePtr bundle);␊ |
61 | #endif␊ |
62 | ␊ |
63 | #if macho_64␊ |
64 | unsigned int handle_symtable(char *module, UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, char*, long long, char), char is64);␊ |
65 | #else␊ |
66 | unsigned int handle_symtable(char *module, UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, char*, long long));␊ |
67 | #endif␊ |
68 | ␊ |
69 | #if DEBUG_MODULES␊ |
70 | VOID print_symbol_list(VOID);␊ |
71 | VOID print_hook_list(VOID);␊ |
72 | ␊ |
73 | VOID print_hook_list(VOID)␊ |
74 | {␊ |
75 | ␉moduleHook_t* hooks = moduleCallbacks;␊ |
76 | ␉printf("Hook list: \n");␊ |
77 | ␉while(hooks)␊ |
78 | ␉{␊ |
79 | ␉␉printf("* %s\n", hooks->name);␊ |
80 | ␉␉hooks = hooks->next;␊ |
81 | ␉}␊ |
82 | ␉printf("\n");␊ |
83 | }␊ |
84 | ␊ |
85 | VOID print_symbol_list(VOID)␊ |
86 | {␊ |
87 | ␉symbolList_t* symbol = moduleSymbols;␊ |
88 | ␉printf("Symbol list: \n");␊ |
89 | ␉while(symbol)␊ |
90 | ␉{␊ |
91 | ␉␉printf("* %s : %s\n", symbol->module, symbol->symbol);␊ |
92 | ␉␉symbol = symbol->next;␊ |
93 | ␉}␊ |
94 | ␉printf("\n");␊ |
95 | }␊ |
96 | #endif␊ |
97 | ␊ |
98 | #if DYLIB_SUPPORT␊ |
99 | ␊ |
100 | typedef struct dylbList_t␊ |
101 | {␊ |
102 | ␉char* dylib_name;␊ |
103 | ␉struct dylbList_t* next;␊ |
104 | } dylbList_t;␊ |
105 | ␊ |
106 | dylbList_t* loadedDylib = NULL;␊ |
107 | ␊ |
108 | ␊ |
109 | static EFI_STATUS is_system_loaded(void)␊ |
110 | {␊ |
111 | ␉msglog("* Attempting to load system module\n");␊ |
112 | ␊ |
113 | ␊ |
114 | if((UInt32)lookup_symbol != 0xFFFFFFFF)␊ |
115 | {␊ |
116 | #if␉DEBUG_MODULES == 2␊ |
117 | printf("System successfully Loaded.\n");␊ |
118 | getc(); ␊ |
119 | #endif␊ |
120 | return EFI_SUCCESS;␊ |
121 | }␊ |
122 | ␊ |
123 | ␊ |
124 | #if␉DEBUG_MODULES == 2␊ |
125 | printf("Failed to load system module\n");␊ |
126 | getc(); ␊ |
127 | #endif␊ |
128 | ␉return EFI_LOAD_ERROR;␊ |
129 | }␊ |
130 | ␊ |
131 | /*␊ |
132 | * print out the information about the loaded module␊ |
133 | */␊ |
134 | static VOID add_dylib(const char* name)␊ |
135 | {␊ |
136 | ␉dylbList_t* new_entry = malloc(sizeof(dylbList_t));␊ |
137 | ␉if (new_entry)␊ |
138 | ␉{␉␊ |
139 | ␉␉bzero(new_entry,sizeof(dylbList_t));␊ |
140 | ␉␉␊ |
141 | ␉␉new_entry->next = loadedDylib;␊ |
142 | ␉␉␊ |
143 | ␉␉loadedDylib = new_entry;␊ |
144 | ␉␉␊ |
145 | ␉␉new_entry->dylib_name = (char*)name;␉␉␊ |
146 | ␉}␊ |
147 | }␊ |
148 | ␊ |
149 | static EFI_STATUS is_dylib_loaded(const char* name)␊ |
150 | {␊ |
151 | ␉dylbList_t* entry = loadedDylib;␊ |
152 | ␉while(entry)␊ |
153 | ␉{␊ |
154 | ␉␉DBG("Comparing %s with %s\n", name, entry->dylib_name);␊ |
155 | ␉␉char *fullname = newStringWithFormat("%s.dylib",name);␊ |
156 | ␉␉if(fullname && ((strcmp(entry->dylib_name, name) == 0) || (strcmp(entry->dylib_name, fullname) == 0)))␊ |
157 | ␉␉{␊ |
158 | ␉␉␉free(fullname);␊ |
159 | ␉␉␉DBG("Located module %s\n", name);␊ |
160 | ␉␉␉return EFI_SUCCESS;␊ |
161 | ␉␉}␊ |
162 | ␉␉else␊ |
163 | ␉␉{␊ |
164 | ␉␉␉entry = entry->next;␊ |
165 | ␉␉}␊ |
166 | ␉␉␊ |
167 | ␉}␊ |
168 | ␉DBG("Module %s not found\n", name);␊ |
169 | ␉␊ |
170 | ␉return EFI_NOT_FOUND;␊ |
171 | }␊ |
172 | ␊ |
173 | /*␊ |
174 | * Load a dylib ␊ |
175 | *␊ |
176 | * ex: load_dylib("/Extra/modules/", "AcpiCodec.dylib");␊ |
177 | */␊ |
178 | VOID load_dylib(const char * dylib_path, const char * name)␊ |
179 | {␊ |
180 | void (*module_start)(void);␊ |
181 | ␉␊ |
182 | char *tmp = newStringWithFormat("%s%s",dylib_path, name);␉␉␉␉␉␉␉␉␊ |
183 | if (!tmp) {␊ |
184 | return;␊ |
185 | }␊ |
186 | char *dylib_name = newString(name);␉␉␉␉␉␉␉␉␊ |
187 | if (!dylib_name) {␊ |
188 | free(tmp);␊ |
189 | return;␊ |
190 | }␊ |
191 | msglog("* Attempting to load module: %s\n", tmp);␊ |
192 | module_start = (void*)load_module(dylib_name,tmp, NULL);␊ |
193 | ␊ |
194 | if(module_start && ( module_start != (void*)0xFFFFFFFF))␊ |
195 | {␊ |
196 | add_dylib(name);␊ |
197 | module_start();␊ |
198 | }␊ |
199 | else␊ |
200 | {␊ |
201 | // failed to load or already loaded␊ |
202 | free(tmp);␊ |
203 | free(dylib_name);␊ |
204 | ␊ |
205 | }␊ |
206 | }␊ |
207 | ␊ |
208 | /*␊ |
209 | * Load all dylib in the /Extra/modules/ directory␊ |
210 | */␊ |
211 | ␊ |
212 | VOID load_all_dylib(void)␊ |
213 | {␊ |
214 | ␉char* name;␊ |
215 | ␉long flags;␊ |
216 | ␉long time;␊ |
217 | ␊ |
218 | if (is_system_loaded() != EFI_SUCCESS) return;␊ |
219 | ␊ |
220 | long ret, length, flags, time, bundleType;␊ |
221 | long long␉ index;␊ |
222 | long result = -1;␊ |
223 | const char * name;␊ |
224 | void (*module_start)(void);␊ |
225 | ␉␊ |
226 | ␉DBG("FileLoadBundles in %s\n",dirSpec);␊ |
227 | ␊ |
228 | index = 0;␊ |
229 | while (1) {␊ |
230 | ret = GetDirEntry("/Extra/modules/", &index, &name, &flags, &time);␊ |
231 | if (ret == -1) break; ␊ |
232 | ␉␉␊ |
233 | // Make sure this is not a directory.␊ |
234 | if ((flags & kFileTypeMask) == kFileTypeDirectory) continue;␊ |
235 | ␊ |
236 | if ((strncmp("Symbols.dylib",name, sizeof("Symbols.dylib"))) == 0) continue; // if we found Symbols.dylib, just skip it␊ |
237 | ␊ |
238 | if (is_dylib_loaded(name) == EFI_SUCCESS) continue;␊ |
239 | ␊ |
240 | ␊ |
241 | // Make sure this is a kext.␊ |
242 | length = strlen(name);␊ |
243 | if (strncmp(name + length - 6, ".dylib", 6)) continue;␊ |
244 | ␉␉␊ |
245 | char *tmp = newStringWithFormat( "/Extra/modules/%s",name);␉␉␉␉␉␉␉␉␊ |
246 | if (!tmp) {␊ |
247 | continue;␊ |
248 | }␊ |
249 | char *dylib_name = newString(name);␉␉␉␉␉␉␉␉␊ |
250 | if (!dylib_name) {␊ |
251 | free(tmp);␊ |
252 | continue;␊ |
253 | }␊ |
254 | msglog("* Attempting to load module: %s\n", tmp);␊ |
255 | module_start = (void*)load_module(dylib_name,tmp, NULL);␊ |
256 | ␊ |
257 | if(module_start && ( module_start != (void*)0xFFFFFFFF))␊ |
258 | {␊ |
259 | add_dylib(name);␊ |
260 | module_start();␊ |
261 | }␊ |
262 | else␊ |
263 | {␊ |
264 | // failed to load or already loaded␊ |
265 | free(tmp);␊ |
266 | free(dylib_name);␊ |
267 | ␊ |
268 | }␊ |
269 | }␉␊ |
270 | ␉␊ |
271 | #if DEBUG_MODULES␊ |
272 | ␉print_symbol_list();␊ |
273 | #endif␊ |
274 | }␊ |
275 | ␊ |
276 | #endif␊ |
277 | ␊ |
278 | /*␊ |
279 | * Load a module file ␊ |
280 | */␊ |
281 | static unsigned int load_module(char * name, char* module, BundlePtr bundle)␊ |
282 | {␊ |
283 | ␉unsigned int module_start = 0xFFFFFFFF;␊ |
284 | ␊ |
285 | ␉␊ |
286 | ␉int fh = -1;␊ |
287 | ␉␊ |
288 | ␉fh = open(module,0);␊ |
289 | ␉if(fh < 0)␊ |
290 | ␉{␉␉␊ |
291 | #if DEBUG_MODULES␊ |
292 | ␉␉DBG("Unable to locate module %s\n", module);␊ |
293 | ␉␉getc();␊ |
294 | #else␊ |
295 | ␉␉msglog("Unable to locate module %s\n", module);␊ |
296 | #endif␊ |
297 | ␉␉return 0xFFFFFFFF;␉␉␊ |
298 | ␉}␊ |
299 | ␉␊ |
300 | ␉{␊ |
301 | ␉␉int moduleSize = file_size(fh);␊ |
302 | ␉␉␊ |
303 | ␉␉char* module_base = NULL;␊ |
304 | ␉␉␊ |
305 | ␉␉if (moduleSize > 0)␊ |
306 | ␉␉{␊ |
307 | ␉␉␉module_base = (char*) malloc(moduleSize);␊ |
308 | ␉␉}␉␉␊ |
309 | ␉␉␊ |
310 | ␉␉if (!module_base)␊ |
311 | ␉␉{␊ |
312 | ␉␉␉goto out;␊ |
313 | ␉␉}␊ |
314 | ␉␉bzero(module_base,moduleSize);␊ |
315 | ␉␉␊ |
316 | ␉␉if (read(fh, module_base, moduleSize) == moduleSize)␊ |
317 | ␉␉{␊ |
318 | ␉␉␉␊ |
319 | ␉␉␉DBG("Module %s read in.\n", module);␊ |
320 | ␉␉␉␊ |
321 | ␉␉␉// Module loaded into memory, parse it␊ |
322 | ␉␉␉module_start = parse_mach(name, module_base, &add_symbol, bundle); ␊ |
323 | ␉␉␉␊ |
324 | ␉␉␉␊ |
325 | ␉␉}␊ |
326 | ␉␉else␊ |
327 | ␉␉{␊ |
328 | ␉␉␉printf("Unable to read in module %s\n.", module);␊ |
329 | #if DEBUG_MODULES␉␉␊ |
330 | ␉␉␉getc();␊ |
331 | #endif␊ |
332 | ␉␉␉free(module_base);␊ |
333 | ␉␉}␊ |
334 | ␉}␊ |
335 | out:␊ |
336 | ␉close(fh);␊ |
337 | ␉return module_start;␊ |
338 | }␊ |
339 | ␊ |
340 | moduleHook_t* get_callback(const char* name)␊ |
341 | {␊ |
342 | ␉moduleHook_t* hooks = moduleCallbacks;␊ |
343 | ␉␊ |
344 | ␉// look for a hook. If it exists, return the moduleHook_t*,␊ |
345 | ␉// If not, return NULL.␊ |
346 | ␉while(hooks)␊ |
347 | ␉{␊ |
348 | ␉␉if(strcmp(name, hooks->name) == 0)␊ |
349 | ␉␉{␊ |
350 | ␉␉␉//DBG("Located hook %s\n", name);␊ |
351 | ␉␉␉return hooks;␊ |
352 | ␉␉}␊ |
353 | ␉␉hooks = hooks->next;␊ |
354 | ␉}␊ |
355 | ␉return NULL;␊ |
356 | ␉␊ |
357 | }␊ |
358 | ␊ |
359 | /*␊ |
360 | *␉execute_hook( const char* name )␊ |
361 | *␉␉name - Name of the module hook␊ |
362 | *␉␉␉If any callbacks have been registered for this hook␊ |
363 | *␉␉␉they will be executed now in the same order that the␊ |
364 | *␉␉␉hooks were added.␊ |
365 | */␊ |
366 | EFI_STATUS execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4, void* arg5, void* arg6)␊ |
367 | {␊ |
368 | ␉DBG("Attempting to execute hook '%s'\n", name);␊ |
369 | ␉moduleHook_t* hook = get_callback(name);␊ |
370 | ␉␊ |
371 | ␉if(hook)␊ |
372 | ␉{␊ |
373 | ␉␉// Loop through all callbacks for this module␊ |
374 | ␉␉callbackList_t* callbacks = hook->callbacks;␊ |
375 | ␉␉␊ |
376 | ␉␉while(callbacks)␊ |
377 | ␉␉{␊ |
378 | ␉␉␉// Execute callback␊ |
379 | ␉␉␉callbacks->callback(arg1, arg2, arg3, arg4, arg5, arg6);␊ |
380 | ␉␉␉callbacks = callbacks->next;␊ |
381 | ␉␉}␊ |
382 | ␉␉DBG("Hook '%s' executed.\n", name); ␊ |
383 | ␉␉return EFI_SUCCESS;␊ |
384 | ␉}␊ |
385 | ␉␊ |
386 | ␉// Callback for this hook doesn't exist;␊ |
387 | ␉DBG("No callbacks for '%s' hook.\n", name);␊ |
388 | ␉return EFI_NOT_FOUND;␊ |
389 | ␉␊ |
390 | }␊ |
391 | ␊ |
392 | /*␊ |
393 | *␉register_hook_callback( const char* name, void(*callback)())␊ |
394 | *␉␉name - Name of the module hook to attach to.␊ |
395 | *␉␉callbacks - The funciton pointer that will be called when the␊ |
396 | *␉␉␉hook is executed. When registering a new callback name, the callback is added sorted.␊ |
397 | *␉␉␉NOTE: the hooks take four void* arguments.␊ |
398 | */␊ |
399 | static VOID __register_hook_callback(moduleHook_t* hook, const char* name, void(*callback)(void*, void*, void*, void*, void*, void*))␊ |
400 | {␊ |
401 | ␉if(hook)␊ |
402 | ␉{␊ |
403 | ␉␉// append␊ |
404 | ␉␉callbackList_t* newCallback = malloc(sizeof(callbackList_t));␊ |
405 | ␉␉if (!newCallback) {␊ |
406 | ␉␉␉DBG("Unable to allocate memory for callback \n");␊ |
407 | ␉␉␉return;␊ |
408 | ␉␉}␊ |
409 | ␉␉bzero(newCallback,sizeof(callbackList_t));␊ |
410 | ␉␉␊ |
411 | ␉␉newCallback->next = hook->callbacks;␊ |
412 | ␉␉hook->callbacks = newCallback;␊ |
413 | ␉␉newCallback->callback = callback;␊ |
414 | ␉}␊ |
415 | ␉else␊ |
416 | ␉{␊ |
417 | ␉␉// create new hook␊ |
418 | ␉␉moduleHook_t* newHook = malloc(sizeof(moduleHook_t));␊ |
419 | ␉␉if (!newHook) {␊ |
420 | ␉␉␉DBG("Unable to allocate memory for hook '%s'.\n", name);␊ |
421 | ␉␉␉return;␊ |
422 | ␉␉}␊ |
423 | ␉␉bzero(newHook,sizeof(moduleHook_t));␊ |
424 | ␉␉␊ |
425 | ␉␉newHook->name = name;␊ |
426 | ␉␉newHook->callbacks = malloc(sizeof(callbackList_t));␊ |
427 | ␉␉if (!newHook->callbacks) {␊ |
428 | ␉␉␉DBG("Unable to allocate memory for callback \n");␊ |
429 | ␉␉␉free(newHook);␊ |
430 | ␉␉␉return;␊ |
431 | ␉␉}␊ |
432 | ␉␉bzero(newHook->callbacks,sizeof(callbackList_t));␊ |
433 | ␉␉␊ |
434 | ␉␉newHook->callbacks->callback = callback;␊ |
435 | ␉␉newHook->callbacks->next = NULL;␊ |
436 | ␉␉␊ |
437 | ␉␉newHook->next = moduleCallbacks;␊ |
438 | ␉␉moduleCallbacks = newHook;␊ |
439 | ␉␉␊ |
440 | ␉}␊ |
441 | ␉␊ |
442 | #if DEBUG_MODULES␊ |
443 | ␉print_hook_list();␊ |
444 | ␉getc();␊ |
445 | #endif␊ |
446 | }␊ |
447 | ␊ |
448 | VOID register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*, void*, void*))␊ |
449 | {␉␊ |
450 | ␉DBG("Adding callback for hook '%s'.\n", name);␊ |
451 | ␉␊ |
452 | ␉moduleHook_t* hook = get_callback(name);␊ |
453 | ␉␊ |
454 | ␉__register_hook_callback(hook, name, callback);␊ |
455 | }␊ |
456 | ␊ |
457 | VOID register_one_callback(const char* name, void(*callback)(void*, void*, void*, void*, void*, void*))␊ |
458 | {␉␊ |
459 | ␉DBG("Adding one callback for hook '%s'.\n", name);␊ |
460 | ␉␊ |
461 | ␉moduleHook_t* hook = get_callback(name);␊ |
462 | ␉␊ |
463 | ␉if (hook) ␊ |
464 | ␉{␊ |
465 | ␉␉return;␊ |
466 | ␉}␉␊ |
467 | ␉__register_hook_callback(hook, name, callback);␊ |
468 | }␊ |
469 | ␊ |
470 | #if DEBUG_MODULES␊ |
471 | unsigned long vmaddr;␊ |
472 | long vmsize;␊ |
473 | #endif␊ |
474 | ␊ |
475 | /*␊ |
476 | * Parse through a macho module. The module will be rebased and binded␊ |
477 | * as specified in the macho header. If the module is successfully loaded␊ |
478 | * the module iinit address will be returned.␊ |
479 | * NOTE; all dependecies will be loaded before this module is started␊ |
480 | * NOTE: If the module is unable to load ot completeion, the modules␊ |
481 | * symbols will still be available (TODO: fix this). This should not␊ |
482 | * happen as all dependencies are verified before the sybols are read in.␊ |
483 | */␊ |
484 | #if macho_64␊ |
485 | static unsigned int parse_mach(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long, char), BundlePtr bundle)␉// TODO: add param to specify valid archs␊ |
486 | #else␊ |
487 | static unsigned int parse_mach(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long), BundlePtr bundle)␉// TODO: add param to specify valid archs␊ |
488 | #endif␊ |
489 | {␉␊ |
490 | #if macho_64␊ |
491 | ␉char is64 = false;␊ |
492 | #endif␊ |
493 | ␉unsigned int module_start = 0xFFFFFFFF;␊ |
494 | ␉EFI_STATUS bind_status = EFI_SUCCESS;␊ |
495 | ␊ |
496 | ␉// TODO convert all of the structs to a union␉␊ |
497 | ␉struct dyld_info_command* dyldInfoCommand = NULL;␉␊ |
498 | ␉struct symtab_command* symtabCommand = NULL;␉␊ |
499 | ␉␊ |
500 | ␉{␊ |
501 | ␉␉struct segment_command *segCommand = NULL;␊ |
502 | #if macho_64␊ |
503 | ␉␉struct segment_command_64 *segCommand64 = NULL;␊ |
504 | #endif␊ |
505 | ␉␉struct load_command *loadCommand = NULL;␊ |
506 | ␉␉UInt32 binaryIndex = 0;␊ |
507 | ␉␉UInt16 cmd = 0;␊ |
508 | ␉␉␊ |
509 | ␉␉// Parse through the load commands␊ |
510 | ␉␉if(((struct mach_header*)binary)->magic == MH_MAGIC)␊ |
511 | ␉␉{␊ |
512 | #if macho_64␊ |
513 | ␉␉␉is64 = false;␊ |
514 | #endif␊ |
515 | ␉␉␉binaryIndex += sizeof(struct mach_header);␊ |
516 | ␉␉}␊ |
517 | #if macho_64␊ |
518 | ␉␉else if(((struct mach_header_64*)binary)->magic == MH_MAGIC_64)␊ |
519 | ␉␉{␊ |
520 | ␉␉␉// NOTE: modules cannot be 64bit...␊ |
521 | ␉␉␉is64 = true;␊ |
522 | ␉␉␉binaryIndex += sizeof(struct mach_header_64);␊ |
523 | ␉␉}␊ |
524 | #endif␊ |
525 | ␉␉else␊ |
526 | ␉␉{␊ |
527 | ␉␉␉printf("Modules: Invalid mach magic\n");␊ |
528 | ␉␉␉getc();␊ |
529 | ␉␉␉return 0xFFFFFFFF;␊ |
530 | ␉␉}␊ |
531 | ␉␉␊ |
532 | ␉␉␊ |
533 | ␉␉␊ |
534 | ␉␉/*if(((struct mach_header*)binary)->filetype != MH_DYLIB)␊ |
535 | ␉␉ {␊ |
536 | ␉␉ printf("Module is not a dylib. Unable to load.\n");␊ |
537 | ␉␉ getc();␊ |
538 | ␉␉ return NULL; // Module is in the incorrect format␊ |
539 | ␉␉ }*/␊ |
540 | ␉␉␊ |
541 | ␉␉while(cmd < ((struct mach_header*)binary)->ncmds)␊ |
542 | ␉␉{␊ |
543 | ␉␉␉cmd++;␊ |
544 | ␉␉␉␊ |
545 | ␉␉␉loadCommand = binary + binaryIndex;␊ |
546 | ␉␉␉UInt32 cmdSize = loadCommand->cmdsize;␊ |
547 | ␉␉␉␊ |
548 | ␉␉␉␊ |
549 | ␉␉␉switch ((loadCommand->cmd & 0x7FFFFFFF))␊ |
550 | ␉␉␉{␊ |
551 | ␉␉␉␉case LC_SYMTAB:␊ |
552 | ␉␉␉␉␉symtabCommand = binary + binaryIndex;␊ |
553 | ␉␉␉␉␉break;␊ |
554 | ␉␉␉␉␉␊ |
555 | ␉␉␉␉case LC_SEGMENT: // 32bit macho␊ |
556 | ␉␉␉␉{␊ |
557 | ␉␉␉␉␉segCommand = binary + binaryIndex;␊ |
558 | ␉␉␉␉␉␊ |
559 | ␉␉␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
560 | ␉␉␉␉␉␊ |
561 | ␉␉␉␉␉if(strncmp("__TEXT", segCommand->segname, sizeof("__TEXT")) == 0)␊ |
562 | ␉␉␉␉␉{␊ |
563 | ␉␉␉␉␉␉UInt32 sectionIndex;␊ |
564 | ␉␉␉␉␉␉␊ |
565 | #if DEBUG_MODULES␊ |
566 | ␉␉␉␉␉␉unsigned long fileaddr;␊ |
567 | ␉␉␉␉␉␉long filesize;␉␉␉␉␉␊ |
568 | ␉␉␉␉␉␉vmaddr = (segCommand->vmaddr & 0x3fffffff);␊ |
569 | ␉␉␉␉␉␉vmsize = segCommand->vmsize;␉ ␊ |
570 | ␉␉␉␉␉␉fileaddr = ((unsigned long)(binary + binaryIndex) + segCommand->fileoff);␊ |
571 | ␉␉␉␉␉␉filesize = segCommand->filesize;␊ |
572 | ␉␉␉␉␉␉␊ |
573 | ␉␉␉␉␉␉printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",␊ |
574 | ␉␉␉␉␉␉␉ segCommand->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize,␊ |
575 | ␉␉␉␉␉␉␉ (unsigned) segCommand->nsects, (unsigned)segCommand->flags);␊ |
576 | #if DEBUG_MODULES==2␊ |
577 | ␉␉␉␉␉␉␊ |
578 | ␉␉␉␉␉␉getc();␊ |
579 | #endif␊ |
580 | #endif␊ |
581 | ␉␉␉␉␉␉␊ |
582 | ␉␉␉␉␉␉sectionIndex = sizeof(struct segment_command);␊ |
583 | ␉␉␉␉␉␉␊ |
584 | ␉␉␉␉␉␉struct section *sect;␊ |
585 | ␉␉␉␉␉␉␊ |
586 | ␉␉␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
587 | ␉␉␉␉␉␉{␊ |
588 | ␉␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
589 | ␉␉␉␉␉␉␉␊ |
590 | ␉␉␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
591 | ␉␉␉␉␉␉␉␊ |
592 | ␉␉␉␉␉␉␉␊ |
593 | ␉␉␉␉␉␉␉if(strncmp("__text", sect->sectname,sizeof("__text")) == 0)␊ |
594 | ␉␉␉␉␉␉␉{␊ |
595 | ␉␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
596 | ␉␉␉␉␉␉␉␉textSection = sect->offset;␊ |
597 | ␉␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
598 | ␉␉␉␉␉␉␉␉break;␊ |
599 | ␉␉␉␉␉␉␉}␉␉␉␉␉␊ |
600 | ␉␉␉␉␉␉}␊ |
601 | ␉␉␉␉␉}␊ |
602 | ␉␉␉␉␉break;␊ |
603 | ␉␉␉␉}␉␊ |
604 | #if macho_64␊ |
605 | ␉␉␉␉case LC_SEGMENT_64:␉// 64bit macho's␊ |
606 | ␉␉␉␉{␊ |
607 | ␉␉␉␉␉segCommand64 = binary + binaryIndex;␊ |
608 | ␉␉␉␉␉␊ |
609 | ␉␉␉␉␉//printf("Segment name is %s\n", segCommand->segname);␊ |
610 | ␉␉␉␉␉␊ |
611 | ␉␉␉␉␉if(strncmp("__TEXT", segCommand64->segname, sizeof("__TEXT")) == 0)␊ |
612 | ␉␉␉␉␉{␊ |
613 | ␉␉␉␉␉␉UInt32 sectionIndex;␊ |
614 | ␉␉␉␉␉␉␊ |
615 | #if DEBUG_MODULES␉␉␉␉␉␉␊ |
616 | ␉␉␉␉␉␉unsigned long fileaddr;␊ |
617 | ␉␉␉␉␉␉long filesize;␉␉␉␉␉␊ |
618 | ␉␉␉␉␉␉vmaddr = (segCommand64->vmaddr & 0x3fffffff);␊ |
619 | ␉␉␉␉␉␉vmsize = segCommand64->vmsize;␉ ␊ |
620 | ␉␉␉␉␉␉fileaddr = ((unsigned long)(binary + binaryIndex) + segCommand64->fileoff);␊ |
621 | ␉␉␉␉␉␉filesize = segCommand64->filesize;␊ |
622 | ␉␉␉␉␉␉␊ |
623 | ␉␉␉␉␉␉printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",␊ |
624 | ␉␉␉␉␉␉␉ segCommand64->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize,␊ |
625 | ␉␉␉␉␉␉␉ (unsigned) segCommand64->nsects, (unsigned)segCommand64->flags);␊ |
626 | #if DEBUG_MODULES==2␊ |
627 | ␉␉␉␉␉␉␊ |
628 | ␉␉␉␉␉␉getc();␊ |
629 | #endif␊ |
630 | #endif␊ |
631 | ␉␉␉␉␉␉␊ |
632 | ␉␉␉␉␉␉sectionIndex = sizeof(struct segment_command_64);␊ |
633 | ␉␉␉␉␉␉␊ |
634 | ␉␉␉␉␉␉struct section_64 *sect;␊ |
635 | ␉␉␉␉␉␉␊ |
636 | ␉␉␉␉␉␉while(sectionIndex < segCommand64->cmdsize)␊ |
637 | ␉␉␉␉␉␉{␊ |
638 | ␉␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
639 | ␉␉␉␉␉␉␉␊ |
640 | ␉␉␉␉␉␉␉sectionIndex += sizeof(struct section_64);␊ |
641 | ␉␉␉␉␉␉␉␊ |
642 | ␉␉␉␉␉␉␉␊ |
643 | ␉␉␉␉␉␉␉if(strncmp("__text", sect->sectname, sizeof("__text")) == 0)␊ |
644 | ␉␉␉␉␉␉␉{␊ |
645 | ␉␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
646 | ␉␉␉␉␉␉␉␉textSection = sect->offset;␊ |
647 | ␉␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
648 | ␉␉␉␉␉␉␉␉␊ |
649 | ␉␉␉␉␉␉␉␉break;␊ |
650 | ␉␉␉␉␉␉␉}␉␉␉␉␉␊ |
651 | ␉␉␉␉␉␉}␊ |
652 | ␉␉␉␉␉}␊ |
653 | ␉␉␉␉␉␊ |
654 | ␉␉␉␉␉break;␊ |
655 | ␉␉␉␉}␊ |
656 | #endif␊ |
657 | ␉␉␉␉case LC_DYSYMTAB:␊ |
658 | ␉␉␉␉␉break;␊ |
659 | ␉␉␉␉␉␊ |
660 | ␉␉␉␉case LC_LOAD_DYLIB:␊ |
661 | ␉␉␉␉case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:␊ |
662 | break;␊ |
663 | ␊ |
664 | ␉␉␉␉case LC_ID_DYLIB:␊ |
665 | break;␊ |
666 | ␊ |
667 | ␉␉␉␉␉␊ |
668 | ␉␉␉␉case LC_DYLD_INFO:␊ |
669 | ␉␉␉␉␉// Bind and rebase info is stored here␊ |
670 | ␉␉␉␉␉dyldInfoCommand = binary + binaryIndex;␊ |
671 | ␉␉␉␉␉break;␊ |
672 | ␉␉␉␉␉␊ |
673 | ␉␉␉␉case LC_UUID:␊ |
674 | ␉␉␉␉␉break;␊ |
675 | ␉␉␉␉␉␊ |
676 | ␉␉␉␉case LC_UNIXTHREAD:␊ |
677 | ␉␉␉␉␉break;␊ |
678 | ␉␉␉␉␉␊ |
679 | ␉␉␉␉default:␊ |
680 | ␉␉␉␉␉DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);␊ |
681 | ␉␉␉␉␉break;␊ |
682 | ␉␉␉␉␉␊ |
683 | ␉␉␉}␊ |
684 | ␉␉␉␊ |
685 | ␉␉␉binaryIndex += cmdSize;␊ |
686 | ␉␉}␊ |
687 | ␉␉//if(!moduleName) return NULL;␊ |
688 | ␉}␉␉␊ |
689 | ␉␊ |
690 | ␉// bind_macho uses the symbols.␊ |
691 | #if macho_64␊ |
692 | ␉module_start = handle_symtable(module, (UInt32)binary, symtabCommand, symbol_handler, is64);␊ |
693 | #else␊ |
694 | ␉module_start = handle_symtable(module, (UInt32)binary, symtabCommand, symbol_handler);␊ |
695 | #endif␊ |
696 | ␉// Rebase the module before binding it.␊ |
697 | ␉if(dyldInfoCommand && dyldInfoCommand->rebase_off)␊ |
698 | ␉{␊ |
699 | ␉␉rebase_macho(binary, (char*)dyldInfoCommand->rebase_off, dyldInfoCommand->rebase_size);␊ |
700 | ␉}␊ |
701 | ␉␊ |
702 | ␉if(dyldInfoCommand && dyldInfoCommand->bind_off)␊ |
703 | ␉{␊ |
704 | ␉␉bind_status = _bind_macho(module, binary, (char*)dyldInfoCommand->bind_off, dyldInfoCommand->bind_size, bundle);␊ |
705 | ␉}␊ |
706 | ␉␊ |
707 | ␉if(dyldInfoCommand && dyldInfoCommand->weak_bind_off && (bind_status == EFI_SUCCESS))␊ |
708 | ␉{␊ |
709 | ␉␉// NOTE: this currently should never happen.␊ |
710 | ␉␉bind_status = _bind_macho(module, binary, (char*)dyldInfoCommand->weak_bind_off, dyldInfoCommand->weak_bind_size, bundle);␊ |
711 | ␉}␊ |
712 | ␉␊ |
713 | ␉if(dyldInfoCommand && dyldInfoCommand->lazy_bind_off && (bind_status == EFI_SUCCESS))␊ |
714 | ␉{␊ |
715 | ␉␉// NOTE: we are binding the lazy pointers as a module is laoded,␊ |
716 | ␉␉// This should be changed to bind when a symbol is referened at runtime instead.␊ |
717 | ␉␉bind_status = _bind_macho(module, binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size, bundle);␊ |
718 | ␉}␊ |
719 | ␉␊ |
720 | if (bind_status != EFI_SUCCESS) {␊ |
721 | module_start = 0xFFFFFFFF;␊ |
722 | }␊ |
723 | ␊ |
724 | ␉return module_start;␊ |
725 | ␉␊ |
726 | }␊ |
727 | ␊ |
728 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
729 | void rebase_macho(void* base, char* rebase_stream, UInt32 size)␊ |
730 | {␊ |
731 | ␉rebase_stream += (UInt32)base;␊ |
732 | ␉␊ |
733 | ␉UInt8 immediate = 0;␊ |
734 | ␉UInt8 opcode = 0;␊ |
735 | ␉UInt8 type = 0;␊ |
736 | ␉␊ |
737 | ␉UInt32 segmentAddress = 0;␊ |
738 | ␉␊ |
739 | ␉␊ |
740 | ␉␊ |
741 | ␉UInt32 tmp = 0;␊ |
742 | ␉UInt32 tmp2 = 0;␊ |
743 | ␉UInt8 bits = 0;␊ |
744 | ␉UInt32 index = 0;␊ |
745 | ␉␊ |
746 | ␉//int done = 0;␊ |
747 | ␉unsigned int i = 0;␊ |
748 | ␉␊ |
749 | ␉while(/*!done &&*/ i < size)␊ |
750 | ␉{␊ |
751 | ␉␉immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;␊ |
752 | ␉␉opcode = rebase_stream[i] & REBASE_OPCODE_MASK;␊ |
753 | ␉␉␊ |
754 | ␉␉␊ |
755 | ␉␉switch(opcode)␊ |
756 | ␉␉{␊ |
757 | ␉␉␉case REBASE_OPCODE_DONE:␊ |
758 | ␉␉␉␉// Rebase complete.␊ |
759 | ␉␉␉␉//done = 1;␊ |
760 | ␉␉␉␉break;␊ |
761 | ␉␉␉␉␊ |
762 | ␉␉␉␉␊ |
763 | ␉␉␉case REBASE_OPCODE_SET_TYPE_IMM:␊ |
764 | ␉␉␉␉// Set rebase type (pointer, absolute32, pcrel32)␊ |
765 | ␉␉␉␉//DBG("Rebase type = 0x%X\n", immediate);␊ |
766 | ␉␉␉␉type = immediate;␊ |
767 | ␉␉␉␉break;␊ |
768 | ␉␉␉␉␊ |
769 | ␉␉␉␉␊ |
770 | ␉␉␉case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
771 | ␉␉␉{␊ |
772 | ␉␉␉␉// Locate address to begin rebasing␊ |
773 | ␉␉␉␉//segmentAddress = 0;␊ |
774 | ␉␉␉␉␊ |
775 | ␉␉␉␉struct segment_command* segCommand = NULL; // NOTE: 32bit only␊ |
776 | ␉␉␉␉␊ |
777 | ␉␉␉␉{␊ |
778 | ␉␉␉␉␉unsigned int binIndex = 0;␊ |
779 | ␉␉␉␉␉index = 0;␊ |
780 | ␉␉␉␉␉do␊ |
781 | ␉␉␉␉␉{␊ |
782 | ␉␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
783 | ␉␉␉␉␉␉␊ |
784 | ␉␉␉␉␉␉␊ |
785 | ␉␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
786 | ␉␉␉␉␉␉index++;␊ |
787 | ␉␉␉␉␉}␊ |
788 | ␉␉␉␉␉while(index <= immediate);␊ |
789 | ␉␉␉␉}␉␉␉␉␊ |
790 | ␉␉␉␉␊ |
791 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
792 | ␉␉␉␉␊ |
793 | ␉␉␉␉tmp = 0;␊ |
794 | ␉␉␉␉bits = 0;␊ |
795 | ␉␉␉␉do␊ |
796 | ␉␉␉␉{␊ |
797 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
798 | ␉␉␉␉␉bits += 7;␊ |
799 | ␉␉␉␉}␊ |
800 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
801 | ␉␉␉␉␊ |
802 | ␉␉␉␉segmentAddress += tmp;␊ |
803 | ␉␉␉␉break;␊ |
804 | ␉␉␉}␉␉␉␉␊ |
805 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_ULEB:␊ |
806 | ␉␉␉␉// Add value to rebase address␊ |
807 | ␉␉␉␉tmp = 0;␊ |
808 | ␉␉␉␉bits = 0;␊ |
809 | ␉␉␉␉do␊ |
810 | ␉␉␉␉{␊ |
811 | ␉␉␉␉␉tmp <<= bits;␊ |
812 | ␉␉␉␉␉tmp |= rebase_stream[++i] & 0x7f;␊ |
813 | ␉␉␉␉␉bits += 7;␊ |
814 | ␉␉␉␉}␊ |
815 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
816 | ␉␉␉␉␊ |
817 | ␉␉␉␉segmentAddress +=␉tmp; ␊ |
818 | ␉␉␉␉break;␊ |
819 | ␉␉␉␉␊ |
820 | ␉␉␉case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:␊ |
821 | ␉␉␉␉segmentAddress += immediate * sizeof(void*);␊ |
822 | ␉␉␉␉break;␊ |
823 | ␉␉␉␉␊ |
824 | ␉␉␉␉␊ |
825 | ␉␉␉case REBASE_OPCODE_DO_REBASE_IMM_TIMES:␊ |
826 | ␉␉␉␉for (index = 0; index < immediate; ++index)␊ |
827 | ␉␉␉␉{␊ |
828 | ␉␉␉␉␉rebase_location(base + segmentAddress, (char*)base, type);␊ |
829 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
830 | ␉␉␉␉}␊ |
831 | ␉␉␉␉break;␉␉␉␉␊ |
832 | ␉␉␉␉␊ |
833 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:␊ |
834 | ␉␉␉␉tmp = 0;␊ |
835 | ␉␉␉␉bits = 0;␊ |
836 | ␉␉␉␉do␊ |
837 | ␉␉␉␉{␊ |
838 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
839 | ␉␉␉␉␉bits += 7;␊ |
840 | ␉␉␉␉}␊ |
841 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
842 | ␉␉␉␉␊ |
843 | ␉␉␉␉for (index = 0; index < tmp; ++index)␊ |
844 | ␉␉␉␉{␊ |
845 | ␉␉␉␉␉//DBG("\tRebasing 0x%X\n", segmentAddress);␊ |
846 | ␉␉␉␉␉rebase_location(base + segmentAddress, (char*)base, type);␉␉␉␉␉␊ |
847 | ␉␉␉␉␉segmentAddress += sizeof(void*);␊ |
848 | ␉␉␉␉}␊ |
849 | ␉␉␉␉break;␊ |
850 | ␉␉␉␉␊ |
851 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:␊ |
852 | ␉␉␉␉tmp = 0;␊ |
853 | ␉␉␉␉bits = 0;␊ |
854 | ␉␉␉␉do␊ |
855 | ␉␉␉␉{␊ |
856 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
857 | ␉␉␉␉␉bits += 7;␊ |
858 | ␉␉␉␉}␊ |
859 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
860 | ␉␉␉␉␊ |
861 | ␉␉␉␉rebase_location(base + segmentAddress, (char*)base, type);␊ |
862 | ␉␉␉␉␊ |
863 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
864 | ␉␉␉␉break;␊ |
865 | ␉␉␉␉␊ |
866 | ␉␉␉case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:␊ |
867 | ␉␉␉␉tmp = 0;␊ |
868 | ␉␉␉␉bits = 0;␊ |
869 | ␉␉␉␉do␊ |
870 | ␉␉␉␉{␊ |
871 | ␉␉␉␉␉tmp |= (rebase_stream[++i] & 0x7f) << bits;␊ |
872 | ␉␉␉␉␉bits += 7;␊ |
873 | ␉␉␉␉}␊ |
874 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
875 | ␉␉␉␉␊ |
876 | ␉␉␉␉␊ |
877 | ␉␉␉␉tmp2 = 0;␊ |
878 | ␉␉␉␉bits = 0;␊ |
879 | ␉␉␉␉do␊ |
880 | ␉␉␉␉{␊ |
881 | ␉␉␉␉␉tmp2 |= (rebase_stream[++i] & 0x7f) << bits;␊ |
882 | ␉␉␉␉␉bits += 7;␊ |
883 | ␉␉␉␉}␊ |
884 | ␉␉␉␉while(rebase_stream[i] & 0x80);␊ |
885 | ␉␉␉␉␊ |
886 | ␉␉␉␉for (index = 0; index < tmp; ++index)␊ |
887 | ␉␉␉␉{␊ |
888 | ␉␉␉␉␉␊ |
889 | ␉␉␉␉␉rebase_location(base + segmentAddress, (char*)base, type);␊ |
890 | ␉␉␉␉␉␊ |
891 | ␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
892 | ␉␉␉␉}␊ |
893 | ␉␉␉␉break;␊ |
894 | ␉␉␉default:␊ |
895 | ␉␉␉␉break;␊ |
896 | ␉␉}␊ |
897 | ␉␉i++;␊ |
898 | ␉}␊ |
899 | }␊ |
900 | ␊ |
901 | // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
902 | // NOTE: this uses 32bit values, and not 64bit values. ␊ |
903 | // There is apossibility that this could cause issues,␊ |
904 | // however the macho file is 32 bit, so it shouldn't matter too much␊ |
905 | EFI_STATUS bind_macho(char* module, void* base, char* bind_stream, UInt32 size)␊ |
906 | {␊ |
907 | ␉return _bind_macho( module, base, bind_stream, size, NULL);␊ |
908 | }␊ |
909 | ␊ |
910 | static EFI_STATUS _bind_macho(char* module, void* base, char* bind_stream, UInt32 size, BundlePtr bundle)␊ |
911 | {␉␊ |
912 | ␉bind_stream += (UInt32)base;␊ |
913 | ␉␊ |
914 | ␉UInt8 immediate = 0;␊ |
915 | ␉UInt8 opcode = 0;␊ |
916 | ␉␊ |
917 | ␉UInt32 segmentAddress = 0;␊ |
918 | ␉␊ |
919 | ␉UInt32 address = 0;␊ |
920 | ␉␊ |
921 | ␉SInt32 addend = 0;␉␉␉// TODO: handle this␊ |
922 | ␉␊ |
923 | ␉const char* symbolName = NULL;␊ |
924 | ␉UInt32 symbolAddr = 0xFFFFFFFF;␊ |
925 | ␉␊ |
926 | ␉// Temperary variables␊ |
927 | ␉UInt8 bits = 0;␊ |
928 | ␉UInt32 tmp = 0;␊ |
929 | ␉UInt32 tmp2 = 0;␊ |
930 | ␉␊ |
931 | ␉UInt32 index = 0;␊ |
932 | ␉unsigned int i = 0;␊ |
933 | ␉␊ |
934 | ␉while(i < size)␊ |
935 | ␉{␊ |
936 | ␉␉immediate = bind_stream[i] & BIND_IMMEDIATE_MASK;␊ |
937 | ␉␉opcode = bind_stream[i] & BIND_OPCODE_MASK;␊ |
938 | ␉␉␊ |
939 | ␉␉␊ |
940 | ␉␉switch(opcode)␊ |
941 | ␉␉{␊ |
942 | ␉␉␉case BIND_OPCODE_DONE:␊ |
943 | ␉␉␉␉break;␊ |
944 | ␉␉␉␉␊ |
945 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:␊ |
946 | {␊ |
947 | #if DEBUG_MODULES==2␊ |
948 | ␉␉␉␉SInt32 libraryOrdinal = immediate;␊ |
949 | ␉␉␉␉DBG("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);␊ |
950 | #endif␊ |
951 | ␉␉␉␉break;␊ |
952 | }␊ |
953 | ␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:␊ |
954 | {␊ |
955 | #if DEBUG_MODULES==2␊ |
956 | ␉␉␉␉SInt32 libraryOrdinal = 0;␊ |
957 | ␉␉␉␉UInt8 bits = 0;␊ |
958 | ␉␉␉␉do␊ |
959 | ␉␉␉␉{␊ |
960 | ␉␉␉␉␉libraryOrdinal |= (bind_stream[++i] & 0x7f) << bits;␊ |
961 | ␉␉␉␉␉bits += 7;␊ |
962 | ␉␉␉␉}␊ |
963 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
964 | ␉␉␉␉␊ |
965 | ␉␉␉␉DBG("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);␊ |
966 | #else␊ |
967 | do␊ |
968 | ␉␉␉␉{␊ |
969 | ␉␉␉␉␉i++;␊ |
970 | ␉␉␉␉}␊ |
971 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
972 | #endif␊ |
973 | ␉␉␉␉break;␊ |
974 | ␉␉␉}␉␊ |
975 | ␉␉␉case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:␊ |
976 | {␊ |
977 | #if DEBUG_MODULES==2␊ |
978 | // NOTE: this is wrong, fortunately we don't use it␊ |
979 | ␉␉␉␉SInt32 libraryOrdinal = -immediate;␊ |
980 | ␉␉␉␉DBG("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);␊ |
981 | #endif␉␉␊ |
982 | ␉␉␉␉break;␊ |
983 | ␉␉␉}␉␊ |
984 | ␉␉␉case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:␊ |
985 | {␊ |
986 | ␉␉␉␉symbolName = (char*)&bind_stream[++i];␊ |
987 | ␉␉␉␉i += strlen((char*)&bind_stream[i]);␊ |
988 | #if DEBUG_MODULES==2␊ |
989 | ␉␉␉␉UInt8 symbolFlags = immediate;␊ |
990 | DBG("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symbolFlags);␊ |
991 | #endif␉␉␉␉␊ |
992 | ␉␉␉␉symbolAddr = 0xFFFFFFFF;␊ |
993 | ␉␉␉␉TagPtr prop;␊ |
994 | ␉␉␉␉␊ |
995 | ␉␉␉␉if (bundle != NULL)␊ |
996 | ␉␉␉␉{␊ |
997 | ␉␉␉␉␉prop = XMLGetProperty(bundle->dict, kPropOSBundleLibraries);␊ |
998 | ␉␉␉␉␉if (prop != 0)␊ |
999 | ␉␉␉␉␉{␊ |
1000 | ␉␉␉␉␉␉prop = prop->tag;␊ |
1001 | ␉␉␉␉␉␉while (prop != 0)␊ |
1002 | ␉␉␉␉␉␉{␊ |
1003 | ␉␉␉␉␉␉␉/* the order in OSBundleLibraries is important */␊ |
1004 | ␉␉␉␉␉␉␉␊ |
1005 | ␉␉␉␉␉␉␉if (prop->string)␊ |
1006 | ␉␉␉␉␉␉␉{␊ |
1007 | ␉␉␉␉␉␉␉␉symbolAddr = lookup_all_symbols(prop->string ,symbolName); ␊ |
1008 | ␉␉␉␉␉␉␉␉␊ |
1009 | ␉␉␉␉␉␉␉␉if (symbolAddr != 0xFFFFFFFF) break; // the symbol is found , we can exit the loop␊ |
1010 | ␉␉␉␉␉␉␉}␉␉␉␉␉␉␉␊ |
1011 | ␉␉␉␉␉␉␉␊ |
1012 | ␉␉␉␉␉␉␉prop = prop->tagNext;␊ |
1013 | ␉␉␉␉␉␉␉␊ |
1014 | ␉␉␉␉␉␉}␊ |
1015 | ␉␉␉␉␉}␊ |
1016 | ␉␉␉␉␉␊ |
1017 | ␉␉␉␉}␉␉␉␉␊ |
1018 | ␉␉␉␉␊ |
1019 | if (symbolAddr == 0xFFFFFFFF) symbolAddr = lookup_all_symbols(NULL ,symbolName); // at this point if the symbol is still undefined, we search everywhere by starting to the internal symbols␊ |
1020 | ␉␉␉␉␊ |
1021 | if((symbolAddr == 0xFFFFFFFF) && (strncmp(symbolName, SYMBOL_DYLD_STUB_BINDER,sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0))␊ |
1022 | ␉␉␉␉{␉␉␉␉␉␊ |
1023 | ␉␉␉␉␉printf("Unable to bind symbol %s needed by %s\n", symbolName, module);␊ |
1024 | getc();␊ |
1025 | goto error;␊ |
1026 | ␊ |
1027 | ␉␉␉␉}␊ |
1028 | ␉␉␉␉␊ |
1029 | ␉␉␉␉break;␊ |
1030 | }␊ |
1031 | ␉␉␉case BIND_OPCODE_SET_TYPE_IMM:␊ |
1032 | {␊ |
1033 | ␉␉␉␉// Set bind type (pointer, absolute32, pcrel32)␊ |
1034 | #if DEBUG_MODULES==2␊ |
1035 | UInt8 type = immediate;␊ |
1036 | ␉␉␉␉DBG("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);␊ |
1037 | #endif␊ |
1038 | ␉␉␉␉break;␊ |
1039 | }␊ |
1040 | ␉␉␉case BIND_OPCODE_SET_ADDEND_SLEB:␊ |
1041 | ␉␉␉␉addend = 0;␊ |
1042 | ␉␉␉␉bits = 0;␊ |
1043 | ␉␉␉␉do␊ |
1044 | ␉␉␉␉{␊ |
1045 | ␉␉␉␉␉addend |= (bind_stream[++i] & 0x7f) << bits;␊ |
1046 | ␉␉␉␉␉bits += 7;␊ |
1047 | ␉␉␉␉}␊ |
1048 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
1049 | ␉␉␉␉␊ |
1050 | ␉␉␉␉if(!(bind_stream[i-1] & 0x40)) addend *= -1;␊ |
1051 | #if DEBUG_MODULES==2␊ |
1052 | ␉␉␉␉DBG("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);␊ |
1053 | #endif␊ |
1054 | ␊ |
1055 | ␉␉␉␉break;␊ |
1056 | ␉␉␉␉␊ |
1057 | ␉␉␉case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:␊ |
1058 | ␉␉␉{␉␉␉␉␊ |
1059 | ␉␉␉␉// Locate address␊ |
1060 | ␉␉␉␉struct segment_command* segCommand = NULL;␉// NOTE: 32bit only␊ |
1061 | ␉␉␉␉␊ |
1062 | ␉␉␉␉{␊ |
1063 | ␉␉␉␉␉unsigned int binIndex = 0;␊ |
1064 | ␉␉␉␉␉index = 0;␊ |
1065 | ␉␉␉␉␉do␊ |
1066 | ␉␉␉␉␉{␊ |
1067 | ␉␉␉␉␉␉segCommand = base + sizeof(struct mach_header) + binIndex;␊ |
1068 | ␉␉␉␉␉␉binIndex += segCommand->cmdsize;␊ |
1069 | ␉␉␉␉␉␉index++;␊ |
1070 | ␉␉␉␉␉}while(index <= immediate);␊ |
1071 | ␉␉␉␉}␊ |
1072 | ␉␉␉␉␊ |
1073 | ␉␉␉␉␊ |
1074 | ␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
1075 | ␉␉␉␉␊ |
1076 | ␉␉␉␉// Read in offset␊ |
1077 | ␉␉␉␉tmp = 0;␊ |
1078 | ␉␉␉␉bits = 0;␊ |
1079 | ␉␉␉␉do␊ |
1080 | ␉␉␉␉{␊ |
1081 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
1082 | ␉␉␉␉␉bits += 7;␊ |
1083 | ␉␉␉␉}while(bind_stream[i] & 0x80);␊ |
1084 | ␉␉␉␉␊ |
1085 | ␉␉␉␉segmentAddress += tmp;␊ |
1086 | #if DEBUG_MODULES==2␊ |
1087 | ␉␉␉␉DBG("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress);␊ |
1088 | #endif␊ |
1089 | ␉␉␉␉break;␊ |
1090 | ␉␉␉}␉␉␉␉␊ |
1091 | ␉␉␉case BIND_OPCODE_ADD_ADDR_ULEB:␊ |
1092 | ␉␉␉␉// Read in offset␊ |
1093 | ␉␉␉␉tmp = 0;␊ |
1094 | ␉␉␉␉bits = 0;␊ |
1095 | ␉␉␉␉do␊ |
1096 | ␉␉␉␉{␊ |
1097 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
1098 | ␉␉␉␉␉bits += 7;␊ |
1099 | ␉␉␉␉}␊ |
1100 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
1101 | ␉␉␉␉␊ |
1102 | ␉␉␉␉segmentAddress += tmp;␊ |
1103 | #if DEBUG_MODULES==2␊ |
1104 | ␉␉␉␉DBG("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);␊ |
1105 | #endif␊ |
1106 | ␊ |
1107 | ␉␉␉␉break;␊ |
1108 | ␉␉␉␉␊ |
1109 | ␉␉␉case BIND_OPCODE_DO_BIND:␊ |
1110 | #if DEBUG_MODULES==2␊ |
1111 | ␉␉␉␉DBG("BIND_OPCODE_DO_BIND\n");␊ |
1112 | #endif ␊ |
1113 | ␊ |
1114 | if(symbolAddr != 0xFFFFFFFF)␊ |
1115 | ␉␉␉␉{␊ |
1116 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
1117 | ␉␉␉␉␉␊ |
1118 | ␉␉␉␉␉bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);␊ |
1119 | ␉␉␉␉}␊ |
1120 | ␉␉␉␉else if(symbolName && (strncmp(symbolName, SYMBOL_DYLD_STUB_BINDER,sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0))␊ |
1121 | ␉␉␉␉{␊ |
1122 | ␉␉␉␉␉printf("Unable to bind symbol %s needed by %s\n", symbolName, module);␊ |
1123 | getc();␊ |
1124 | goto error;␊ |
1125 | ␊ |
1126 | ␉␉␉␉}␊ |
1127 | ␉␉␉␉␊ |
1128 | ␉␉␉␉segmentAddress += sizeof(void*);␊ |
1129 | ␉␉␉␉break;␊ |
1130 | ␉␉␉␉␊ |
1131 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:␊ |
1132 | #if DEBUG_MODULES==2␊ |
1133 | ␉␉␉␉DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");␊ |
1134 | #endif␉␉␊ |
1135 | ␉␉␉␉␊ |
1136 | ␉␉␉␉// Read in offset␊ |
1137 | ␉␉␉␉tmp = 0;␊ |
1138 | ␉␉␉␉bits = 0;␊ |
1139 | ␉␉␉␉do␊ |
1140 | ␉␉␉␉{␊ |
1141 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
1142 | ␉␉␉␉␉bits += 7;␊ |
1143 | ␉␉␉␉}␊ |
1144 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
1145 | ␉␉␉␉␊ |
1146 | ␊ |
1147 | if(symbolAddr != 0xFFFFFFFF)␊ |
1148 | ␉␉␉␉{␊ |
1149 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
1150 | ␉␉␉␉␉␊ |
1151 | ␉␉␉␉␉bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);␊ |
1152 | ␉␉␉␉}␊ |
1153 | ␉␉␉␉else if(symbolName && (strncmp(symbolName, SYMBOL_DYLD_STUB_BINDER,sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0))␊ |
1154 | ␉␉␉␉{␊ |
1155 | ␉␉␉␉␉printf("Unable to bind symbol %s needed by %s\n", symbolName, module);␊ |
1156 | getc();␊ |
1157 | goto error; ␊ |
1158 | ␊ |
1159 | ␉␉␉␉}␊ |
1160 | ␊ |
1161 | ␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
1162 | ␉␉␉␉␊ |
1163 | ␉␉␉␉␊ |
1164 | ␉␉␉␉break;␊ |
1165 | ␉␉␉␉␊ |
1166 | ␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:␊ |
1167 | #if DEBUG_MODULES==2␊ |
1168 | ␉␉␉␉DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");␊ |
1169 | #endif␉␉␉␉␉␉␊ |
1170 | ␊ |
1171 | if(symbolAddr != 0xFFFFFFFF)␊ |
1172 | ␉␉␉␉{␊ |
1173 | ␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
1174 | ␉␉␉␉␉␊ |
1175 | ␉␉␉␉␉bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);␊ |
1176 | ␉␉␉␉}␊ |
1177 | ␉␉␉␉else if(symbolName && (strncmp(symbolName, SYMBOL_DYLD_STUB_BINDER,sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0))␊ |
1178 | ␉␉␉␉{␊ |
1179 | ␉␉␉␉␉printf("Unable to bind symbol %s needed by %s\n", symbolName, module);␊ |
1180 | getc();␊ |
1181 | goto error; ␊ |
1182 | ␊ |
1183 | ␉␉␉␉}␊ |
1184 | ␉␉␉␉segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);␉␉␉␉␊ |
1185 | ␉␉␉␉␊ |
1186 | ␉␉␉␉break;␊ |
1187 | ␉␉␉␉␊ |
1188 | ␉␉␉case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:␊ |
1189 | ␉␉␉␉␊ |
1190 | ␉␉␉␉tmp = 0;␊ |
1191 | ␉␉␉␉bits = 0;␊ |
1192 | ␉␉␉␉do␊ |
1193 | ␉␉␉␉{␊ |
1194 | ␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
1195 | ␉␉␉␉␉bits += 7;␊ |
1196 | ␉␉␉␉}␊ |
1197 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
1198 | ␉␉␉␉␊ |
1199 | ␉␉␉␉␊ |
1200 | ␉␉␉␉tmp2 = 0;␊ |
1201 | ␉␉␉␉bits = 0;␊ |
1202 | ␉␉␉␉do␊ |
1203 | ␉␉␉␉{␊ |
1204 | ␉␉␉␉␉tmp2 |= (bind_stream[++i] & 0x7f) << bits;␊ |
1205 | ␉␉␉␉␉bits += 7;␊ |
1206 | ␉␉␉␉}␊ |
1207 | ␉␉␉␉while(bind_stream[i] & 0x80);␊ |
1208 | ␉␉␉␉␊ |
1209 | #if DEBUG_MODULES==2␊ |
1210 | ␉␉␉␉DBG("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);␊ |
1211 | #endif␉␉␉␉␊ |
1212 | ␊ |
1213 | if(symbolAddr != 0xFFFFFFFF)␊ |
1214 | ␉␉␉␉{␊ |
1215 | ␉␉␉␉␉for(index = 0; index < tmp; index++)␊ |
1216 | ␉␉␉␉␉{␊ |
1217 | ␉␉␉␉␉␉␊ |
1218 | ␉␉␉␉␉␉address = segmentAddress + (UInt32)base;␊ |
1219 | ␉␉␉␉␉␉␊ |
1220 | ␉␉␉␉␉␉bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);␊ |
1221 | ␉␉␉␉␉␉␊ |
1222 | ␉␉␉␉␉␉segmentAddress += tmp2 + sizeof(void*);␊ |
1223 | ␉␉␉␉␉}␊ |
1224 | ␉␉␉␉}␊ |
1225 | ␉␉␉␉else if(symbolName && (strncmp(symbolName, SYMBOL_DYLD_STUB_BINDER,sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0))␊ |
1226 | ␉␉␉␉{␊ |
1227 | ␉␉␉␉␉printf("Unable to bind symbol %s needed by %s\n", symbolName, module);␊ |
1228 | getc();␊ |
1229 | goto error; ␊ |
1230 | ␊ |
1231 | ␉␉␉␉}␉␉␉␉␊ |
1232 | ␉␉␉␉␊ |
1233 | ␉␉␉␉break;␊ |
1234 | ␉␉␉default:␊ |
1235 | ␉␉␉␉break;␊ |
1236 | ␉␉␉␉␊ |
1237 | ␉␉}␊ |
1238 | ␉␉i++;␊ |
1239 | ␉}␊ |
1240 | return EFI_SUCCESS;␊ |
1241 | error:␊ |
1242 | return EFI_NOT_FOUND;␊ |
1243 | }␊ |
1244 | ␊ |
1245 | void rebase_location(UInt32* location, char* base, int type)␊ |
1246 | {␉␊ |
1247 | ␉switch(type)␊ |
1248 | ␉{␊ |
1249 | ␉␉case REBASE_TYPE_POINTER:␊ |
1250 | ␉␉case REBASE_TYPE_TEXT_ABSOLUTE32:␊ |
1251 | ␉␉␉*location += (UInt32)base;␊ |
1252 | ␉␉␉break;␊ |
1253 | ␉␉␉␊ |
1254 | ␉␉default:␊ |
1255 | ␉␉␉break;␊ |
1256 | ␉}␊ |
1257 | }␊ |
1258 | ␊ |
1259 | void bind_location(UInt32* location, char* value, UInt32 addend, int type)␊ |
1260 | {␉␊ |
1261 | ␉// do actual update␊ |
1262 | ␉char* newValue = value + addend;␊ |
1263 | ␉␊ |
1264 | ␉switch (type) {␊ |
1265 | ␉␉case BIND_TYPE_POINTER:␊ |
1266 | ␉␉case BIND_TYPE_TEXT_ABSOLUTE32:␊ |
1267 | ␉␉␉break;␊ |
1268 | ␉␉␉␊ |
1269 | ␉␉case BIND_TYPE_TEXT_PCREL32:␊ |
1270 | ␉␉␉newValue -= ((UInt32)location + 4);␊ |
1271 | ␉␉␉␊ |
1272 | ␉␉␉break;␊ |
1273 | ␉␉default:␊ |
1274 | ␉␉␉return;␊ |
1275 | ␉}␊ |
1276 | ␉*location = (UInt32)newValue;␊ |
1277 | ␉␊ |
1278 | ␉␊ |
1279 | }␊ |
1280 | ␊ |
1281 | /*␊ |
1282 | * add_symbol␊ |
1283 | * This function adds a symbol from a module to the list of known symbols ␊ |
1284 | * possibly change to a pointer and add this to the Symbol module so that it can␊ |
1285 | * adjust it's internal symbol list (sort) to optimize locating new symbols␊ |
1286 | * NOTE: returns the address if the symbol is "start", else returns 0xFFFFFFFF␊ |
1287 | */␊ |
1288 | #if macho_64␊ |
1289 | long long add_symbol(char* module,char* symbol, long long addr, char is64)␊ |
1290 | #else␊ |
1291 | long long add_symbol(char* module,char* symbol, long long addr)␊ |
1292 | #endif␊ |
1293 | {␊ |
1294 | #if macho_64␊ |
1295 | ␉if(is64) return 0xFFFFFFFF; // Fixme␊ |
1296 | #endif␊ |
1297 | ␉// This only can handle 32bit symbols ␊ |
1298 | ␉symbolList_t* new_entry= malloc(sizeof(symbolList_t));␊ |
1299 | ␉DBG("Adding symbol %s at 0x%X\n", symbol, addr);␊ |
1300 | ␉if (new_entry)␊ |
1301 | ␉{␉␊ |
1302 | ␉␉bzero(new_entry,sizeof(symbolList_t));␊ |
1303 | ␉␉␊ |
1304 | ␉␉new_entry->next = moduleSymbols;␊ |
1305 | ␉␉␊ |
1306 | ␉␉moduleSymbols = new_entry;␊ |
1307 | ␉␉␊ |
1308 | ␉␉new_entry->addr = (UInt32)addr;␊ |
1309 | new_entry->module = module;␊ |
1310 | ␉␉new_entry->symbol = symbol;␊ |
1311 | ␉␉return addr;␊ |
1312 | ␉}␉␊ |
1313 | ␉␊ |
1314 | ␉return 0xFFFFFFFF;␊ |
1315 | ␉␊ |
1316 | }␊ |
1317 | ␊ |
1318 | // Look for symbols using the Smbols moduel function.␊ |
1319 | // If non are found, look through the list of module symbols␊ |
1320 | unsigned int lookup_all_symbols(const char* module, const char* name)␊ |
1321 | {␊ |
1322 | ␊ |
1323 | unsigned int addr = 0xFFFFFFFF;␊ |
1324 | ␊ |
1325 | do {␊ |
1326 | ␊ |
1327 | if ((module != NULL) && (strncmp(module,SYMBOLS_BUNDLE,sizeof(SYMBOLS_BUNDLE)) != 0))␊ |
1328 | break; ␊ |
1329 | ␊ |
1330 | if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF)␊ |
1331 | {␊ |
1332 | addr = lookup_symbol(name, &strcmp);␊ |
1333 | if(addr != 0xFFFFFFFF)␊ |
1334 | {␊ |
1335 | DBG("Internal symbol %s located at 0x%X\n", name, addr);␊ |
1336 | goto out;␊ |
1337 | }␊ |
1338 | } ␊ |
1339 | ␊ |
1340 | } while (0);␊ |
1341 | ␊ |
1342 | ␊ |
1343 | ␉{␊ |
1344 | ␉␉symbolList_t* entry = moduleSymbols;␊ |
1345 | ␉␉while(entry)␊ |
1346 | ␉␉{␊ |
1347 | if ((module != NULL) && (strcmp(entry->module,module) != 0))␊ |
1348 | {␊ |
1349 | entry = entry->next;␊ |
1350 | continue; ␊ |
1351 | }␊ |
1352 | ␊ |
1353 | if(strcmp(entry->symbol, name) == 0)␊ |
1354 | {␊ |
1355 | DBG("External symbol %s located at 0x%X\n", name, entry->addr);␊ |
1356 | addr = entry->addr;␊ |
1357 | goto out;␊ |
1358 | }␊ |
1359 | else␊ |
1360 | {␊ |
1361 | entry = entry->next;␊ |
1362 | } ␊ |
1363 | ␊ |
1364 | ␉␉}␊ |
1365 | ␉}␊ |
1366 | ␉␊ |
1367 | #if DEBUG_MODULES␊ |
1368 | ␉if(strncmp(name, SYMBOL_DYLD_STUB_BINDER, sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0)␊ |
1369 | ␉{␊ |
1370 | ␉␉verbose("Unable to locate symbol %s\n", name);␊ |
1371 | ␉␉getc();␊ |
1372 | ␉}␊ |
1373 | #endif␊ |
1374 | out:␊ |
1375 | return addr;␊ |
1376 | ␊ |
1377 | }␊ |
1378 | ␊ |
1379 | ␊ |
1380 | /*␊ |
1381 | * parse the symbol table␊ |
1382 | * Lookup any undefined symbols␊ |
1383 | */␊ |
1384 | #if macho_64␊ |
1385 | unsigned int handle_symtable(char *module, UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, char*, long long, char), char is64)␊ |
1386 | #else␊ |
1387 | unsigned int handle_symtable(char *module, UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, char*, long long))␊ |
1388 | #endif␊ |
1389 | {␉␉␊ |
1390 | ␉unsigned int module_start = 0xFFFFFFFF;␊ |
1391 | ␉␊ |
1392 | ␉UInt32 symbolIndex = 0;␊ |
1393 | if (!symtabCommand) {␊ |
1394 | return 0xFFFFFFFF;␊ |
1395 | }␊ |
1396 | ␉char* symbolString = base + (char*)symtabCommand->stroff;␊ |
1397 | #if macho_64␊ |
1398 | ␉if(!is64)␊ |
1399 | #endif␊ |
1400 | ␉{␊ |
1401 | ␉␉struct nlist* symbolEntry = (void*)base + symtabCommand->symoff;␊ |
1402 | ␉␉while(symbolIndex < symtabCommand->nsyms)␊ |
1403 | ␉␉{␉␉␉␉␉␉␊ |
1404 | ␉␉␉if(symbolEntry->n_value)␊ |
1405 | ␉␉␉{␉␉␉␉␊ |
1406 | ␉␉␉␉if(strstr(symbolString + symbolEntry->n_un.n_strx, "module_start") || (strncmp(symbolString + symbolEntry->n_un.n_strx, "start", sizeof("start")) == 0))␊ |
1407 | ␉␉␉␉{␊ |
1408 | ␉␉␉␉␉module_start = base + symbolEntry->n_value;␊ |
1409 | ␉␉␉␉␉DBG("n_value %x module_start %x\n", (unsigned)symbolEntry->n_value, (unsigned)module_start);␊ |
1410 | ␉␉␉␉}␊ |
1411 | ␉␉␉␉else␊ |
1412 | ␉␉␉␉{␊ |
1413 | #if macho_64␊ |
1414 | ␉␉␉␉␉symbol_handler(module, symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64);␊ |
1415 | #else␊ |
1416 | ␉␉␉␉␉symbol_handler(module, symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value);␊ |
1417 | #endif␊ |
1418 | ␉␉␉␉␉␊ |
1419 | ␉␉␉␉}␊ |
1420 | #if DEBUG_MODULES␊ |
1421 | ␉␉␉␉bool isTexT = (((unsigned)symbolEntry->n_value > (unsigned)vmaddr) && ((unsigned)(vmaddr + vmsize) > (unsigned)symbolEntry->n_value ));␊ |
1422 | ␉␉␉␉printf("%s %s\n", isTexT ? "__TEXT :" : "__DATA(OR ANY) :", symbolString + symbolEntry->n_un.n_strx);␊ |
1423 | #if DEBUG_MODULES==2␉␊ |
1424 | ␉␉␉␉␊ |
1425 | ␉␉␉␉if(strcmp(symbolString + symbolEntry->n_un.n_strx, "_BootHelp_txt") == 0)␊ |
1426 | ␉␉␉␉{␊ |
1427 | ␉␉␉␉␉long long addr = (long long)base + symbolEntry->n_value;␊ |
1428 | ␉␉␉␉␉unsigned char *BootHelp = NULL;␊ |
1429 | ␉␉␉␉␉BootHelp = (unsigned char*)(UInt32)addr;␉␉␉␉␉␊ |
1430 | ␉␉␉␉␉printf("method 1: __DATA : BootHelp_txt[0] %x\n", BootHelp[0]);␊ |
1431 | ␉␉␉␉␉␊ |
1432 | ␉␉␉␉␉long long addr2 = symbolEntry->n_value;␊ |
1433 | ␉␉␉␉␉unsigned char *BootHelp2 = NULL;␊ |
1434 | ␉␉␉␉␉BootHelp2 = (unsigned char*)(UInt32)addr2;␉␉␉␉␉␊ |
1435 | ␉␉␉␉␉printf("method 2: __DATA : BootHelp_txt[0] %x\n", BootHelp2[0]);␊ |
1436 | ␉␉␉␉}␊ |
1437 | #endif␊ |
1438 | #endif␊ |
1439 | ␉␉␉␉␊ |
1440 | ␉␉␉}␊ |
1441 | ␉␉␉␊ |
1442 | ␉␉␉symbolEntry++;␊ |
1443 | ␉␉␉symbolIndex++;␉// TODO remove␊ |
1444 | ␉␉}␊ |
1445 | ␉}␊ |
1446 | #if macho_64␊ |
1447 | ␉else␊ |
1448 | ␉{␊ |
1449 | ␉␉struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff;␊ |
1450 | ␉␉// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now)␉␊ |
1451 | ␉␉while(symbolIndex < symtabCommand->nsyms)␊ |
1452 | ␉␉{␉␊ |
1453 | ␉␉␉␊ |
1454 | ␉␉␉if(strstr(symbolString + symbolEntry->n_un.n_strx, "module_start") || (strncmp(symbolString + symbolEntry->n_un.n_strx, "start",sizeof("start")) == 0))␊ |
1455 | ␉␉␉{␊ |
1456 | ␉␉␉␉module_start = (unsigned int)(base + symbolEntry->n_value);␊ |
1457 | ␉␉␉}␊ |
1458 | ␉␉␉else␊ |
1459 | ␉␉␉{␊ |
1460 | ␉␉␉␉symbol_handler(module, symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64);␊ |
1461 | ␉␉␉}␊ |
1462 | ␉␉␉␊ |
1463 | ␉␉␉symbolEntry++;␊ |
1464 | ␉␉␉symbolIndex++;␉// TODO remove␊ |
1465 | ␉␉}␊ |
1466 | ␉}␊ |
1467 | #endif␊ |
1468 | ␉␊ |
1469 | ␉return module_start;␊ |
1470 | ␉␊ |
1471 | }␊ |
1472 | ␊ |
1473 | ␊ |
1474 | /*␊ |
1475 | * Locate the symbol for an already loaded function and modify the beginning of␊ |
1476 | * the function to jump directly to the new one␊ |
1477 | * example: replace_system_function("_getc", &replacement);␊ |
1478 | * replace_function(module_name,"_getc", &replacement);␊ |
1479 | * replace_function_any("_getc", &replacement);␊ |
1480 | */␊ |
1481 | EFI_STATUS replace_function(const char* module, const char* symbol, void* newAddress)␊ |
1482 | {␉␉ ␊ |
1483 | ␉// TODO: look into using the next four bytes of the function instead␊ |
1484 | ␉// Most functions should support this, as they probably will be at ␊ |
1485 | ␉// least 10 bytes long, but you never know, this is sligtly safer as␊ |
1486 | ␉// function can be as small as 6 bytes.␊ |
1487 | ␉UInt32 addr = lookup_all_symbols(module, symbol);␊ |
1488 | ␉␊ |
1489 | ␉char* binary = (char*)addr;␊ |
1490 | ␉if(addr != 0xFFFFFFFF)␊ |
1491 | ␉{␊ |
1492 | ␉␉UInt32* jumpPointer = malloc(sizeof(UInt32));␊ |
1493 | ␉␉if (!jumpPointer) {␊ |
1494 | ␉␉␉return EFI_OUT_OF_RESOURCES;␊ |
1495 | ␉␉}␊ |
1496 | ␉␉bzero(jumpPointer,sizeof(UInt32));␊ |
1497 | ␉␉␊ |
1498 | ␉␉*binary++ = 0xFF;␉// Jump␊ |
1499 | ␉␉*binary++ = 0x25;␉// Long Jump␊ |
1500 | ␉␉*((UInt32*)binary) = (UInt32)jumpPointer;␊ |
1501 | ␉␉␊ |
1502 | ␉␉*jumpPointer = (UInt32)newAddress;␊ |
1503 | ␉␉␊ |
1504 | ␉␉return EFI_SUCCESS;␊ |
1505 | ␉}␊ |
1506 | ␉␊ |
1507 | ␉return EFI_NOT_FOUND;␊ |
1508 | ␉␊ |
1509 | }␊ |
1510 | ␊ |
1511 | EFI_STATUS replace_system_function(const char* symbol, void* newAddress)␊ |
1512 | {␉␉ ␊ |
1513 | ␉␊ |
1514 | ␉return replace_function(SYMBOLS_BUNDLE,symbol,newAddress);␊ |
1515 | ␉␊ |
1516 | }␊ |
1517 | ␊ |
1518 | EFI_STATUS replace_function_any(const char* symbol, void* newAddress)␊ |
1519 | {␉␉ ␊ |
1520 | ␉␊ |
1521 | ␉return replace_function(NULL,symbol,newAddress);␊ |
1522 | ␉␊ |
1523 | }␊ |
1524 | /*␊ |
1525 | * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.␊ |
1526 | *␊ |
1527 | * @APPLE_LICENSE_HEADER_START@␊ |
1528 | * ␊ |
1529 | * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights␊ |
1530 | * Reserved. This file contains Original Code and/or Modifications of␊ |
1531 | * Original Code as defined in and that are subject to the Apple Public␊ |
1532 | * Source License Version 2.0 (the 'License'). You may not use this file␊ |
1533 | * except in compliance with the License. Please obtain a copy of the␊ |
1534 | * License at http://www.apple.com/publicsource and read it before using␊ |
1535 | * this file.␊ |
1536 | * ␊ |
1537 | * The Original Code and all software distributed under the License are␊ |
1538 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
1539 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
1540 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
1541 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the␊ |
1542 | * License for the specific language governing rights and limitations␊ |
1543 | * under the License.␊ |
1544 | * ␊ |
1545 | * @APPLE_LICENSE_HEADER_END@␊ |
1546 | */␊ |
1547 | /*␊ |
1548 | * drivers.c - Driver Loading Functions.␊ |
1549 | *␊ |
1550 | * Copyright (c) 2000 Apple Computer, Inc.␊ |
1551 | *␊ |
1552 | * DRI: Josh de Cesare␊ |
1553 | */␊ |
1554 | ␊ |
1555 | /*␊ |
1556 | * Copyright 2012 Cadet-petit Armel <armelcadetpetit@gmail.com>. All rights reserved.␊ |
1557 | *␊ |
1558 | * Cleaned, Added (runtime) bundles support.␊ |
1559 | *␊ |
1560 | */␊ |
1561 | #include <mach-o/fat.h>␊ |
1562 | #include <libkern/OSByteOrder.h>␊ |
1563 | #include <mach/machine.h>␊ |
1564 | ␊ |
1565 | ␊ |
1566 | ␊ |
1567 | ␊ |
1568 | enum {␊ |
1569 | ␉kCFBundleType2,␊ |
1570 | ␉kCFBundleType3␊ |
1571 | };␊ |
1572 | ␊ |
1573 | enum {␊ |
1574 | ␉BundlePriorityNull = 0,␊ |
1575 | ␉BundlePriorityInit = 1,␊ |
1576 | ␉BundlePrioritySystem = 2,␊ |
1577 | ␉BundlePrioritySystemLib = 3,␊ |
1578 | BundlePriorityNormalPriority = 4,␊ |
1579 | BundlePriorityLowestPriority = 99,␊ |
1580 | ␉BundlePriorityEnd = 100 // can not be assigned␊ |
1581 | ␊ |
1582 | };␊ |
1583 | ␊ |
1584 | static BundlePtr gBundleHead;␊ |
1585 | static char * gBundlesSpec;␊ |
1586 | static char * gDriverSpec;␊ |
1587 | static char * gFileSpec;␊ |
1588 | static char * gTempSpec;␊ |
1589 | static char * gFileName;␊ |
1590 | static int gLowestLoadPriority;␊ |
1591 | ␊ |
1592 | static long ParseXML(char *buffer, BundlePtr *module);␊ |
1593 | static BundlePtr FindBundle( char * bundle_id );␊ |
1594 | ␊ |
1595 | static void␊ |
1596 | FreeBundleSupport( void )␊ |
1597 | {␊ |
1598 | ␊ |
1599 | if ( gBundlesSpec ) free(gBundlesSpec);␊ |
1600 | if ( gDriverSpec) free(gDriverSpec);␊ |
1601 | if ( gFileSpec ) free(gFileSpec);␊ |
1602 | if ( gTempSpec ) free(gTempSpec);␊ |
1603 | if ( gFileName ) free(gFileName);␊ |
1604 | }␊ |
1605 | ␊ |
1606 | //==========================================================================␊ |
1607 | // InitBundleSupport␊ |
1608 | ␊ |
1609 | long␊ |
1610 | InitBundleSupport( void )␊ |
1611 | {␊ |
1612 | ␉DBG("InitBundleSupport\n");␊ |
1613 | ␊ |
1614 | static bool BundleSet = false;␊ |
1615 | ␊ |
1616 | if (BundleSet == true) return 0; ␊ |
1617 | ␊ |
1618 | gBundlesSpec = calloc( DEFAULT_BUNDLE_SPEC_SIZE, sizeof(char) );␊ |
1619 | gDriverSpec = calloc( DEFAULT_BUNDLE_SPEC_SIZE, sizeof(char) );␊ |
1620 | gFileSpec = calloc( DEFAULT_BUNDLE_SPEC_SIZE, sizeof(char) );␊ |
1621 | gTempSpec = calloc( DEFAULT_BUNDLE_SPEC_SIZE, sizeof(char) );␊ |
1622 | gFileName = calloc( DEFAULT_BUNDLE_SPEC_SIZE, sizeof(char) );␊ |
1623 | ␊ |
1624 | if ( !gBundlesSpec || !gDriverSpec || !gFileSpec || !gTempSpec || !gFileName )␊ |
1625 | goto error;␊ |
1626 | ␊ |
1627 | BundleSet = true;␊ |
1628 | ␊ |
1629 | return 0;␊ |
1630 | error:␊ |
1631 | FreeBundleSupport();␊ |
1632 | return 1;␊ |
1633 | }␊ |
1634 | ␊ |
1635 | //==========================================================================␊ |
1636 | // LoadBundles␊ |
1637 | ␊ |
1638 | long LoadBundles( char * dirSpec )␊ |
1639 | {␉␊ |
1640 | ␉DBG("LoadBundles\n");␊ |
1641 | ␊ |
1642 | if ( InitBundleSupport() != 0 )␊ |
1643 | return 1;␊ |
1644 | ␉␊ |
1645 | ␉␊ |
1646 | ␉strlcpy(gBundlesSpec, dirSpec, DEFAULT_BUNDLE_SPEC_SIZE);␊ |
1647 | strlcat(gBundlesSpec, "Modules", DEFAULT_BUNDLE_SPEC_SIZE);␊ |
1648 | FileLoadBundles(gBundlesSpec, 0);␉␉␊ |
1649 | ␊ |
1650 | ␉␊ |
1651 | MatchBundlesLibraries();␊ |
1652 | ␉␊ |
1653 | LoadMatchedBundles();␊ |
1654 | ␊ |
1655 | ␉DBG("LoadBundles Finished\n");␊ |
1656 | ␊ |
1657 | return 0;␊ |
1658 | }␊ |
1659 | ␊ |
1660 | //==========================================================================␊ |
1661 | // FileLoadBundles␊ |
1662 | long␊ |
1663 | FileLoadBundles( char * dirSpec, long plugin )␊ |
1664 | {␊ |
1665 | long ret, length, flags, time, bundleType;␊ |
1666 | long long␉ index;␊ |
1667 | long result = -1;␊ |
1668 | const char * name;␊ |
1669 | ␊ |
1670 | ␉DBG("FileLoadBundles in %s\n",dirSpec);␊ |
1671 | ␊ |
1672 | index = 0;␊ |
1673 | while (1) {␊ |
1674 | ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);␊ |
1675 | if (ret == -1) break;␊ |
1676 | ␉␉␊ |
1677 | // Make sure this is a directory.␊ |
1678 | if ((flags & kFileTypeMask) != kFileTypeDirectory) continue;␊ |
1679 | ␊ |
1680 | // Make sure this is a kext.␊ |
1681 | length = strlen(name);␊ |
1682 | if (strncmp(name + length - 7, ".bundle",7)) continue;␊ |
1683 | ␉␉␊ |
1684 | // Save the file name.␊ |
1685 | strlcpy(gFileName, name, DEFAULT_BUNDLE_SPEC_SIZE);␊ |
1686 | ␉␉DBG("Load Bundles %s\n",gFileName);␊ |
1687 | ␊ |
1688 | // Determine the bundle type.␊ |
1689 | snprintf(gTempSpec,DEFAULT_BUNDLE_SPEC_SIZE,"%s/%s", dirSpec, gFileName);␊ |
1690 | ret = GetFileInfo(gTempSpec, "Contents", &flags, &time);␊ |
1691 | if (ret == 0) bundleType = kCFBundleType2;␊ |
1692 | else bundleType = kCFBundleType3;␊ |
1693 | ␉␉␊ |
1694 | ␉␉DBG("Bundles type = %d\n",bundleType);␊ |
1695 | ␊ |
1696 | if (!plugin)␊ |
1697 | snprintf(gDriverSpec, DEFAULT_BUNDLE_SPEC_SIZE,"%s/%s/%sPlugIns", dirSpec, gFileName,␊ |
1698 | ␉␉␉␉␉ (bundleType == kCFBundleType2) ? "Contents/" : "");␊ |
1699 | ␉␉␊ |
1700 | ret = LoadBundlePList( dirSpec, gFileName, bundleType);␊ |
1701 | ␉␉␊ |
1702 | if (result != 0)␊ |
1703 | ␉␉␉result = ret;␊ |
1704 | ␉␉␊ |
1705 | if (!plugin) ␊ |
1706 | ␉␉␉FileLoadBundles(gDriverSpec, 1);␊ |
1707 | }␊ |
1708 | ␉␊ |
1709 | return result;␊ |
1710 | }␊ |
1711 | ␊ |
1712 | ␊ |
1713 | static void add_bundle(BundlePtr module,char* name)␊ |
1714 | {␊ |
1715 | ␉BundlePtr new_entry= malloc(sizeof(Bundle));␊ |
1716 | ␉DBG("Adding bundle %s \n", name );␊ |
1717 | ␉if (new_entry)␊ |
1718 | ␉{␉␊ |
1719 | ␉␉bzero(new_entry,sizeof(Bundle));␊ |
1720 | ␉␉␊ |
1721 | ␉␉new_entry->nextBundle = gBundleHead;␊ |
1722 | ␉␉␊ |
1723 | ␉␉gBundleHead = new_entry;␊ |
1724 | ␉␉␊ |
1725 | ␉␉new_entry->executablePath = module->executablePath;␊ |
1726 | new_entry->bundlePath = module->bundlePath;␊ |
1727 | new_entry->bundlePathLength = module->bundlePathLength;␊ |
1728 | new_entry->plistAddr = module->plistAddr;␊ |
1729 | new_entry->willLoad = module->willLoad;␊ |
1730 | new_entry->dict = module->dict;␊ |
1731 | new_entry->plistLength = module->plistLength;␊ |
1732 | new_entry->personalities = module->personalities;␊ |
1733 | ␊ |
1734 | ␉}␉␊ |
1735 | ␉␊ |
1736 | }␊ |
1737 | ␊ |
1738 | //==========================================================================␊ |
1739 | // LoadBundlePList␊ |
1740 | ␊ |
1741 | long␊ |
1742 | LoadBundlePList( char * dirSpec, char * name, long bundleType )␊ |
1743 | {␊ |
1744 | long length, executablePathLength, bundlePathLength;␊ |
1745 | BundlePtr module = 0;␊ |
1746 | char * buffer = 0;␊ |
1747 | char * tmpExecutablePath = 0;␊ |
1748 | char * tmpBundlePath = 0;␊ |
1749 | long ret = -1;␊ |
1750 | ␉DBG("LoadBundlePList\n");␊ |
1751 | ␊ |
1752 | do {␊ |
1753 | // Save the driver path.␊ |
1754 | ␊ |
1755 | snprintf(gFileSpec,DEFAULT_BUNDLE_SPEC_SIZE,"%s/%s/%s", dirSpec, name,␊ |
1756 | ␉␉␉␉ (bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");␊ |
1757 | executablePathLength = strlen(gFileSpec) + 1;␊ |
1758 | ␉␉␊ |
1759 | tmpExecutablePath = calloc(executablePathLength,sizeof(char));␊ |
1760 | if (tmpExecutablePath == 0) break;␊ |
1761 | ␊ |
1762 | strlcpy(tmpExecutablePath, gFileSpec, executablePathLength);␊ |
1763 | ␊ |
1764 | snprintf(gFileSpec, DEFAULT_BUNDLE_SPEC_SIZE,"%s/%s", dirSpec, name);␊ |
1765 | bundlePathLength = strlen(gFileSpec) + 1;␊ |
1766 | ␉␉␊ |
1767 | tmpBundlePath = calloc(bundlePathLength,sizeof(char));␊ |
1768 | if (tmpBundlePath == 0) break;␊ |
1769 | ␉␉␊ |
1770 | strlcpy(tmpBundlePath, gFileSpec, bundlePathLength);␊ |
1771 | ␊ |
1772 | ␊ |
1773 | // Construct the file spec to the plist, then load it.␊ |
1774 | ␉␉␊ |
1775 | snprintf(gFileSpec, DEFAULT_BUNDLE_SPEC_SIZE,"%s/%s/%sInfo.plist", dirSpec, name,␊ |
1776 | ␉␉␉␉ (bundleType == kCFBundleType2) ? "Contents/" : "");␊ |
1777 | ␉␉␊ |
1778 | ␉␉DBG("Loading Bundle PList %s\n",gFileSpec);␊ |
1779 | ␊ |
1780 | length = LoadFile(gFileSpec);␊ |
1781 | if (length == -1) break;␊ |
1782 | ␉␉␊ |
1783 | length = length + 1;␊ |
1784 | buffer = malloc(length);␊ |
1785 | if (buffer == 0) break;␊ |
1786 | ␉␉␊ |
1787 | ␉␉bzero(buffer, length);␊ |
1788 | ␉␉␊ |
1789 | strlcpy(buffer, (char *)kLoadAddr, length);␊ |
1790 | ␉␉␊ |
1791 | // Parse the plist.␊ |
1792 | ␉␉␊ |
1793 | ret = ParseXML(buffer, &module);␊ |
1794 | if (ret != 0 ) { printf("Unable to read plist of %s",name); break; }␊ |
1795 | ␉␉␊ |
1796 | ␉␉if (!module) {ret = -1;break;} // Should never happen but it will make the compiler happy␊ |
1797 | ␊ |
1798 | // Allocate memory for the driver path and the plist.␊ |
1799 | ␊ |
1800 | module->executablePath = tmpExecutablePath;␊ |
1801 | module->bundlePath = tmpBundlePath;␊ |
1802 | module->bundlePathLength = bundlePathLength;␊ |
1803 | module->plistAddr = malloc(length);␊ |
1804 | ␉␉␊ |
1805 | if ((module->executablePath == 0) || (module->bundlePath == 0) || (module->plistAddr == 0))␊ |
1806 | {␊ |
1807 | if ( module->plistAddr ) free(module->plistAddr);␊ |
1808 | ␉␉␉ret = -1;␊ |
1809 | break;␊ |
1810 | } ␊ |
1811 | ␉␉bzero(module->plistAddr, length);␊ |
1812 | ␉␉␊ |
1813 | // Add the plist to the module.␊ |
1814 | ␉␉␊ |
1815 | strlcpy(module->plistAddr, (char *)kLoadAddr, length);␊ |
1816 | module->plistLength = length;␊ |
1817 | ␉␉␊ |
1818 | // Add the module to the module list.␊ |
1819 | ␊ |
1820 | add_bundle(module, name); ␊ |
1821 | ␊ |
1822 | ␊ |
1823 | ret = 0;␊ |
1824 | }␊ |
1825 | while (0);␊ |
1826 | ␊ |
1827 | if ( buffer ) free( buffer );␊ |
1828 | if ( module ) free( module );␊ |
1829 | ␊ |
1830 | if (ret != 0) {␊ |
1831 | if ( tmpExecutablePath ) free( tmpExecutablePath );␊ |
1832 | if ( tmpBundlePath ) free( tmpBundlePath );␊ |
1833 | }␉␊ |
1834 | return ret;␊ |
1835 | }␊ |
1836 | ␊ |
1837 | #define WillLoadBundles \␊ |
1838 | module = gBundleHead; \␊ |
1839 | while (module != NULL) \␊ |
1840 | { \␊ |
1841 | if (module->willLoad == willLoad) \␊ |
1842 | { \␊ |
1843 | prop = XMLGetProperty(module->dict, kPropCFBundleExecutable); \␊ |
1844 | \␊ |
1845 | if (prop != 0) \␊ |
1846 | { \␊ |
1847 | fileName = prop->string; \␊ |
1848 | snprintf(gFileSpec, DEFAULT_BUNDLE_SPEC_SIZE,"%s%s", module->executablePath, fileName); \␊ |
1849 | \␊ |
1850 | module_start = (void*)load_module((char*)fileName,gFileSpec,module); \␊ |
1851 | if(!module_start || (*module_start == (void*)0xFFFFFFFF)) \␊ |
1852 | { \␊ |
1853 | if (module->willLoad > BundlePrioritySystemLib) \␊ |
1854 | { \␊ |
1855 | module->willLoad = BundlePriorityNull ; \␊ |
1856 | printf("Unable to start %s\n", gFileSpec); \␊ |
1857 | } \␊ |
1858 | } else module_start(); \␊ |
1859 | if (module->willLoad == BundlePrioritySystem) \␊ |
1860 | { \␊ |
1861 | lookup_symbol = (void*)lookup_all_symbols(SYMBOLS_BUNDLE,SYMBOL_LOOKUP_SYMBOL); \␊ |
1862 | if((UInt32)lookup_symbol != 0xFFFFFFFF) \␊ |
1863 | { \␊ |
1864 | msglog("%s successfully Loaded.\n", gFileSpec); \␊ |
1865 | } else return -1; \␊ |
1866 | } \␊ |
1867 | } \␊ |
1868 | } \␊ |
1869 | module = module->nextBundle; \␊ |
1870 | } ␊ |
1871 | ␊ |
1872 | //==========================================================================␊ |
1873 | // LoadMatchedBundles␊ |
1874 | ␊ |
1875 | long LoadMatchedBundles( void )␊ |
1876 | {␊ |
1877 | TagPtr prop;␊ |
1878 | BundlePtr module;␊ |
1879 | char *fileName;␊ |
1880 | void (*module_start)(void);␊ |
1881 | long willLoad;␊ |
1882 | ␊ |
1883 | ␉DBG("LoadMatchedBundles\n");␊ |
1884 | ␊ |
1885 | ␉int priority_end = MIN(gLowestLoadPriority+1, BundlePriorityEnd);␊ |
1886 | ␊ |
1887 | for (willLoad = BundlePrioritySystem; willLoad < priority_end ; willLoad++)␊ |
1888 | {␊ |
1889 | ␊ |
1890 | WillLoadBundles ;␊ |
1891 | ␊ |
1892 | }␊ |
1893 | ␊ |
1894 | return 0;␊ |
1895 | }␊ |
1896 | ␊ |
1897 | //==========================================================================␊ |
1898 | // MatchBundlesLibraries␊ |
1899 | ␊ |
1900 | long MatchBundlesLibraries( void )␊ |
1901 | {␊ |
1902 | ␊ |
1903 | TagPtr prop, prop2;␊ |
1904 | BundlePtr module, module2,dummy_module;␊ |
1905 | ␉␊ |
1906 | // Check for active modules with the same Bundle IDs or same principal class, only one must remain (except for type 3 aka system libs)␊ |
1907 | {␊ |
1908 | module = gBundleHead;␊ |
1909 | ␊ |
1910 | while (module != 0)␊ |
1911 | {␊ |
1912 | if (!(module->willLoad > BundlePriorityInit)) // if the module load priority is not higher than initialized, continue␊ |
1913 | {␊ |
1914 | module = module->nextBundle;␊ |
1915 | continue;␊ |
1916 | }␊ |
1917 | ␊ |
1918 | prop = XMLGetProperty(module->dict, kPropNSPrincipalClass);␊ |
1919 | prop2 = XMLGetProperty(module->dict, kPropCFBundleIdentifier); ␊ |
1920 | ␊ |
1921 | if (prop != 0 && prop2 != 0)␊ |
1922 | { ␊ |
1923 | module2 = gBundleHead;␊ |
1924 | ␊ |
1925 | TagPtr prop3,prop4;␊ |
1926 | ␊ |
1927 | while (module2 != 0)␊ |
1928 | {␊ |
1929 | prop3 = XMLGetProperty(module2->dict, kPropNSPrincipalClass);␊ |
1930 | prop4 = XMLGetProperty(module2->dict, kPropCFBundleIdentifier); ␊ |
1931 | ␊ |
1932 | if ((prop3 != 0) && (prop4 != 0) && (module != module2))␊ |
1933 | {␊ |
1934 | ␊ |
1935 | if ((module2->willLoad == BundlePrioritySystemLib) && ((strcmp(prop2->string, prop4->string)!= 0) /*&& (!strcmp(prop->string, prop3->string))*/)) {␊ |
1936 | continue;␊ |
1937 | }␊ |
1938 | ␊ |
1939 | if ((!strcmp(prop2->string, prop4->string)) || (!strcmp(prop->string, prop3->string))) {␊ |
1940 | if (module2->willLoad > BundlePriorityNull) module2->willLoad = BundlePriorityNull;␊ |
1941 | }␊ |
1942 | ␊ |
1943 | }␊ |
1944 | module2 = module2->nextBundle;␊ |
1945 | } ␊ |
1946 | ␊ |
1947 | }␊ |
1948 | ␊ |
1949 | module = module->nextBundle;␊ |
1950 | }␊ |
1951 | }␊ |
1952 | ␊ |
1953 | // Check for dependencies (it works in most cases, still a little buggy but should be sufficient for what we have to do, ␊ |
1954 | ␉// clearly the Achilles' heel of this implementation, please use dependencies with caution !!!)␊ |
1955 | dummy_module = gBundleHead;␊ |
1956 | while (dummy_module != 0)␊ |
1957 | {␊ |
1958 | module = gBundleHead;␊ |
1959 | ␊ |
1960 | while (module != 0)␊ |
1961 | {␊ |
1962 | if (module->willLoad > BundlePrioritySystemLib)␊ |
1963 | { ␊ |
1964 | prop = XMLGetProperty(module->dict, kPropOSBundleLibraries);␊ |
1965 | if (prop != 0)␊ |
1966 | {␊ |
1967 | prop = prop->tag;␊ |
1968 | while (prop != 0)␊ |
1969 | {␊ |
1970 | module2 = gBundleHead;␊ |
1971 | while (module2 != 0)␊ |
1972 | {␊ |
1973 | prop2 = XMLGetProperty(module2->dict, kPropCFBundleIdentifier);␊ |
1974 | if ((prop2 != 0) && (!strncmp(prop->string, prop2->string, strlen( prop->string))))␊ |
1975 | {␊ |
1976 | // found a parent␊ |
1977 | ␊ |
1978 | if (module2->willLoad > BundlePriorityInit)␊ |
1979 | { ␊ |
1980 | // parent is active␊ |
1981 | if (module->willLoad == BundlePriorityNull) {␊ |
1982 | module->willLoad = BundlePriorityNormalPriority;␊ |
1983 | } ␊ |
1984 | ␊ |
1985 | // Check if the version of the parent >= version of the child␊ |
1986 | if (strtol(XMLCastString ( XMLGetProperty(module2->dict,"CFBundleShortVersionString") ), NULL, 10) >= strtol(XMLCastString( prop->tag ), NULL, 10)) {␊ |
1987 | ␊ |
1988 | if ((module2->willLoad >= module->willLoad) && (module->willLoad > BundlePrioritySystemLib))␊ |
1989 | ␉␉␉␉␉␉␉␉␉␉␉module->willLoad = MIN(MAX(module->willLoad, module2->willLoad+1), BundlePriorityLowestPriority); // child must be loaded after the parent, this allow the to find symbols of the parent while we bind the child.␊ |
1990 | ␊ |
1991 | } else {␊ |
1992 | module->willLoad = BundlePriorityNull;␊ |
1993 | goto nextmodule;␊ |
1994 | }␊ |
1995 | break;␊ |
1996 | }␊ |
1997 | ␊ |
1998 | }␊ |
1999 | ␉␉␉␉␉␉␉if (module->willLoad != BundlePriorityNull) module->willLoad = BundlePriorityNull;␊ |
2000 | module2 = module2->nextBundle;␊ |
2001 | }␊ |
2002 | if (module->willLoad == BundlePriorityNull) goto nextmodule;␊ |
2003 | prop = prop->tagNext;␊ |
2004 | }␊ |
2005 | }␊ |
2006 | }␊ |
2007 | nextmodule:␊ |
2008 | module = module->nextBundle;␊ |
2009 | }␊ |
2010 | ␊ |
2011 | ␉␉dummy_module = dummy_module->nextBundle;␊ |
2012 | }␉␊ |
2013 | ␉␊ |
2014 | // Get the lowest load priority␊ |
2015 | {␊ |
2016 | gLowestLoadPriority = BundlePriorityNormalPriority;␊ |
2017 | module = gBundleHead;␊ |
2018 | ␊ |
2019 | while (module != 0)␊ |
2020 | {␊ |
2021 | if (module->willLoad > BundlePriorityInit)␊ |
2022 | { ␊ |
2023 | gLowestLoadPriority = MIN(MAX(module->willLoad,gLowestLoadPriority), BundlePriorityLowestPriority); ␊ |
2024 | }␊ |
2025 | module = module->nextBundle;␊ |
2026 | }␊ |
2027 | }␊ |
2028 | ␊ |
2029 | return 0;␊ |
2030 | }␊ |
2031 | ␊ |
2032 | ␊ |
2033 | //==========================================================================␊ |
2034 | // FindBundle␊ |
2035 | ␊ |
2036 | static BundlePtr␊ |
2037 | FindBundle( char * bundle_id )␊ |
2038 | {␊ |
2039 | BundlePtr module;␊ |
2040 | TagPtr prop;␊ |
2041 | ␉DBG("FindBundle %s\n",bundle_id);␊ |
2042 | ␊ |
2043 | module = gBundleHead;␊ |
2044 | ␊ |
2045 | while (module != 0)␊ |
2046 | {␊ |
2047 | prop = XMLGetProperty(module->dict, kPropCFBundleIdentifier);␊ |
2048 | if ((prop != 0) && !strcmp(bundle_id, prop->string)) break;␊ |
2049 | module = module->nextBundle;␊ |
2050 | }␊ |
2051 | ␊ |
2052 | return module;␊ |
2053 | }␊ |
2054 | ␊ |
2055 | //==========================================================================␊ |
2056 | // GetBundleDict␊ |
2057 | ␊ |
2058 | void *␊ |
2059 | GetBundleDict( char * bundle_id )␊ |
2060 | {␊ |
2061 | BundlePtr module;␊ |
2062 | ␉DBG("GetBundleDict %s\n",bundle_id);␊ |
2063 | ␊ |
2064 | module = FindBundle( bundle_id );␊ |
2065 | ␊ |
2066 | if (module != 0)␊ |
2067 | {␊ |
2068 | return (void *)module->dict;␊ |
2069 | }␊ |
2070 | ␊ |
2071 | return 0;␊ |
2072 | }␊ |
2073 | ␊ |
2074 | //==========================================================================␊ |
2075 | // GetBundlePersonality␊ |
2076 | ␊ |
2077 | void *␊ |
2078 | GetBundlePersonality( char * bundle_id )␊ |
2079 | {␊ |
2080 | BundlePtr module;␊ |
2081 | ␉DBG("GetBundlePersonalities %s\n",bundle_id);␊ |
2082 | ␊ |
2083 | module = FindBundle( bundle_id );␊ |
2084 | ␊ |
2085 | if (module != 0)␊ |
2086 | {␊ |
2087 | return (void *)module->personalities;␊ |
2088 | }␊ |
2089 | ␊ |
2090 | return 0;␊ |
2091 | }␊ |
2092 | ␊ |
2093 | //==========================================================================␊ |
2094 | // GetBundlePath␊ |
2095 | ␊ |
2096 | char *␊ |
2097 | GetBundlePath( char * bundle_id )␊ |
2098 | {␊ |
2099 | BundlePtr module;␊ |
2100 | ␉DBG("GetBundlePath %s\n",bundle_id);␊ |
2101 | ␊ |
2102 | module = FindBundle( bundle_id );␊ |
2103 | ␊ |
2104 | if (module != 0)␊ |
2105 | {␊ |
2106 | return module->bundlePath;␊ |
2107 | }␊ |
2108 | ␊ |
2109 | return 0;␊ |
2110 | }␊ |
2111 | ␊ |
2112 | //==========================================================================␊ |
2113 | // ParseXML␊ |
2114 | ␊ |
2115 | static long␊ |
2116 | ParseXML( char * buffer, BundlePtr * module )␊ |
2117 | {␊ |
2118 | ␉long length, pos;␊ |
2119 | ␉TagPtr moduleDict, prop;␊ |
2120 | ␉BundlePtr tmpBundle;␊ |
2121 | ␉␊ |
2122 | pos = 0;␊ |
2123 | ␉DBG("ParseXML\n");␊ |
2124 | ␊ |
2125 | ␉if (!module) {␊ |
2126 | return -1;␊ |
2127 | }␊ |
2128 | ␉␊ |
2129 | while (1)␊ |
2130 | {␊ |
2131 | length = XMLParseNextTag(buffer + pos, &moduleDict);␊ |
2132 | if (length == -1) break;␊ |
2133 | ␉␉␊ |
2134 | pos += length;␊ |
2135 | ␉␉␊ |
2136 | if (moduleDict == 0) continue;␊ |
2137 | if (moduleDict->type == kTagTypeDict) break;␊ |
2138 | ␉␉␊ |
2139 | XMLFreeTag(moduleDict);␊ |
2140 | }␊ |
2141 | ␉␊ |
2142 | if (length == -1) ␊ |
2143 | {␊ |
2144 | return -1;␊ |
2145 | }␊ |
2146 | ␉␊ |
2147 | ␊ |
2148 | tmpBundle = malloc(sizeof(Bundle));␊ |
2149 | if (tmpBundle == 0)␊ |
2150 | {␊ |
2151 | XMLFreeTag(moduleDict);␊ |
2152 | return -1;␊ |
2153 | }␊ |
2154 | ␉bzero(tmpBundle, sizeof(Bundle));␊ |
2155 | ␉␊ |
2156 | tmpBundle->dict = moduleDict;␊ |
2157 | ␊ |
2158 | do {␊ |
2159 | prop = XMLGetProperty(moduleDict, kPropOSBundleEnabled);␊ |
2160 | if ((prop != 0) && prop->string)␊ |
2161 | {␊ |
2162 | if ( (strlen(prop->string) >= 1) && (prop->string[0] == 'N' || prop->string[0] == 'n') )␊ |
2163 | {␊ |
2164 | tmpBundle->willLoad = 0;␊ |
2165 | break;␊ |
2166 | }␊ |
2167 | }␊ |
2168 | prop = XMLGetProperty(moduleDict, kPropNSPrincipalClass);␊ |
2169 | if ((prop != 0) && prop->string)␊ |
2170 | {␊ |
2171 | if (!strncmp(prop->string,SYSLIB_CLASS, sizeof(SYSLIB_CLASS))) ␊ |
2172 | {␊ |
2173 | tmpBundle->willLoad = BundlePrioritySystemLib;␊ |
2174 | break;␊ |
2175 | }␊ |
2176 | if (!strncmp(prop->string,SYS_CLASS, sizeof(SYS_CLASS))) ␊ |
2177 | {␊ |
2178 | tmpBundle->willLoad = BundlePrioritySystem;␊ |
2179 | break;␊ |
2180 | }␊ |
2181 | } ␊ |
2182 | ␊ |
2183 | prop = XMLGetProperty(moduleDict, kPropOSBundlePriority);␊ |
2184 | if ((prop != 0) && prop->string)␊ |
2185 | {␊ |
2186 | int tmpwillLoad;␊ |
2187 | if ((tmpwillLoad = strtoul(prop->string, NULL, 10)) > BundlePrioritySystemLib )␊ |
2188 | { ␊ |
2189 | tmpBundle->willLoad = MIN(tmpwillLoad, BundlePriorityLowestPriority);␊ |
2190 | break;␊ |
2191 | ␊ |
2192 | }␊ |
2193 | ␊ |
2194 | }␊ |
2195 | ␉␉␊ |
2196 | tmpBundle->willLoad = BundlePriorityNormalPriority;␊ |
2197 | ␉␉␊ |
2198 | #if 0␊ |
2199 | ␉␉prop = XMLGetProperty(moduleDict, kPropCFBundleLocalizations);␊ |
2200 | if ((prop != 0) && prop->string)␊ |
2201 | {␊ |
2202 | ␉␉␉char * path = newStringWithFormat("%s%s",module->bundlePath,prop->string);␊ |
2203 | ␉␉␉if (path == NULL) {␊ |
2204 | ␉␉␉␉break;␊ |
2205 | ␉␉␉}␊ |
2206 | ␉␉␉␊ |
2207 | if (loadConfigFile(path, module->LanguageConfig) != 0)␊ |
2208 | ␉␉␉{␊ |
2209 | ␉␉␉␉free(path);␊ |
2210 | ␉␉␉␉path = NULL;␊ |
2211 | ␉␉␉␉␊ |
2212 | ␉␉␉␉const char * default_local;␊ |
2213 | ␉␉␉␉if ((default_local = getStringForKey(kPropCFBundleLocalizations, DEFAULT_BOOT_CONFIG))) ␊ |
2214 | ␉␉␉␉{␊ |
2215 | ␉␉␉␉␉path = newStringWithFormat("%s%s",module->bundlePath,default_local);␊ |
2216 | ␉␉␉␉␉if (path == NULL) {␊ |
2217 | ␉␉␉␉␉␉break;␊ |
2218 | ␉␉␉␉␉}␊ |
2219 | ␉␉␉␉␉loadConfigFile(path, module->LanguageConfig);␊ |
2220 | ␉␉␉␉}␊ |
2221 | ␉␉␉␉␊ |
2222 | ␉␉␉}␊ |
2223 | ␉␉␉␊ |
2224 | ␉␉␉if (path) {␊ |
2225 | ␉␉␉␉free(path);␊ |
2226 | ␉␉␉} ␊ |
2227 | }␊ |
2228 | #endif␊ |
2229 | ␊ |
2230 | } while (0);␊ |
2231 | ␊ |
2232 | // Get the personalities.␊ |
2233 | tmpBundle->personalities = XMLGetProperty(moduleDict, kPropIOKitPersonalities);␊ |
2234 | ␊ |
2235 | *module = tmpBundle;␊ |
2236 | ␉␊ |
2237 | ␉␊ |
2238 | ␉␊ |
2239 | return 0;␊ |
2240 | }␊ |
2241 | |