Chameleon

Chameleon Commit Details

Date:2011-02-09 17:59:24 (13 years 1 month ago)
Author:Evan Lojewski
Commit:742
Parents: 741
Message:Module system cleanup. Potential bugfix: If a module symbol is missing, bind symbol with void function w/o notifying user.
Changes:
M/branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c
M/branches/meklort/i386/boot2/modules.c
M/branches/meklort/i386/boot2/modules.h

File differences

branches/meklort/i386/boot2/modules.c
108108
109109
110110
111
111
112112
113113
114114
......
127127
128128
129129
130
130
131131
132132
133133
......
259259
260260
261261
262
263
262
263
264
265
266
264267
265268
266269
......
273276
274277
275278
276
277
279
278280
279
281
280282
281283
282284
......
340342
341343
342344
343
344345
345346
346347
......
348349
349350
350351
351
352
353352
354353
355354
......
377376
378377
379378
380
381
382
383
379
384380
385381
386382
......
409405
410406
411407
412
413
414408
415409
416410
......
426420
427421
428422
423
429424
430
431
432425
433426
434427
......
448441
449442
450443
444
451445
452
453
454446
455447
456448
......
462454
463455
464456
465
466
467
457
468458
469459
470460
471
472
461
473462
474
463
464
465
466
467
468
475469
476470
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495471
496472
497473
......
503479
504480
505481
482
483
484
485
506486
507487
508
509
510
511
512
513
514488
515489
516490
......
532506
533507
534508
535
509
536510
537511
538512
......
550524
551525
552526
553
554527
555
556528
557529
558530
......
563535
564536
565537
566
567538
568539
569540
570
571541
572542
573543
574544
575
576
577545
578546
579
547
580548
581549
582550
......
585553
586554
587555
588
589
556
557
558
559
560
590561
591562
592563
593564
594565
595
596
597566
598567
599568
......
601570
602571
603572
604
605573
606574
607575
......
744712
745713
746714
747
748
715
716
749717
750718
751719
......
769737
770738
771739
772
773740
774
775741
776742
777
743
778744
779745
780746
......
790756
791757
792758
793
794759
795760
796761
797762
798763
799
800764
801765
802766
......
808772
809773
810774
811
812
813
814775
815776
816777
817
818778
819
820
821779
822780
823781
824782
825783
826784
827
828
785
829786
830
831787
832788
833789
834
835790
836
837
838791
839792
840793
......
848801
849802
850803
851
852
853804
854805
855806
......
906857
907858
908859
909
860
910861
911862
912863
913
914864
915865
916866
......
960910
961911
962912
963
964913
965914
966915
......
996945
997946
998947
999
1000
1001948
1002
1003949
1004950
1005951
......
1038984
1039985
1040986
1041
1042
1043
1044
1045987
1046988
1047989
......
1053995
1054996
1055997
1056
1057998
1058999
1059
1060
1061
1062
1063
1000
10641001
10651002
10661003
......
10801017
10811018
10821019
1083
1020
10841021
10851022
1086
10871023
10881024
10891025
1090
1091
10921026
10931027
10941028
/*
* Load a module file in /Extra/modules
* Load a module file in /Extra/modules/
*/
int load_module(char* module)
{
fh = open(modString, 0);
if(fh < 0)
{
printf("WARNING: Unable to locate module %s\n", modString); DBGPAUSE();
DBG("WARNING: Unable to locate module %s\n", modString); DBGPAUSE();
return 0;
}
verbose("Unable to locate symbol %s\n", name);
getc();
#endif
return 0xFFFFFFFF;
if(strcmp(name, VOID_SYMBOL) == 0) return 0xFFFFFFFF;
// In the event that a symbol does not exist
// Return a pointer to a void function.
else return lookup_all_symbols(VOID_SYMBOL);
}
/********************************************************************************/
* the module iinit address will be returned.
* NOTE; all dependecies will be loaded before this module is started
* NOTE: If the module is unable to load ot completeion, the modules
* symbols will still be available (TODO: fix this). This should not
* happen as all dependencies are verified before the sybols are read in.
* symbols will still be available.
*/
void* parse_mach(void* binary, int(*dylib_loader)(char*), long long(*symbol_handler)(char*, long long, char))// TODO: add param to specify valid archs
void* parse_mach(void* binary, int(*dylib_loader)(char*), long long(*symbol_handler)(char*, long long, char))
{
char is64 = false;
void (*module_start)(void) = NULL;
switch ((loadCommand->cmd & 0x7FFFFFFF))
{
// TODO: sepeare function to handel appropriate sections
case LC_SYMTAB:
symtabCommand = binary + binaryIndex;
break;
case LC_SEGMENT: // 32bit macho
segCommand = binary + binaryIndex;
//printf("Segment name is %s\n", segCommand->segname);
if(strcmp("__TEXT", segCommand->segname) == 0)
{
UInt32 sectionIndex;
break;
case LC_SEGMENT_64:// 64bit macho's
segCommand64 = binary + binaryIndex;
//printf("Segment name is %s\n", segCommand->segname);
segCommand64 = binary + binaryIndex;
if(strcmp("__TEXT", segCommand64->segname) == 0)
{
UInt32 sectionIndex;
break;
case LC_DYSYMTAB:
break;
case LC_LOAD_DYLIB:
case LC_LOAD_WEAK_DYLIB ^ LC_REQ_DYLD:
if (!dylib_loader(name))
{
// NOTE: any symbols exported by dep will be replace with the void function
free(name);
// Unable to load dependancy
//return NULL;
}
}
dyldInfoCommand = binary + binaryIndex;
break;
case LC_DYSYMTAB:
case LC_UUID:
break;
case LC_UNIXTHREAD:
break;
binaryIndex += cmdSize;
}
//if(!moduleName) return NULL;
// bind_macho uses the symbols, if the textAdd does not exist (Symbols.dylib, no code), addresses are static and not relative
module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbol_handler, is64);
// Rebase the module before binding it.
if(dyldInfoCommand && dyldInfoCommand->rebase_off)
if(dyldInfoCommand)
{
rebase_macho(binary, (char*)dyldInfoCommand->rebase_off, dyldInfoCommand->rebase_size);
// Rebase the module before binding it.
if(dyldInfoCommand->rebase_off)rebase_macho(binary, (char*)dyldInfoCommand->rebase_off,dyldInfoCommand->rebase_size);
// Bind all symbols.
if(dyldInfoCommand->bind_off)bind_macho(binary, (char*)dyldInfoCommand->bind_off,dyldInfoCommand->bind_size);
if(dyldInfoCommand->weak_bind_off)bind_macho(binary, (char*)dyldInfoCommand->weak_bind_off,dyldInfoCommand->weak_bind_size);
if(dyldInfoCommand->lazy_bind_off)bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off,dyldInfoCommand->lazy_bind_size);
}
if(dyldInfoCommand && dyldInfoCommand->bind_off)
{
bind_macho(binary, (char*)dyldInfoCommand->bind_off, dyldInfoCommand->bind_size);
}
if(dyldInfoCommand && dyldInfoCommand->weak_bind_off)
{
// NOTE: this currently should never happen.
bind_macho(binary, (char*)dyldInfoCommand->weak_bind_off, dyldInfoCommand->weak_bind_size);
}
if(dyldInfoCommand && dyldInfoCommand->lazy_bind_off)
{
// NOTE: we are binding the lazy pointers as a module is laoded,
// This should be changed to bind when a symbol is referened at runtime instead.
bind_macho(binary, (char*)dyldInfoCommand->lazy_bind_off, dyldInfoCommand->lazy_bind_size);
}
return module_start;
}
unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, long long, char), char is64)
{
unsigned int module_start= 0xFFFFFFFF;
UInt32 symbolIndex= 0;
char* symbolString= base + (char*)symtabCommand->stroff;
// TODO: verify that the _TEXT,_text segment starts at the same locaiton in the file. If not
//subtract the vmaddress and add the actual file address back on. (NOTE: if compiled properly, not needed)
unsigned int module_start = 0xFFFFFFFF;
UInt32 symbolIndex = 0;
char* symbolString = base + (char*)symtabCommand->stroff;
//char* symbolTable = base + symtabCommand->symoff;
if(!is64)
{
struct nlist* symbolEntry = (void*)base + symtabCommand->symoff;
else
{
struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff;
// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now)
// NOTE First entry is *not* correct, but we can ignore it (i'm getting radar:// right now, verify later)
while(symbolIndex < symtabCommand->nsyms)
{
symbolIndex++;// TODO remove
}
}
return module_start;
}
// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
UInt8 immediate = 0;
UInt8 opcode = 0;
UInt8 type = 0;
UInt32 segmentAddress = 0;
UInt32 tmp = 0;
UInt32 tmp2 = 0;
UInt8 bits = 0;
int index = 0;
//int done = 0;
unsigned int i = 0;
while(/*!done &&*/ i < size)
while(i < size)
{
immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK;
opcode = rebase_stream[i] & REBASE_OPCODE_MASK;
switch(opcode)
{
case REBASE_OPCODE_DONE:
// Rebase complete.
//done = 1;
// Rebase complete, reset vars
immediate = 0;
opcode = 0;
type = 0;
segmentAddress = 0;
default:
break;
case REBASE_OPCODE_SET_TYPE_IMM:
// Set rebase type (pointer, absolute32, pcrel32)
//DBG("Rebase type = 0x%X\n", immediate);
type = immediate;
break;
case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
// Locate address to begin rebasing
segmentAddress = 0;
struct segment_command* segCommand = NULL; // NOTE: 32bit only
unsigned int binIndex = 0;
// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp
// NOTE: this uses 32bit values, and not 64bit values.
// There is apossibility that this could cause issues,
// however the macho file is 32 bit, so it shouldn't matter too much
// There is a possibility that this could cause issues,
// however the modules are 32 bits, so it shouldn't matter too much
void bind_macho(void* base, char* bind_stream, UInt32 size)
{
bind_stream += (UInt32)base;
UInt8 bits = 0;
UInt32 tmp = 0;
UInt32 tmp2 = 0;
UInt32 index = 0;
//int done = 0;
unsigned int i = 0;
while(/*!done &&*/ i < size)
while(i < size)
{
immediate = bind_stream[i] & BIND_IMMEDIATE_MASK;
opcode = bind_stream[i] & BIND_OPCODE_MASK;
addend = 0;
libraryOrdinal = 0;
symbolAddr = 0xFFFFFFFF;
//done = 1;
default:
break;
case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
libraryOrdinal = immediate;
//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: %d\n", libraryOrdinal);
break;
case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
bits += 7;
}
while(bind_stream[i] & 0x80);
//printf("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: %d\n", libraryOrdinal);
break;
case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
// NOTE: this is wrong, fortunately we don't use it
libraryOrdinal = immediate ? (SInt8)(BIND_OPCODE_MASK | immediate) : immediate;
//printf("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: %d\n", libraryOrdinal);
break;
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
symboFlags = immediate;
symbolName = (char*)&bind_stream[++i];
i += strlen((char*)&bind_stream[i]);
//DBG("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: %s, 0x%X", symbolName, symboFlags);
symbolAddr = lookup_all_symbols(symbolName);
//DBG(", addr = 0x%X\n", symbolAddr);
break;
case BIND_OPCODE_SET_TYPE_IMM:
// Set bind type (pointer, absolute32, pcrel32)
type = immediate;
//DBG("BIND_OPCODE_SET_TYPE_IMM: %d\n", type);
break;
case BIND_OPCODE_SET_ADDEND_SLEB:
while(bind_stream[i] & 0x80);
if(!(bind_stream[i-1] & 0x40)) addend *= -1;
//DBG("BIND_OPCODE_SET_ADDEND_SLEB: %d\n", addend);
break;
case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
}
else
{
printf("Unable to bind symbol %s, libraryOrdinal = %d, symboFlags = %d, type = %d\n", symbolName, libraryOrdinal, symboFlags, type);
printf("Unable to bind symbol %s\n", symbolName);
getc();
}
segmentAddress += sizeof(void*);
break;
break;
case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
tmp = 0;
bits = 0;
do
printf("Unable to bind symbol %s\n", symbolName);
getc();
}
break;
}
i++;
}
int replace_function(const char* symbol, void* newAddress)
{
UInt32* jumpPointer = malloc(sizeof(UInt32*));
// TODO: look into using the next four bytes of the function instead
// Most functions should support this, as they probably will be at
// least 10 bytes long, but you never know, this is sligtly safer as
// function can be as small as 6 bytes.
UInt32 addr = lookup_all_symbols(symbol);
char* binary = (char*)addr;
*((UInt32*)binary) = (UInt32)jumpPointer;
*jumpPointer = (UInt32)newAddress;
return 1;
}
else
{
return 0;
}
return 0;
}
{
// Loop through all callbacks for this module
callbackList_t* callbacks = hook->callbacks;
while(callbacks)
{
//DBG("Executing '%s' callback at 0x%X.\n", name, callbacks->callback);
// Execute callback
callbacks->callback(arg1, arg2, arg3, arg4);
callbacks = callbacks->next;
//DBG("Hook '%s' callback executed, next is 0x%X.\n", name, callbacks);
}
DBG("Hook '%s' executed.\n", name); DBGPAUSE();
return 1;
branches/meklort/i386/boot2/modules.h
1313
1414
1515
16
16
1717
1818
1919
#define MODULE_PATH"/Extra/modules/"
#define SYMBOLS_MODULE "Symbols.dylib"
#define VOID_SYMBOL"dyld_void_start"
extern unsigned long long textAddress;
extern unsigned long long textSection;
branches/meklort/i386/modules/KernelPatcher/kernel_patcher.c
3636
3737
3838
39
39
4040
4141
4242
......
5757
5858
5959
60
6160
62
61
6362
6463
6564
register_kernel_symbol(KERNEL_ANY, "_lapic_start");
register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt_base");
// lapic_interrup symbols
// lapic_interrupt symbols
//register_kernel_patch(patch_lapic_interrupt, KERNEL_ANY, CPUID_MODEL_ANY);
//register_kernel_symbol(KERNEL_ANY, "_lapic_interrupt");
// AKA, don't at 64bit patches if it's a 32bit only machine
patchRoutine_t* entry;
// TODO: verify Platform->CPU.Model is populated this early in bootup
// Check to ensure that the patch is valid on this machine
// If it is not, exit early form this function
// If it is not, exit early from this function
if(cpus != Platform->CPU.Model)
{
if(cpus != CPUID_MODEL_ANY)

Archive Download the corresponding diff file

Revision: 742