Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/iFabio/Chameleon/i386/boot2/modules.c

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

Archive Download this file

Revision: 307