Chameleon

Chameleon Svn Source Tree

Root/branches/meklortOld/i386/boot2/modules.c

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

Archive Download this file

Revision: 1146