From a31d6e8db5e73a7dfcb10c4f4539862879983356 Mon Sep 17 00:00:00 2001 From: Maschell Date: Tue, 13 Feb 2018 22:20:38 +0100 Subject: [PATCH] [Loader] Huge refactoring. Getting rid of the global lists in C. Using std::vector now and classes. --- loader/src/ElfTools.cpp | 229 ++++++++ loader/src/ElfTools.h | 48 ++ loader/src/EntryData.h | 62 ++ loader/src/HookData.h | 49 ++ loader/src/ModuleData.cpp | 778 ++++++++++++++++++++++++++ loader/src/ModuleData.h | 159 ++++++ loader/src/elf_utils.cpp | 430 -------------- loader/src/elf_utils.h | 26 - loader/src/link_utils.cpp | 362 ------------ loader/src/link_utils.h | 26 - loader/src/main.cpp | 168 +++--- loader/src/main.h | 20 +- loader/src/module_parser.cpp | 491 ---------------- loader/src/module_parser.h | 48 -- loader/src/patcher/function_patcher.h | 2 +- loader/src/utils.cpp | 29 - loader/src/utils.h | 2 - 17 files changed, 1430 insertions(+), 1499 deletions(-) create mode 100644 loader/src/ElfTools.cpp create mode 100644 loader/src/ElfTools.h create mode 100644 loader/src/EntryData.h create mode 100644 loader/src/HookData.h create mode 100644 loader/src/ModuleData.cpp create mode 100644 loader/src/ModuleData.h delete mode 100644 loader/src/elf_utils.cpp delete mode 100644 loader/src/elf_utils.h delete mode 100644 loader/src/link_utils.cpp delete mode 100644 loader/src/link_utils.h delete mode 100644 loader/src/module_parser.cpp delete mode 100644 loader/src/module_parser.h diff --git a/loader/src/ElfTools.cpp b/loader/src/ElfTools.cpp new file mode 100644 index 0000000..a24c270 --- /dev/null +++ b/loader/src/ElfTools.cpp @@ -0,0 +1,229 @@ +/* based on module.c + * by Alex Chadwick + * + * Copyright (C) 2014, Alex Chadwick + * Modified 2018, Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "ElfTools.h" +#include +#include +#include +#include +#include + +bool ElfTools::elfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr,void *destination) { + + assert(destination != NULL); + + switch (shdr->sh_type) { + case SHT_SYMTAB: + case SHT_PROGBITS: { + Elf_Data *data; + size_t n; + + n = 0; + for (data = elf_getdata(scn, NULL); data != NULL; data = elf_getdata(scn, data)) { + memcpy((char *)destination + n, data->d_buf, data->d_size); + n += data->d_size; + } + return true; + } case SHT_NOBITS: { + memset(destination, 0, shdr->sh_size); + return true; + } default: + return false; + } +} + +bool ElfTools::loadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count, size_t *symtab_strndx) { + Elf_Scn *scn; + bool result = false; + + for (scn = elf_nextscn(elf, NULL); + scn != NULL; + scn = elf_nextscn(elf, scn)) { + + Elf32_Shdr *shdr; + + shdr = elf32_getshdr(scn); + if (shdr == NULL) + continue; + + if (shdr->sh_type == SHT_SYMTAB) { + size_t sym; + + assert (*symtab == NULL); + *symtab = (Elf32_Sym *)malloc(shdr->sh_size); + if (*symtab == NULL) + continue; + + *symtab_count = shdr->sh_size / sizeof(Elf32_Sym); + *symtab_strndx = shdr->sh_link; + + if (!elfLoadSection(elf, scn, shdr, *symtab)) + goto exit_error; + + for (sym = 0; sym < *symtab_count; sym++){ + (*symtab)[sym].st_other = 0; + } + + break; + } + } + + if (*symtab == NULL) + goto exit_error; + + result = true; +exit_error: + return result; +} + + +void ElfTools::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 + * symbol address has been calculated. */ + for (i = 0; i < symtab_count; i++) { + if (symtab[i].st_shndx == shndx && + symtab[i].st_other == 0) { + + symtab[i].st_value += (Elf32_Addr)destination; + symtab[i].st_other = 1; + } + } +} + +bool ElfTools::elfLinkOne(char type, size_t offset, int addend, void *destination, uint32_t symbol_addr) { + int value; + char *target = (char *)destination + offset; + bool result = false; + + switch (type) { + case R_PPC_ADDR32: + case R_PPC_ADDR24: + case R_PPC_ADDR16: + case R_PPC_ADDR16_HI: + case R_PPC_ADDR16_HA: + case R_PPC_ADDR16_LO: + case R_PPC_ADDR14: + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + case R_PPC_UADDR32: + case R_PPC_UADDR16: { + value = (int)symbol_addr + addend; + break; + } case R_PPC_REL24: + case R_PPC_PLTREL24: + case R_PPC_LOCAL24PC: + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: + case R_PPC_REL32: + case R_PPC_ADDR30: { + value = (int)symbol_addr + addend - (int)target; + break; + } case R_PPC_SECTOFF: + case R_PPC_SECTOFF_LO: + case R_PPC_SECTOFF_HI: + case R_PPC_SECTOFF_HA: { + value = offset + addend; + break; + } case R_PPC_EMB_NADDR32: + case R_PPC_EMB_NADDR16: + case R_PPC_EMB_NADDR16_LO: + case R_PPC_EMB_NADDR16_HI: + case R_PPC_EMB_NADDR16_HA: { + value = addend - (int)symbol_addr; + break; + } default: + DEBUG_FUNCTION_LINE("Module_ElfLinkOne01: %02X\n",type); + goto exit_error; + } + + switch (type) { + case R_PPC_ADDR32: + case R_PPC_UADDR32: + case R_PPC_REL32: + case R_PPC_SECTOFF: + case R_PPC_EMB_NADDR32: { + *(int *)target = value; + break; + } case R_PPC_ADDR24: + case R_PPC_PLTREL24: + case R_PPC_LOCAL24PC: + case R_PPC_REL24: { + *(int *)target = + (*(int *)target & 0xfc000003) | (value & 0x03fffffc); + break; + } case R_PPC_ADDR16: + case R_PPC_UADDR16: + case R_PPC_EMB_NADDR16: { + *(short *)target = value; + break; + } case R_PPC_ADDR16_HI: + case R_PPC_SECTOFF_HI: + case R_PPC_EMB_NADDR16_HI: { + *(short *)target = value >> 16; + break; + } case R_PPC_ADDR16_HA: + case R_PPC_SECTOFF_HA: + case R_PPC_EMB_NADDR16_HA: { + *(short *)target = (value >> 16) + ((value >> 15) & 1); + break; + } case R_PPC_ADDR16_LO: + case R_PPC_SECTOFF_LO: + case R_PPC_EMB_NADDR16_LO: { + *(short *)target = value & 0xffff; + break; + } case R_PPC_ADDR14: + case R_PPC_REL14: { + *(int *)target = + (*(int *)target & 0xffff0003) | (value & 0x0000fffc); + break; + } case R_PPC_ADDR14_BRTAKEN: + case R_PPC_REL14_BRTAKEN: { + *(int *)target = + (*(int *)target & 0xffdf0003) | (value & 0x0000fffc) | + 0x00200000; + break; + } case R_PPC_ADDR14_BRNTAKEN: + case R_PPC_REL14_BRNTAKEN: { + *(int *)target = + (*(int *)target & 0xffdf0003) | (value & 0x0000fffc); + break; + } case R_PPC_ADDR30: { + *(int *)target = + (*(int *)target & 0x00000003) | (value & 0xfffffffc); + break; + }default: + DEBUG_FUNCTION_LINE("Module_ElfLinkOne01: %02X\n",type); + goto exit_error; + } + + result = true; +exit_error: + if (!result) DEBUG_FUNCTION_LINE("Module_ElfLinkOne: exit_error\n"); + return result; +} + diff --git a/loader/src/ElfTools.h b/loader/src/ElfTools.h new file mode 100644 index 0000000..9dbe1b1 --- /dev/null +++ b/loader/src/ElfTools.h @@ -0,0 +1,48 @@ +/* based on module.c + * by Alex Chadwick + * + * Copyright (C) 2014, Alex Chadwick + * Modified 2018, Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _ELF_TOOLS_H_ +#define _ELF_TOOLS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +} +#endif + +class ElfTools{ + +public: + static bool elfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr,void *destination); + static bool loadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count, size_t *symtab_strndx); + static void elfLoadSymbols(size_t shndx, const void *destination, Elf32_Sym *symtab, size_t symtab_count); + static bool elfLinkOne(char type, size_t offset, int addend, void *destination, uint32_t symbol_addr); +}; + +#endif diff --git a/loader/src/EntryData.h b/loader/src/EntryData.h new file mode 100644 index 0000000..1206328 --- /dev/null +++ b/loader/src/EntryData.h @@ -0,0 +1,62 @@ +/**************************************************************************** + * Copyright (C) 2018 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef _ENTRY_DATA_H_ +#define _ENTRY_DATA_H_ + +#include +#include + +class EntryData{ + +public: + EntryData(const char * name, wups_loader_library_type_t library, void * target, void * call_addr){ + this->name = name; + this->library = library; + this->replaceAddr = target; + this->replaceCall = call_addr; + } + + ~EntryData(){ + + } + + std::string getName(){ + return this->name; + } + + wups_loader_library_type_t getLibrary(){ + return this->library; + } + + void * getReplaceAddress(){ + return replaceAddr; + } + + void * getReplaceCall(){ + return replaceCall; + } + +private: + std::string name; + wups_loader_library_type_t library; + void * replaceAddr = NULL; + void * replaceCall = NULL; +}; + + +#endif diff --git a/loader/src/HookData.h b/loader/src/HookData.h new file mode 100644 index 0000000..ce13d79 --- /dev/null +++ b/loader/src/HookData.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * Copyright (C) 2018 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef _HOOK_DATA_H_ +#define _HOOK_DATA_H_ + +#include +#include + +class HookData{ + +public: + HookData(void * function_pointer, wups_loader_hook_type_t type){ + this->function_pointer = function_pointer; + this->type = type; + } + + ~HookData(){ + + } + + void * getFunctionPointer(){ + return function_pointer; + } + + wups_loader_hook_type_t getType(){ + return this->type; + } +private: + void * function_pointer; + wups_loader_hook_type_t type; +}; + + +#endif diff --git a/loader/src/ModuleData.cpp b/loader/src/ModuleData.cpp new file mode 100644 index 0000000..410e963 --- /dev/null +++ b/loader/src/ModuleData.cpp @@ -0,0 +1,778 @@ +/* based on module.c + * by Alex Chadwick + * + * Copyright (C) 2014, Alex Chadwick + * Modified 2018, Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "ModuleData.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ElfTools.h" + +bool ModuleData::checkFile() { + const char *extension; + + const char * path_c = getPath().c_str(); + + /* find the file extension */ + extension = strrchr(path_c, '.'); + if (extension == NULL){ + extension = strchr(path_c, '\0'); + }else{ + extension++; + } + + assert(extension != NULL); + + if (strcmp(extension, "mod") == 0 || + strcmp(extension, "o") == 0 || + strcmp(extension, "a") == 0 || + strcmp(extension, "elf") == 0) { + return true; + } + return false; +} + +bool ModuleData::load(uint8_t ** space) { + bool result = false; + int fd = -1; + Elf *elf = NULL; + + /* check for compile errors */ + if (elf_version(EV_CURRENT) == EV_NONE){ + DEBUG_FUNCTION_LINE("Compiler errors in '%s' \n", getPath().c_str()); + goto exit_error; + } + + fd = open(getPath().c_str(), O_RDONLY, 0); + + if (fd == -1){ + DEBUG_FUNCTION_LINE("failed to open '%s' \n", getPath().c_str()); + goto exit_error; + } + + elf = elf_begin(fd, ELF_C_READ, NULL); + + if (elf == NULL){ + DEBUG_FUNCTION_LINE("elf was NULL\n"); + goto exit_error; + } + + switch (elf_kind(elf)) { + case ELF_K_AR: + /* TODO */ + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Archives not yet supported.\n", getPath().c_str()); + goto exit_error; + case ELF_K_ELF: + if(!this->loadElf(elf)){ + goto exit_error; + } + result = linkModuleElf(elf,space); + break; + default: + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF file.\n", getPath().c_str()); + goto exit_error; + } + +exit_error: + if (elf != NULL) + elf_end(elf); + if (fd != -1) + close(fd); + return result; +} + +bool ModuleData::loadElf( Elf *elf) { + bool res = false; + Elf_Scn *scn; + Elf32_Ehdr *ehdr; + char *ident; + size_t shstrndx, sz, symtab_count, symtab_strndx; + Elf32_Sym *symtab = NULL; + + size_t cur_size = 0; + + const char * path_c = getPath().c_str(); + + assert(elf != NULL); + assert(elf_kind(elf) == ELF_K_ELF); + + ident = elf_getident(elf, &sz); + + if (ident == NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF header.\n", path_c); + goto exit_error; + } + if (sz < 7) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF header.\n", path_c); + goto exit_error; + } + if (ident[4] != ELFCLASS32) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not 32 bit ELF.\n", path_c); + goto exit_error; + } + if (ident[5] != ELFDATA2MSB) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not Big Endian.\n", path_c); + goto exit_error; + } + if (ident[6] != EV_CURRENT) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Unknown ELF version.\n", path_c); + goto exit_error; + } + + ehdr = elf32_getehdr(elf); + + if (ehdr == NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF header\n", path_c); + goto exit_error; + } + if (ehdr->e_type != ET_REL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not relocatable ELF.\n", path_c); + goto exit_error; + } + if (ehdr->e_machine != EM_PPC) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Architecture not EM_PPC.\n", path_c); + goto exit_error; + } + if (ehdr->e_version != EV_CURRENT) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Unknown ELF version.\n", path_c); + goto exit_error; + } + + if (!ElfTools::loadElfSymtab(elf, &symtab, &symtab_count, &symtab_strndx)) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't parse symtab.\n", path_c); + goto exit_error; + } + + assert(symtab != NULL); + + DEBUG_FUNCTION_LINE("Reading metadata from path %s.\n", path_c); + + if(!metadataRead(elf, symtab, symtab_count, symtab_strndx)){ + goto exit_error; + } + + if (elf_getshdrstrndx(elf, &shstrndx) != 0) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't find shdrstndx.\n", path_c); + goto exit_error; + } + + for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) { + Elf32_Shdr *shdr; + + shdr = elf32_getshdr(scn); + if (shdr == NULL){ + continue; + } + + if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && + (shdr->sh_flags & SHF_ALLOC)) { + + const char *name; + + name = elf_strptr(elf, shstrndx, shdr->sh_name); + if (name == NULL){ + continue; + } + + if (strcmp(name, ".wups.meta") == 0) { + continue; + } else if (strcmp(name, ".wups.load") == 0) { + cur_size += + shdr->sh_size / sizeof(wups_loader_entry_t) * 6*4; + } else if (strcmp(name, ".wups.hooks") == 0) { + cur_size += + shdr->sh_size / sizeof(wups_loader_hook_t) * 2*4; + } else { + cur_size += shdr->sh_size; + /* add alignment padding to size */ + if (shdr->sh_addralign > 3){ + /* roundup to multiple of sh_addralign */ + cur_size += (-cur_size & (shdr->sh_addralign - 1)); + }else{ + /* roundup to multiple of 4 */ + cur_size += (-cur_size & 3); + } + } + } + } + + /* roundup to multiple of 4 */ + cur_size += (-cur_size & 3); + + this->setSize(cur_size); + + res = true; +exit_error: + if (symtab != NULL){ + free(symtab); + } + + return res; +} + +bool ModuleData::metadataRead(Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx) { + char *metadata = NULL, *metadata_cur, *metadata_end; + const char *game, *name, *author, *version, *license, *wups; + + Elf_Scn *scn; + size_t shstrndx; + + if (elf_getshdrstrndx(elf, &shstrndx) != 0) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't find shstrndx\n", path); + goto exit_error; + } + + for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) { + Elf32_Shdr *shdr; + const char *name; + + shdr = elf32_getshdr(scn); + if (shdr == NULL){ + continue; + } + + name = elf_strptr(elf, shstrndx, shdr->sh_name); + if (name == NULL){ + continue; + } + + if (strcmp(name, ".wups.meta") == 0) { + if (shdr->sh_size == 0){ + continue; + } + + if (metadata != NULL){ + continue; + } + + metadata = (char*) malloc(shdr->sh_size); + + if (metadata == NULL){ + continue; + } + + if (!ElfTools::elfLoadSection(elf, scn, shdr, metadata)) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't load .wups.meta.\n", path); + goto exit_error; + } + + ElfTools::elfLoadSymbols(elf_ndxscn(scn), metadata, symtab, symtab_count); + + if (!elfLink(elf, elf_ndxscn(scn), metadata, symtab, symtab_count, symtab_strndx, false)) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - .wups.meta contains invalid relocations.\n", path); + goto exit_error; + } + + metadata_end = metadata + shdr->sh_size; + metadata_end[-1] = '\0'; + } + } + + if (metadata == NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not a WUPS module file.\n", path); + goto exit_error; + } + + game = NULL; + name = NULL; + author = NULL; + version = NULL; + license = NULL; + wups = NULL; + + for (metadata_cur = metadata; metadata_cur < metadata_end; metadata_cur = strchr(metadata_cur, '\0') + 1) { + + char *eq; + + assert(metadata_cur >= metadata && metadata_cur < metadata_end); + + if (*metadata_cur == '\0'){ + continue; + } + + eq = strchr(metadata_cur, '='); + if (eq == NULL){ + continue; + } + + 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); + 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); + goto exit_error; + } + name = eq + 1; + } else if (strncmp(metadata_cur, "author", eq - metadata_cur) == 0) { + if (author != NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Multiple WUPS_MODULE_AUTHOR declarations.\n", path); + goto exit_error; + } + author = eq + 1; + } else if (strncmp(metadata_cur, "version", eq - metadata_cur) == 0) { + if (version != NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Multiple WUPS_MODULE_VERSION declarations.\n", path); + goto exit_error; + } + version = eq + 1; + } else if (strncmp(metadata_cur, "license", eq - metadata_cur) == 0) { + if (license != NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Multiple WUPS_MODULE_LICENSE declarations.\n", path); + goto exit_error; + } + license = eq + 1; + } else if (strncmp(metadata_cur, "wups", eq - metadata_cur) == 0) { + if (wups != NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Multiple WUPS_MODULE_NAME declarations.\n", path); + goto exit_error; + } + wups = eq + 1; + } + } + + if (game == NULL){ + game = ""; + } + // TODO: + /*if (wups == NULL || strcmp(wups, "0.1") != 0) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Unrecognised WUPS version.\n", path); + goto exit_error; + }*/ + if (name == NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Missing WUPS_MODULE_NAME declaration.\n",path); + goto exit_error; + } + if (author == NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Missing WUPS_MODULE_AUTHOR declaration.\n", path); + goto exit_error; + } + if (version == NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Missing WUPS_MODULE_VERSION declaration.\n", path); + goto exit_error; + } + if (license == NULL) { + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Missing WUPS_MODULE_LICENSE declaration.\n", path); + goto exit_error; + } + + this->setName(name); + this->setAuthor(author); + this->setVersion(version); + this->setLicense(license); + + return true; + +exit_error: + + if (metadata != NULL){ + free(metadata); + } + return false; +} + +bool ModuleData::elfLink(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)) { + Elf32_Shdr *shdr; + + shdr = elf32_getshdr(scn); + if (shdr == NULL) + continue; + + switch (shdr->sh_type) { + case SHT_REL: { + const Elf32_Rel *rel; + Elf_Data *data; + size_t i; + + if (shdr->sh_info != shndx){ + continue; + } + + data = elf_getdata(scn, NULL); + if (data == NULL){ + continue; + } + + rel = (const Elf32_Rel *) data->d_buf; + + for (i = 0; i < shdr->sh_size / sizeof(Elf32_Rel); i++) { + uint32_t symbol_addr; + size_t symbol; + + symbol = ELF32_R_SYM(rel[i].r_info); + + if (symbol > symtab_count) + return false; + + switch (symtab[symbol].st_shndx) { + case SHN_ABS: { + symbol_addr = symtab[symbol].st_value; + break; + } case SHN_COMMON: { + return false; + } case SHN_UNDEF: { + + if (allow_globals) { + DEBUG_FUNCTION_LINE("The elf still have unresolved relocations. This is not supported."); + /* + Not support and not needed. + + module_unresolved_relocation_t *reloc; + char *name; + + 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); + + if (name == NULL) { + module_relocations_count--; + return false; + } + + reloc->name = strdup(name); + if (reloc->name == NULL) { + module_relocations_count--; + return false; + } + + reloc->module = index; + reloc->address = destination; + reloc->offset = rel[i].r_offset; + reloc->type = ELF32_R_TYPE(rel[i].r_info); + reloc->addend = *(int *)((char *)destination + rel[i].r_offset); + + continue; + */ + return false; + } else { + return false; + } + } default: { + if (symtab[symbol].st_other != 1) { + return false; + } + + symbol_addr = symtab[symbol].st_value; + break; + } + } + + if (!ElfTools::elfLinkOne(ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, *(int *)((char *)destination + rel[i].r_offset), destination, symbol_addr)){ + return false; + } + } + break; + } case SHT_RELA: { + const Elf32_Rela *rela; + Elf_Data *data; + size_t i; + + if (shdr->sh_info != shndx) + continue; + + data = elf_getdata(scn, NULL); + if (data == NULL) + continue; + + rela = (const Elf32_Rela *) data->d_buf; + + for (i = 0; i < shdr->sh_size / sizeof(Elf32_Rela); i++) { + uint32_t symbol_addr; + size_t symbol; + + symbol = ELF32_R_SYM(rela[i].r_info); + + if (symbol > symtab_count) + return false; + + switch (symtab[symbol].st_shndx) { + case SHN_ABS: { + symbol_addr = symtab[symbol].st_value; + break; + } case SHN_COMMON: { + return false; + } case SHN_UNDEF: { + if (allow_globals) { + DEBUG_FUNCTION_LINE("The elf still have unresolved relocations. This is not supported."); + /* + Not support and not needed. + module_unresolved_relocation_t *reloc; + char *name; + + 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); + + if (name == NULL) { + module_relocations_count--; + return false; + } + + reloc->name = strdup(name); + if (reloc->name == NULL) { + 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; + + continue;*/ + return false; + } else + return false; + } default: { + + if (symtab[symbol].st_other != 1){ + return false; + } + symbol_addr = symtab[symbol].st_value; + break; + } + } + + if (!ElfTools::elfLinkOne(ELF32_R_TYPE(rela[i].r_info), rela[i].r_offset,rela[i].r_addend, destination, symbol_addr)){ + return false; + } + } + break; + } + } + } + + return true; +} + +bool ModuleData::linkModuleElf(Elf *elf, uint8_t **space) { + Elf_Scn *scn; + size_t symtab_count, section_count, shstrndx, symtab_strndx, entries_count, hooks_count; + Elf32_Sym *symtab = NULL; + uint8_t **destinations = NULL; + wups_loader_entry_t *entries = NULL; + wups_loader_hook_t *hooks = NULL; + bool result = false; + + std::vector entry_t_list; + std::vector hook_t_list; + + std::vector entry_data_list; + std::vector hook_data_list; + + if (!ElfTools::loadElfSymtab(elf, &symtab, &symtab_count, &symtab_strndx)){ + goto exit_error; + } + + assert(symtab != NULL); + + if (elf_getshdrnum(elf, §ion_count) != 0){ + goto exit_error; + } + if (elf_getshdrstrndx(elf, &shstrndx) != 0){ + goto exit_error; + } + + destinations = (uint8_t **) malloc(sizeof(uint8_t *) * section_count); + + for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) { + + Elf32_Shdr *shdr; + + shdr = elf32_getshdr(scn); + if (shdr == NULL){ + continue; + } + + if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && + (shdr->sh_flags & SHF_ALLOC)) { + + const char *name; + + destinations[elf_ndxscn(scn)] = NULL; + + name = elf_strptr(elf, shstrndx, shdr->sh_name); + if (name == NULL){ + continue; + } + + if (strcmp(name, ".wups.meta") == 0) { + continue; + } else if (strcmp(name, ".wups.load") == 0) { + if (entries != NULL){ + 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); + + if (entries == NULL){ + goto exit_error; + } + + destinations[elf_ndxscn(scn)] = (uint8_t *)entries; + if (!ElfTools::elfLoadSection(elf, scn, shdr, entries)){ + goto exit_error; + } + + ElfTools::elfLoadSymbols(elf_ndxscn(scn), entries, symtab, symtab_count); + + for(size_t i = 0;i< entries_count;i++){ + entry_t_list.push_back(&entries[i]); + } + }else if (strcmp(name, ".wups.hooks") == 0) { + if (hooks != NULL){ + goto exit_error; + } + + hooks_count = shdr->sh_size / sizeof(wups_loader_hook_t); + hooks = (wups_loader_hook_t *) malloc(sizeof(wups_loader_hook_t) * hooks_count); + + if (hooks == NULL){ + goto exit_error; + } + + destinations[elf_ndxscn(scn)] = (uint8_t *)hooks; + if (!ElfTools::elfLoadSection(elf, scn, shdr, hooks)){ + goto exit_error; + } + ElfTools::elfLoadSymbols(elf_ndxscn(scn), hooks, symtab, symtab_count); + + for(size_t i = 0;i< hooks_count;i++){ + hook_t_list.push_back(&hooks[i]); + } + + } else { + *space -= shdr->sh_size; + + if (shdr->sh_addralign > 3) + *space = (uint8_t *)((int)*space & + ~(shdr->sh_addralign - 1)); + else + *space = (uint8_t *)((int)*space & ~3); + + destinations[elf_ndxscn(scn)] = *space; + + assert(*space != NULL); + if((u32) *space < getApplicationEndAddr()){ + DEBUG_FUNCTION_LINE("Not enough space to load function %s into memory at %08X.\n",name,*space); + goto exit_error; + } + + DEBUG_FUNCTION_LINE("Copy section %s to %08X\n",name,*space); + if (!ElfTools::elfLoadSection(elf, scn, shdr, *space)){ + goto exit_error; + } + ElfTools::elfLoadSymbols(elf_ndxscn(scn), *space, symtab, symtab_count); + } + } + } + + if (entries == NULL){ + goto exit_error; + } + + for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) { + Elf32_Shdr *shdr; + + shdr = elf32_getshdr(scn); + if (shdr == NULL){ + continue; + } + + if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && + (shdr->sh_flags & SHF_ALLOC) && + destinations[elf_ndxscn(scn)] != NULL) { + + if (!elfLink(elf, elf_ndxscn(scn), destinations[elf_ndxscn(scn)], symtab, symtab_count, symtab_strndx, true)){ + goto exit_error; + } + } + } + + for(size_t j=0;jtype,(void*) hook->target); + HookData * hook_data = new HookData((void *) hook->target,hook->type); + addHookData(hook_data); + } + + for(size_t j=0;j_function.name,getName().c_str(),entry->_function.library,entry->_function.target); + EntryData * entry_data = new EntryData(entry->_function.name,entry->_function.library, (void *) entry->_function.target, (void *) entry->_function.call_addr); + addEntryData(entry_data); + } + + result = true; +exit_error: + if (!result) DEBUG_FUNCTION_LINE("exit_error\n"); + if (destinations != NULL){ + free(destinations); + } + if (symtab != NULL){ + free(symtab); + } + if (hooks != NULL){ + free(hooks); + } + if (entries != NULL){ + free(entries); + } + return result; +} diff --git a/loader/src/ModuleData.h b/loader/src/ModuleData.h new file mode 100644 index 0000000..e1ab12f --- /dev/null +++ b/loader/src/ModuleData.h @@ -0,0 +1,159 @@ +/* based on module.c + * by Alex Chadwick + * + * Copyright (C) 2014, Alex Chadwick + * Modified 2018, Maschell + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _MODULE_DATA_H_ +#define _MODULE_DATA_H_ + +#include +#include +#include "EntryData.h" +#include "HookData.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +} +#endif + +class ModuleData{ + public: + ModuleData(std::string path, uint8_t ** space){ + this->path = path; + if(checkFile()){ + DEBUG_FUNCTION_LINE("Checkfile successfully, loading now \n"); + this->loadedSuccessfully = load(space); + } else { + this->loadedSuccessfully = false; + } + } + + ~ModuleData(){ + for(size_t i = 0;i< entry_data_list.size();i++){ + if(entry_data_list[i] != NULL){ + free(entry_data_list[i]); + } + } + + for(size_t i = 0;i< hook_data_list.size();i++){ + if(hook_data_list[i] != NULL){ + free(hook_data_list[i]); + } + } + } + + void setName(const char * name){ + this->name = name; + } + + void setAuthor(const char * author){ + this->author = author; + } + + void setVersion(const char * version){ + this->version = version; + } + + void setLicense(const char * license){ + this->license = license; + } + + void setSize(size_t size){ + this->size = size; + } + + std::string getName(){ + return this->name; + } + + std::string getAuthor(){ + return this->author; + } + + std::string getVersion(){ + return this->version; + } + + std::string getLicense(){ + return this->license; + } + + std::string getPath(){ + return path; + } + + bool isLoadedSuccessfully(){ + return loadedSuccessfully; + } + + void addEntryData(EntryData * entry_data){ + entry_data_list.push_back(entry_data); + } + + std::vector getEntryDataList(){ + return entry_data_list; + } + + void addHookData(HookData * hook_data){ + hook_data_list.push_back(hook_data); + } + + std::vector getHookDataList(){ + return hook_data_list; + } + + private: + + bool checkFile(); + + bool load(uint8_t ** space); + + bool loadElf(Elf *elf); + + bool metadataRead(Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx); + + bool elfLink(Elf *elf, size_t shndx, void *destination, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx, bool allow_globals); + + bool linkModuleElf(Elf *elf, uint8_t **space); + + bool loadedSuccessfully = false; + + std::string path; + std::string name; + std::string author; + std::string version; + std::string license; + size_t size; + + std::vector entry_data_list; + std::vector hook_data_list; +}; + + +#endif diff --git a/loader/src/elf_utils.cpp b/loader/src/elf_utils.cpp deleted file mode 100644 index 31cb920..0000000 --- a/loader/src/elf_utils.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* elf_utils.cpp - * by Alex Chadwick - * - * Copyright (C) 2014, Alex Chadwick - * Modified 2018, Maschell - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "elf_utils.h" -#include -#include -#include -#include -#include -#include -#include -#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) { - - assert(destination != NULL); - - switch (shdr->sh_type) { - case SHT_SYMTAB: - case SHT_PROGBITS: { - Elf_Data *data; - size_t n; - - n = 0; - for (data = elf_getdata(scn, NULL); - data != NULL; - data = elf_getdata(scn, data)) { - memcpy((char *)destination + n, data->d_buf, data->d_size); - n += data->d_size; - } - return true; - } case SHT_NOBITS: { - memset(destination, 0, shdr->sh_size); - return true; - } default: - return false; - } -} - -bool Module_LoadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count, size_t *symtab_strndx) { - Elf_Scn *scn; - bool result = false; - - for (scn = elf_nextscn(elf, NULL); - scn != NULL; - scn = elf_nextscn(elf, scn)) { - - Elf32_Shdr *shdr; - - shdr = elf32_getshdr(scn); - if (shdr == NULL) - continue; - - if (shdr->sh_type == SHT_SYMTAB) { - size_t sym; - - assert (*symtab == NULL); - *symtab = (Elf32_Sym *)malloc(shdr->sh_size); - if (*symtab == NULL) - continue; - - *symtab_count = shdr->sh_size / sizeof(Elf32_Sym); - *symtab_strndx = shdr->sh_link; - - if (!Module_ElfLoadSection(elf, scn, shdr, *symtab)) - goto exit_error; - - for (sym = 0; sym < *symtab_count; sym++){ - (*symtab)[sym].st_other = 0; - } - - break; - } - } - - if (*symtab == NULL) - goto exit_error; - - 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 - * symbol address has been calculated. */ - for (i = 0; i < symtab_count; i++) { - if (symtab[i].st_shndx == shndx && - symtab[i].st_other == 0) { - - symtab[i].st_value += (Elf32_Addr)destination; - symtab[i].st_other = 1; - } - } -} - -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)) { - - Elf32_Shdr *shdr; - - shdr = elf32_getshdr(scn); - if (shdr == NULL) - continue; - - switch (shdr->sh_type) { - case SHT_REL: { - const Elf32_Rel *rel; - Elf_Data *data; - size_t i; - - if (shdr->sh_info != shndx) - continue; - - data = elf_getdata(scn, NULL); - if (data == NULL) - continue; - - rel = (const Elf32_Rel *) data->d_buf; - - for (i = 0; i < shdr->sh_size / sizeof(Elf32_Rel); i++) { - uint32_t symbol_addr; - size_t symbol; - - symbol = ELF32_R_SYM(rel[i].r_info); - - if (symbol > symtab_count) - return false; - - switch (symtab[symbol].st_shndx) { - case SHN_ABS: { - symbol_addr = symtab[symbol].st_value; - break; - } case SHN_COMMON: { - return false; - } case SHN_UNDEF: { - if (allow_globals) { - module_unresolved_relocation_t *reloc; - char *name; - - 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); - - if (name == NULL) { - module_relocations_count--; - return false; - } - - reloc->name = strdup(name); - if (reloc->name == NULL) { - 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); - reloc->addend = - *(int *)((char *)destination + - rel[i].r_offset); - - continue; - } else - return false; - } default: { - if (symtab[symbol].st_other != 1) - return false; - - symbol_addr = symtab[symbol].st_value; - break; - } - } - - if (!Module_ElfLinkOne( - ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, - *(int *)((char *)destination + rel[i].r_offset), - destination, symbol_addr)) - return false; - } - break; - } case SHT_RELA: { - const Elf32_Rela *rela; - Elf_Data *data; - size_t i; - - if (shdr->sh_info != shndx) - continue; - - data = elf_getdata(scn, NULL); - if (data == NULL) - continue; - - rela = (const Elf32_Rela *) data->d_buf; - - for (i = 0; i < shdr->sh_size / sizeof(Elf32_Rela); i++) { - uint32_t symbol_addr; - size_t symbol; - - symbol = ELF32_R_SYM(rela[i].r_info); - - if (symbol > symtab_count) - return false; - - switch (symtab[symbol].st_shndx) { - case SHN_ABS: { - symbol_addr = symtab[symbol].st_value; - break; - } case SHN_COMMON: { - return false; - } case SHN_UNDEF: { - if (allow_globals) { - module_unresolved_relocation_t *reloc; - char *name; - - 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); - - if (name == NULL) { - module_relocations_count--; - return false; - } - - reloc->name = strdup(name); - if (reloc->name == NULL) { - 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; - - continue; - } else - return false; - } default: { - - if (symtab[symbol].st_other != 1) - return false; - symbol_addr = symtab[symbol].st_value; - break; - } - } - - if (!Module_ElfLinkOne( - ELF32_R_TYPE(rela[i].r_info), rela[i].r_offset, - rela[i].r_addend, destination, symbol_addr)) - return false; - } - break; - } - } - } - - return true; -} - -bool Module_ElfLinkOne(char type, size_t offset, int addend, void *destination, uint32_t symbol_addr) { - int value; - char *target = (char *)destination + offset; - bool result = false; - - switch (type) { - case R_PPC_ADDR32: - case R_PPC_ADDR24: - case R_PPC_ADDR16: - case R_PPC_ADDR16_HI: - case R_PPC_ADDR16_HA: - case R_PPC_ADDR16_LO: - case R_PPC_ADDR14: - case R_PPC_ADDR14_BRTAKEN: - case R_PPC_ADDR14_BRNTAKEN: - case R_PPC_UADDR32: - case R_PPC_UADDR16: { - value = (int)symbol_addr + addend; - break; - } case R_PPC_REL24: - case R_PPC_PLTREL24: - case R_PPC_LOCAL24PC: - case R_PPC_REL14: - case R_PPC_REL14_BRTAKEN: - case R_PPC_REL14_BRNTAKEN: - case R_PPC_REL32: - case R_PPC_ADDR30: { - value = (int)symbol_addr + addend - (int)target; - break; - } case R_PPC_SECTOFF: - case R_PPC_SECTOFF_LO: - case R_PPC_SECTOFF_HI: - case R_PPC_SECTOFF_HA: { - value = offset + addend; - break; - } case R_PPC_EMB_NADDR32: - case R_PPC_EMB_NADDR16: - case R_PPC_EMB_NADDR16_LO: - case R_PPC_EMB_NADDR16_HI: - case R_PPC_EMB_NADDR16_HA: { - value = addend - (int)symbol_addr; - break; - } default: - DEBUG_FUNCTION_LINE("Module_ElfLinkOne01: %02X\n",type); - goto exit_error; - } - - switch (type) { - case R_PPC_ADDR32: - case R_PPC_UADDR32: - case R_PPC_REL32: - case R_PPC_SECTOFF: - case R_PPC_EMB_NADDR32: { - *(int *)target = value; - break; - } case R_PPC_ADDR24: - case R_PPC_PLTREL24: - case R_PPC_LOCAL24PC: - case R_PPC_REL24: { - *(int *)target = - (*(int *)target & 0xfc000003) | (value & 0x03fffffc); - break; - } case R_PPC_ADDR16: - case R_PPC_UADDR16: - case R_PPC_EMB_NADDR16: { - *(short *)target = value; - break; - } case R_PPC_ADDR16_HI: - case R_PPC_SECTOFF_HI: - case R_PPC_EMB_NADDR16_HI: { - *(short *)target = value >> 16; - break; - } case R_PPC_ADDR16_HA: - case R_PPC_SECTOFF_HA: - case R_PPC_EMB_NADDR16_HA: { - *(short *)target = (value >> 16) + ((value >> 15) & 1); - break; - } case R_PPC_ADDR16_LO: - case R_PPC_SECTOFF_LO: - case R_PPC_EMB_NADDR16_LO: { - *(short *)target = value & 0xffff; - break; - } case R_PPC_ADDR14: - case R_PPC_REL14: { - *(int *)target = - (*(int *)target & 0xffff0003) | (value & 0x0000fffc); - break; - } case R_PPC_ADDR14_BRTAKEN: - case R_PPC_REL14_BRTAKEN: { - *(int *)target = - (*(int *)target & 0xffdf0003) | (value & 0x0000fffc) | - 0x00200000; - break; - } case R_PPC_ADDR14_BRNTAKEN: - case R_PPC_REL14_BRNTAKEN: { - *(int *)target = - (*(int *)target & 0xffdf0003) | (value & 0x0000fffc); - break; - } case R_PPC_ADDR30: { - *(int *)target = - (*(int *)target & 0x00000003) | (value & 0xfffffffc); - break; - }default: - DEBUG_FUNCTION_LINE("Module_ElfLinkOne01: %02X\n",type); - goto exit_error; - } - - 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 deleted file mode 100644 index 4b3fb78..0000000 --- a/loader/src/elf_utils.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _ELF_UTILS_H_ -#define _ELF_UTILS_H_ - -/* Main */ -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifdef __cplusplus -} -#endif - -#include "module_parser.h" - -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(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 deleted file mode 100644 index faa04d0..0000000 --- a/loader/src/link_utils.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/* link_utils.cpp - * by Alex Chadwick - * - * Copyright (C) 2014, Alex Chadwick - * Modified 2018, Maschell - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "link_utils.h" -#include "elf_utils.h" -#include "utils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//TODO: Adjust this. -#define MODULE_ENTRIES_CAPACITY_DEFAULT 128 - -//TODO: Adjust this. -#define MODULE_HOOKS_CAPACITY_DEFAULT 128 - -wups_loader_hook_t *module_hooks = NULL; -size_t module_hooks_count = 0; -size_t module_hooks_capacity = 0; - -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; - - /* check for compile errors */ - assert(elf_version(EV_CURRENT) != EV_NONE); - - fd = open(path, O_RDONLY, 0); - - if (fd == -1) - goto exit_error; - - elf = elf_begin(fd, ELF_C_READ, NULL); - - if (elf == NULL) - goto exit_error; - - switch (elf_kind(elf)) { - case ELF_K_AR: - /* TODO */ - goto exit_error; - case ELF_K_ELF: - DEBUG_FUNCTION_LINE("Calling now Module_LinkModuleElf\n"); - if (!Module_LinkModuleElf(index, elf, space)) - goto exit_error; - break; - default: - goto exit_error; - } - - result = true; -exit_error: - if (!result) DEBUG_FUNCTION_LINE("Module_LinkModule: exit_error\n"); - if (elf != NULL) - elf_end(elf); - if (fd != -1) - close(fd); - return result; -} - -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, hooks_count; - Elf32_Sym *symtab = NULL; - uint8_t **destinations = NULL; - wups_loader_entry_t *entries = NULL; - wups_loader_hook_t *hooks = NULL; - bool result = false; - - if (!Module_LoadElfSymtab(elf, &symtab, &symtab_count, &symtab_strndx)) - goto exit_error; - - assert(symtab != NULL); - - if (elf_getshdrnum(elf, §ion_count) != 0) - goto exit_error; - if (elf_getshdrstrndx(elf, &shstrndx) != 0) - goto exit_error; - - destinations = (uint8_t **) malloc(sizeof(uint8_t *) * section_count); - - for (scn = elf_nextscn(elf, NULL); - scn != NULL; - scn = elf_nextscn(elf, scn)) { - - Elf32_Shdr *shdr; - - shdr = elf32_getshdr(scn); - if (shdr == NULL) - continue; - - if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && - (shdr->sh_flags & SHF_ALLOC)) { - - const char *name; - - destinations[elf_ndxscn(scn)] = NULL; - - name = elf_strptr(elf, shstrndx, shdr->sh_name); - if (name == NULL) - continue; - - if (strcmp(name, ".wups.meta") == 0) { - continue; - } else if (strcmp(name, ".wups.load") == 0) { - if (entries != NULL) - goto exit_error; - - entries_count = shdr->sh_size / sizeof(wups_loader_entry_t); - 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; - - 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); - - int entries_offset = module_entries_count - entries_count; - - for(int i = 0;i< entries_count;i++){ - gbl_replacement_data.module_data[index].functions[i].entry_index = entries_offset +i; - gbl_replacement_data.module_data[index].number_used_functions++; - } - }else if (strcmp(name, ".wups.hooks") == 0) { - if (hooks != NULL) - goto exit_error; - - hooks_count = shdr->sh_size / sizeof(wups_loader_hook_t); - hooks = (wups_loader_hook_t*) Module_ListAllocate( - &module_hooks, sizeof(wups_loader_hook_t), - hooks_count, &module_hooks_capacity, - &module_hooks_count, MODULE_HOOKS_CAPACITY_DEFAULT); - - if (hooks == NULL) - goto exit_error; - - destinations[elf_ndxscn(scn)] = (uint8_t *)hooks; - if (!Module_ElfLoadSection(elf, scn, shdr, hooks)) - goto exit_error; - Module_ElfLoadSymbols(elf_ndxscn(scn), hooks, symtab, symtab_count); - - int hook_offset = module_hooks_count - hooks_count; - - for(int i = 0;i< hooks_count;i++){ - gbl_replacement_data.module_data[index].hooks[i].hook_index = hook_offset +i; - gbl_replacement_data.module_data[index].number_used_hooks++; - } - } else { - *space -= shdr->sh_size; - - if (shdr->sh_addralign > 3) - *space = (uint8_t *)((int)*space & - ~(shdr->sh_addralign - 1)); - else - *space = (uint8_t *)((int)*space & ~3); - - destinations[elf_ndxscn(scn)] = *space; - - assert(*space != NULL); - if((u32) *space < getApplicationEndAddr()){ - DEBUG_FUNCTION_LINE("Not enough space to load function %s into memory at %08X.\n",name,*space); - goto exit_error; - } - - DEBUG_FUNCTION_LINE("Copy section %s to %08X\n",name,*space); - if (!Module_ElfLoadSection(elf, scn, shdr, *space)) - goto exit_error; - Module_ElfLoadSymbols( - elf_ndxscn(scn), *space, symtab, symtab_count); - } - } - } - - if (entries == NULL) - goto exit_error; - - for (scn = elf_nextscn(elf, NULL); - scn != NULL; - scn = elf_nextscn(elf, scn)) { - - Elf32_Shdr *shdr; - - shdr = elf32_getshdr(scn); - if (shdr == NULL) - continue; - - if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && - (shdr->sh_flags & SHF_ALLOC) && - destinations[elf_ndxscn(scn)] != NULL) { - - if (!Module_ElfLink( - index, elf, elf_ndxscn(scn), destinations[elf_ndxscn(scn)], - symtab, symtab_count, symtab_strndx, true)) - goto exit_error; - } - } - - result = true; -exit_error: - if (!result) DEBUG_FUNCTION_LINE("Module_LinkModuleElf: exit_error\n"); - if (destinations != NULL) - free(destinations); - if (symtab != NULL) - free(symtab); - return result; -} - -/** -Relocation the real_XXX calls into the "replace_data" area of the replacement_data_function_t struct. -This function also fill the other data needed of the replacement_data_function_t struct. -**/ -bool Module_ListLinkFinal() { - int has_error = 0; - bool result; - - int relocations = 0; - DEBUG_FUNCTION_LINE("Found modules: %d\n",gbl_replacement_data.number_used_modules); - for(int module_index=0;module_indexmodule_name); - for(int j=0;jnumber_used_hooks;j++){ - replacement_data_hook_t * hook_data = &module_data->hooks[j]; - if(hook_data->hook_index > module_entries_count-1){ - DEBUG_FUNCTION_LINE("Error. hook_index was too high: %d. maximum is %d\n",hook_data->hook_index,module_entries_count-1); - goto exit_error; - } - wups_loader_hook_t * hook = &module_hooks[hook_data->hook_index]; - DEBUG_FUNCTION_LINE("Set hook %d of module \"%s\" of type %08X to target %08X\n",hook_data->hook_index,module_data->module_name,hook->type,(void*) hook->target); - hook_data->func_pointer = (void*) hook->target; - hook_data->type = hook->type; - - } - - - DEBUG_FUNCTION_LINE("number of used function: %d\n",module_data->number_used_functions); - for(int j=0;jnumber_used_functions;j++){ - replacement_data_function_t * function_data = &module_data->functions[j]; - if(function_data->entry_index > module_entries_count-1){ - DEBUG_FUNCTION_LINE("Error. entry_index was too high: %d. maximum is %d\n",function_data->entry_index,module_entries_count-1); - goto exit_error; - } - wups_loader_entry_t * entry = &module_entries[function_data->entry_index]; - if(entry->_function.name != NULL){ - strncpy(function_data->function_name,entry->_function.name,MAXIMUM_FUNCTION_NAME_LENGTH-1); - }else { - DEBUG_FUNCTION_LINE("WARNING NAME IS NULL\n"); - } - function_data->library = entry->_function.library; - function_data->replaceAddr = (u32) entry->_function.target; - function_data->replaceCall = (u32) entry->_function.call_addr; - - /* - We don't need this... - - DEBUG_FUNCTION_LINE("Searching for relocations %d\n",module_relocations_count); - - module_unresolved_relocation_t *reloc = NULL; - for (int relocation_index = 0;relocation_index < module_relocations_count;relocation_index++) { - DEBUG_FUNCTION_LINE("Try relocation %d\n",relocation_index); - if (module_relocations[relocation_index].module == module_index){ - if(strcmp(entry->_function.real_function_name,module_relocations[relocation_index].name) == 0){ - DEBUG_FUNCTION_LINE("Found the entry we want to replace %s\n",entry->_function.real_function_name); - reloc = &module_relocations[relocation_index]; - break; - } - } - } - - if(reloc != NULL){ - u32 call_addr = (u32) &function_data->replace_data[0]; - //DEBUG_FUNCTION_LINE("Found reloc. We need to find the symbol for: %s in lib %d\n",entry->_function.name,entry->_function.library); - //u32 call_addr = (u32) new_GetAddressOfFunction("OSFatal",WUPS_LOADER_LIBRARY_COREINIT); - DEBUG_FUNCTION_LINE("Relocating\n"); - if (!Module_ElfLinkOne(reloc->type, reloc->offset, reloc->addend, reloc->address, (uint32_t)call_addr)){ - goto exit_error; - }else{ - relocations++; - DEBUG_FUNCTION_LINE("Success! relocated to %08X\n",call_addr); - } - }else{ - - }*/ - } - } - module_relocations_count -= relocations; - - //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; - if(module_relocations_count == 0){ - free(module_relocations); - } - return result; -} - diff --git a/loader/src/link_utils.h b/loader/src/link_utils.h deleted file mode 100644 index a36fd77..0000000 --- a/loader/src/link_utils.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _LINK_UTILS_H_ -#define _LINK_UTILS_H_ - -/* Main */ -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifdef __cplusplus -} -#endif - -#include "module_parser.h" - -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(); - -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 edf4bf0..7ca459e 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -17,30 +17,26 @@ #include #include "common/retain_vars.h" #include "common/common.h" +#include "ModuleData.h" #include -#include + #include "version.h" #include "main.h" #include "utils.h" -#include "module_parser.h" -#include "link_utils.h" -#include "elf_utils.h" #include "patcher/function_patcher.h" -static void printModuleInfos(); -static bool loadSamplePlugin(); -static void printInfos(); -static void printReplacementInfos(); +static bool loadSamplePlugins(); static void ApplyPatches(); void CallHook(wups_loader_hook_type_t hook_type); static void RestorePatches(); s32 isInMiiMakerHBL(); +static void copyDataIntoGlobalStruct(std::vector* modules); +static void loadElf(std::vector* modules, const char * elfPath, uint8_t ** space); u8 isFirstBoot __attribute__((section(".data"))) = 1; - /* Entry point */ extern "C" int Menu_Main(int argc, char **argv){ InitOSFunctionPointers(); @@ -56,16 +52,11 @@ extern "C" int Menu_Main(int argc, char **argv){ if(isFirstBoot){ memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data)); - if(!loadSamplePlugin()){ + if(!loadSamplePlugins()){ return EXIT_SUCCESS; } } - if(module_relocations_count != 0){ - DEBUG_FUNCTION_LINE("We still have undefined symbol. Make sure to link them in =/ Exiting!\n"); - return EXIT_SUCCESS; - } - //Reset everything when were going back to the Mii Maker if(!isFirstBoot && isInMiiMakerHBL()){ DEBUG_FUNCTION_LINE("Returing to the Homebrew Launcher!\n"); @@ -78,6 +69,7 @@ extern "C" int Menu_Main(int argc, char **argv){ } if(!isInMiiMakerHBL()){ //Starting the application + DEBUG_FUNCTION_LINE("Calling init hook.\n"); CallHook(WUPS_LOADER_HOOK_INIT_FUNCTION); return EXIT_RELAUNCH_ON_LOAD; } @@ -120,7 +112,6 @@ void CallHook(wups_loader_hook_type_t hook_type){ DEBUG_FUNCTION_LINE("Was not defined\n"); } } - } } } @@ -144,100 +135,111 @@ s32 isInMiiMakerHBL(){ return 0; } -bool loadSamplePlugin(){ +bool loadSamplePlugins(){ DEBUG_FUNCTION_LINE("Mount SD partition\n"); int res = 0; if((res = mount_sd_fat("sd")) >= 0){ DEBUG_FUNCTION_LINE("Mounting successful\n"); - loadElf("sd:/wiiu/plugins/hid_to_vpad.mod"); - loadElf("sd:/wiiu/plugins/sdcafiine.mod"); - //loadElf("sd:/wiiu/plugins/example_plugin.mod"); - loadElf("sd:/wiiu/plugins/padcon.mod"); - loadElf("sd:/wiiu/plugins/swapdrc.mod"); + std::vector modules; - if(module_list_count == 0){ - DEBUG_FUNCTION_LINE("Found no valid modules! =( Exiting\n"); - return false; - } - - DEBUG_FUNCTION_LINE("Found %d modules!\n",module_list_count); - - printInfos(); - - DEBUG_FUNCTION_LINE("Relocating them now\n"); unsigned char * space = (unsigned char*)0x01000000; - if(!Module_ListLink(&space)){ - return false; + loadElf(&modules, "sd:/wiiu/plugins/hid_to_vpad.mod",&space); + loadElf(&modules, "sd:/wiiu/plugins/sdcafiine.mod",&space); + loadElf(&modules, "sd:/wiiu/plugins/padcon.mod",&space); + loadElf(&modules, "sd:/wiiu/plugins/swipswapme.mod",&space); + + copyDataIntoGlobalStruct(&modules); + + // Free memory. + for(size_t i = 0; i< modules.size();i++){ + ModuleData * cur_module = modules[i]; + if(cur_module != NULL){ + free(cur_module); + } } - Module_ListLinkFinal(); DEBUG_FUNCTION_LINE("Flush memory\n"); DCFlushRange ((void*)getApplicationEndAddr(),0x01000000-getApplicationEndAddr()); DCInvalidateRange((void*)getApplicationEndAddr(),0x01000000-getApplicationEndAddr()); - if(module_relocations_count != 0){ - DEBUG_FUNCTION_LINE("We still have undefined symbol. Make sure to link them in =/ Exiting\n"); - return false; - } - - DEBUG_FUNCTION_LINE("Printing some information before replacing the functions\n"); - - printReplacementInfos(); - unmount_sd_fat("sd"); } return true; } -void loadElf(const char * elfPath){ - DEBUG_FUNCTION_LINE("Reading elf from path: %s\n",elfPath); +static void copyDataIntoGlobalStruct(std::vector* modules){ + int module_index = 0; + // Copy data to global struct. + for(size_t i = 0; i< modules->size();i++){ + ModuleData * cur_module = modules->at(i); - DEBUG_FUNCTION_LINE("Try to load %s\n",elfPath); - if(Module_CheckFile(elfPath)){ - Module_Load(elfPath); - } -} + std::vector entry_data_list = cur_module->getEntryDataList(); + std::vector hook_data_list = cur_module->getHookDataList(); + if(module_index >= MAXIMUM_MODULES ){ + DEBUG_FUNCTION_LINE("Maximum of %d modules reached. %s won't be loaded!\n",MAXIMUM_MODULES,cur_module->getName().c_str()); + continue; + } + if(entry_data_list.size() > MAXIMUM_FUNCTION_PER_MODULE){ + DEBUG_FUNCTION_LINE("Module %s would replace to many function (%d, maximum is %d). It won't be loaded.\n",cur_module->getName().c_str(),entry_data_list.size(),MAXIMUM_FUNCTION_PER_MODULE); + continue; + } + if(hook_data_list.size() > MAXIMUM_HOOKS_PER_MODULE){ + DEBUG_FUNCTION_LINE("Module %s would set too many hooks (%d, maximum is %d). It won't be loaded.\n",cur_module->getName().c_str(),hook_data_list.size(),MAXIMUM_HOOKS_PER_MODULE); + continue; + } -static void printReplacementInfos(){ - DEBUG_FUNCTION_LINE("Found modules: %d\n",gbl_replacement_data.number_used_modules); - for(int module_index=0;module_indexmodule_name); - DEBUG_FUNCTION_LINE("Functions that will be replaced: %d\n",module_data->number_used_functions); - for(int j=0;jnumber_used_functions;j++){ + + strncpy(module_data->module_name,cur_module->getName().c_str(),MAXIMUM_MODULE_NAME_LENGTH-1); + + for(size_t j = 0; j < entry_data_list.size();j++){ replacement_data_function_t * function_data = &module_data->functions[j]; - DEBUG_FUNCTION_LINE("[%d] function: %s from lib %d\n",j,function_data->function_name, function_data->library); + + EntryData * cur_entry = entry_data_list[j]; + DEBUG_FUNCTION_LINE("Adding entry \"%s\" for module \"%s\"\n",cur_entry->getName().c_str(),module_data->module_name); + + //TODO: Warning/Error if string is too long. + strncpy(function_data->function_name,cur_entry->getName().c_str(),MAXIMUM_FUNCTION_NAME_LENGTH-1); + + function_data->library = cur_entry->getLibrary(); + function_data->replaceAddr = (u32) cur_entry->getReplaceAddress(); + function_data->replaceCall = (u32) cur_entry->getReplaceCall(); + + module_data->number_used_functions++; } - DEBUG_FUNCTION_LINE("--- function list end ---\n"); + + DEBUG_FUNCTION_LINE("Entries for module \"%s\": %d\n",module_data->module_name,module_data->number_used_functions); + + for(size_t j = 0; j < hook_data_list.size();j++){ + replacement_data_hook_t * hook_data = &module_data->hooks[j]; + + HookData * hook_entry = hook_data_list[j]; + + DEBUG_FUNCTION_LINE("Set hook for module \"%s\" of type %08X to target %08X\n",module_data->module_name,hook_entry->getType(),(void*) hook_entry->getFunctionPointer()); + hook_data->func_pointer = (void*) hook_entry->getFunctionPointer(); + hook_data->type = hook_entry->getType(); + module_data->number_used_hooks++; + } + + DEBUG_FUNCTION_LINE("Hooks for module \"%s\": %d\n",module_data->module_name,module_data->number_used_hooks); + + module_index++; + gbl_replacement_data.number_used_modules++; } - DEBUG_FUNCTION_LINE("--- module list end ---\n"); } -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]._function.library); - DEBUG_FUNCTION_LINE("function: %s \n",module_entries[i]._function.name); - DEBUG_FUNCTION_LINE("pointer: %08X \n",module_entries[i]._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"); +static void loadElf(std::vector* modules, const char * elfPath, uint8_t ** space){ + DEBUG_FUNCTION_LINE("Try to load %s\n",elfPath); + + ModuleData * module = new ModuleData(elfPath,space); + if(module->isLoadedSuccessfully()){ + DEBUG_FUNCTION_LINE("%s loading was successful!. \n", elfPath); + modules->push_back(module); + } else { + DEBUG_FUNCTION_LINE("%s loading failed. \n", elfPath); + } } diff --git a/loader/src/main.h b/loader/src/main.h index 7e9cf4a..4c6daf0 100644 --- a/loader/src/main.h +++ b/loader/src/main.h @@ -1,3 +1,20 @@ +/**************************************************************************** + * Copyright (C) 2018 Maschell + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + #ifndef _MAIN_H_ #define _MAIN_H_ @@ -9,9 +26,10 @@ extern "C" { #endif +#include + //! C wrapper for our C++ functions int Menu_Main(int argc, char **argv); -void loadElf(const char * elfPath); #ifdef __cplusplus } diff --git a/loader/src/module_parser.cpp b/loader/src/module_parser.cpp deleted file mode 100644 index 8101c8b..0000000 --- a/loader/src/module_parser.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/* module_parser.cpp - * by Alex Chadwick - * - * Copyright (C) 2014, Alex Chadwick - * Modified 2018, Maschell - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "module_parser.h" -#include "elf_utils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "common/retain_vars.h" -#include "utils.h" - -bool module_has_error; -bool module_has_info; - -#define MODULE_LIST_CAPACITY_DEFAULT 16 - -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; - -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; - - /* find the file extension */ - extension = strrchr(path, '.'); - if (extension == NULL){ - extension = strchr(path, '\0'); - }else{ - extension++; - } - - assert(extension != NULL); - - if (strcmp(extension, "mod") == 0 || - strcmp(extension, "o") == 0 || - strcmp(extension, "a") == 0 || - strcmp(extension, "elf") == 0) { - return true; - } - return false; -} - -void Module_Load(const char *path) { - int fd = -1; - Elf *elf = NULL; - - /* check for compile errors */ - if (elf_version(EV_CURRENT) == EV_NONE) - goto exit_error; - - fd = open(path, O_RDONLY, 0); - - if (fd == -1) - goto exit_error; - - elf = elf_begin(fd, ELF_C_READ, NULL); - - if (elf == NULL) - goto exit_error; - - switch (elf_kind(elf)) { - case ELF_K_AR: - /* TODO */ - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Archives not yet supported.\n", path); - module_has_info = true; - goto exit_error; - case ELF_K_ELF: - Module_LoadElf(path, elf); - break; - default: - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - Invalid ELF file.\n", path); - goto exit_error; - } - -exit_error: - if (elf != NULL) - elf_end(elf); - if (fd != -1) - close(fd); -} - -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_metadata_t **list_ptr; - - assert(elf != NULL); - assert(elf_kind(elf) == ELF_K_ELF); - - ident = elf_getident(elf, &sz); - - if (ident == NULL) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF header.\n", path); - module_has_info = true; - goto exit_error; - } - if (sz < 7) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF header.\n", path); - 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 = true; - goto exit_error; - } - if (ident[5] != ELFDATA2MSB) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not Big Endian.\n", path); - 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 = true; - goto exit_error; - } - - ehdr = elf32_getehdr(elf); - - if (ehdr == NULL) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF header\n", path); - 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 = 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 = true; - goto exit_error; - } - if (ehdr->e_version != EV_CURRENT) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Unknown ELF version.\n", path); - module_has_info = true; - goto exit_error; - } - - if (!Module_LoadElfSymtab(elf, &symtab, &symtab_count, &symtab_strndx)) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't parse symtab.\n", path); - module_has_info = true; - goto exit_error; - } - - assert(symtab != NULL); - - DEBUG_FUNCTION_LINE("Reading metadata from path %s.\n", path); - - 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 = true; - goto exit_error; - } - - for (scn = elf_nextscn(elf, NULL); - scn != NULL; - scn = elf_nextscn(elf, scn)) { - - Elf32_Shdr *shdr; - - shdr = elf32_getshdr(scn); - if (shdr == NULL) - continue; - - if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) && - (shdr->sh_flags & SHF_ALLOC)) { - - const char *name; - - name = elf_strptr(elf, shstrndx, shdr->sh_name); - if (name == NULL) - continue; - - if (strcmp(name, ".wups.meta") == 0) { - continue; - } else if (strcmp(name, ".wups.load") == 0) { - metadata->size += - shdr->sh_size / sizeof(wups_loader_entry_t) * 6*4; - } else if (strcmp(name, ".wups.hooks") == 0) { - metadata->size += - shdr->sh_size / sizeof(wups_loader_hook_t) * 2*4; - } else { - metadata->size += shdr->sh_size; - /* add alignment padding to size */ - if (shdr->sh_addralign > 3) - /* roundup to multiple of sh_addralign */ - 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); - - strncpy(gbl_replacement_data.module_data[module_list_count].module_name,metadata->name,MAXIMUM_MODULE_NAME_LENGTH-1); - - 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; - - gbl_replacement_data.number_used_modules++; - - -exit_error: - if (metadata != NULL) - free(metadata); - if (symtab != NULL) - free(symtab); -} - -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 *game, *name, *author, *version, *license, *wups; - module_metadata_t *ret = NULL; - Elf_Scn *scn; - size_t shstrndx, entries_count; - - if (elf_getshdrstrndx(elf, &shstrndx) != 0) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't find shstrndx\n", path); - module_has_info = true; - goto exit_error; - } - - entries_count = 0; - - for (scn = elf_nextscn(elf, NULL); - scn != NULL; - scn = elf_nextscn(elf, scn)) { - - Elf32_Shdr *shdr; - const char *name; - - shdr = elf32_getshdr(scn); - if (shdr == NULL) - continue; - - name = elf_strptr(elf, shstrndx, shdr->sh_name); - if (name == NULL) - continue; - - if (strcmp(name, ".wups.meta") == 0) { - if (shdr->sh_size == 0) - continue; - - if (metadata != NULL) - continue; - metadata = (char*) malloc(shdr->sh_size); - if (metadata == NULL) - continue; - - if (!Module_ElfLoadSection(elf, scn, shdr, metadata)) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't load .wups.meta.\n", path); - module_has_info = true; - goto exit_error; - } - - Module_ElfLoadSymbols( - elf_ndxscn(scn), metadata, symtab, symtab_count); - - 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 = true; - goto exit_error; - } - - metadata_end = metadata + shdr->sh_size; - metadata_end[-1] = '\0'; - } else if (strcmp(name, ".wups.load") == 0) { - entries_count = shdr->sh_size / sizeof(wups_loader_entry_t); - } - } - - if (metadata == NULL) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Not a WUPS module file.\n", path); - module_has_info = true; - goto exit_error; - } - - game = NULL; - name = NULL; - author = NULL; - version = NULL; - license = NULL; - wups = NULL; - - for (metadata_cur = metadata; - metadata_cur < metadata_end; - metadata_cur = strchr(metadata_cur, '\0') + 1) { - - char *eq; - - assert(metadata_cur >= metadata && metadata_cur < metadata_end); - - if (*metadata_cur == '\0') - continue; - - eq = strchr(metadata_cur, '='); - if (eq == NULL) - continue; - - 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 = true; - goto exit_error; - } - name = eq + 1; - } else if (strncmp(metadata_cur, "author", eq - metadata_cur) == 0) { - if (author != NULL) { - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - Multiple WUPS_MODULE_AUTHOR " - "declarations.\n", path); - module_has_info = true; - goto exit_error; - } - author = eq + 1; - } else if (strncmp(metadata_cur, "version", eq - metadata_cur) == 0) { - if (version != NULL) { - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - Multiple WUPS_MODULE_VERSION " - "declarations.\n", path); - module_has_info = true; - goto exit_error; - } - version = eq + 1; - } else if (strncmp(metadata_cur, "license", eq - metadata_cur) == 0) { - if (license != NULL) { - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - Multiple WUPS_MODULE_LICENSE " - "declarations.\n", path); - module_has_info = true; - goto exit_error; - } - license = eq + 1; - } else if (strncmp(metadata_cur, "wups", eq - metadata_cur) == 0) { - if (wups != NULL) { - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - Multiple WUPS_MODULE_NAME " - "declarations.\n", path); - 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 = true; - goto exit_error; - } - if (name == NULL) { - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - Missing WUPS_MODULE_NAME declaration.\n", - path); - 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 = true; - goto exit_error; - } - if (version == NULL) { - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - Missing WUPS_MODULE_VERSION " - "declaration.\n", path); - 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 = true; - goto exit_error; - } - - 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 WUPS metadata.\n", path); - module_has_info = true; - goto exit_error; - } - - tmp = (char *)(ret + 1); - strcpy(tmp, path); - ret->path = tmp; - tmp = tmp + strlen(path) + 1; - strcpy(tmp, name); - ret->name = tmp; - tmp = tmp + strlen(name) + 1; - strcpy(tmp, author); - ret->author = tmp; - tmp = tmp + strlen(author) + 1; - strcpy(tmp, version); - ret->version = tmp; - tmp = tmp + strlen(version) + 1; - strcpy(tmp, license); - ret->license = tmp; - ret->size = 0; - ret->entries_count = entries_count; - -exit_error: - if (metadata != NULL) - free(metadata); - - return ret; -} diff --git a/loader/src/module_parser.h b/loader/src/module_parser.h deleted file mode 100644 index d63e5c4..0000000 --- a/loader/src/module_parser.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef _MODULE_PARSER_H_ -#define _MODULE_PARSER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifdef __cplusplus -} -#endif - -#include -#include -#include - -typedef struct { - const char *path; - const char *name; - const char *author; - const char *version; - const char *license; - size_t size; - size_t entries_count; -} module_metadata_t; - -typedef struct { - size_t module; - const char *name; - void *address; - size_t offset; - char type; - int addend; -} module_unresolved_relocation_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 Module_Load(const char *path); - -#endif diff --git a/loader/src/patcher/function_patcher.h b/loader/src/patcher/function_patcher.h index e2feaaf..6aaa762 100644 --- a/loader/src/patcher/function_patcher.h +++ b/loader/src/patcher/function_patcher.h @@ -62,7 +62,7 @@ struct replacement_data_hook_t{ }; -#define MAXIMUM_HOOKS_PER_MODULE 4 +#define MAXIMUM_HOOKS_PER_MODULE 10 #define MAXIMUM_FUNCTION_PER_MODULE 100 struct replacement_data_module_t{ diff --git a/loader/src/utils.cpp b/loader/src/utils.cpp index 2f02628..bf7915d 100644 --- a/loader/src/utils.cpp +++ b/loader/src/utils.cpp @@ -38,32 +38,3 @@ void dumpHex(const void* data, size_t size) { } } } - -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 065f69f..ac94926 100644 --- a/loader/src/utils.h +++ b/loader/src/utils.h @@ -12,6 +12,4 @@ 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