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

Archive Download this file

Revision: 1025