diff --git a/loader/Makefile b/loader/Makefile index 5d33db9..3af2aa5 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -45,9 +45,9 @@ INCLUDES := src/libelf \ # options for code generation #--------------------------------------------------------------------------------- CFLAGS := -std=gnu11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ - -O3 -D__wiiu__ -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) + -O0 -D__wiiu__ -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing $(INCLUDE) CXXFLAGS := -std=gnu++11 -mrvl -mcpu=750 -meabi -mhard-float -ffast-math \ - -O3 -D__wiiu__ -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing -D_GNU_SOURCE $(INCLUDE) + -O0 -D__wiiu__ -Wall -Wextra -Wno-unused-parameter -Wno-strict-aliasing -D_GNU_SOURCE $(INCLUDE) ifeq ($(DO_LOGGING), 1) CFLAGS += -D__LOGGING__ diff --git a/loader/src/elf_utils.cpp b/loader/src/elf_utils.cpp index 0d00fc9..4535004 100644 --- a/loader/src/elf_utils.cpp +++ b/loader/src/elf_utils.cpp @@ -34,8 +34,16 @@ #include #include #include +#include "utils.h" + +#define MODULE_RELOCATIONS_CAPCITY_DEFAULT 128 + +module_unresolved_relocation_t *module_relocations = NULL; +size_t module_relocations_count = 0; +size_t module_relocations_capacity = 0; + +bool Module_ElfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr,void *destination) { -int Module_ElfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr, void *destination) { assert(destination != NULL); switch (shdr->sh_type) { @@ -51,18 +59,18 @@ int Module_ElfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr, memcpy((char *)destination + n, data->d_buf, data->d_size); n += data->d_size; } - return 1; + return true; } case SHT_NOBITS: { memset(destination, 0, shdr->sh_size); - return 1; + return true; } default: - return 0; + return false; } } -int Module_LoadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count,size_t *symtab_strndx) { +bool Module_LoadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count, size_t *symtab_strndx) { Elf_Scn *scn; - int result = 0; + bool result = false; for (scn = elf_nextscn(elf, NULL); scn != NULL; @@ -75,12 +83,10 @@ int Module_LoadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count,size continue; if (shdr->sh_type == SHT_SYMTAB) { - size_t shstrndx; - size_t sym; assert (*symtab == NULL); - *symtab = (Elf32_Sym *) malloc(shdr->sh_size); + *symtab = (Elf32_Sym *)malloc(shdr->sh_size); if (*symtab == NULL) continue; @@ -90,8 +96,9 @@ int Module_LoadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count,size if (!Module_ElfLoadSection(elf, scn, shdr, *symtab)) goto exit_error; - for (sym = 0; sym < *symtab_count; sym++) + for (sym = 0; sym < *symtab_count; sym++){ (*symtab)[sym].st_other = 0; + } break; } @@ -100,13 +107,12 @@ int Module_LoadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count,size if (*symtab == NULL) goto exit_error; - result = 1; + result = true; exit_error: return result; } void Module_ElfLoadSymbols(size_t shndx, const void *destination, Elf32_Sym *symtab, size_t symtab_count) { - size_t i; /* use the st_other field (no defined meaning) to indicate whether or not a @@ -121,18 +127,17 @@ void Module_ElfLoadSymbols(size_t shndx, const void *destination, Elf32_Sym *sym } } -bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t shndx, void *destination,Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx,int allow_globals) { +bool Module_ElfLink(size_t index, Elf *elf, size_t shndx, void *destination, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx, bool allow_globals) { Elf_Scn *scn; - for (scn = elf_nextscn(elf, NULL); - scn != NULL; - scn = elf_nextscn(elf, scn)) { + for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) { Elf32_Shdr *shdr; shdr = elf32_getshdr(scn); if (shdr == NULL) continue; + switch (shdr->sh_type) { case SHT_REL: { const Elf32_Rel *rel; @@ -168,25 +173,32 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t module_unresolved_relocation_t *reloc; char *name; - reloc = (module_unresolved_relocation_t*) malloc(sizeof(module_unresolved_relocation_t)); - if (reloc == NULL){ - DEBUG_FUNCTION_LINE("WARNING: failed to allocate space for relocate struct.\n"); + reloc = (module_unresolved_relocation_t *) Module_ListAllocate( + &module_relocations, + sizeof(module_unresolved_relocation_t), 1, + &module_relocations_capacity, + &module_relocations_count, + MODULE_RELOCATIONS_CAPCITY_DEFAULT); + if (reloc == NULL) return false; - } - name = elf_strptr(elf, symtab_strndx, symtab[symbol].st_name); + name = elf_strptr( + elf, symtab_strndx, symtab[symbol].st_name); if (name == NULL) { - DEBUG_FUNCTION_LINE("WARNING: name == NULL.\n"); + module_relocations_count--; return false; } reloc->name = strdup(name); if (reloc->name == NULL) { - DEBUG_FUNCTION_LINE("WARNING: strdup failed.\n"); + module_relocations_count--; return false; } + DEBUG_FUNCTION_LINE("Adding relocation!\n"); + + reloc->module = index; reloc->address = destination; reloc->offset = rel[i].r_offset; reloc->type = ELF32_R_TYPE(rel[i].r_info); @@ -194,8 +206,6 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t *(int *)((char *)destination + rel[i].r_offset); - module_information->rel.push_back(reloc); - continue; } else return false; @@ -227,7 +237,7 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t if (data == NULL) continue; - rela = (Elf32_Rela*) data->d_buf; + rela = (const Elf32_Rela *) data->d_buf; for (i = 0; i < shdr->sh_size / sizeof(Elf32_Rela); i++) { uint32_t symbol_addr; @@ -249,40 +259,44 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t module_unresolved_relocation_t *reloc; char *name; - reloc = (module_unresolved_relocation_t*) malloc(sizeof(module_unresolved_relocation_t)); - if (reloc == NULL){ - DEBUG_FUNCTION_LINE("WARNING: failed to allocate space for relocate struct.\n"); + reloc = (module_unresolved_relocation_t *) Module_ListAllocate( + &module_relocations, + sizeof(module_unresolved_relocation_t), 1, + &module_relocations_capacity, + &module_relocations_count, + MODULE_RELOCATIONS_CAPCITY_DEFAULT); + if (reloc == NULL) return false; - } - - name = elf_strptr(elf, symtab_strndx, symtab[symbol].st_name); + name = elf_strptr( + elf, symtab_strndx, symtab[symbol].st_name); if (name == NULL) { - DEBUG_FUNCTION_LINE("WARNING: name == NULL.\n"); + module_relocations_count--; return false; } reloc->name = strdup(name); if (reloc->name == NULL) { - DEBUG_FUNCTION_LINE("WARNING: strdup failed.\n"); + module_relocations_count--; return false; } + DEBUG_FUNCTION_LINE("Adding relocation!\n"); + + reloc->module = index; reloc->address = destination; reloc->offset = rela[i].r_offset; reloc->type = ELF32_R_TYPE(rela[i].r_info); reloc->addend = rela[i].r_addend; - module_information->rel.push_back(reloc); - continue; } else return false; } default: { + if (symtab[symbol].st_other != 1) return false; - symbol_addr = symtab[symbol].st_value; break; } @@ -298,13 +312,13 @@ bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t } } - return 1; + return true; } -int Module_ElfLinkOne(char type, size_t offset, int addend, void *destination, uint32_t symbol_addr) { +bool Module_ElfLinkOne(char type, size_t offset, int addend, void *destination, uint32_t symbol_addr) { int value; char *target = (char *)destination + offset; - int result = 0; + bool result = false; switch (type) { case R_PPC_ADDR32: @@ -403,8 +417,9 @@ int Module_ElfLinkOne(char type, size_t offset, int addend, void *destination, u goto exit_error; } - result = 1; + result = true; exit_error: if (!result) DEBUG_FUNCTION_LINE("Module_ElfLinkOne: exit_error\n"); return result; } + diff --git a/loader/src/elf_utils.h b/loader/src/elf_utils.h index e636266..4b3fb78 100644 --- a/loader/src/elf_utils.h +++ b/loader/src/elf_utils.h @@ -14,11 +14,13 @@ extern "C" { #include "module_parser.h" -int Module_ElfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr, void *destination); -int Module_LoadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count,size_t *symtab_strndx); +bool Module_ElfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr,void *destination); +bool Module_LoadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count, size_t *symtab_strndx); void Module_ElfLoadSymbols(size_t shndx, const void *destination, Elf32_Sym *symtab, size_t symtab_count); -bool Module_ElfLink(module_information_t * module_information, Elf *elf, size_t shndx, void *destination,Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx,int allow_globals); -int Module_ElfLinkOne(char type, size_t offset, int addend, void *destination, uint32_t symbol_addr); -void *Module_ListAllocate(void *list, size_t entry_size, size_t num, size_t *capacity, size_t *count, size_t default_capacity); +bool Module_ElfLink(size_t index, Elf *elf, size_t shndx, void *destination, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx, bool allow_globals); +bool Module_ElfLinkOne(char type, size_t offset, int addend, void *destination, uint32_t symbol_addr); +extern size_t module_relocations_count; +extern module_unresolved_relocation_t *module_relocations; +extern size_t module_relocations_capacity; #endif diff --git a/loader/src/link_utils.cpp b/loader/src/link_utils.cpp index 50673c1..b5b26e1 100644 --- a/loader/src/link_utils.cpp +++ b/loader/src/link_utils.cpp @@ -36,20 +36,32 @@ #include #include #include +#include -bool Module_LinkModule(module_information_t * module_information, uint8_t **space) { - if(module_information == NULL){ - DEBUG_FUNCTION_LINE("module_information is null\n"); - } - module_metadata_t * metadata = module_information->metadata; - const char * path = NULL; - if(metadata != NULL && metadata->path != NULL){ - path = metadata->path; - }else{ - DEBUG_FUNCTION_LINE("metadata is null\n"); - return false; +#define MODULE_ENTRIES_CAPACITY_DEFAULT 128 + +wups_loader_entry_t *module_entries = NULL; +size_t module_entries_count = 0; +size_t module_entries_capacity = 0; + +bool Module_ListLink(uint8_t **space) { + size_t i; + bool result = false; + + for (i = 0; i < module_list_count; i++) { + if (!Module_LinkModule(i, module_list[i]->path, space)) + goto exit_error; } + result = true; +exit_error: + if (!result) DEBUG_FUNCTION_LINE("Module_ListLink: exit_error\n"); + return result; +} + +bool Module_LinkModule(size_t index, const char *path, uint8_t **space) { + DEBUG_FUNCTION_LINE("Running Module_LinkModule for %s\n",path); + int fd = -1; Elf *elf = NULL; bool result = false; @@ -72,7 +84,8 @@ bool Module_LinkModule(module_information_t * module_information, uint8_t **spac /* TODO */ goto exit_error; case ELF_K_ELF: - if (!Module_LinkModuleElf(module_information, elf, space)) + DEBUG_FUNCTION_LINE("Calling now Module_LinkModuleElf\n"); + if (!Module_LinkModuleElf(index, elf, space)) goto exit_error; break; default: @@ -89,7 +102,7 @@ exit_error: return result; } -bool Module_LinkModuleElf(module_information_t * module_information, Elf *elf, uint8_t **space) { +bool Module_LinkModuleElf(size_t index, Elf *elf, uint8_t **space) { Elf_Scn *scn; size_t symtab_count, section_count, shstrndx, symtab_strndx, entries_count; Elf32_Sym *symtab = NULL; @@ -137,7 +150,10 @@ bool Module_LinkModuleElf(module_information_t * module_information, Elf *elf, u goto exit_error; entries_count = shdr->sh_size / sizeof(wups_loader_entry_t); - entries = (wups_loader_entry_t*) malloc(sizeof(wups_loader_entry_t)*entries_count); + entries = (wups_loader_entry_t*) Module_ListAllocate( + &module_entries, sizeof(wups_loader_entry_t), + entries_count, &module_entries_capacity, + &module_entries_count, MODULE_ENTRIES_CAPACITY_DEFAULT); if (entries == NULL) goto exit_error; @@ -145,14 +161,10 @@ bool Module_LinkModuleElf(module_information_t * module_information, Elf *elf, u destinations[elf_ndxscn(scn)] = (uint8_t *)entries; if (!Module_ElfLoadSection(elf, scn, shdr, entries)) goto exit_error; - Module_ElfLoadSymbols(elf_ndxscn(scn), entries, symtab, symtab_count); - for(int i = 0;ientries.push_back(curEntry); - } - + Module_ElfLoadSymbols( + elf_ndxscn(scn), entries, symtab, symtab_count); } else { - DEBUG_FUNCTION_LINE("Copy the function to %08X\n",*space); + DEBUG_FUNCTION_LINE("Copy function to %08X\n",*space); *space -= shdr->sh_size; if (shdr->sh_addralign > 3) *space = (uint8_t *)((int)*space & @@ -165,7 +177,8 @@ bool Module_LinkModuleElf(module_information_t * module_information, Elf *elf, u assert(*space != NULL); if (!Module_ElfLoadSection(elf, scn, shdr, *space)) goto exit_error; - Module_ElfLoadSymbols(elf_ndxscn(scn), *space, symtab, symtab_count); + Module_ElfLoadSymbols( + elf_ndxscn(scn), *space, symtab, symtab_count); } } } @@ -187,7 +200,8 @@ bool Module_LinkModuleElf(module_information_t * module_information, Elf *elf, u (shdr->sh_flags & SHF_ALLOC) && destinations[elf_ndxscn(scn)] != NULL) { - if (!Module_ElfLink(module_information, elf, elf_ndxscn(scn), destinations[elf_ndxscn(scn)], + if (!Module_ElfLink( + index, elf, elf_ndxscn(scn), destinations[elf_ndxscn(scn)], symtab, symtab_count, symtab_strndx, true)) goto exit_error; } @@ -202,3 +216,83 @@ exit_error: free(symtab); return result; } + +bool Module_ListLinkFinal(uint8_t **space) { + size_t relocation_index, entry_index, module_index; + bool result = false, has_error = false; + + relocation_index = 0; + entry_index = 0; + + /* Process the replacements the link each module in turn. + * It must be done in this order, otherwise two replacements to the same + * function will cause an infinite loop. */ + for (module_index = 0; module_index < module_list_count; module_index++) { + size_t limit; + + limit = entry_index + module_list[module_index]->entries_count; + + /*for (; entry_index < limit; entry_index++) { + wups_loader_entry_t *entry; + + assert(entry_index < module_entries_count); + + entry = module_entries + entry_index; + + switch (entry->type) { + case WUPS_LOADER_ENTRY_EXPORT: { + break; + } case WUPS_LOADER_ENTRY_FUNCTION: + case WUPS_LOADER_ENTRY_FUNCTION_MANDATORY: { + if (!Module_ListLinkFinalReplaceFunction(space, entry)) + goto exit_error; + break; + } default: + goto exit_error; + } + }*/ + + for (; + relocation_index < module_relocations_count; + relocation_index++) { + module_unresolved_relocation_t *reloc; + void *symbol; + + reloc = module_relocations + relocation_index; + + if (reloc->module != module_index) + break; + + assert(reloc->name != NULL); + //symbol = Search_SymbolLookup(reloc->name); + + if (symbol == NULL) { + DEBUG_FUNCTION_LINE( + "Missing symbol '%s' needed by '%s'\n", reloc->name, + module_list[module_index]->name); + has_error = true; + continue; + } + + if (!Module_ElfLinkOne( + reloc->type, reloc->offset, reloc->addend, + reloc->address, (uint32_t)symbol)) + goto exit_error; + } + } + + assert(entry_index == module_entries_count); + assert(relocation_index == module_relocations_count); + + if (has_error) + goto exit_error; + + result = true; +exit_error: + if (!result) DEBUG_FUNCTION_LINE("Module_ListLinkFinal: exit_error\n"); + module_relocations_count = 0; + module_relocations_capacity = 0; + free(module_relocations); + return result; +} + diff --git a/loader/src/link_utils.h b/loader/src/link_utils.h index b3033c7..8920604 100644 --- a/loader/src/link_utils.h +++ b/loader/src/link_utils.h @@ -14,6 +14,13 @@ extern "C" { #include "module_parser.h" -bool Module_LinkModule(module_information_t * module_information, uint8_t **space); -bool Module_LinkModuleElf(module_information_t * module_information, Elf *elf, uint8_t **space); +bool Module_ListLink(uint8_t **space); +bool Module_LinkModule(size_t index, const char *path, uint8_t **space); +bool Module_LinkModuleElf(size_t index, Elf *elf, uint8_t **space); +bool Module_ListLinkFinal(uint8_t **space); + +extern wups_loader_entry_t *module_entries; +extern size_t module_entries_count; +extern size_t module_entries_capacity; + #endif diff --git a/loader/src/main.cpp b/loader/src/main.cpp index b7eb818..958988b 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -21,6 +21,10 @@ #include "utils.h" #include "module_parser.h" #include "link_utils.h" +#include "elf_utils.h" + +static void printModuleInfos(); +static void printInfos(); /* Entry point */ extern "C" int Menu_Main(int argc, char **argv){ @@ -68,11 +72,50 @@ void loadAndProcessElf(const char * elfPath){ DEBUG_FUNCTION_LINE("Now try to use brainslug code\n"); if(Module_CheckFile(elfPath)){ - module_information_t * moduleInformation = Module_LoadModuleInformation(elfPath); - if(moduleInformation != NULL){ - uint8_t * space = (uint8_t *)0x880000; - Module_LinkModule(moduleInformation,&space); - printModuleInformation(moduleInformation); + Module_Load(elfPath); + DEBUG_FUNCTION_LINE("Found %d modules!\n",module_list_count); + //printInfos(); + unsigned char * space = (unsigned char*)0x00910000; + Module_ListLink(&space); + + if(module_relocations_count == 0){ + DEBUG_FUNCTION_LINE("We need no relocations, we can call the functions!!\n"); + DEBUG_FUNCTION_LINE("Calling %d functions!\n",module_entries_count); + for (unsigned int i = 0; i < module_entries_count; i++) { + DEBUG_FUNCTION_LINE("--- Function %d ---\n",i); + if( module_entries[i].type == WUPS_LOADER_ENTRY_FUNCTION || + module_entries[i].type == WUPS_LOADER_ENTRY_FUNCTION_MANDATORY){ + DEBUG_FUNCTION_LINE("Let's call the function: %s \n",module_entries[i].data._function.name); + int ret = ( (int (*)(void))((unsigned int*)module_entries[i].data._function.target) )(); + DEBUG_FUNCTION_LINE("result: %d \n",ret); + } + } } } + +} + +static void printInfos(){ + for (unsigned int i = 0; i < module_list_count; i++) { + DEBUG_FUNCTION_LINE("--- Module %d ---\n",i); + DEBUG_FUNCTION_LINE("name: %s\n",module_list[i]->name); + DEBUG_FUNCTION_LINE("path: %s\n",module_list[i]->path); + DEBUG_FUNCTION_LINE("author: %s\n",module_list[i]->author); + } + DEBUG_FUNCTION_LINE("--- Module list end ---\n"); + for (unsigned int i = 0; i < module_entries_count; i++) { + DEBUG_FUNCTION_LINE("--- Entry %d ---\n",i); + if( module_entries[i].type == WUPS_LOADER_ENTRY_FUNCTION || + module_entries[i].type == WUPS_LOADER_ENTRY_FUNCTION_MANDATORY){ + DEBUG_FUNCTION_LINE("library: %d \n",module_entries[i].data._function.library); + DEBUG_FUNCTION_LINE("function: %s \n",module_entries[i].data._function.name); + DEBUG_FUNCTION_LINE("pointer: %08X \n",module_entries[i].data._function.target); + } + } + DEBUG_FUNCTION_LINE("--- Entry list end ---\n"); + for (unsigned int i = 0; i < module_relocations_count; i++) { + DEBUG_FUNCTION_LINE("--- Relocation %d ---\n",i); + DEBUG_FUNCTION_LINE("name: %s\n",module_relocations[i].name); + } + DEBUG_FUNCTION_LINE("--- Relocation list end ---\n"); } diff --git a/loader/src/module_parser.cpp b/loader/src/module_parser.cpp index 86164eb..e125085 100644 --- a/loader/src/module_parser.cpp +++ b/loader/src/module_parser.cpp @@ -37,72 +37,18 @@ #include #include "utils.h" -static module_information_t* Module_LoadMetaDataFromElf(const char *path, Elf *elf); -static module_information_t* Module_ModuleInformationRead(const char *path, Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx); +bool module_has_error; +bool module_has_info; -void printModuleInformation(module_information_t* module_information){ - if(module_information == NULL){ - DEBUG_FUNCTION_LINE("module_information is null\n"); - } +#define MODULE_LIST_CAPACITY_DEFAULT 16 - module_metadata_t * metadata = module_information->metadata; - std::vector relocations = module_information->rel; - DEBUG_FUNCTION_LINE("relocations size: %d\n",relocations.size()); - for (std::vector::iterator it = relocations.begin() ; it != relocations.end(); ++it){ - module_unresolved_relocation_t * relo = *it; - DEBUG_FUNCTION_LINE("----\n",relo); - DEBUG_FUNCTION_LINE("name %s\n",relo->name); - DEBUG_FUNCTION_LINE("offset %d\n",relo->offset); - DEBUG_FUNCTION_LINE("type %d\n",relo->type); - DEBUG_FUNCTION_LINE("address %08X\n",relo->address); - DEBUG_FUNCTION_LINE("append %d\n",relo->addend); - } +size_t module_list_size = 0; +module_metadata_t **module_list = NULL; +size_t module_list_count = 0; +static size_t module_list_capacity = 0; - DEBUG_FUNCTION_LINE("entries size: %d\n",relocations.size()); - std::vector entries = module_information->entries; - for (std::vector::iterator it = entries.begin() ; it != entries.end(); ++it){ - //Added entry. - wups_loader_entry_t * curEntry = *it; - DEBUG_FUNCTION_LINE("Found entry @ %08X\n",curEntry); - dumpHex(curEntry,sizeof(wups_loader_entry_t)); - - DEBUG_FUNCTION_LINE("type %d\n",curEntry->type); - if( curEntry->type == WUPS_LOADER_ENTRY_FUNCTION || - curEntry->type == WUPS_LOADER_ENTRY_FUNCTION_MANDATORY){ - - DEBUG_FUNCTION_LINE("library %d \n",curEntry->data._function.library); - DEBUG_FUNCTION_LINE("function %s \n",curEntry->data._function.name); - DEBUG_FUNCTION_LINE("target pointer %08X \n",curEntry->data._function.target); - dumpHex(curEntry->data._function.target,0x100); - } - } - - if(metadata != NULL){ - if(metadata->author != NULL){ - DEBUG_FUNCTION_LINE("Author: %s.\n", metadata->author); - }else{ - DEBUG_FUNCTION_LINE("Author: is null\n"); - } - if(metadata->license != NULL){ - DEBUG_FUNCTION_LINE("License: %s.\n", metadata->license); - }else{ - DEBUG_FUNCTION_LINE("License: is null\n"); - } - if(metadata->name != NULL){ - DEBUG_FUNCTION_LINE("Name: %s.\n", metadata->name); - }else{ - DEBUG_FUNCTION_LINE("Name: is null\n"); - } - if(metadata->path != NULL){ - DEBUG_FUNCTION_LINE("Path: %s.\n", metadata->path); - }else{ - DEBUG_FUNCTION_LINE("Path: is null\n"); - } - DEBUG_FUNCTION_LINE("entries_count: %d \n",metadata->entries_count); - }else{ - DEBUG_FUNCTION_LINE("metadata is null\n"); - } -} +static void Module_LoadElf(const char *path, Elf *elf); +static module_metadata_t *Module_MetadataRead(const char *path, size_t index, Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx); bool Module_CheckFile(const char *path) { const char *extension; @@ -126,10 +72,7 @@ bool Module_CheckFile(const char *path) { return false; } -module_information_t* Module_LoadModuleInformation(const char *path) { - DEBUG_FUNCTION_LINE("Loading path: %s\n", path); - - module_information_t* result = NULL; +void Module_Load(const char *path) { int fd = -1; Elf *elf = NULL; @@ -150,34 +93,34 @@ module_information_t* Module_LoadModuleInformation(const char *path) { switch (elf_kind(elf)) { case ELF_K_AR: /* TODO */ - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Archives not yet supported.\n", path); - //module_has_info = 1; + DEBUG_FUNCTION_LINE( + "Warning: Ignoring '%s' - Archives not yet supported.\n", path); + module_has_info = true; goto exit_error; case ELF_K_ELF: - DEBUG_FUNCTION_LINE("Module_LoadElf(path, elf);\n"); - result = Module_LoadMetaDataFromElf(path, elf); + Module_LoadElf(path, elf); break; default: - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF file.\n", path); + DEBUG_FUNCTION_LINE( + "Warning: Ignoring '%s' - Invalid ELF file.\n", path); goto exit_error; } exit_error: if (elf != NULL) - //elf_end(elf); + elf_end(elf); if (fd != -1) close(fd); - return result; } -module_information_t* Module_LoadMetaDataFromElf(const char *path, Elf *elf) { +static void Module_LoadElf(const char *path, Elf *elf) { Elf_Scn *scn; Elf32_Ehdr *ehdr; char *ident; size_t shstrndx, sz, symtab_count, i, symtab_strndx; Elf32_Sym *symtab = NULL; module_metadata_t *metadata = NULL; - module_information_t* result = NULL; + module_metadata_t **list_ptr; assert(elf != NULL); assert(elf_kind(elf) == ELF_K_ELF); @@ -186,27 +129,27 @@ module_information_t* Module_LoadMetaDataFromElf(const char *path, Elf *elf) { if (ident == NULL) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF header.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (sz < 7) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF header.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (ident[4] != ELFCLASS32) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not 32 bit ELF.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (ident[5] != ELFDATA2MSB) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not Big Endian.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (ident[6] != EV_CURRENT) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Unknown ELF version.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } @@ -214,50 +157,43 @@ module_information_t* Module_LoadMetaDataFromElf(const char *path, Elf *elf) { if (ehdr == NULL) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF header\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (ehdr->e_type != ET_REL) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not relocatable ELF.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (ehdr->e_machine != EM_PPC) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Architecture not EM_PPC.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (ehdr->e_version != EV_CURRENT) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Unknown ELF version.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } - - DEBUG_FUNCTION_LINE("Loading Elf symtab\n"); if (!Module_LoadElfSymtab(elf, &symtab, &symtab_count, &symtab_strndx)) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't parse symtab.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } assert(symtab != NULL); - result = Module_ModuleInformationRead(path, elf, symtab, symtab_count, symtab_strndx); + DEBUG_FUNCTION_LINE("Reading metadata from path %s.\n", path); - if (result == NULL){ - DEBUG_FUNCTION_LINE("Module_ModuleInformationRead was null\n"); - goto exit_error; - } - - metadata = result->metadata; + metadata = Module_MetadataRead(path, module_list_count, elf, symtab, symtab_count, symtab_strndx); if (metadata == NULL) /* error reporting done inside method */ goto exit_error; if (elf_getshdrstrndx(elf, &shstrndx) != 0) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't find shdrstndx.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } @@ -283,56 +219,67 @@ module_information_t* Module_LoadMetaDataFromElf(const char *path, Elf *elf) { if (strcmp(name, ".wups.meta") == 0) { continue; } else if (strcmp(name, ".wups.load") == 0) { - metadata->size += shdr->sh_size / sizeof(wups_loader_entry_t) * 12; + metadata->size += + shdr->sh_size / sizeof(wups_loader_entry_t) * 12; } else { metadata->size += shdr->sh_size; /* add alignment padding to size */ - if (shdr->sh_addralign > 3){ + if (shdr->sh_addralign > 3) /* roundup to multiple of sh_addralign */ - metadata->size += (-metadata->size & (shdr->sh_addralign - 1)); - }else{ + metadata->size += + (-metadata->size & (shdr->sh_addralign - 1)); + else /* roundup to multiple of 4 */ metadata->size += (-metadata->size & 3); - } } } } /* roundup to multiple of 4 */ metadata->size += (-metadata->size & 3); - return result; + + list_ptr = (module_metadata_t **)Module_ListAllocate( + &module_list, sizeof(module_metadata_t *), 1, &module_list_capacity, + &module_list_count, MODULE_LIST_CAPACITY_DEFAULT); + if (list_ptr == NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - ENOMEM.\n", path); + module_has_info = true; + goto exit_error; + } + + assert(module_list != NULL); + assert(module_list_count <= module_list_capacity); + + *list_ptr = metadata; + module_list_size += metadata->size; + /* prevent the data being freed */ + metadata = NULL; exit_error: if (metadata != NULL) free(metadata); if (symtab != NULL) free(symtab); - return result; } -static module_information_t *Module_ModuleInformationRead(const char *path, Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx) { +static module_metadata_t *Module_MetadataRead(const char *path, size_t index, Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx) { char *metadata = NULL, *metadata_cur, *metadata_end, *tmp; - const char *name, *author, *version, *license, *wups; + const char *game, *name, *author, *version, *license, *wups; module_metadata_t *ret = NULL; - module_information_t *result = NULL; Elf_Scn *scn; size_t shstrndx, entries_count; - result = (module_information_t *) malloc(sizeof(module_information_t)); - if (result == NULL){ - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - couldn't allocate memory for meta information struct.\n", path); - return NULL; - } - if (elf_getshdrstrndx(elf, &shstrndx) != 0) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't find shstrndx\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } entries_count = 0; - for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) { + for (scn = elf_nextscn(elf, NULL); + scn != NULL; + scn = elf_nextscn(elf, scn)) { Elf32_Shdr *shdr; const char *name; @@ -346,14 +293,12 @@ static module_information_t *Module_ModuleInformationRead(const char *path, Elf continue; if (strcmp(name, ".wups.meta") == 0) { - DEBUG_FUNCTION_LINE("In section \"%s\" \n",name); - if (shdr->sh_size == 0) continue; if (metadata != NULL) continue; - metadata = (char *) malloc(shdr->sh_size); + metadata = (char*) malloc(shdr->sh_size); if (metadata == NULL) continue; @@ -361,17 +306,20 @@ static module_information_t *Module_ModuleInformationRead(const char *path, Elf DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Couldn't load .wups.meta.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } - Module_ElfLoadSymbols(elf_ndxscn(scn), metadata, symtab, symtab_count); + Module_ElfLoadSymbols( + elf_ndxscn(scn), metadata, symtab, symtab_count); - if (!Module_ElfLink(result, elf, elf_ndxscn(scn), metadata, symtab, symtab_count, symtab_strndx, 0)) { + if (!Module_ElfLink( + index, elf, elf_ndxscn(scn), metadata, + symtab, symtab_count, symtab_strndx, false)) { DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - .wups.meta contains invalid " "relocations.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } @@ -384,10 +332,11 @@ static module_information_t *Module_ModuleInformationRead(const char *path, Elf if (metadata == NULL) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not a WUPS module file.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } + game = NULL; name = NULL; author = NULL; version = NULL; @@ -409,12 +358,21 @@ static module_information_t *Module_ModuleInformationRead(const char *path, Elf if (eq == NULL) continue; - if (strncmp(metadata_cur, "name", eq - metadata_cur) == 0) { + if (strncmp(metadata_cur, "game", eq - metadata_cur) == 0) { + if (game != NULL) { + DEBUG_FUNCTION_LINE( + "Warning: Ignoring '%s' - Multiple WUPS_MODULE_GAME " + "declarations.\n", path); + module_has_info = true; + goto exit_error; + } + game = eq + 1; + } else if (strncmp(metadata_cur, "name", eq - metadata_cur) == 0) { if (name != NULL) { DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Multiple WUPS_MODULE_NAME " "declarations.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } name = eq + 1; @@ -423,7 +381,7 @@ static module_information_t *Module_ModuleInformationRead(const char *path, Elf DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Multiple WUPS_MODULE_AUTHOR " "declarations.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } author = eq + 1; @@ -432,7 +390,7 @@ static module_information_t *Module_ModuleInformationRead(const char *path, Elf DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Multiple WUPS_MODULE_VERSION " "declarations.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } version = eq + 1; @@ -441,7 +399,7 @@ static module_information_t *Module_ModuleInformationRead(const char *path, Elf DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Multiple WUPS_MODULE_LICENSE " "declarations.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } license = eq + 1; @@ -450,53 +408,56 @@ static module_information_t *Module_ModuleInformationRead(const char *path, Elf DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Multiple WUPS_MODULE_NAME " "declarations.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } wups = eq + 1; } } + if (game == NULL) + game = ""; if (wups == NULL || strcmp(wups, "0.1") != 0) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Unrecognised BSlug version.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (name == NULL) { DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Missing WUPS_MODULE_NAME declaration.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (author == NULL) { DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Missing WUPS_MODULE_AUTHOR " "declaration.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (version == NULL) { DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Missing WUPS_MODULE_VERSION " "declaration.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } if (license == NULL) { DEBUG_FUNCTION_LINE( "Warning: Ignoring '%s' - Missing WUPS_MODULE_LICENSE " "declaration.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } - ret = (module_metadata_t *) malloc(sizeof(module_metadata_t) + strlen(path) + - strlen(name) + strlen(author) + + ret = (module_metadata_t *)malloc( + sizeof(module_metadata_t) + strlen(path) + + strlen(game) + strlen(name) + strlen(author) + strlen(version) + strlen(license) + 6); if (ret == NULL) { DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't parse BSlug metadata.\n", path); - //module_has_info = 1; + module_has_info = true; goto exit_error; } @@ -518,10 +479,9 @@ static module_information_t *Module_ModuleInformationRead(const char *path, Elf ret->size = 0; ret->entries_count = entries_count; - result->metadata = ret; exit_error: if (metadata != NULL) free(metadata); - return result; + return ret; } diff --git a/loader/src/module_parser.h b/loader/src/module_parser.h index ce7bd5d..d63e5c4 100644 --- a/loader/src/module_parser.h +++ b/loader/src/module_parser.h @@ -17,7 +17,6 @@ extern "C" { typedef struct { const char *path; - const char *game; const char *name; const char *author; const char *version; @@ -27,6 +26,7 @@ typedef struct { } module_metadata_t; typedef struct { + size_t module; const char *name; void *address; size_t offset; @@ -34,14 +34,15 @@ typedef struct { int addend; } module_unresolved_relocation_t; -typedef struct { - std::vector rel; - std::vector entries; - module_metadata_t * metadata; -} module_information_t; +extern bool module_has_error; +/* whether or not to delay loading for debug messages. */ +extern bool module_has_info; + +extern size_t module_list_size; +extern module_metadata_t **module_list; +extern size_t module_list_count; bool Module_CheckFile(const char *path); -void printModuleInformation(module_information_t* module_information); -module_information_t* Module_LoadModuleInformation(const char *path); +void Module_Load(const char *path); #endif diff --git a/loader/src/utils.cpp b/loader/src/utils.cpp index ef365b1..2f02628 100644 --- a/loader/src/utils.cpp +++ b/loader/src/utils.cpp @@ -37,4 +37,33 @@ void dumpHex(const void* data, size_t size) { } } } -} \ No newline at end of file +} + +void *Module_ListAllocate(void *list, size_t entry_size, size_t num, size_t *capacity, size_t *count, size_t default_capacity) { + void *result; + + while (*capacity < *count + num) { + if (*count == 0) { + *(void **)list = malloc(entry_size * default_capacity); + + if (*(void **)list == NULL) + return NULL; + + *capacity = default_capacity; + } else { + void *temp; + + temp = realloc(*(void **)list, entry_size * *capacity * 2); + if (temp == NULL) + return NULL; + + *(void **)list = temp; + *capacity = *capacity * 2; + } + } + + result = *(char **)list + entry_size * *count; + (*count) += num; + + return result; +} diff --git a/loader/src/utils.h b/loader/src/utils.h index ac94926..065f69f 100644 --- a/loader/src/utils.h +++ b/loader/src/utils.h @@ -12,4 +12,6 @@ void dumpHex(const void* data, size_t size); } #endif +void *Module_ListAllocate(void *list, size_t entry_size, size_t num,size_t *capacity, size_t *count, size_t default_capacity); + #endif