␊ |
#if CONFIG_MODULE_DEBUG␊ |
#define DBG(x...)␉printf(x);␊ |
#define DBGPAUSE()␉getc()␊ |
#define DBGPAUSE()␉getchar()␊ |
#else␊ |
#define DBG(x...)␊ |
#define DBGPAUSE()␊ |
#endif␊ |
␊ |
// NOTE: Global so that modules can link with this␊ |
unsigned long long textAddress = 0;␊ |
unsigned long long textSection = 0;␊ |
UInt64 textAddress = 0;␊ |
UInt64 textSection = 0;␊ |
␊ |
void* symbols_module_start = (void*)0xFFFFFFFF;␉// Global, value is populated by the makefile with actual address␊ |
␊ |
|
␉if(symbols_module_start != (void*)0xFFFFFFFF)␊ |
␉{␊ |
␉␉// Module system was compiled in (Symbols.dylib addr known)␊ |
␉␉module_start = parse_mach(module_data, &load_module, &add_symbol);␊ |
␉␉module_start = parse_mach(module_data, &load_module, &add_symbol, NULL);␊ |
␉␉␊ |
␉␉if(module_start && module_start != (void*)0xFFFFFFFF)␊ |
␉␉{␊ |
|
␉␉else␊ |
␉␉{␊ |
module_data -= 0x10; // XCODE 4 HACK␊ |
module_start = parse_mach(module_data, &load_module, &add_symbol);␊ |
module_start = parse_mach(module_data, &load_module, &add_symbol, NULL);␊ |
␊ |
if(module_start && module_start != (void*)0xFFFFFFFF)␊ |
{␊ |
|
else␊ |
{␊ |
// The module does not have a valid start function␊ |
printf("Unable to start %s\n", SYMBOLS_MODULE); getc();␊ |
printf("Unable to start %s\n", SYMBOLS_MODULE); getchar();␊ |
}␉␉␊ |
␉␉}␉␉␊ |
␉}␊ |
|
␉if (moduleSize && read(fh, module_base, moduleSize) == moduleSize)␊ |
␉{␊ |
␉␉// Module loaded into memory, parse it␊ |
␉␉module_start = parse_mach(module_base, &load_module, &add_symbol);␊ |
␉␉module_start = parse_mach(module_base, &load_module, &add_symbol, NULL);␊ |
␊ |
␉␉if(module_start && module_start != (void*)0xFFFFFFFF)␊ |
␉␉{␊ |
|
␉␉else // The module does not have a valid start function. This may be a library.␊ |
␉␉{␊ |
␉␉␉printf("WARNING: Unable to start %s\n", module);␊ |
␉␉␉getc();␊ |
␉␉␉getchar();␊ |
␉␉}␊ |
#else␊ |
␉␉else msglog("WARNING: Unable to start %s\n", module);␊ |
|
␉}␊ |
␉␊ |
#if CONFIG_MODULE_DEBUG␊ |
␉verbose("Unable to locate symbol %s\n", name);␊ |
␉getc();␊ |
␉printf("Unable to locate symbol %s\n", name);␊ |
␉getchar();␊ |
#endif␊ |
␉␊ |
␉if(strcmp(name, VOID_SYMBOL) == 0) return 0xFFFFFFFF;␊ |
|
* NOTE: If the module is unable to load ot completeion, the modules␊ |
* symbols will still be available.␊ |
*/␊ |
void* parse_mach(void* binary, int(*dylib_loader)(char*), long long(*symbol_handler)(char*, long long, char))␊ |
void* parse_mach(void* binary, ␊ |
int(*dylib_loader)(char*), ␊ |
long long(*symbol_handler)(char*, long long, char),␊ |
void (*section_handler)(char* section, char* segment, long long offset, long long address)␊ |
)␊ |
{␉␊ |
␉char is64 = false;␊ |
␉void (*module_start)(void) = NULL;␊ |
|
␉else␊ |
␉{␊ |
␉␉verbose("Invalid mach magic 0x%X\n", ((struct mach_header*)binary)->magic);␊ |
␉␉//getc();␊ |
␉␉//getchar();␊ |
␉␉return NULL;␊ |
␉}␊ |
␉␊ |
|
␉/*if(((struct mach_header*)binary)->filetype != MH_DYLIB)␊ |
␉ {␊ |
␉ printf("Module is not a dylib. Unable to load.\n");␊ |
␉ getc();␊ |
␉ getchar();␊ |
␉ return NULL; // Module is in the incorrect format␊ |
␉ }*/␊ |
␉␊ |
|
␉␉␉␉break;␊ |
␉␉␉␉␊ |
␉␉␉case LC_SEGMENT: // 32bit macho␊ |
␉␉␉␉segCommand = binary + binaryIndex;␊ |
␉␉␉␉␊ |
␉␉␉␉if(strcmp("__TEXT", segCommand->segname) == 0)␊ |
␉␉␉␉{␊ |
␉␉␉␉␉UInt32 sectionIndex;␊ |
␉␉␉␉␉␊ |
␉␉␉␉␉sectionIndex = sizeof(struct segment_command);␊ |
␉␉␉␉␉␊ |
␉␉␉␉␉struct section *sect;␊ |
␉␉␉␉␉␊ |
␉␉␉␉␉while(sectionIndex < segCommand->cmdsize)␊ |
␉␉␉␉␉{␊ |
␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉sectionIndex += sizeof(struct section);␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉if(strcmp("__text", sect->sectname) == 0)␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
␉␉␉␉␉␉␉textSection = sect->offset;␊ |
␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
␉␉␉␉␉␉␉break;␊ |
␉␉␉␉␉␉}␉␉␉␉␉␊ |
␉␉␉␉␉}␊ |
␉␉␉␉}␊ |
␉␉␉␉␊ |
{␊ |
segCommand = binary + binaryIndex;␊ |
␊ |
UInt32 sectionIndex;␊ |
␊ |
sectionIndex = sizeof(struct segment_command);␊ |
␊ |
struct section *sect;␊ |
␊ |
while(sectionIndex < segCommand->cmdsize)␊ |
{␊ |
sect = binary + binaryIndex + sectionIndex;␊ |
␊ |
sectionIndex += sizeof(struct section);␊ |
␊ |
if(section_handler) section_handler(sect->sectname, segCommand->segname, sect->offset, sect->addr);␊ |
␊ |
␊ |
␊ |
if((strcmp("__TEXT", segCommand->segname) == 0) && (strcmp("__text", sect->sectname) == 0))␊ |
{␊ |
// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
textSection = sect->offset;␊ |
textAddress = sect->addr;␊ |
}␉␉␉␉␉␊ |
}␊ |
}␊ |
␉␉␉␉break;␊ |
␉␉␉case LC_SEGMENT_64:␉// 64bit macho's␊ |
␉␉␉␉segCommand64 = binary + binaryIndex;␉␉␉␉␊ |
␉␉␉␉if(strcmp("__TEXT", segCommand64->segname) == 0)␊ |
␉␉␉␉{␊ |
␉␉␉␉␉UInt32 sectionIndex;␊ |
␉␉␉␉␉␊ |
␉␉␉␉␉sectionIndex = sizeof(struct segment_command_64);␊ |
␉␉␉␉␉␊ |
␉␉␉␉␉struct section_64 *sect;␊ |
␉␉␉␉␉␊ |
␉␉␉␉␉while(sectionIndex < segCommand64->cmdsize)␊ |
␉␉␉␉␉{␊ |
␉␉␉␉␉␉sect = binary + binaryIndex + sectionIndex;␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉sectionIndex += sizeof(struct section_64);␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␊ |
␉␉␉␉␉␉if(strcmp("__text", sect->sectname) == 0)␊ |
␉␉␉␉␉␉{␊ |
␉␉␉␉␉␉␉// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
␉␉␉␉␉␉␉textSection = sect->offset;␊ |
␉␉␉␉␉␉␉textAddress = sect->addr;␊ |
␉␉␉␉␉␉␉␊ |
␉␉␉␉␉␉␉break;␊ |
␉␉␉␉␉␉}␉␉␉␉␉␊ |
␉␉␉␉␉}␊ |
␉␉␉␉}␉␉␉␉␊ |
␉␉␉␉␊ |
{␊ |
segCommand64 = binary + binaryIndex;␉␉␉␉␊ |
UInt32 sectionIndex;␊ |
␊ |
sectionIndex = sizeof(struct segment_command_64);␊ |
␊ |
struct section_64 *sect;␊ |
␊ |
while(sectionIndex < segCommand64->cmdsize)␊ |
{␊ |
sect = binary + binaryIndex + sectionIndex;␊ |
␊ |
sectionIndex += sizeof(struct section_64);␊ |
␊ |
if(section_handler) section_handler(sect->sectname, segCommand->segname, sect->offset, sect->addr);␊ |
␊ |
␊ |
if((strcmp("__TEXT", segCommand->segname) == 0) && (strcmp("__text", sect->sectname) == 0))␊ |
{␊ |
// __TEXT,__text found, save the offset and address for when looking for the calls.␊ |
textSection = sect->offset;␊ |
textAddress = sect->addr;␊ |
}␉␉␉␉␉␊ |
}␉␊ |
␉␉␉␉}␉␉␉␊ |
␉␉␉␉break;␊ |
␉␉␉␉␊ |
␉␉␉␉␊ |
|
␉␉// 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->bind_off)␉␉bind_macho(binary, (UInt8*)dyldInfoCommand->bind_off,␉␉dyldInfoCommand->bind_size);␊ |
␉␉if(dyldInfoCommand->weak_bind_off)␉bind_macho(binary, (UInt8*)dyldInfoCommand->weak_bind_off,␉dyldInfoCommand->weak_bind_size);␊ |
␉␉if(dyldInfoCommand->lazy_bind_off)␉bind_macho(binary, (UInt8*)dyldInfoCommand->lazy_bind_off,␉dyldInfoCommand->lazy_bind_size);␊ |
␉}␊ |
␉␊ |
␉return module_start;␊ |
|
}␊ |
␊ |
␊ |
UInt32 read_uleb(UInt8* bind_stream, unsigned int* i)␊ |
{␊ |
// Read in offset␊ |
UInt32 tmp = 0;␊ |
UInt8 bits = 0;␊ |
do␊ |
{␊ |
if(bits < sizeof(UInt32)*8) // hack␊ |
{␊ |
tmp |= (bind_stream[++(*i)] & 0x7f) << bits;␊ |
bits += 7;␊ |
}␊ |
else␊ |
{␊ |
++(*i);␊ |
}␊ |
}␊ |
while(bind_stream[*i] & 0x80);␊ |
return tmp;␊ |
}␊ |
␊ |
␊ |
// Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp␊ |
// NOTE: this uses 32bit values, and not 64bit values. ␊ |
// 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)␊ |
void bind_macho(void* base, UInt8* bind_stream, UInt32 size)␊ |
{␉␊ |
␉bind_stream += (UInt32)base;␊ |
␉␊ |
|
␉UInt32 symbolAddr = 0xFFFFFFFF;␊ |
␉␊ |
␉// Temperary variables␊ |
␉UInt8 bits = 0;␊ |
␉UInt32 tmp = 0;␊ |
␉UInt32 tmp2 = 0;␊ |
␉UInt32 index = 0;␊ |
|
␉␉␉␉break;␊ |
␉␉␉␉␊ |
␉␉␉case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:␊ |
␉␉␉␉libraryOrdinal = 0;␊ |
␉␉␉␉bits = 0;␊ |
␉␉␉␉do␊ |
␉␉␉␉{␊ |
␉␉␉␉␉libraryOrdinal |= (bind_stream[++i] & 0x7f) << bits;␊ |
␉␉␉␉␉bits += 7;␊ |
␉␉␉␉}␊ |
␉␉␉␉while(bind_stream[i] & 0x80);␊ |
␉␉␉␉libraryOrdinal = read_uleb(bind_stream, &i);␊ |
␉␉␉␉break;␊ |
␉␉␉␉␊ |
␉␉␉case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:␊ |
|
␉␉␉␉break;␊ |
␉␉␉␉␊ |
␉␉␉case BIND_OPCODE_SET_ADDEND_SLEB:␊ |
␉␉␉␉addend = 0;␊ |
␉␉␉␉bits = 0;␊ |
␉␉␉␉do␊ |
␉␉␉␉{␊ |
␉␉␉␉␉addend |= (bind_stream[++i] & 0x7f) << bits;␊ |
␉␉␉␉␉bits += 7;␊ |
␉␉␉␉}␊ |
␉␉␉␉while(bind_stream[i] & 0x80);␊ |
␉␉␉␉␊ |
␉␉␉␉addend = read_uleb(bind_stream, &i);␉␉␉␉␊ |
␉␉␉␉if(!(bind_stream[i-1] & 0x40)) addend *= -1;␊ |
␉␉␉␉break;␊ |
␉␉␉␉␊ |
|
␉␉␉␉while(index <= immediate);␊ |
␉␉␉␉␊ |
␉␉␉␉segmentAddress = segCommand->fileoff;␊ |
␉␉␉␉␊ |
␉␉␉␉// Read in offset␊ |
␉␉␉␉tmp = 0;␊ |
␉␉␉␉bits = 0;␊ |
␉␉␉␉do␊ |
␉␉␉␉{␊ |
␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
␉␉␉␉␉bits += 7;␊ |
␉␉␉␉}␊ |
␉␉␉␉while(bind_stream[i] & 0x80);␊ |
␉␉␉␉␊ |
␉␉␉␉segmentAddress += tmp;␊ |
␉␉␉␉␉␉␉␉␊ |
␉␉␉␉segmentAddress += read_uleb(bind_stream, &i);␊ |
␉␉␉␉break;␊ |
␉␉␉␉␊ |
␉␉␉case BIND_OPCODE_ADD_ADDR_ULEB:␊ |
␉␉␉␉// Read in offset␊ |
␉␉␉␉tmp = 0;␊ |
␉␉␉␉bits = 0;␊ |
␉␉␉␉do␊ |
␉␉␉␉{␊ |
␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
␉␉␉␉␉bits += 7;␊ |
␉␉␉␉}␊ |
␉␉␉␉while(bind_stream[i] & 0x80);␊ |
␉␉␉␉␊ |
␉␉␉␉segmentAddress += tmp;␊ |
␉␉␉␉segmentAddress += read_uleb(bind_stream, &i);␊ |
␉␉␉␉break;␊ |
␉␉␉␉␊ |
␉␉␉case BIND_OPCODE_DO_BIND:␊ |
|
␉␉␉␉else␊ |
␉␉␉␉{␊ |
␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
␉␉␉␉␉getc();␊ |
␉␉␉␉␉getchar();␊ |
␉␉␉␉}␊ |
␉␉␉␉␊ |
␉␉␉␉segmentAddress += sizeof(void*);␊ |
|
␉␉␉␉␊ |
␉␉␉case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:␊ |
␉␉␉␉// Read in offset␊ |
␉␉␉␉tmp = 0;␊ |
␉␉␉␉bits = 0;␊ |
␉␉␉␉do␊ |
␉␉␉␉{␊ |
␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
␉␉␉␉␉bits += 7;␊ |
␉␉␉␉}␊ |
␉␉␉␉while(bind_stream[i] & 0x80);␊ |
␉␉␉␉tmp = read_uleb(bind_stream, &i);␊ |
␊ |
␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
␉␉␉␉{␊ |
|
␉␉␉␉else␊ |
␉␉␉␉{␊ |
␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
␉␉␉␉␉getc();␊ |
␉␉␉␉␉getchar();␊ |
␉␉␉␉}␊ |
␊ |
␉␉␉␉segmentAddress += tmp + sizeof(void*);␊ |
|
␉␉␉␉else␊ |
␉␉␉␉{␊ |
␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
␉␉␉␉␉getc();␊ |
␉␉␉␉␉getchar();␊ |
␉␉␉␉}␊ |
␉␉␉␉segmentAddress += (immediate * sizeof(void*)) + sizeof(void*);␊ |
␉␉␉␉␊ |
|
␉␉␉␉break;␊ |
␉␉␉␉␊ |
␉␉␉case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:␊ |
␉␉␉␉tmp = 0;␊ |
␉␉␉␉bits = 0;␊ |
␉␉␉␉do␊ |
␉␉␉␉{␊ |
␉␉␉␉␉tmp |= (bind_stream[++i] & 0x7f) << bits;␊ |
␉␉␉␉␉bits += 7;␊ |
␉␉␉␉}␊ |
␉␉␉␉while(bind_stream[i] & 0x80);␊ |
␉␉␉␉tmp = read_uleb(bind_stream, &i);␉␉␉␉␊ |
␉␉␉␉␊ |
␉␉␉␉tmp2 = read_uleb(bind_stream, &i);␉␉␉␉␊ |
␉␉␉␉␊ |
␉␉␉␉tmp2 = 0;␊ |
␉␉␉␉bits = 0;␊ |
␉␉␉␉do␊ |
␉␉␉␉{␊ |
␉␉␉␉␉tmp2 |= (bind_stream[++i] & 0x7f) << bits;␊ |
␉␉␉␉␉bits += 7;␊ |
␉␉␉␉}␊ |
␉␉␉␉while(bind_stream[i] & 0x80);␊ |
␉␉␉␉␊ |
␉␉␉␉␊ |
␉␉␉␉if(symbolAddr != 0xFFFFFFFF)␊ |
␉␉␉␉{␊ |
␉␉␉␉␉for(index = 0; index < tmp; index++)␊ |
|
␉␉␉␉else␊ |
␉␉␉␉{␊ |
␉␉␉␉␉printf("Unable to bind symbol %s\n", symbolName);␊ |
␉␉␉␉␉getc();␊ |
␉␉␉␉␉getchar();␊ |
␉␉␉␉}␊ |
␉␉␉␉break;␊ |
␉␉}␊ |
␉␉i++;␊ |
␉}␊ |
}␊ |
␊ |
␊ |
inline void bind_location(UInt32* location, char* value, UInt32 addend, int type)␊ |
{␉␊ |
|
␉␊ |
#if CONFIG_MODULE_DEBUG␊ |
␉//print_hook_list();␊ |
␉//getc();␊ |
␉//getchar();␊ |
#endif␊ |
␉␊ |
}␊ |
|
␉␉hooks = hooks->next;␊ |
␉}␊ |
}␊ |
␊ |
#endif␊ |
␊ |
/********************************************************************************/␊ |
/*␉dyld / Linker Interface␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉*/␊ |
/*␉dyld / Linker Interface␉␉␉␉␉␉␉␉␉␉␉␉␉␉*/␊ |
/********************************************************************************/␊ |
␊ |
void dyld_stub_binder()␊ |
{␊ |
␉printf("ERROR: dyld_stub_binder was called, should have been take care of by the linker.\n");␊ |
␉getc();␊ |
␉getchar();␊ |
}␊ |
␊ |
#else /* CONFIG_MODULES */␊ |