Chameleon

Chameleon Svn Source Tree

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

Source at commit 363 created 13 years 8 months ago.
By meklort, Cleaned up some code, added comments
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: 363