Index: branches/meklort/i386/boot2/modules.c =================================================================== --- branches/meklort/i386/boot2/modules.c (revision 716) +++ branches/meklort/i386/boot2/modules.c (revision 717) @@ -3,19 +3,21 @@ * * TODO: Zero out bss if needed */ +#ifndef DEBUG_MODULES +#define DEBUG_MODULES 0 +#endif #include "boot.h" #include "bootstruct.h" #include "modules.h" -#ifndef DEBUG_MODULES -#define DEBUG_MODULES 0 -#endif #if DEBUG_MODULES -#define DBG(x...) printf(x); getc() +#define DBG(x...) printf(x); +#define DBGPAUSE() getc() #else #define DBG(x...) +#define DBGPAUSE() #endif // NOTE: Global so that modules can link with this @@ -31,23 +33,6 @@ unsigned int (*lookup_symbol)(const char*) = NULL; - - - -#if DEBUG_MODULES -void print_hook_list() -{ - printf("---Hook Table---\n"); - - moduleHook_t* hooks = moduleCallbacks; - while(hooks) - { - printf("Hook: %s\n", hooks->name); - hooks = hooks->next; - } -} -#endif - /* * Initialize the module system by loading the Symbols.dylib module. * Once loaded, locate the _lookup_symbol function so that internal @@ -61,7 +46,7 @@ // Intialize module system if(symbols_module_start == (void*)0xFFFFFFFF) { - DBG("Module system not compiled in\n"); + DBG("Module system not compiled in.\n"); DBGPAUSE(); load_module(SYMBOLS_MODULE); lookup_symbol = (void*)lookup_all_symbols(SYMBOL_LOOKUP_SYMBOL); @@ -92,7 +77,7 @@ } else { // The module does not have a valid start function - printf("Unable to start %s\n", SYMBOLS_MODULE); + printf("Unable to start %s\n", SYMBOLS_MODULE); DBGPAUSE(); getc(); } return 0; @@ -121,7 +106,6 @@ char* tmp = malloc(strlen(name) + 1); strcpy(tmp, name); - DBG("Attempting to load %s\n", tmp); if(!load_module(tmp)) { // failed to load @@ -149,9 +133,6 @@ // Check to see if the module has already been loaded if(is_module_loaded(module)) { - // NOTE: Symbols.dylib tries to load twice, this catches it as well - // as when a module links with an already loaded module - DBG("Module %s already loaded\n", module); return 1; } @@ -161,7 +142,7 @@ fh = open(modString, 0); if(fh < 0) { - printf("Unable to locate module %s\n", modString); + printf("Unable to locate module %s\n", modString); DBGPAUSE(); getc(); return 0; } @@ -171,7 +152,7 @@ if (moduleSize && read(fh, module_base, moduleSize) == moduleSize) { - DBG("Module %s read in.\n", modString); + //DBG("Module %s read in.\n", modString); // Module loaded into memory, parse it module_start = parse_mach(module_base, &load_module, &add_symbol); @@ -180,8 +161,9 @@ { // Notify the system that it was laoded module_loaded(module/*moduleName, moduleVersion, moduleCompat*/); + (*module_start)(); // Start the module - DBG("Module %s Loaded.\n", module); + DBG("Module %s Loaded.\n", module); DBGPAUSE(); } else { // The module does not have a valid start function @@ -195,136 +177,137 @@ getc(); } close(fh); + return 1; } /* - * execute_hook( const char* name ) - * name - Name of the module hook - * If any callbacks have been registered for this hook - * they will be executed now in the same order that the - * hooks were added. + * add_symbol + * This function adds a symbol from a module to the list of known symbols + * possibly change to a pointer and add this to the Symbol module so that it can + * adjust it's internal symbol list (sort) to optimize locating new symbols + * NOTE: returns the address if the symbol is "start", else returns 0xFFFFFFFF */ -int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4) +long long add_symbol(char* symbol, long long addr, char is64) { - DBG("Attempting to execute hook '%s'\n", name); - moduleHook_t* hooks = moduleCallbacks; + if(is64) return 0xFFFFFFFF; // Fixme - while(hooks && strcmp(name, hooks->name) < 0) + // This only can handle 32bit symbols + symbolList_t* entry; + //DBG("Adding symbol %s at 0x%X\n", symbol, addr); + + if(!moduleSymbols) { - //DBG("%s cmp %s = %d\n", name, hooks->name, strcmp(name, hooks->name)); - hooks = hooks->next; - } + moduleSymbols = entry = malloc(sizeof(symbolList_t)); - if(hooks && strcmp(name, hooks->name) == 0) + } + else { - // Loop through all callbacks for this module - callbackList_t* callbacks = hooks->callbacks; - - while(callbacks) + entry = moduleSymbols; + while(entry->next) { - DBG("Executing '%s' with callback 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); - + entry = entry->next; } - DBG("Hook '%s' executed.\n", name); - return 1; + entry->next = malloc(sizeof(symbolList_t)); + entry = entry->next; } + + entry->next = NULL; + entry->addr = (UInt32)addr; + entry->symbol = symbol; + + if(strcmp(symbol, "start") == 0) + { + return addr; + } else { - DBG("No callbacks for '%s' hook.\n", name); - - // Callbaack for this module doesn't exist; - //verbose("Unable execute hook '%s', no callbacks registered.\n", name); - //pause(); - return 0; + return 0xFFFFFFFF; // fixme } } - /* - * register_hook_callback( const char* name, void(*callback)()) - * name - Name of the module hook to attach to. - * callbacks - The funciton pointer that will be called when the - * hook is executed. When registering a new callback name, the callback is added sorted. - * NOTE: the hooks take four void* arguments. - * TODO: refactor + * print out the information about the loaded module */ -void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*)) -{ - DBG("Adding callback for '%s' hook.\n", name); +void module_loaded(const char* name/*, UInt32 version, UInt32 compat*/) +{ + // TODO: insert sorted + moduleList_t* new_entry = malloc(sizeof(moduleList_t)); - moduleHook_t* newHook = malloc(sizeof(moduleHook_t)); - if(!moduleCallbacks) + new_entry->next = loadedModules; + loadedModules = new_entry; + + new_entry->module = (char*)name; + new_entry->version = 0; //version; + new_entry->compat = 0; //compat; +} + +int is_module_loaded(const char* name) +{ + // todo sorted search + moduleList_t* entry = loadedModules; + while(entry) { - newHook->next = moduleCallbacks; - moduleCallbacks = newHook; - - newHook->name = name; - newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t)); - newHook->callbacks->callback = callback; - newHook->callbacks->next = NULL; - } - else - { - moduleHook_t* hooks = moduleCallbacks; - - while(hooks->next && strcmp(name, hooks->next->name) < 0) + if(strcmp(entry->module, name) == 0) { - hooks = hooks->next; + DBG("Located module %s\n", name); DBGPAUSE(); + return 1; } - - if(!hooks->next) + else { - // Appent to the end - newHook->next = NULL; - hooks->next = newHook; - newHook->name = name; - newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t)); - newHook->callbacks->callback = callback; - newHook->callbacks->next = NULL; - - + entry = entry->next; } - else if(strcmp(name, hooks->next->name) == 0) + + } + DBG("Module %s not found\n", name); DBGPAUSE(); + + return 0; +} + +// Look for symbols using the Smbols moduel function. +// If non are found, look through the list of module symbols +unsigned int lookup_all_symbols(const char* name) +{ + unsigned int addr = 0xFFFFFFFF; + symbolList_t* entry = moduleSymbols; + while(entry) + { + if(strcmp(entry->symbol, name) == 0) { - // We found the hook - // Hook alreday exists, add a callback to this hook - callbackList_t* callbacks = hooks->next->callbacks; - while(callbacks->next != NULL) - { - callbacks = callbacks->next; - } - // Add new entry to end of hook list. - callbacks->next = (callbackList_t*)malloc(sizeof(callbackList_t)); - callbacks = callbacks->next; - callbacks->next = NULL; - callbacks->callback = callback; + //DBG("External symbol %s located at 0x%X\n", name, entry->addr); + return entry->addr; } else { - // We are too far beyond the hook - newHook->next = hooks->next; - hooks->next = newHook; - newHook->name = name; - newHook->callbacks = (callbackList_t*)malloc(sizeof(callbackList_t)); - newHook->callbacks->callback = callback; - newHook->callbacks->next = NULL; - + entry = entry->next; } + } + + if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF) + { + addr = lookup_symbol(name); + if(addr != 0xFFFFFFFF) + { + //DBG("Internal symbol %s located at 0x%X\n", name, addr); + return addr; + } + } + + #if DEBUG_MODULES - print_hook_list(); + verbose("Unable to locate symbol %s\n", name); getc(); #endif - + + return 0xFFFFFFFF; } +/********************************************************************************/ +/* Macho Parser */ +/********************************************************************************/ /* * Parse through a macho module. The module will be rebased and binded @@ -342,9 +325,9 @@ // Module info /*char* moduleName = NULL; - UInt32 moduleVersion = 0; - UInt32 moduleCompat = 0; - */ + UInt32 moduleVersion = 0; + UInt32 moduleCompat = 0; + */ // TODO convert all of the structs to a union struct load_command *loadCommand = NULL; struct dylib_command* dylibCommand = NULL; @@ -353,11 +336,11 @@ struct symtab_command* symtabCommand = NULL; struct segment_command *segCommand = NULL; struct segment_command_64 *segCommand64 = NULL; - + //struct dysymtab_command* dysymtabCommand = NULL; UInt32 binaryIndex = 0; UInt16 cmd = 0; - + // Parse through the load commands if(((struct mach_header*)binary)->magic == MH_MAGIC) { @@ -376,15 +359,15 @@ getc(); return NULL; } - - + + /*if(((struct mach_header*)binary)->filetype != MH_DYLIB) - { - printf("Module is not a dylib. Unable to load.\n"); - getc(); - return NULL; // Module is in the incorrect format - }*/ + { + printf("Module is not a dylib. Unable to load.\n"); + getc(); + return NULL; // Module is in the incorrect format + }*/ while(cmd < ((struct mach_header*)binary)->ncmds) { @@ -392,11 +375,11 @@ loadCommand = binary + binaryIndex; UInt32 cmdSize = loadCommand->cmdsize; - + switch ((loadCommand->cmd & 0x7FFFFFFF)) { - // TODO: sepeare function to handel appropriate sections + // TODO: sepeare function to handel appropriate sections case LC_SYMTAB: symtabCommand = binary + binaryIndex; break; @@ -430,31 +413,7 @@ } } } - else if(strcmp("__DATA", 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("__bss", sect->sectname) == 0) - { - // __TEXT,__text found, save the offset and address for when looking for the calls. - //printf("__DATA,__bss found.\n"); getc(); - break; - } - } - - } - + break; case LC_SEGMENT_64: // 64bit macho's segCommand64 = binary + binaryIndex; @@ -485,33 +444,8 @@ break; } } - } - else if(strcmp("__DATA", segCommand->segname) == 0) - { - UInt32 sectionIndex; - - sectionIndex = sizeof(struct segment_command_64); - - struct section_64 *sect; - - while(sectionIndex < segCommand->cmdsize) - { - sect = binary + binaryIndex + sectionIndex; - - sectionIndex += sizeof(struct section); - - - if(strcmp("__bss", sect->sectname) == 0) - { - // __TEXT,__text found, save the offset and address for when looking for the calls. - //printf("__DATA,__bss found.\n"); getc(); - break; - } - } - - } + } - break; case LC_DYSYMTAB: @@ -528,7 +462,7 @@ { char* name = malloc(strlen(module) + strlen(".dylib") + 1); sprintf(name, "%s.dylib", module); - + if (!dylib_loader(name)) { free(name); @@ -536,18 +470,19 @@ //return NULL; } } - + break; case LC_ID_DYLIB: dylibCommand = binary + binaryIndex; /*moduleName = binary + binaryIndex + ((UInt32)*((UInt32*)&dylibCommand->dylib.name)); - moduleVersion = dylibCommand->dylib.current_version; - moduleCompat = dylibCommand->dylib.compatibility_version; + moduleVersion = dylibCommand->dylib.current_version; + moduleCompat = dylibCommand->dylib.compatibility_version; */ break; - + case LC_DYLD_INFO: + //case LC_DYLD_INFO_ONLY: // compressed info, 10.6+ macho files, already handeled // Bind and rebase info is stored here dyldInfoCommand = binary + binaryIndex; break; @@ -561,17 +496,17 @@ default: DBG("Unhandled loadcommand 0x%X\n", loadCommand->cmd & 0x7FFFFFFF); break; - + } - + binaryIndex += cmdSize; } //if(!moduleName) return NULL; - - + + // bind_macho uses the symbols. module_start = (void*)handle_symtable((UInt32)binary, symtabCommand, symbol_handler, is64); - + // Rebase the module before binding it. if(dyldInfoCommand && dyldInfoCommand->rebase_off) { @@ -595,12 +530,70 @@ // 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; } +/* + * parse the symbol table + * Lookup any undefined symbols + */ +unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, long long, char), char is64) +{ + // 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; + while(symbolIndex < symtabCommand->nsyms) + { + // If the symbol is exported by this module + if(symbolEntry->n_value && + symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF) + { + + // Module start located. Start is an alias so don't register it + module_start = base + symbolEntry->n_value; + } + + symbolEntry++; + symbolIndex++; // TODO remove + } + } + 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) + while(symbolIndex < symtabCommand->nsyms) + { + + + // If the symbol is exported by this module + if(symbolEntry->n_value && + symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF) + { + + // Module start located. Start is an alias so don't register it + module_start = base + symbolEntry->n_value; + } + + symbolEntry++; + symbolIndex++; // TODO remove + } + } + + return module_start; + +} + // Based on code from dylibinfo.cpp and ImageLoaderMachOCompressed.cpp void rebase_macho(void* base, char* rebase_stream, UInt32 size) { @@ -626,8 +619,8 @@ { immediate = rebase_stream[i] & REBASE_IMMEDIATE_MASK; opcode = rebase_stream[i] & REBASE_OPCODE_MASK; - + switch(opcode) { case REBASE_OPCODE_DONE: @@ -647,7 +640,7 @@ 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; @@ -661,8 +654,8 @@ index++; } while(index <= immediate); - - + + segmentAddress = segCommand->fileoff; tmp = 0; @@ -705,8 +698,8 @@ segmentAddress += sizeof(void*); } break; - + case REBASE_OPCODE_DO_REBASE_ULEB_TIMES: tmp = 0; bits = 0; @@ -762,7 +755,7 @@ index = 0; for (index = 0; index < tmp; ++index) { - + rebase_location(base + segmentAddress, (char*)base, type); segmentAddress += tmp2 + sizeof(void*); @@ -773,6 +766,21 @@ } } +inline void rebase_location(UInt32* location, char* base, int type) +{ + switch(type) + { + case REBASE_TYPE_POINTER: + case REBASE_TYPE_TEXT_ABSOLUTE32: + *location += (UInt32)base; + break; + + default: + break; + } +} + + // 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, @@ -783,15 +791,15 @@ UInt8 immediate = 0; UInt8 opcode = 0; - UInt8 type = 0; + UInt8 type = BIND_TYPE_POINTER; UInt32 segmentAddress = 0; UInt32 address = 0; - SInt32 addend = 0; // TODO: handle this + SInt32 addend = 0; SInt32 libraryOrdinal = 0; - + const char* symbolName = NULL; UInt8 symboFlags = 0; UInt32 symbolAddr = 0xFFFFFFFF; @@ -814,6 +822,13 @@ switch(opcode) { case BIND_OPCODE_DONE: + // reset vars + type = BIND_TYPE_POINTER; + segmentAddress = 0; + address = 0; + addend = 0; + libraryOrdinal = 0; + symbolAddr = 0xFFFFFFFF; //done = 1; default: break; @@ -834,31 +849,31 @@ 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\n", symbolName, symboFlags); - + //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: @@ -878,7 +893,7 @@ case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: segmentAddress = 0; - + // Locate address struct segment_command* segCommand = NULL; // NOTE: 32bit only @@ -905,8 +920,6 @@ while(bind_stream[i] & 0x80); segmentAddress += tmp; - - //DBG("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 0x%X\n", segmentAddress); break; case BIND_OPCODE_ADD_ADDR_ULEB: @@ -921,40 +934,26 @@ while(bind_stream[i] & 0x80); segmentAddress += tmp; - //DBG("BIND_OPCODE_ADD_ADDR_ULEB: 0x%X\n", segmentAddress); break; case BIND_OPCODE_DO_BIND: - //DBG("BIND_OPCODE_DO_BIND\n"); - if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER) + if(symbolAddr != 0xFFFFFFFF) { - // HACK(ish) - // Internal symbol, don't bind + address = segmentAddress + (UInt32)base; + + bind_location((UInt32*)address, (char*)symbolAddr, addend, type); } else { - //printf("Binding symbol %s, libraryOrdinal = %d, symboFlags = %d, type = %d\n", symbolName, libraryOrdinal, symboFlags, type); - - if(symbolAddr != 0xFFFFFFFF) - { - address = segmentAddress + (UInt32)base; - - bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER); - } - else - { - printf("Unable to bind symbol %s, libraryOrdinal = %d, symboFlags = %d, type = %d\n", symbolName, libraryOrdinal, symboFlags, type); - getc(); - } + printf("Unable to bind symbol %s, libraryOrdinal = %d, symboFlags = %d, type = %d\n", symbolName, libraryOrdinal, symboFlags, type); + getc(); } + segmentAddress += sizeof(void*); break; case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: - //DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB\n"); - - // Read in offset tmp = 0; bits = 0; @@ -964,58 +963,43 @@ bits += 7; } while(bind_stream[i] & 0x80); - - - if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER) + + if(symbolAddr != 0xFFFFFFFF) { - // Internal symbol, don't bind + address = segmentAddress + (UInt32)base; + + bind_location((UInt32*)address, (char*)symbolAddr, addend, type); } else { - if(symbolAddr != 0xFFFFFFFF) - { - address = segmentAddress + (UInt32)base; - - bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER); - } - else - { - printf("Unable to bind symbol %s\n", symbolName); - getc(); - } + printf("Unable to bind symbol %s\n", symbolName); + getc(); } - segmentAddress += tmp + sizeof(void*); + segmentAddress += tmp + sizeof(void*); + break; case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: - //DBG("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n"); - if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER) + if(symbolAddr != 0xFFFFFFFF) { - // Internal symbol, don't bind + address = segmentAddress + (UInt32)base; + + bind_location((UInt32*)address, (char*)symbolAddr, addend, type); } else { - if(symbolAddr != 0xFFFFFFFF) - { - address = segmentAddress + (UInt32)base; - - bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER); - } - else - { - printf("Unable to bind symbol %s\n", symbolName); - getc(); - } + printf("Unable to bind symbol %s\n", symbolName); + getc(); } segmentAddress += (immediate * sizeof(void*)) + sizeof(void*); - + break; case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: - + tmp = 0; bits = 0; do @@ -1024,8 +1008,8 @@ bits += 7; } while(bind_stream[i] & 0x80); - + tmp2 = 0; bits = 0; do @@ -1036,38 +1020,20 @@ while(bind_stream[i] & 0x80); - //DBG("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0x%X 0x%X\n", tmp, tmp2); - - if(symbolAddr != 0xFFFFFFFF) { for(index = 0; index < tmp; index++) { address = segmentAddress + (UInt32)base; - if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER) - { - // Internal symbol, don't bind - } - else - { - - bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER); - } + bind_location((UInt32*)address, (char*)symbolAddr, addend, type); segmentAddress += tmp2 + sizeof(void*); } } else { - if(libraryOrdinal == BIND_SPECIAL_DYLIB_FLAT_LOOKUP && type == BIND_TYPE_POINTER) - { - // Internal symbol, don't bind - } - else - { - printf("Unable to bind symbol %s\n", symbolName); - getc(); - } + printf("Unable to bind symbol %s\n", symbolName); + getc(); } @@ -1078,264 +1044,188 @@ } } -inline void rebase_location(UInt32* location, char* base, int type) -{ - switch(type) - { - case REBASE_TYPE_POINTER: - case REBASE_TYPE_TEXT_ABSOLUTE32: - *location += (UInt32)base; - break; - - default: - break; - } -} - inline void bind_location(UInt32* location, char* value, UInt32 addend, int type) { // do actual update char* newValue = value + addend; - + switch (type) { case BIND_TYPE_POINTER: case BIND_TYPE_TEXT_ABSOLUTE32: break; - + case BIND_TYPE_TEXT_PCREL32: newValue -= ((UInt32)location + 4); - + break; default: return; } - + //DBG("Binding 0x%X to 0x%X (was 0x%X)\n", location, newValue, *location); *location = (UInt32)newValue; } +/********************************************************************************/ +/* Module Hook Interface */ +/********************************************************************************/ /* - * add_symbol - * This function adds a symbol from a module to the list of known symbols - * possibly change to a pointer and add this to the Symbol module so that it can - * adjust it's internal symbol list (sort) to optimize locating new symbols - * NOTE: returns the address if the symbol is "start", else returns 0xFFFFFFFF - */ -long long add_symbol(char* symbol, long long addr, char is64) +* Locate the symbol for an already loaded function and modify the beginning of +* the function to jump directly to the new one +* example: replace_function("_HelloWorld_start", &replacement_start); +*/ +int replace_function(const char* symbol, void* newAddress) { - if(is64) return 0xFFFFFFFF; // Fixme - - // This only can handle 32bit symbols - symbolList_t* entry; - //DBG("Adding symbol %s at 0x%X\n", symbol, addr); + 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); - if(!moduleSymbols) + char* binary = (char*)addr; + if(addr != 0xFFFFFFFF) { - moduleSymbols = entry = malloc(sizeof(symbolList_t)); - + //DBG("Replacing %s to point to 0x%x\n", symbol, newAddress); + *binary++ = 0xFF; // Jump + *binary++ = 0x25; // Long Jump + *((UInt32*)binary) = (UInt32)jumpPointer; + + *jumpPointer = (UInt32)newAddress; + + return 1; } - else + else { - entry = moduleSymbols; - while(entry->next) - { - entry = entry->next; - } - - entry->next = malloc(sizeof(symbolList_t)); - entry = entry->next; + return 0; } + +} - entry->next = NULL; - entry->addr = (UInt32)addr; - entry->symbol = symbol; + +/* + * execute_hook( const char* name ) + * name - Name of the module hook + * If any callbacks have been registered for this hook + * they will be executed now in the same order that the + * hooks were added. +*/ +int execute_hook(const char* name, void* arg1, void* arg2, void* arg3, void* arg4) +{ + DBG("Attempting to execute hook '%s'\n", name); DBGPAUSE(); + moduleHook_t* hook = hook_exists(name); - if(strcmp(symbol, "start") == 0) + if(hook) { - return addr; + // 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; } else { - return 0xFFFFFFFF; // fixme + // Callback for this hook doesn't exist; + DBG("No callbacks for '%s' hook.\n", name); + return 0; } } + /* - * print out the information about the loaded module - + * register_hook_callback( const char* name, void(*callback)()) + * name - Name of the module hook to attach to. + * callbacks - The funciton pointer that will be called when the + * hook is executed. When registering a new callback name, the callback is added sorted. + * NOTE: the hooks take four void* arguments. */ -void module_loaded(const char* name/*, UInt32 version, UInt32 compat*/) -{ - // TODO: insert sorted - moduleList_t* new_entry = malloc(sizeof(moduleList_t)); - - new_entry->next = loadedModules; - loadedModules = new_entry; +void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*)) +{ + DBG("Adding callback for '%s' hook.\n", name); DBGPAUSE(); - new_entry->module = (char*)name; - new_entry->version = 0; //version; - new_entry->compat = 0; //compat; -} - -int is_module_loaded(const char* name) -{ - // todo sorted search - moduleList_t* entry = loadedModules; - while(entry) + moduleHook_t* hook = hook_exists(name); + + if(hook) { - DBG("Comparing %s with %s\n", name, entry->module); - if(strcmp(entry->module, name) == 0) - { - DBG("Located module %s\n", name); - return 1; - } - else - { - entry = entry->next; - } - + // append + callbackList_t* newCallback = malloc(sizeof(callbackList_t)); + newCallback->next = hook->callbacks; + hook->callbacks = newCallback; + newCallback->callback = callback; } - DBG("Module %s not found\n", name); - - return 0; -} - -// Look for symbols using the Smbols moduel function. -// If non are found, look through the list of module symbols -unsigned int lookup_all_symbols(const char* name) -{ - unsigned int addr = 0xFFFFFFFF; - symbolList_t* entry = moduleSymbols; - while(entry) + else { - if(strcmp(entry->symbol, name) == 0) - { - //DBG("External symbol %s located at 0x%X\n", name, entry->addr); - return entry->addr; - } - else - { - entry = entry->next; - } - + // create new hook + moduleHook_t* newHook = malloc(sizeof(moduleHook_t)); + newHook->name = name; + newHook->callbacks = malloc(sizeof(callbackList_t)); + newHook->callbacks->callback = callback; + newHook->callbacks->next = NULL; + + newHook->next = moduleCallbacks; + moduleCallbacks = newHook; + } - if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF) - { - addr = lookup_symbol(name); - if(addr != 0xFFFFFFFF) - { - //DBG("Internal symbol %s located at 0x%X\n", name, addr); - return addr; - } - } - - #if DEBUG_MODULES - verbose("Unable to locate symbol %s\n", name); - getc(); + //print_hook_list(); + //getc(); #endif - - return 0xFFFFFFFF; + } -/* - * parse the symbol table - * Lookup any undefined symbols - */ - -unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, long long, char), char is64) +moduleHook_t* hook_exists(const char* name) { - // 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) + moduleHook_t* hooks = moduleCallbacks; - unsigned int module_start = 0xFFFFFFFF; - - UInt32 symbolIndex = 0; - char* symbolString = base + (char*)symtabCommand->stroff; - //char* symbolTable = base + symtabCommand->symoff; - if(!is64) + // look for a hook. If it exists, return the moduleHook_t*, + // If not, return NULL. + while(hooks) { - struct nlist* symbolEntry = (void*)base + symtabCommand->symoff; - while(symbolIndex < symtabCommand->nsyms) + if(strcmp(name, hooks->name) == 0) { - // If the symbol is exported by this module - if(symbolEntry->n_value && - symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF) - { - - // Module start located. Start is an alias so don't register it - module_start = base + symbolEntry->n_value; - } - - symbolEntry++; - symbolIndex++; // TODO remove + //DBG("Located hook %s\n", name); + return hooks; } + hooks = hooks->next; } - 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) - while(symbolIndex < symtabCommand->nsyms) - { - - - // If the symbol is exported by this module - if(symbolEntry->n_value && - symbol_handler(symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64) != 0xFFFFFFFF) - { - - // Module start located. Start is an alias so don't register it - module_start = base + symbolEntry->n_value; - } - - symbolEntry++; - symbolIndex++; // TODO remove - } - } - - return module_start; + //DBG("Hook %s does not exist\n", name); + return NULL; } - -/* - * Locate the symbol for an already loaded function and modify the beginning of - * the function to jump directly to the new one - * example: replace_function("_HelloWorld_start", &replacement_start); - */ -int replace_function(const char* symbol, void* newAddress) +#if DEBUG_MODULES +void print_hook_list() { - 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); + printf("---Hook Table---\n"); - char* binary = (char*)addr; - if(addr != 0xFFFFFFFF) + moduleHook_t* hooks = moduleCallbacks; + while(hooks) { - DBG("Replacing %s to point to 0x%x\n", symbol, newAddress); - *binary++ = 0xFF; // Jump - *binary++ = 0x25; // Long Jump - *((UInt32*)binary) = (UInt32)jumpPointer; - - *jumpPointer = (UInt32)newAddress; - - return 1; + printf("Hook: %s\n", hooks->name); + hooks = hooks->next; } - else - { - return 0; - } - } +#endif +/********************************************************************************/ +/* dyld / Linker Interface */ +/********************************************************************************/ + void dyld_stub_binder() { // TODO: actualy impliment this function (asm) - stop("ERROR: dyld_stub_binder was called, should have been take care of by the linker.\n"); -} \ No newline at end of file + printf("ERROR: dyld_stub_binder was called, should have been take care of by the linker.\n"); + getc(); +} Index: branches/meklort/i386/boot2/modules.h =================================================================== --- branches/meklort/i386/boot2/modules.h (revision 716) +++ branches/meklort/i386/boot2/modules.h (revision 717) @@ -64,44 +64,56 @@ int init_module_system(); void load_all_modules(); -/* - * Modules Interface - * execute_hook - * Exexutes a registered hook. All callbaks are - * called in the same order that they were added - * - * register_hook_callback - * registers a void function to be executed when a - * hook is executed. - */ -int execute_hook(const char* name, void*, void*, void*, void*); -void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*)); -inline void rebase_location(UInt32* location, char* base, int type); -inline void bind_location(UInt32* location, char* value, UInt32 addend, int type); -void rebase_macho(void* base, char* rebase_stream, UInt32 size); -void bind_macho(void* base, char* bind_stream, UInt32 size); int load_module(char* module); int is_module_loaded(const char* name); void module_loaded(const char* name/*, UInt32 version, UInt32 compat*/); -long long add_symbol(char* symbol, long long addr, char is64); -void* parse_mach(void* binary, - int(*dylib_loader)(char*), - long long(*symbol_handler)(char*, long long, char) - ); -unsigned int handle_symtable(UInt32 base, + +/********************************************************************************/ +/* Symbol Functions */ +/********************************************************************************/ +long long add_symbol(char* symbol, long long addr, char is64); +unsigned int lookup_all_symbols(const char* name); + + + +/********************************************************************************/ +/* Macho Parser */ +/********************************************************************************/ +void* parse_mach(void* binary, + int(*dylib_loader)(char*), + long long(*symbol_handler)(char*, long long, char)); +unsigned int handle_symtable(UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, long long, char), char is64); - -unsigned int lookup_all_symbols(const char* name); +void rebase_macho(void* base, char* rebase_stream, UInt32 size); +inline void rebase_location(UInt32* location, char* base, int type); +void bind_macho(void* base, char* bind_stream, UInt32 size); +inline void bind_location(UInt32* location, char* value, UInt32 addend, int type); -int replace_function(const char* symbol, void* newAddress); -//extern unsigned int (*lookup_symbol)(const char*); + +/********************************************************************************/ +/* Module Interface */ +/********************************************************************************/ +int replace_function(const char* symbol, void* newAddress); +int execute_hook(const char* name, void*, void*, void*, void*); +void register_hook_callback(const char* name, void(*callback)(void*, void*, void*, void*)); +moduleHook_t* hook_exists(const char* name); + +#if DEBUG_MODULES +void print_hook_list(); +#endif + +/********************************************************************************/ +/* dyld Interface */ +/********************************************************************************/ +void dyld_stub_binder(); + #endif /* __BOOT_MODULES_H */ \ No newline at end of file Index: branches/meklort/i386/boot2/modules_support.s =================================================================== --- branches/meklort/i386/boot2/modules_support.s (revision 716) +++ branches/meklort/i386/boot2/modules_support.s (revision 717) @@ -1,4 +1,4 @@ #include LABEL(dyld_stub_binder) - ret \ No newline at end of file + jmp _dyld_stub_binder \ No newline at end of file Index: branches/meklort/i386/boot2/Makefile =================================================================== --- branches/meklort/i386/boot2/Makefile (revision 716) +++ branches/meklort/i386/boot2/Makefile (revision 717) @@ -93,8 +93,21 @@ -Wl,-sectcreate,__DATA,__Symbols,$(SYMROOT)/Symbols.dylib \ -o $(SYMROOT)/boot.sys $(filter %.o,$^) $(LIBS) -lcc_kext + @# Second pass, fixup global var locations + @${RM} $(OBJROOT)/Symbols.o + @${RM} $(SYMROOT)/${SYMBOLS_MODULE} + @${RM} $(SYMROOT)/Symbols.h + @make Symbols.dylib + @${RM} $(SYMROOT)/boot.sys + @echo "\t[LD] boot.sys" + @$(LD) -static -Wl,-preload -Wl,-segaddr,__INIT,$(BOOT2ADDR) \ + -nostdlib -arch i386 -Wl,-segalign,20 \ + -Wl,-sectcreate,__DATA,__Symbols,$(SYMROOT)/Symbols.dylib \ + -o $(SYMROOT)/boot.sys $(filter %.o,$^) $(LIBS) -lcc_kext + + @ld -arch i386 \ -undefined dynamic_lookup \ -dylib -read_only_relocs suppress \ @@ -107,6 +120,7 @@ @make embed_symbols # this is done in a sub process after boot.sys exists so the strings are populated correctly + @${RM} $(SYMROOT)/boot2.sys @${RM} $(SYMROOT)/${SYMBOLS_MODULE} Index: branches/meklort/i386/modules/KextPatcher/kext_patcher.c =================================================================== --- branches/meklort/i386/modules/KextPatcher/kext_patcher.c (revision 716) +++ branches/meklort/i386/modules/KextPatcher/kext_patcher.c (revision 717) @@ -424,7 +424,7 @@ case PCI_CLASS_NETWORK_OTHER: // Patch BCM43xx - if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFF00) == 0x4300)) + if(current->vendor_id == 0x14E4 && ((current->device_id & 0xFFD0) == 0x4300)) { patch_bcm_deviceid = current->device_id; } Index: branches/meklort/i386/modules/Resolution/Resolution.c =================================================================== --- branches/meklort/i386/modules/Resolution/Resolution.c (revision 716) +++ branches/meklort/i386/modules/Resolution/Resolution.c (revision 717) @@ -9,6 +9,6 @@ void Resolution_start() { - //patchVideoBios(); + patchVideoBios(); } Index: branches/meklort/i386/modules/Memory/spd.c =================================================================== --- branches/meklort/i386/modules/Memory/spd.c (revision 716) +++ branches/meklort/i386/modules/Memory/spd.c (revision 717) @@ -80,12 +80,7 @@ outb(base + SMBHSTSTS, 0x1f); // reset SMBus Controller outb(base + SMBHSTDAT, 0xff); - while( inb(base + SMBHSTSTS) & 0x01) - { - rdtsc(l2, h2); - t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / (Platform->CPU.TSCFrequency / 100); - if(t > 50) return 0xFF; // hack, exit if unresponsive. - } + while( inb(base + SMBHSTSTS) & 0x01); outb(base + SMBHSTCMD, cmd); outb(base + SMBHSTADD, (adr << 1) | 0x01 ); Index: branches/meklort/i386/modules/Makefile =================================================================== --- branches/meklort/i386/modules/Makefile (revision 716) +++ branches/meklort/i386/modules/Makefile (revision 717) @@ -26,7 +26,7 @@ VPATH = $(OBJROOT):$(SYMROOT) # The order of building is important. -SUBDIRS = klibc uClibc++ Resolution KernelPatcher GUI KextPatcher GraphicsEnabler HPET USBFix Memory Networking NetbookInstaller ACPIPatcher HelloWorld +SUBDIRS = klibc uClibc++ Resolution KernelPatcher GUI KextPatcher GraphicsEnabler HPET USBFix Memory Networking NetbookInstaller ACPIPatcher #SUBDIRS = HelloWorld all embedtheme optionrom tags debug install installhdrs: objroot_dirs lazydylib1.o