Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 357