Chameleon Applications

Chameleon Applications Svn Source Tree

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

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

Archive Download this file

Revision: 296