Chameleon

Chameleon Svn Source Tree

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

Source at commit 426 created 13 years 10 months ago.
By azimutz, Doc edit. CHANGES.txt and README.txt are final for now, though README can suffer changes at any time, since it's an introduction file. On to FileLoad.txt and TODO.txt.
1/*
2 * Copyright 2010 Evan Lojewski. All rights reserved.
3 *
4 */
5
6#include "boot.h"
7#include "bootstruct.h"
8#include "multiboot.h"
9#include "modules.h"
10
11
12moduleList_t* loadedModules = NULL;
13symbolList_t* moduleSymbols = NULL;
14unsigned int (*lookup_symbol)(const char*) = NULL;
15
16
17void rebase_macho(void* base, char* rebase_stream, UInt32 size);
18void bind_macho(void* base, char* bind_stream, UInt32 size);
19
20
21/*
22 * Initialize the module system by loading the Symbols.dylib module.
23 * Once laoded, locate the _lookup_symbol function so that internal
24 * symbols can be resolved.
25 */
26int init_module_system()
27{
28// Intialize module system
29if(load_module(SYMBOLS_MODULE))
30{
31lookup_symbol = (void*)lookup_all_symbols("_lookup_symbol");
32}
33
34if((UInt32)lookup_symbol == 0xFFFFFFFF)
35{
36return 0;
37}
38else
39{
40return 1;
41}
42}
43
44/*
45 * Load all modules in the /Extra/modules/ directory
46 * Module depencdies will be loaded first
47 * MOdules will only be loaded once. When loaded a module must
48 * setup apropriete function calls and hooks as required.
49 * NOTE: To ensure a module loads after another you may
50 * link one module with the other. For dyld to allow this, you must
51 * reference at least one symbol within the module.
52 */
53void load_all_modules()
54{
55char* name;
56long flags;
57long time;
58struct dirstuff* moduleDir = opendir("/Extra/modules/");
59while(readdir(moduleDir, (const char**)&name, &flags, &time) >= 0)
60{
61// TODO: verify ends in .dylib
62if(strlen(name) > sizeof(".dylib"))
63{
64name[strlen(name) - sizeof(".dylib")] = 0;
65load_module(name);
66}
67}
68}
69
70
71/*
72 * Load a module file in /Extra/modules
73 * TODO: verify version number of module
74 */
75int load_module(const char* module)
76{
77// Check to see if the module has already been loaded
78if(is_module_laoded(module))
79{
80return 1;
81}
82
83char modString[128];
84int fh = -1;
85sprintf(modString, "/Extra/modules/%s.dylib", module);
86fh = open(modString, 0);
87if(fh < 0)
88{
89printf("Unable to locate module %s\n", modString);
90getc();
91return 0;
92}
93
94unsigned int moduleSize = file_size(fh);
95char* module_base = (char*) malloc(moduleSize);
96if (read(fh, module_base, moduleSize) == moduleSize)
97{
98void (*module_start)(void) = NULL;
99
100printf("Module %s read in.\n", modString);
101
102// Module loaded into memory, parse it
103module_start = parse_mach(module_base);
104
105if(module_start)
106{
107(*module_start)();// Start the module
108printf("Module started\n");
109}
110else {
111printf("Unabel to locate module start\n");
112}
113
114
115getc();
116
117// TODO: Add module to loaded list if loaded successfuly
118
119}
120else
121{
122printf("Unable to read in module %s.dylib\n.", module);
123getc();
124}
125return 1;
126}
127
128/*
129 * Parse through a macho module. The module will be rebased and binded
130 * as specified in the macho header. If the module is sucessfuly laoded
131 * the module iinit address will be returned.
132 * NOTE; all dependecies will be loaded before this module is started
133 * NOTE: If the module is unable to load ot completeion, the modules
134 * symbols will still be available (TODO: fix this). This should not
135 * happen as all dependencies are verified before the sybols are read in.
136 */
137void* parse_mach(void* binary)
138{
139void (*module_start)(void) = NULL;
140
141// Module info
142char* moduleName = NULL;
143UInt32 moduleVersion = 0;
144UInt32 moduleCompat = 0;
145
146char* symbolStub = NULL;
147char* nonlazy = NULL;
148//char* nonlazy_variables = NULL;
149
150// TODO convert all of the structs to a union
151struct load_command *loadCommand = NULL;
152struct dylib_command* dylibCommand = NULL;
153struct dyld_info_command* dyldInfoCommand = NULL;
154struct symtab_command* symtabCommand = NULL;
155struct segment_command* segmentCommand = NULL;
156//struct dysymtab_command* dysymtabCommand = NULL;
157struct section* section = NULL;
158UInt32 binaryIndex = sizeof(struct mach_header);
159UInt16 cmd = 0;
160
161// Parse through the load commands
162if(((struct mach_header*)binary)->magic != MH_MAGIC)
163{
164printf("Module is not 32bit\n");
165return NULL;// 32bit only
166}
167
168if(((struct mach_header*)binary)->filetype != MH_DYLIB)
169{
170printf("Module is not a dylib. Unable to load.\n");
171return NULL; // Module is in the incorrect format
172}
173
174while(cmd < ((struct mach_header*)binary)->ncmds)// TODO: for loop instead
175{
176cmd++;
177
178loadCommand = binary + binaryIndex;
179UInt32 cmdSize = loadCommand->cmdsize;
180
181
182switch ((loadCommand->cmd & 0x7FFFFFFF))
183{
184case LC_SYMTAB:
185symtabCommand = binary + binaryIndex;
186break;
187case LC_SEGMENT:
188segmentCommand = binary + binaryIndex;
189
190UInt32 sections = segmentCommand->nsects;
191section = binary + binaryIndex + sizeof(struct segment_command);
192
193// Loop untill needed variables are found
194while(!(nonlazy && symbolStub) && sections)
195{
196// Look for some sections and save the addresses
197if(strcmp(section->sectname, SECT_NON_LAZY_SYMBOL_PTR) == 0)
198{
199/*printf("\tSection non lazy pointers at 0x%X, %d symbols\n",
200 section->offset,
201 section->size / 4);
202*/
203switch(section->flags)
204{
205case S_NON_LAZY_SYMBOL_POINTERS:
206//printf("%s S_NON_LAZY_SYMBOL_POINTERS section\n", SECT_NON_LAZY_SYMBOL_PTR);
207
208//nonlazy_variables = binary + section->offset;
209nonlazy = binary + section->offset;
210break;
211
212case S_LAZY_SYMBOL_POINTERS:
213//nonlazy = binary + section->offset;
214//printf("%s S_LAZY_SYMBOL_POINTERS section, 0x%X\n", SECT_NON_LAZY_SYMBOL_PTR, nonlazy);
215// Fucntions
216break;
217
218default:
219//printf("Unhandled %s section\n", SECT_NON_LAZY_SYMBOL_PTR);
220//getc();
221break;
222}
223//getc();
224}
225else if(strcmp(section->sectname, SECT_SYMBOL_STUBS) == 0)
226{
227symbolStub = binary + section->offset;
228}
229/*
230else
231{
232printf("Unhandled section %s\n", section->sectname);
233}
234*/
235sections--;
236section++;
237}
238
239
240break;
241
242case LC_DYSYMTAB:
243//dysymtabCommand = binary + binaryIndex;
244//printf("Unhandled loadcommand LC_DYSYMTAB\n");
245break;
246
247case LC_LOAD_DYLIB:
248case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:
249dylibCommand = binary + binaryIndex;
250char* module = binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));
251// TODO: verify version
252// =dylibCommand->dylib.current_version;
253// =dylibCommand->dylib.compatibility_version;
254
255if(!load_module(module))
256{
257// Unable to load dependancy
258return NULL;
259}
260break;
261
262case LC_ID_DYLIB:
263dylibCommand = binary + binaryIndex;
264moduleName =binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));
265moduleVersion =dylibCommand->dylib.current_version;
266moduleCompat =dylibCommand->dylib.compatibility_version;
267break;
268
269case LC_DYLD_INFO:
270// Bind and rebase info is stored here
271dyldInfoCommand = binary + binaryIndex;
272break;
273
274case LC_UUID:
275break;
276
277default:
278printf("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF);
279break;
280
281}
282
283binaryIndex += cmdSize;
284}
285if(!moduleName) return NULL;
286
287
288// bind_macho uses the symbols added in for some reason...
289module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbolStub, (UInt32)nonlazy);
290
291// REbase the module before binding it.
292if(dyldInfoCommand && dyldInfoCommand->rebase_off)
293{
294rebase_macho(binary, (char*)dyldInfoCommand->rebase_off, dyldInfoCommand->rebase_size);
295}
296
297if(dyldInfoCommand && dyldInfoCommand->bind_off)
298{
299bind_macho(binary, (char*)dyldInfoCommand->bind_off, dyldInfoCommand->bind_size);
300}
301
302if(dyldInfoCommand && dyldInfoCommand->weak_bind_off)
303{
304// NOTE: this currently should never happen.
305bind_macho(binary, (char*)dyldInfoCommand->weak_bind_off, dyldInfoCommand->weak_bind_size);
306}
307
308if(dyldInfoCommand && dyldInfoCommand->lazy_bind_off)
309{
310// NOTE: we are binding the lazy pointers as a module is laoded,
311// This should be cahnged to bund when a symbol is referened at runtime.
312bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size);
313}
314
315
316
317
318// Notify the system that it was laoded
319module_loaded(moduleName, moduleVersion, moduleCompat);
320
321return module_start;
322
323}
324
325
326// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
327void rebase_macho(void* base, char* rebase_stream, UInt32 size)
328{
329rebase_stream += (UInt32)base;
330
331UInt8 immediate = 0;
332UInt8 opcode = 0;
333UInt8 type = 0;
334
335UInt32 segmentAddress = 0;
336
337
338
339UInt32 tmp = 0;
340UInt32 tmp2 = 0;
341UInt8 bits = 0;
342int index = 0;
343
344int done = 0;
345unsigned int i = 0;
346
347while(/*!done &&*/ i < size)
348{
349immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;
350opcode = rebase_stream[i] & REBASE_OPCODE_MASK;
351
352
353switch(opcode)
354{
355case REBASE_OPCODE_DONE:
356// Rebase complete.
357done = 1;
358break;
359
360
361case REBASE_OPCODE_SET_TYPE_IMM:
362// Set rebase type (pointer, absolute32, pcrel32)
363//printf("Rebase type = 0x%X\n", immediate);
364// NOTE: This is currently NOT used
365type = immediate;
366break;
367
368
369case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
370// Locate address to begin rebasing
371segmentAddress = 0;
372
373struct segment_command* segCommand = NULL;
374
375unsigned int binIndex = 0;
376index = 0;
377do
378{
379segCommand = base + sizeof(struct mach_header) + binIndex;
380
381
382binIndex += segCommand->cmdsize;
383index++;
384}
385while(index <= immediate);
386
387
388segmentAddress = segCommand->fileoff;
389
390tmp = 0;
391bits = 0;
392do
393{
394tmp |= (rebase_stream[++i] & 0x7f) << bits;
395bits += 7;
396}
397while(rebase_stream[i] & 0x80);
398
399segmentAddress += tmp;
400break;
401
402
403case REBASE_OPCODE_ADD_ADDR_ULEB:
404// Add value to rebase address
405tmp = 0;
406bits = 0;
407do
408{
409tmp <<= bits;
410tmp |= rebase_stream[++i] & 0x7f;
411bits += 7;
412}
413while(rebase_stream[i] & 0x80);
414
415segmentAddress +=tmp;
416break;
417
418case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
419segmentAddress += immediate * sizeof(void*);
420break;
421
422
423case REBASE_OPCODE_DO_REBASE_IMM_TIMES:
424index = 0;
425for (index = 0; index < immediate; ++index) {
426rebase_location(base + segmentAddress, (char*)base);
427segmentAddress += sizeof(void*);
428}
429break;
430
431
432case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
433tmp = 0;
434bits = 0;
435do
436{
437tmp |= (rebase_stream[++i] & 0x7f) << bits;
438bits += 7;
439}
440while(rebase_stream[i] & 0x80);
441
442index = 0;
443for (index = 0; index < tmp; ++index) {
444//printf("\tRebasing 0x%X\n", segmentAddress);
445rebase_location(base + segmentAddress, (char*)base);
446segmentAddress += sizeof(void*);
447}
448break;
449
450case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
451tmp = 0;
452bits = 0;
453do
454{
455tmp |= (rebase_stream[++i] & 0x7f) << bits;
456bits += 7;
457}
458while(rebase_stream[i] & 0x80);
459
460rebase_location(base + segmentAddress, (char*)base);
461
462segmentAddress += tmp + sizeof(void*);
463break;
464
465case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
466tmp = 0;
467bits = 0;
468do
469{
470tmp |= (rebase_stream[++i] & 0x7f) << bits;
471bits += 7;
472}
473while(rebase_stream[i] & 0x80);
474
475
476tmp2 = 0;
477bits = 0;
478do
479{
480tmp2 |= (rebase_stream[++i] & 0x7f) << bits;
481bits += 7;
482}
483while(rebase_stream[i] & 0x80);
484
485index = 0;
486for (index = 0; index < tmp; ++index) {
487rebase_location(base + segmentAddress, (char*)base);
488
489segmentAddress += tmp2 + sizeof(void*);
490}
491break;
492}
493i++;
494}
495}
496
497// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
498// NOTE: this uses 32bit values, and not 64bit values.
499// There is apossibility that this could cause issues,
500// however the macho file is 32 bit, so it shouldn't matter too much
501void bind_macho(void* base, char* bind_stream, UInt32 size)
502{
503bind_stream += (UInt32)base;
504
505UInt8 immediate = 0;
506UInt8 opcode = 0;
507UInt8 type = 0;
508
509UInt32 segmentAddress = 0;
510
511UInt32 address = 0;
512
513SInt32 addend = 0;// TODO: handle this
514SInt32 libraryOrdinal = 0;
515
516const char* symbolName = NULL;
517UInt8 symboFlags = 0;
518UInt32 symbolAddr = 0xFFFFFFFF;
519
520// Temperary variables
521UInt8 bits = 0;
522UInt32 tmp = 0;
523UInt32 tmp2 = 0;
524
525UInt32 index = 0;
526int done = 0;
527unsigned int i = 0;
528
529while(/*!done &&*/ i < size)
530{
531immediate = bind_stream[i] & BIND_IMMEDIATE_MASK;
532opcode = bind_stream[i] & BIND_OPCODE_MASK;
533
534
535switch(opcode)
536{
537case BIND_OPCODE_DONE:
538done = 1;
539break;
540
541case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
542libraryOrdinal = immediate;
543//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);
544break;
545
546case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
547libraryOrdinal = 0;
548bits = 0;
549do
550{
551libraryOrdinal |= (bind_stream[++i] & 0x7f) << bits;
552bits += 7;
553}
554while(bind_stream[i] & 0x80);
555
556//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);
557
558break;
559
560case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
561// NOTE: this is wrong, fortunately we don't use it
562libraryOrdinal = -immediate;
563//printf("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);
564
565break;
566
567case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
568symboFlags = immediate;
569symbolName = (char*)&bind_stream[++i];
570i += strlen((char*)&bind_stream[i]);
571//printf("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symboFlags);
572
573symbolAddr = lookup_all_symbols(symbolName);
574
575break;
576
577case BIND_OPCODE_SET_TYPE_IMM:
578// Set bind type (pointer, absolute32, pcrel32)
579type = immediate;
580//printf("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);
581
582break;
583
584case BIND_OPCODE_SET_ADDEND_SLEB:
585addend = 0;
586bits = 0;
587do
588{
589addend |= (bind_stream[++i] & 0x7f) << bits;
590bits += 7;
591}
592while(bind_stream[i] & 0x80);
593
594if(!(bind_stream[i-1] & 0x40)) addend *= -1;
595
596//printf("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);
597break;
598
599case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
600segmentAddress = 0;
601
602// Locate address
603struct segment_command* segCommand = NULL;
604
605unsigned int binIndex = 0;
606index = 0;
607do
608{
609segCommand = base + sizeof(struct mach_header) + binIndex;
610binIndex += segCommand->cmdsize;
611index++;
612}
613while(index <= immediate);
614
615segmentAddress = segCommand->fileoff;
616
617// Read in offset
618tmp = 0;
619bits = 0;
620do
621{
622tmp |= (bind_stream[++i] & 0x7f) << bits;
623bits += 7;
624}
625while(bind_stream[i] & 0x80);
626
627segmentAddress += tmp;
628
629//printf("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress);
630break;
631
632case BIND_OPCODE_ADD_ADDR_ULEB:
633// Read in offset
634tmp = 0;
635bits = 0;
636do
637{
638tmp |= (bind_stream[++i] & 0x7f) << bits;
639bits += 7;
640}
641while(bind_stream[i] & 0x80);
642
643segmentAddress += tmp;
644//printf("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);
645break;
646
647case BIND_OPCODE_DO_BIND:
648//printf("BIND_OPCODE_DO_BIND\n");
649if(symbolAddr != 0xFFFFFFFF)
650{
651address = segmentAddress + (UInt32)base;
652
653((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;
654((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;
655((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;
656((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;
657}
658else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)
659{
660printf("Unable to bind symbol %s\n", symbolName);
661}
662
663segmentAddress += sizeof(void*);
664break;
665
666case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
667//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");
668
669
670// Read in offset
671tmp = 0;
672bits = 0;
673do
674{
675tmp |= (bind_stream[++i] & 0x7f) << bits;
676bits += 7;
677}
678while(bind_stream[i] & 0x80);
679
680
681
682if(symbolAddr != 0xFFFFFFFF)
683{
684address = segmentAddress + (UInt32)base;
685
686((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;
687((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;
688((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;
689((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;
690}
691else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)
692{
693printf("Unable to bind symbol %s\n", symbolName);
694}
695segmentAddress += tmp + sizeof(void*);
696
697
698break;
699
700case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
701//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");
702
703if(symbolAddr != 0xFFFFFFFF)
704{
705address = segmentAddress + (UInt32)base;
706
707((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;
708((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;
709((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;
710((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;
711}
712else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)
713{
714printf("Unable to bind symbol %s\n", symbolName);
715}
716segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);
717
718
719break;
720
721case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
722
723tmp = 0;
724bits = 0;
725do
726{
727tmp |= (bind_stream[++i] & 0x7f) << bits;
728bits += 7;
729}
730while(bind_stream[i] & 0x80);
731
732
733tmp2 = 0;
734bits = 0;
735do
736{
737tmp2 |= (bind_stream[++i] & 0x7f) << bits;
738bits += 7;
739}
740while(bind_stream[i] & 0x80);
741
742
743//printf("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);
744
745
746if(symbolAddr != 0xFFFFFFFF)
747{
748for(index = 0; index < tmp; index++)
749{
750
751address = segmentAddress + (UInt32)base;
752
753((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;
754((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;
755((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;
756((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;
757
758segmentAddress += tmp2 + sizeof(void*);
759}
760}
761else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)
762{
763printf("Unable to bind symbol %s\n", symbolName);
764}
765
766
767break;
768
769}
770i++;
771}
772}
773
774inline void rebase_location(UInt32* location, char* base)
775{
776*location += (UInt32)base;
777}
778
779/*
780 * add_symbol
781 * This function adds a symbol from a module to the list of known symbols
782 * possibly change to a pointer and add this to the Symbol module so that it can
783 * adjust it's internal symbol list (sort) to optimize locating new symbols
784 */
785void add_symbol(char* symbol, void* addr)
786{
787symbolList_t* entry;
788//printf("Adding symbol %s at 0x%X\n", symbol, addr);
789
790if(!moduleSymbols)
791{
792moduleSymbols = entry = malloc(sizeof(symbolList_t));
793
794}
795else
796{
797entry = moduleSymbols;
798while(entry->next)
799{
800entry = entry->next;
801}
802
803entry->next = malloc(sizeof(symbolList_t));
804entry = entry->next;
805}
806
807entry->next = NULL;
808entry->addr = (unsigned int)addr;
809entry->symbol = symbol;
810}
811
812
813/*
814 * print out the information about the loaded module
815
816 */
817void module_loaded(char* name, UInt32 version, UInt32 compat)
818{
819moduleList_t* entry;
820/*
821printf("\%s.dylib Version %d.%d.%d loaded\n"
822 "\tCompatibility Version: %d.%d.%d\n",
823 name,
824 (version >> 16) & 0xFFFF,
825 (version >> 8) & 0x00FF,
826 (version >> 0) & 0x00FF,
827 (compat >> 16) & 0xFFFF,
828 (compat >> 8) & 0x00FF,
829 (compat >> 0) & 0x00FF);
830*/
831if(loadedModules == NULL)
832{
833loadedModules = entry = malloc(sizeof(moduleList_t));
834}
835else
836{
837entry = loadedModules;
838while(entry->next)
839{
840entry = entry->next;
841}
842entry->next = malloc(sizeof(moduleList_t));
843entry = entry->next;
844}
845
846entry->next = NULL;
847entry->module = name;
848entry->version = version;
849entry->compat = compat;
850
851
852}
853
854int is_module_laoded(const char* name)
855{
856moduleList_t* entry = loadedModules;
857while(entry)
858{
859if(strcmp(entry->module, name) == 0)
860{
861return 1;
862}
863else
864{
865entry = entry->next;
866}
867
868}
869return 0;
870}
871
872// Look for symbols using the Smbols moduel function.
873// If non are found, look through the list of module symbols
874unsigned int lookup_all_symbols(const char* name)
875{
876unsigned int addr = 0xFFFFFFFF;
877if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF)
878{
879addr = lookup_symbol(name);
880if(addr != 0xFFFFFFFF)
881{
882//printf("Internal symbol %s located at 0x%X\n", name, addr);
883return addr;
884}
885}
886
887
888symbolList_t* entry = moduleSymbols;
889while(entry)
890{
891if(strcmp(entry->symbol, name) == 0)
892{
893//printf("External symbol %s located at 0x%X\n", name, entry->addr);
894return entry->addr;
895}
896else
897{
898entry = entry->next;
899}
900
901}
902if(strcmp(name, SYMBOL_DYLD_STUB_BINDER) != 0)
903{
904printf("Unable to locate symbol %s\n", name);
905}
906return 0xFFFFFFFF;
907}
908
909
910/*
911 * parse the symbol table
912 * Lookup any undefined symbols
913 */
914
915unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, char* symbolStub, UInt32 nonlazy)
916{
917unsigned int module_start = 0xFFFFFFFF;
918
919UInt32 symbolIndex = 0;
920char* symbolString = base + (char*)symtabCommand->stroff;
921//char* symbolTable = base + symtabCommand->symoff;
922
923while(symbolIndex < symtabCommand->nsyms)
924{
925
926struct nlist* symbolEntry = (void*)base + symtabCommand->symoff + (symbolIndex * sizeof(struct nlist));
927
928// If the symbol is exported by this module
929if(symbolEntry->n_value)
930{
931if(strcmp(symbolString + symbolEntry->n_un.n_strx, "start") == 0)
932{
933// Module start located. Start is an alias so don't register it
934module_start = base + symbolEntry->n_value;
935}
936else
937{
938add_symbol(symbolString + symbolEntry->n_un.n_strx, (void*)base + symbolEntry->n_value);
939}
940}
941
942symbolEntry+= sizeof(struct nlist);
943symbolIndex++;// TODO remove
944}
945
946return module_start;
947
948}
949
950
951/*
952 * Locate the symbol for an already loaded function and modify the beginning of
953 * the function to jump directly to the new one
954 * example: replace_function("_HelloWorld_start", &replacement_start);
955 */
956int replace_function(const char* symbol, void* newAddress)
957{
958UInt32* jumpPointer = malloc(sizeof(UInt32*));
959// TODO: look into using the next four bytes of the function instead
960// Most functions should support this, as they probably will be at
961// least 10 bytes long, but you never know, this is sligtly saver as
962// function can be as small as 6 bytes.
963UInt32 addr = lookup_all_symbols(symbol);
964
965char* binary = (char*)addr;
966if(addr != 0xFFFFFFFF)
967{
968*binary++ = 0xFF;// Jump
969*binary++ = 0x25;// Long Jump
970*((UInt32*)binary) = (UInt32)jumpPointer;
971
972*jumpPointer = (UInt32)newAddress;
973
974return 1;
975}
976else
977{
978return 0;
979}
980
981}

Archive Download this file

Revision: 426