Chameleon

Chameleon Svn Source Tree

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

Source at commit 359 created 13 years 8 months ago.
By meklort, Used the wrong variable in the rebase function. created a rebase_location function to make the code a little cleaner.
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 * 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 0;
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// Module info
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 to 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;
97//struct dysymtab_command* dysymtabCommand = NULL;
98struct section* section = NULL;
99UInt32 binaryIndex = sizeof(struct mach_header);
100UInt16 cmd = 0;
101
102// Parse through the load 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);
133
134// Loop untill needed variables are found
135while(!(nonlazy && symbolStub) && sections)
136{
137// Look for some sections and save the addresses
138if(strcmp(section->sectname, SECT_NON_LAZY_SYMBOL_PTR) == 0)
139{
140/*printf("\tSection non lazy pointers at 0x%X, %d symbols\n",
141 section->offset,
142 section->size / 4);
143*/
144switch(section->flags)
145{
146case S_NON_LAZY_SYMBOL_POINTERS:
147//printf("%s S_NON_LAZY_SYMBOL_POINTERS section\n", SECT_NON_LAZY_SYMBOL_PTR);
148
149//nonlazy_variables = binary + section->offset;
150nonlazy = binary + section->offset;
151break;
152
153case S_LAZY_SYMBOL_POINTERS:
154//nonlazy = binary + section->offset;
155//printf("%s S_LAZY_SYMBOL_POINTERS section, 0x%X\n", SECT_NON_LAZY_SYMBOL_PTR, nonlazy);
156// Fucntions
157break;
158
159default:
160//printf("Unhandled %s section\n", SECT_NON_LAZY_SYMBOL_PTR);
161//getc();
162break;
163}
164//getc();
165}
166else if(strcmp(section->sectname, SECT_SYMBOL_STUBS) == 0)
167{
168symbolStub = binary + section->offset;
169}
170/*
171else
172{
173printf("Unhandled section %s\n", section->sectname);
174}
175*/
176sections--;
177section++;
178}
179
180
181break;
182
183case LC_DYSYMTAB:
184//dysymtabCommand = binary + binaryIndex;
185//printf("Unhandled loadcommand LC_DYSYMTAB\n");
186break;
187
188case LC_LOAD_DYLIB:
189case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:
190dylibCommand = binary + binaryIndex;
191char* module = binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));
192// TODO: verify version
193// =dylibCommand->dylib.current_version;
194// =dylibCommand->dylib.compatibility_version;
195
196if(!load_module(module))
197{
198// Unable to load dependancy
199return NULL;
200}
201break;
202
203case LC_ID_DYLIB:
204dylibCommand = binary + binaryIndex;
205moduleName =binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name));
206moduleVersion =dylibCommand->dylib.current_version;
207moduleCompat =dylibCommand->dylib.compatibility_version;
208break;
209
210case LC_DYLD_INFO:
211// Bind and rebase info is stored here
212dyldInfoCommand = binary + binaryIndex;
213break;
214
215case LC_UUID:
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// bind_macho uses the symbols added in for some reason...
230module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbolStub, (UInt32)nonlazy);
231
232// REbase the module before binding it.
233if(dyldInfoCommand && dyldInfoCommand->rebase_off)
234{
235rebase_macho(binary, (char*)dyldInfoCommand->rebase_off, dyldInfoCommand->rebase_size);
236}
237
238if(dyldInfoCommand && dyldInfoCommand->bind_off)
239{
240bind_macho(binary, (char*)dyldInfoCommand->bind_off, dyldInfoCommand->bind_size);
241}
242
243if(dyldInfoCommand && dyldInfoCommand->weak_bind_off)
244{
245bind_macho(binary, (char*)dyldInfoCommand->weak_bind_off, dyldInfoCommand->weak_bind_size);
246}
247
248if(dyldInfoCommand && dyldInfoCommand->lazy_bind_off)
249{
250bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size);
251}
252
253
254
255
256// Notify the system that it was laoded
257module_loaded(moduleName, moduleVersion, moduleCompat);
258
259return module_start;
260
261}
262
263
264// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
265void rebase_macho(void* base, char* rebase_stream, UInt32 size)
266{
267rebase_stream += (UInt32)base;
268
269UInt8 immediate = 0;
270UInt8 opcode = 0;
271UInt8 type = 0;
272
273UInt32 segmentAddress = 0;
274
275
276
277UInt32 tmp = 0;
278UInt32 tmp2 = 0;
279UInt8 bits = 0;
280int index = 0;
281
282int done = 0;
283unsigned int i = 0;
284
285while(/*!done &&*/ i < size)
286{
287immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;
288opcode = rebase_stream[i] & REBASE_OPCODE_MASK;
289
290
291switch(opcode)
292{
293case REBASE_OPCODE_DONE:
294// Rebase complete.
295done = 1;
296break;
297
298
299case REBASE_OPCODE_SET_TYPE_IMM:
300// Set rebase type (pointer, absolute32, pcrel32)
301//printf("Rebase type = 0x%X\n", immediate);
302// NOTE: This is currently NOT used
303type = immediate;
304break;
305
306
307case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
308// Locate address to begin rebasing
309segmentAddress = 0;
310
311struct segment_command* segCommand = NULL;
312
313unsigned int binIndex = 0;
314index = 0;
315do
316{
317segCommand = base + sizeof(struct mach_header) + binIndex;
318
319
320binIndex += segCommand->cmdsize;
321index++;
322}
323while(index <= immediate);
324
325
326segmentAddress = segCommand->fileoff;
327
328tmp = 0;
329bits = 0;
330do
331{
332tmp |= (rebase_stream[++i] & 0x7f) << bits;
333bits += 7;
334}
335while(rebase_stream[i] & 0x80);
336
337segmentAddress += tmp;
338break;
339
340
341case REBASE_OPCODE_ADD_ADDR_ULEB:
342// Add value to rebase address
343tmp = 0;
344bits = 0;
345do
346{
347tmp <<= bits;
348tmp |= rebase_stream[++i] & 0x7f;
349bits += 7;
350}
351while(rebase_stream[i] & 0x80);
352
353segmentAddress +=tmp;
354break;
355
356case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
357segmentAddress += immediate * sizeof(void*);
358break;
359
360
361case REBASE_OPCODE_DO_REBASE_IMM_TIMES:
362index = 0;
363for (index = 0; index < immediate; ++index) {
364rebase_location(base + segmentAddress, (char*)base);
365segmentAddress += sizeof(void*);
366}
367break;
368
369
370case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
371tmp = 0;
372bits = 0;
373do
374{
375tmp |= (rebase_stream[++i] & 0x7f) << bits;
376bits += 7;
377}
378while(rebase_stream[i] & 0x80);
379
380index = 0;
381for (index = 0; index < tmp; ++index) {
382//printf("\tRebasing 0x%X\n", segmentAddress);
383rebase_location(base + segmentAddress, (char*)base);
384segmentAddress += sizeof(void*);
385}
386break;
387
388case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
389tmp = 0;
390bits = 0;
391do
392{
393tmp |= (rebase_stream[++i] & 0x7f) << bits;
394bits += 7;
395}
396while(rebase_stream[i] & 0x80);
397
398rebase_location(base + segmentAddress, (char*)base);
399
400segmentAddress += tmp + sizeof(void*);
401break;
402
403case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
404tmp = 0;
405bits = 0;
406do
407{
408tmp |= (rebase_stream[++i] & 0x7f) << bits;
409bits += 7;
410}
411while(rebase_stream[i] & 0x80);
412
413
414tmp2 = 0;
415bits = 0;
416do
417{
418tmp2 |= (rebase_stream[++i] & 0x7f) << bits;
419bits += 7;
420}
421while(rebase_stream[i] & 0x80);
422
423index = 0;
424for (index = 0; index < tmp; ++index) {
425rebase_location(base + segmentAddress, (char*)base);
426
427segmentAddress += tmp2 + sizeof(void*);
428}
429break;
430}
431i++;
432}
433}
434
435// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
436// NOTE: this uses 32bit values, and not 64bit values.
437// There is apossibility that this could cause issues,
438// however the macho file is 32 bit, so it shouldn't matter too much
439void bind_macho(void* base, char* bind_stream, UInt32 size)
440{
441bind_stream += (UInt32)base;
442
443UInt8 immediate = 0;
444UInt8 opcode = 0;
445UInt8 type = 0;
446
447UInt32 segmentAddress = 0;
448
449UInt32 address = 0;
450
451SInt32 addend = 0;// TODO: handle this
452SInt32 libraryOrdinal = 0;
453
454const char* symbolName = NULL;
455UInt8 symboFlags = 0;
456UInt32 symbolAddr = 0xFFFFFFFF;
457
458// Temperary variables
459UInt8 bits = 0;
460UInt32 tmp = 0;
461UInt32 tmp2 = 0;
462
463UInt32 index = 0;
464int done = 0;
465unsigned int i = 0;
466
467while(/*!done &&*/ i < size)
468{
469immediate = bind_stream[i] & BIND_IMMEDIATE_MASK;
470opcode = bind_stream[i] & BIND_OPCODE_MASK;
471
472
473switch(opcode)
474{
475case BIND_OPCODE_DONE:
476done = 1;
477break;
478
479case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
480libraryOrdinal = immediate;
481//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);
482break;
483
484case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
485libraryOrdinal = 0;
486bits = 0;
487do
488{
489libraryOrdinal |= (bind_stream[++i] & 0x7f) << bits;
490bits += 7;
491}
492while(bind_stream[i] & 0x80);
493
494//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);
495
496break;
497
498case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
499// NOTE: this is wrong, fortunately we don't use it
500libraryOrdinal = -immediate;
501//printf("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);
502
503break;
504
505case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
506symboFlags = immediate;
507symbolName = (char*)&bind_stream[++i];
508i += strlen((char*)&bind_stream[i]);
509//printf("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X\n", symbolName, symboFlags);
510
511symbolAddr = lookup_all_symbols(symbolName);
512
513break;
514
515case BIND_OPCODE_SET_TYPE_IMM:
516// Set bind type (pointer, absolute32, pcrel32)
517type = immediate;
518//printf("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);
519
520break;
521
522case BIND_OPCODE_SET_ADDEND_SLEB:
523addend = 0;
524bits = 0;
525do
526{
527addend |= (bind_stream[++i] & 0x7f) << bits;
528bits += 7;
529}
530while(bind_stream[i] & 0x80);
531
532if(!(bind_stream[i-1] & 0x40)) addend *= -1;
533
534//printf("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);
535break;
536
537case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
538segmentAddress = 0;
539
540// Locate address
541struct segment_command* segCommand = NULL;
542
543unsigned int binIndex = 0;
544index = 0;
545do
546{
547segCommand = base + sizeof(struct mach_header) + binIndex;
548binIndex += segCommand->cmdsize;
549index++;
550}
551while(index <= immediate);
552
553segmentAddress = segCommand->fileoff;
554
555// Read in offset
556tmp = 0;
557bits = 0;
558do
559{
560tmp |= (bind_stream[++i] & 0x7f) << bits;
561bits += 7;
562}
563while(bind_stream[i] & 0x80);
564
565segmentAddress += tmp;
566
567//printf("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress);
568break;
569
570case BIND_OPCODE_ADD_ADDR_ULEB:
571// Read in offset
572tmp = 0;
573bits = 0;
574do
575{
576tmp |= (bind_stream[++i] & 0x7f) << bits;
577bits += 7;
578}
579while(bind_stream[i] & 0x80);
580
581segmentAddress += tmp;
582//printf("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress);
583break;
584
585case BIND_OPCODE_DO_BIND:
586//printf("BIND_OPCODE_DO_BIND\n");
587if(symbolAddr != 0xFFFFFFFF)
588{
589address = segmentAddress + (UInt32)base;
590
591((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;
592((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;
593((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;
594((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;
595}
596else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)
597{
598printf("Unable to bind symbol %s\n", symbolName);
599}
600
601segmentAddress += sizeof(void*);
602break;
603
604case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
605//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n");
606
607
608// Read in offset
609tmp = 0;
610bits = 0;
611do
612{
613tmp |= (bind_stream[++i] & 0x7f) << bits;
614bits += 7;
615}
616while(bind_stream[i] & 0x80);
617
618
619
620if(symbolAddr != 0xFFFFFFFF)
621{
622address = segmentAddress + (UInt32)base;
623
624((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;
625((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;
626((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;
627((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;
628}
629else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)
630{
631printf("Unable to bind symbol %s\n", symbolName);
632}
633segmentAddress += tmp + sizeof(void*);
634
635
636break;
637
638case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
639//printf("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");
640
641if(symbolAddr != 0xFFFFFFFF)
642{
643address = segmentAddress + (UInt32)base;
644
645((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;
646((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;
647((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;
648((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;
649}
650else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)
651{
652printf("Unable to bind symbol %s\n", symbolName);
653}
654segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);
655
656
657break;
658
659case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
660
661tmp = 0;
662bits = 0;
663do
664{
665tmp |= (bind_stream[++i] & 0x7f) << bits;
666bits += 7;
667}
668while(bind_stream[i] & 0x80);
669
670
671tmp2 = 0;
672bits = 0;
673do
674{
675tmp2 |= (bind_stream[++i] & 0x7f) << bits;
676bits += 7;
677}
678while(bind_stream[i] & 0x80);
679
680
681//printf("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2);
682
683
684if(symbolAddr != 0xFFFFFFFF)
685{
686for(index = 0; index < tmp; index++)
687{
688
689address = segmentAddress + (UInt32)base;
690
691((char*)address)[0] = (symbolAddr & 0x000000FF) >> 0;
692((char*)address)[1] = (symbolAddr & 0x0000FF00) >> 8;
693((char*)address)[2] = (symbolAddr & 0x00FF0000) >> 16;
694((char*)address)[3] = (symbolAddr & 0xFF000000) >> 24;
695
696segmentAddress += tmp2 + sizeof(void*);
697}
698}
699else if(strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0)
700{
701printf("Unable to bind symbol %s\n", symbolName);
702}
703
704
705break;
706
707}
708i++;
709}
710}
711
712inline void rebase_location(UInt32* location, char* base)
713{
714*location += (UInt32)base;
715}
716
717/*
718 * add_symbol
719 * This function adds a symbol from a module to the list of known symbols
720 * TODO: actualy do something...
721 * possibly change to a pointer and add this to the Symbol module
722 */
723void add_symbol(char* symbol, void* addr)
724{
725//printf("Adding symbol %s at 0x%X\n", symbol, addr);
726
727if(!moduleSymbols)
728{
729moduleSymbols = malloc(sizeof(symbolList_t));
730moduleSymbols->next = NULL;
731moduleSymbols->addr = (unsigned int)addr;
732moduleSymbols->symbol = symbol;
733}
734else
735{
736symbolList_t* entry = moduleSymbols;
737while(entry->next)
738{
739entry = entry->next;
740}
741
742entry->next = malloc(sizeof(symbolList_t));
743entry = entry->next;
744
745entry->next = NULL;
746entry->addr = (unsigned int)addr;
747entry->symbol = symbol;
748
749}
750
751
752}
753
754
755/*
756 * print out the information about the loaded module
757
758 */
759void module_loaded(char* name, UInt32 version, UInt32 compat)
760{
761/*
762printf("\%s.dylib Version %d.%d.%d loaded\n"
763 "\tCompatibility Version: %d.%d.%d\n",
764 name,
765 (version >> 16) & 0xFFFF,
766 (version >> 8) & 0x00FF,
767 (version >> 0) & 0x00FF,
768 (compat >> 16) & 0xFFFF,
769 (compat >> 8) & 0x00FF,
770 (compat >> 0) & 0x00FF);
771*/
772if(loadedModules == NULL)
773{
774loadedModules = malloc(sizeof(moduleList_t));
775loadedModules->next = NULL;
776loadedModules->module = name;
777loadedModules->version = version;
778loadedModules->compat = compat;
779}
780else
781{
782moduleList_t* entry = loadedModules;
783while(entry->next)
784{
785entry = entry->next;
786}
787
788entry->next = malloc(sizeof(moduleList_t));
789entry = entry->next;
790
791entry->next = NULL;
792entry->module = name;
793entry->version = version;
794entry->compat = compat;
795}
796
797
798}
799
800int is_module_laoded(const char* name)
801{
802moduleList_t* entry = loadedModules;
803while(entry)
804{
805if(strcmp(entry->module, name) == 0)
806{
807return 1;
808}
809else
810{
811entry = entry->next;
812}
813
814}
815return 0;
816}
817
818// Look for symbols using the Smbols moduel function.
819// If non are found, look through the list of module symbols
820unsigned int lookup_all_symbols(const char* name)
821{
822unsigned int addr = 0xFFFFFFFF;
823if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF)
824{
825addr = lookup_symbol(name);
826if(addr != 0xFFFFFFFF)
827{
828//printf("Internal symbol %s located at 0x%X\n", name, addr);
829return addr;
830}
831}
832
833
834symbolList_t* entry = moduleSymbols;
835while(entry)
836{
837if(strcmp(entry->symbol, name) == 0)
838{
839//printf("External symbol %s located at 0x%X\n", name, entry->addr);
840return entry->addr;
841}
842else
843{
844entry = entry->next;
845}
846
847}
848if(strcmp(name, SYMBOL_DYLD_STUB_BINDER) != 0)
849{
850printf("Unable to locate symbol %s\n", name);
851}
852return 0xFFFFFFFF;
853}
854
855
856/*
857 * parse the symbol table
858 * Lookup any undefined symbols
859 */
860
861unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, char* symbolStub, UInt32 nonlazy)
862{
863unsigned int module_start = 0xFFFFFFFF;
864
865UInt32 symbolIndex = 0;
866char* symbolString = base + (char*)symtabCommand->stroff;
867//char* symbolTable = base + symtabCommand->symoff;
868
869while(symbolIndex < symtabCommand->nsyms)
870{
871
872struct nlist* symbolEntry = (void*)base + symtabCommand->symoff + (symbolIndex * sizeof(struct nlist));
873
874// If the symbol is exported by this module
875if(symbolEntry->n_value)
876{
877if(strcmp(symbolString + symbolEntry->n_un.n_strx, "start") == 0)
878{
879// Module start located. Start is an alias so don't register it
880module_start = base + symbolEntry->n_value;
881}
882else
883{
884add_symbol(symbolString + symbolEntry->n_un.n_strx, (void*)base + symbolEntry->n_value);
885}
886}
887
888symbolEntry+= sizeof(struct nlist);
889symbolIndex++;// TODO remove
890}
891
892return module_start;
893
894}
895
896/*
897 * Modify a function to call this one, then return once finished.
898 */
899int hook_function(const char* symbol)
900{
901return 0;
902}
903
904/*
905 * Locate the symbol for an already loaded function and modify the beginning of
906 * the function to jump directly to the new one
907 * example: replace_function("_HelloWorld_start", &replacement_start);
908 */
909int replace_function(const char* symbol, void* newAddress)
910{
911UInt32* jumpPointer = malloc(sizeof(UInt32*));
912// TODO: look into using the next four bytes of the function instead
913
914UInt32 addr = lookup_all_symbols(symbol);
915
916char* binary = (char*)addr;
917if(addr != 0xFFFFFFFF)
918{
919*binary++ = 0xFF;// Jump
920*binary++ = 0x25;// Long Jump
921*((UInt32*)binary) = (UInt32)jumpPointer;
922
923*jumpPointer = (UInt32)newAddress;
924
925return 1;
926}
927else
928{
929return 0;
930}
931
932}

Archive Download this file

Revision: 359