Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 341