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

Archive Download this file

Revision: 815