Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/i386/boot2/modules.c

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

Archive Download this file

Revision: 818