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 0
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{
343//Azi: this is double printing when using kernelcache - that's new!
344verbose("Invalid mach magic 0x%X\n", ((struct mach_header*)binary)->magic);
345//getc();
346return NULL;
347}
348
349
350
351/*if(((struct mach_header*)binary)->filetype != MH_DYLIB)
352 {
353 printf("Module is not a dylib. Unable to load.\n");
354 getc();
355 return NULL; // Module is in the incorrect format
356 }*/
357
358while(cmd < ((struct mach_header*)binary)->ncmds)
359{
360cmd++;
361
362loadCommand = binary + binaryIndex;
363UInt32 cmdSize = loadCommand->cmdsize;
364
365
366switch ((loadCommand->cmd & 0x7FFFFFFF))
367{
368case LC_SYMTAB:
369symtabCommand = binary + binaryIndex;
370break;
371
372case LC_SEGMENT: // 32bit macho
373segCommand = binary + binaryIndex;
374
375if(strcmp("__TEXT", segCommand->segname) == 0)
376{
377UInt32 sectionIndex;
378
379sectionIndex = sizeof(struct segment_command);
380
381struct section *sect;
382
383while(sectionIndex < segCommand->cmdsize)
384{
385sect = binary + binaryIndex + sectionIndex;
386
387sectionIndex += sizeof(struct section);
388
389
390if(strcmp("__text", sect->sectname) == 0)
391{
392// __TEXT,__text found, save the offset and address for when looking for the calls.
393textSection = sect->offset;
394textAddress = sect->addr;
395break;
396}
397}
398}
399
400break;
401case LC_SEGMENT_64:// 64bit macho's
402segCommand64 = binary + binaryIndex;
403if(strcmp("__TEXT", segCommand64->segname) == 0)
404{
405UInt32 sectionIndex;
406
407sectionIndex = sizeof(struct segment_command_64);
408
409struct section_64 *sect;
410
411while(sectionIndex < segCommand64->cmdsize)
412{
413sect = binary + binaryIndex + sectionIndex;
414
415sectionIndex += sizeof(struct section_64);
416
417
418if(strcmp("__text", sect->sectname) == 0)
419{
420// __TEXT,__text found, save the offset and address for when looking for the calls.
421textSection = sect->offset;
422textAddress = sect->addr;
423
424break;
425}
426}
427}
428
429break;
430
431
432case LC_LOAD_DYLIB:
433case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:
434dylibCommand = binary + binaryIndex;
435char* module = binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));
436// Possible enhancments: verify version
437// =dylibCommand->dylib.current_version;
438// =dylibCommand->dylib.compatibility_version;
439if(dylib_loader)
440{
441char* name = malloc(strlen(module) + strlen(".dylib") + 1);
442sprintf(name, "%s.dylib", module);
443
444if (!dylib_loader(name))
445{
446// NOTE: any symbols exported by dep will be replace with the void function
447free(name);
448}
449}
450
451break;
452
453case LC_ID_DYLIB:
454dylibCommand = binary + binaryIndex;
455/*moduleName =binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));
456 moduleVersion =dylibCommand->dylib.current_version;
457 moduleCompat =dylibCommand->dylib.compatibility_version;
458 */
459break;
460
461case LC_DYLD_INFO:
462//case LC_DYLD_INFO_ONLY:// compressed info, 10.6+ macho files, already handeled
463// Bind and rebase info is stored here
464dyldInfoCommand = binary + binaryIndex;
465break;
466
467case LC_DYSYMTAB:
468case LC_UUID:
469case LC_UNIXTHREAD:
470break;
471
472default:
473DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);
474break;
475
476}
477
478binaryIndex += cmdSize;
479}
480
481// bind_macho uses the symbols, if the textAdd does not exist (Symbols.dylib, no code), addresses are static and not relative
482module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbol_handler, is64);
483
484if(dyldInfoCommand)
485{
486// Rebase the module before binding it.
487if(dyldInfoCommand->rebase_off)rebase_macho(binary, (char*)dyldInfoCommand->rebase_off,dyldInfoCommand->rebase_size);
488// Bind all symbols.
489if(dyldInfoCommand->bind_off)bind_macho(binary, (char*)dyldInfoCommand->bind_off,dyldInfoCommand->bind_size);
490if(dyldInfoCommand->weak_bind_off)bind_macho(binary, (char*)dyldInfoCommand->weak_bind_off,dyldInfoCommand->weak_bind_size);
491if(dyldInfoCommand->lazy_bind_off)bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off,dyldInfoCommand->lazy_bind_size);
492}
493
494return module_start;
495
496}
497
498/*
499 * parse the symbol table
500 * Lookup any undefined symbols
501 */
502
503unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, long long, char), char is64)
504{
505unsigned int module_start= 0xFFFFFFFF;
506UInt32 symbolIndex= 0;
507char* symbolString= base + (char*)symtabCommand->stroff;
508
509if(!is64)
510{
511struct nlist* symbolEntry = (void*)base + symtabCommand->symoff;
512while(symbolIndex < symtabCommand->nsyms)
513{
514// If the symbol is exported by this module
515if(symbolEntry->n_value &&
516 symbol_handler(symbolString + symbolEntry->n_un.n_strx, textAddress ? (long long)base + symbolEntry->n_value : symbolEntry->n_value, is64) != 0xFFFFFFFF)
517{
518
519// Module start located. Start is an alias so don't register it
520module_start = textAddress ? base + symbolEntry->n_value : symbolEntry->n_value;
521}
522
523symbolEntry++;
524symbolIndex++;// TODO remove
525}
526}
527else
528{
529struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff;
530// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now, verify later)
531while(symbolIndex < symtabCommand->nsyms)
532{
533
534
535// If the symbol is exported by this module
536if(symbolEntry->n_value &&
537 symbol_handler(symbolString + symbolEntry->n_un.n_strx, textAddress ? (long long)base + symbolEntry->n_value : symbolEntry->n_value, is64) != 0xFFFFFFFF)
538{
539
540// Module start located. Start is an alias so don't register it
541module_start = textAddress ? base + symbolEntry->n_value : symbolEntry->n_value;
542}
543
544symbolEntry++;
545symbolIndex++;// TODO remove
546}
547}
548return module_start;
549}
550
551// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
552void rebase_macho(void* base, char* rebase_stream, UInt32 size)
553{
554rebase_stream += (UInt32)base;
555
556UInt8 immediate = 0;
557UInt8 opcode = 0;
558UInt8 type = 0;
559UInt32 segmentAddress = 0;
560
561
562UInt32 tmp = 0;
563UInt32 tmp2 = 0;
564UInt8 bits = 0;
565int index = 0;
566unsigned int i = 0;
567
568while(i < size)
569{
570immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;
571opcode = rebase_stream[i] & REBASE_OPCODE_MASK;
572
573
574switch(opcode)
575{
576case REBASE_OPCODE_DONE:
577// Rebase complete, reset vars
578immediate = 0;
579opcode = 0;
580type = 0;
581segmentAddress = 0;
582default:
583break;
584
585
586case REBASE_OPCODE_SET_TYPE_IMM:
587type = immediate;
588break;
589
590
591case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
592// Locate address to begin rebasing
593segmentAddress = 0;
594struct segment_command* segCommand = NULL; // NOTE: 32bit only
595
596unsigned int binIndex = 0;
597index = 0;
598do
599{
600segCommand = base + sizeof(struct mach_header) + binIndex;
601
602
603binIndex += segCommand->cmdsize;
604index++;
605}
606while(index <= immediate);
607
608
609segmentAddress = segCommand->fileoff;
610
611tmp = 0;
612bits = 0;
613do
614{
615tmp |= (rebase_stream[++i] & 0x7f) << bits;
616bits += 7;
617}
618while(rebase_stream[i] & 0x80);
619
620segmentAddress += tmp;
621break;
622
623
624case REBASE_OPCODE_ADD_ADDR_ULEB:
625// Add value to rebase address
626tmp = 0;
627bits = 0;
628do
629{
630tmp <<= bits;
631tmp |= rebase_stream[++i] & 0x7f;
632bits += 7;
633}
634while(rebase_stream[i] & 0x80);
635
636segmentAddress +=tmp;
637break;
638
639case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
640segmentAddress += immediate * sizeof(void*);
641break;
642
643
644case REBASE_OPCODE_DO_REBASE_IMM_TIMES:
645index = 0;
646for (index = 0; index < immediate; ++index) {
647rebase_location(base + segmentAddress, (char*)base, type);
648segmentAddress += sizeof(void*);
649}
650break;
651
652
653case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
654tmp = 0;
655bits = 0;
656do
657{
658tmp |= (rebase_stream[++i] & 0x7f) << bits;
659bits += 7;
660}
661while(rebase_stream[i] & 0x80);
662
663index = 0;
664for (index = 0; index < tmp; ++index) {
665//DBG("\tRebasing 0x%X\n", segmentAddress);
666rebase_location(base + segmentAddress, (char*)base, type);
667segmentAddress += sizeof(void*);
668}
669break;
670
671case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
672tmp = 0;
673bits = 0;
674do
675{
676tmp |= (rebase_stream[++i] & 0x7f) << bits;
677bits += 7;
678}
679while(rebase_stream[i] & 0x80);
680
681rebase_location(base + segmentAddress, (char*)base, type);
682
683segmentAddress += tmp + sizeof(void*);
684break;
685
686case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
687tmp = 0;
688bits = 0;
689do
690{
691tmp |= (rebase_stream[++i] & 0x7f) << bits;
692bits += 7;
693}
694while(rebase_stream[i] & 0x80);
695
696
697tmp2 = 0;
698bits = 0;
699do
700{
701tmp2 |= (rebase_stream[++i] & 0x7f) << bits;
702bits += 7;
703}
704while(rebase_stream[i] & 0x80);
705
706index = 0;
707for (index = 0; index < tmp; ++index) {
708
709rebase_location(base + segmentAddress, (char*)base, type);
710
711segmentAddress += tmp2 + sizeof(void*);
712}
713break;
714}
715i++;
716}
717}
718
719inline void rebase_location(UInt32* location, char* base, int type)
720{
721switch(type)
722{
723case REBASE_TYPE_POINTER:
724case REBASE_TYPE_TEXT_ABSOLUTE32:
725*location += (UInt32)base;
726break;
727
728default:
729break;
730}
731}
732
733
734// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
735// NOTE: this uses 32bit values, and not 64bit values.
736// There is a possibility that this could cause issues,
737// however the modules are 32 bits, so it shouldn't matter too much
738void bind_macho(void* base, char* bind_stream, UInt32 size)
739{
740bind_stream += (UInt32)base;
741
742UInt8 immediate = 0;
743UInt8 opcode = 0;
744UInt8 type = BIND_TYPE_POINTER;
745
746UInt32 segmentAddress = 0;
747
748UInt32 address = 0;
749
750SInt32 addend = 0;
751SInt32 libraryOrdinal = 0;
752
753const char* symbolName = NULL;
754UInt8 symboFlags = 0;
755UInt32 symbolAddr = 0xFFFFFFFF;
756
757// Temperary variables
758UInt8 bits = 0;
759UInt32 tmp = 0;
760UInt32 tmp2 = 0;
761UInt32 index = 0;
762unsigned int i = 0;
763
764while(i < size)
765{
766immediate = bind_stream[i] & BIND_IMMEDIATE_MASK;
767opcode = bind_stream[i] & BIND_OPCODE_MASK;
768
769
770switch(opcode)
771{
772case BIND_OPCODE_DONE:
773// reset vars
774type = BIND_TYPE_POINTER;
775segmentAddress = 0;
776address = 0;
777addend = 0;
778libraryOrdinal = 0;
779symbolAddr = 0xFFFFFFFF;
780default:
781break;
782
783case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
784libraryOrdinal = immediate;
785break;
786
787case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
788libraryOrdinal = 0;
789bits = 0;
790do
791{
792libraryOrdinal |= (bind_stream[++i] & 0x7f) << bits;
793bits += 7;
794}
795while(bind_stream[i] & 0x80);
796break;
797
798case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
799libraryOrdinal = immediate ? (SInt8)(BIND_OPCODE_MASK | immediate) : immediate;
800break;
801
802case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
803symboFlags = immediate;
804symbolName = (char*)&bind_stream[++i];
805i += strlen((char*)&bind_stream[i]);
806
807symbolAddr = lookup_all_symbols(symbolName);
808break;
809
810case BIND_OPCODE_SET_TYPE_IMM:
811type = immediate;
812break;
813
814case BIND_OPCODE_SET_ADDEND_SLEB:
815addend = 0;
816bits = 0;
817do
818{
819addend |= (bind_stream[++i] & 0x7f) << bits;
820bits += 7;
821}
822while(bind_stream[i] & 0x80);
823
824if(!(bind_stream[i-1] & 0x40)) addend *= -1;
825break;
826
827case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
828segmentAddress = 0;
829
830// Locate address
831struct segment_command* segCommand = NULL;// NOTE: 32bit only
832
833unsigned int binIndex = 0;
834index = 0;
835do
836{
837segCommand = base + sizeof(struct mach_header) + binIndex;
838binIndex += segCommand->cmdsize;
839index++;
840}
841while(index <= immediate);
842
843segmentAddress = segCommand->fileoff;
844
845// Read in offset
846tmp = 0;
847bits = 0;
848do
849{
850tmp |= (bind_stream[++i] & 0x7f) << bits;
851bits += 7;
852}
853while(bind_stream[i] & 0x80);
854
855segmentAddress += tmp;
856break;
857
858case BIND_OPCODE_ADD_ADDR_ULEB:
859// Read in offset
860tmp = 0;
861bits = 0;
862do
863{
864tmp |= (bind_stream[++i] & 0x7f) << bits;
865bits += 7;
866}
867while(bind_stream[i] & 0x80);
868
869segmentAddress += tmp;
870break;
871
872case BIND_OPCODE_DO_BIND:
873if(symbolAddr != 0xFFFFFFFF)
874{
875address = segmentAddress + (UInt32)base;
876
877bind_location((UInt32*)address, (char*)symbolAddr, addend, type);
878}
879else
880{
881printf("Unable to bind symbol %s\n", symbolName);
882getc();
883}
884
885segmentAddress += sizeof(void*);
886break;
887
888case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
889// Read in offset
890tmp = 0;
891bits = 0;
892do
893{
894tmp |= (bind_stream[++i] & 0x7f) << bits;
895bits += 7;
896}
897while(bind_stream[i] & 0x80);
898
899if(symbolAddr != 0xFFFFFFFF)
900{
901address = segmentAddress + (UInt32)base;
902
903bind_location((UInt32*)address, (char*)symbolAddr, addend, type);
904}
905else
906{
907printf("Unable to bind symbol %s\n", symbolName);
908getc();
909}
910
911segmentAddress += tmp + sizeof(void*);
912
913
914break;
915
916case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
917if(symbolAddr != 0xFFFFFFFF)
918{
919address = segmentAddress + (UInt32)base;
920
921bind_location((UInt32*)address, (char*)symbolAddr, addend, type);
922}
923else
924{
925printf("Unable to bind symbol %s\n", symbolName);
926getc();
927}
928segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);
929
930
931break;
932
933case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
934tmp = 0;
935bits = 0;
936do
937{
938tmp |= (bind_stream[++i] & 0x7f) << bits;
939bits += 7;
940}
941while(bind_stream[i] & 0x80);
942
943
944tmp2 = 0;
945bits = 0;
946do
947{
948tmp2 |= (bind_stream[++i] & 0x7f) << bits;
949bits += 7;
950}
951while(bind_stream[i] & 0x80);
952
953
954if(symbolAddr != 0xFFFFFFFF)
955{
956for(index = 0; index < tmp; index++)
957{
958
959address = segmentAddress + (UInt32)base;
960bind_location((UInt32*)address, (char*)symbolAddr, addend, type);
961segmentAddress += tmp2 + sizeof(void*);
962}
963}
964else
965{
966printf("Unable to bind symbol %s\n", symbolName);
967getc();
968}
969break;
970}
971i++;
972}
973}
974
975inline void bind_location(UInt32* location, char* value, UInt32 addend, int type)
976{
977// do actual update
978char* newValue = value + addend;
979
980switch (type) {
981case BIND_TYPE_POINTER:
982case BIND_TYPE_TEXT_ABSOLUTE32:
983break;
984
985case BIND_TYPE_TEXT_PCREL32:
986newValue -= ((UInt32)location + 4);
987
988break;
989default:
990return;
991}
992//DBG("Binding 0x%X to 0x%X (was 0x%X)\n", location, newValue, *location);
993*location = (UInt32)newValue;
994}
995
996/********************************************************************************/
997/*Module Hook Interface*/
998/********************************************************************************/
999
1000/*
1001* Locate the symbol for an already loaded function and modify the beginning of
1002* the function to jump directly to the new one
1003* example: replace_function("_HelloWorld_start", &replacement_start);
1004*/
1005int replace_function(const char* symbol, void* newAddress)
1006{
1007UInt32* jumpPointer = malloc(sizeof(UInt32*));
1008UInt32 addr = lookup_all_symbols(symbol);
1009
1010char* binary = (char*)addr;
1011if(addr != 0xFFFFFFFF)
1012{
1013//DBG("Replacing %s to point to 0x%x\n", symbol, newAddress);
1014*binary++ = 0xFF;// Jump
1015*binary++ = 0x25;// Long Jump
1016*((UInt32*)binary) = (UInt32)jumpPointer;
1017
1018*jumpPointer = (UInt32)newAddress;
1019return 1;
1020}
1021return 0;
1022}
1023
1024
1025/*
1026 *execute_hook( const char* name )
1027 *name - Name of the module hook
1028 *If any callbacks have been registered for this hook
1029 *they will be executed now in the same order that the
1030 *hooks were added.
1031*/
1032int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4)
1033{
1034DBG("Attempting to execute hook '%s'\n", name); DBGPAUSE();
1035moduleHook_t* hook = hook_exists(name);
1036
1037if(hook)
1038{
1039// Loop through all callbacks for this module
1040callbackList_t* callbacks = hook->callbacks;
1041
1042while(callbacks)
1043{
1044// Execute callback
1045callbacks->callback(arg1, arg2, arg3, arg4);
1046callbacks = callbacks->next;
1047}
1048DBG("Hook '%s' executed.\n", name); DBGPAUSE();
1049return 1;
1050}
1051else
1052{
1053// Callback for this hook doesn't exist;
1054DBG("No callbacks for '%s' hook.\n", name);
1055return 0;
1056}
1057}
1058
1059
1060
1061/*
1062 *register_hook_callback( const char* name, void(*callback)())
1063 *name - Name of the module hook to attach to.
1064 *callbacks - The funciton pointer that will be called when the
1065 *hook is executed. When registering a new callback name, the callback is added sorted.
1066 *NOTE: the hooks take four void* arguments.
1067 */
1068void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*))
1069{
1070DBG("Adding callback for '%s' hook.\n", name); DBGPAUSE();
1071
1072moduleHook_t* hook = hook_exists(name);
1073
1074if(hook)
1075{
1076// append
1077callbackList_t* newCallback = malloc(sizeof(callbackList_t));
1078newCallback->next = hook->callbacks;
1079hook->callbacks = newCallback;
1080newCallback->callback = callback;
1081}
1082else
1083{
1084// create new hook
1085moduleHook_t* newHook = malloc(sizeof(moduleHook_t));
1086newHook->name = name;
1087newHook->callbacks = malloc(sizeof(callbackList_t));
1088newHook->callbacks->callback = callback;
1089newHook->callbacks->next = NULL;
1090
1091newHook->next = moduleCallbacks;
1092moduleCallbacks = newHook;
1093
1094}
1095
1096#if DEBUG_MODULES
1097//print_hook_list();
1098//getc();
1099#endif
1100
1101}
1102
1103
1104moduleHook_t* hook_exists(const char* name)
1105{
1106moduleHook_t* hooks = moduleCallbacks;
1107
1108// look for a hook. If it exists, return the moduleHook_t*,
1109// If not, return NULL.
1110while(hooks)
1111{
1112if(strcmp(name, hooks->name) == 0)
1113{
1114//DBG("Located hook %s\n", name);
1115return hooks;
1116}
1117hooks = hooks->next;
1118}
1119//DBG("Hook %s does not exist\n", name);
1120return NULL;
1121
1122}
1123
1124#if DEBUG_MODULES
1125void print_hook_list()
1126{
1127printf("---Hook Table---\n");
1128
1129moduleHook_t* hooks = moduleCallbacks;
1130while(hooks)
1131{
1132printf("Hook: %s\n", hooks->name);
1133hooks = hooks->next;
1134}
1135}
1136#endif
1137
1138/********************************************************************************/
1139/*dyld / Linker Interface*/
1140/********************************************************************************/
1141
1142void dyld_stub_binder()
1143{
1144printf("ERROR: dyld_stub_binder was called, should have been take care of by the linker.\n");
1145getc();
1146}
1147

Archive Download this file

Revision: 840