Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 339