From 51fc349237f46e7a839b5e99489cb4b23b5ce775 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 17 May 2020 21:14:27 +0200 Subject: [PATCH] Add support for WUMS, support for handling and resolving exports --- .gitignore | 1 + Makefile | 3 +- README.md | 6 +-- relocator/Makefile | 5 ++- relocator/src/hooks_patcher_static.cpp | 51 ++++++++++++++++++++--- source/common/export_defines.h | 10 +++++ source/common/module_defines.h | 6 ++- source/main.cpp | 2 +- source/module/ExportData.h | 30 ++++++++++++++ source/module/ModuleData.h | 20 +++++++++ source/module/ModuleDataFactory.cpp | 54 +++++++++++++++++++++++-- source/module/ModuleDataPersistence.cpp | 29 +++++++++++++ 12 files changed, 201 insertions(+), 16 deletions(-) create mode 100644 source/common/export_defines.h create mode 100644 source/module/ExportData.h diff --git a/.gitignore b/.gitignore index cab6c65..83d3e6c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ relocator.h *.layout .idea/ cmake-build-debug/ +*.txt diff --git a/Makefile b/Makefile index 1f8eced..6102869 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ TOPDIR ?= $(CURDIR) include $(DEVKITPRO)/wut/share/wut_rules +WUMS_ROOT := $(DEVKITPRO)/wums #------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -46,7 +47,7 @@ LIBS := -lwut # list of directories containing libraries, this must be the top level # containing include and lib #------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(WUT_ROOT) +LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUMS_ROOT) #------------------------------------------------------------------------------- diff --git a/README.md b/README.md index cbdb4f6..d68ecc1 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ This is a payload that should be run with [CustomRPXLoader](https://github.com/w ## Usage Put the `payload.rpx` in the `sd:/wiiu/` folder of your sd card and use the `CustomRPXLoader` to run this setup payload. -Put modules (in form of `.rpx` files) that should be used a main()-hook into `sd:/wiiu/modules/` and one time modules into `sd:/wiiu/modules/setup`. -- Make sure not to call `exit` in the modules (for example by using a custom crt instead of the wut one) +Put modules (in form of `.wms` files) that should be used a main()-hook into `sd:/wiiu/modules/` and one time modules into `sd:/wiiu/modules/setup`. +- Make sure not to call `exit` in the modules (by using the WiiUModuleSystem) - The one time setups will be run in the order of their ordered filenames. The area between `0x00800000` and whereever this setup is loaded, will be used. ## Building -Make you to have [wut](https://github.com/devkitPro/wut/) installed and use the following command for build: +Make you to have [wut](https://github.com/devkitPro/wut/) and [WiiUModuleSystem](https://github.com/wiiu-env/WiiUModuleSystem) installed and use the following command for build: ``` make install ``` diff --git a/relocator/Makefile b/relocator/Makefile index eda32b2..58135d0 100644 --- a/relocator/Makefile +++ b/relocator/Makefile @@ -22,6 +22,8 @@ export CXX := $(PREFIX)g++ export AR := $(PREFIX)ar export OBJCOPY := $(PREFIX)objcopy +WUMS_ROOT := $(DEVKITPRO)/wums + #--------------------------------------------------------------------------------- # TARGET is the name of the output # BUILD is the directory where object files & intermediate files will be placed @@ -53,7 +55,7 @@ MAKEFLAGS += --no-print-directory #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := +LIBS := -lwums #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing @@ -62,6 +64,7 @@ LIBS := LIBDIRS := $(CURDIR) \ $(DEVKITPPC)/lib \ $(DEVKITPRO)/wut \ + $(WUMS_ROOT) \ $(DEVKITPPC)/lib/gcc/powerpc-eabi/$(GCC_VER) diff --git a/relocator/src/hooks_patcher_static.cpp b/relocator/src/hooks_patcher_static.cpp index c6e83c2..14459d4 100644 --- a/relocator/src/hooks_patcher_static.cpp +++ b/relocator/src/hooks_patcher_static.cpp @@ -1,21 +1,60 @@ #include "utils/logger.h" #include "utils/function_patcher.h" +#include "../../source/common/module_defines.h" #include #include +#define gModuleData ((module_information_t *) (0x00880000)) + DECL(OSDynLoad_Error, OSDynLoad_Acquire, char const *name, OSDynLoad_Module *outModule) { - DEBUG_FUNCTION_LINE("%s\n", name); - return real_OSDynLoad_Acquire(name, outModule); + OSDynLoad_Error result = real_OSDynLoad_Acquire(name, outModule); + if (result == OS_DYNLOAD_OK) { + return OS_DYNLOAD_OK; + } + DEBUG_FUNCTION_LINE("Looking for module %s\n", name); + for (uint32_t i = 0; i < MAXIMUM_MODULES; i++) { + if (strncmp(name, gModuleData->module_data[i].module_export_name, MAXIMUM_EXPORT_MODULE_NAME_LENGTH) == 0) { + *outModule = (OSDynLoad_Module) (0x13370000 + i); + return OS_DYNLOAD_OK; + } + } + return result; } DECL(OSDynLoad_Error, OSDynLoad_FindExport, OSDynLoad_Module module, BOOL isData, char const *name, void **outAddr) { - DEBUG_FUNCTION_LINE("%s\n", name); - return real_OSDynLoad_FindExport(module, isData, name, outAddr); + //DEBUG_FUNCTION_LINE("%08X\n", module); + OSDynLoad_Error result = real_OSDynLoad_FindExport(module, isData, name, outAddr); + if (result == OS_DYNLOAD_OK) { + return OS_DYNLOAD_OK; + } + + DEBUG_FUNCTION_LINE("Looking for %s in handle %d\n", name); + if (((uint32_t) module & 0xFFFF0000) == 0x13370000) { + uint32_t modulehandle = ((uint32_t) module) & 0x0000FFFF; + if (modulehandle > MAXIMUM_MODULES) { + return result; + } + export_data_t *exportEntries = gModuleData->module_data[modulehandle].export_entries; + for (uint32_t i = 0; i < EXPORT_ENTRY_LIST_LENGTH; i++) { + if (strncmp(name, exportEntries[i].name, EXPORT_MAXIMUM_NAME_LENGTH) == 0) { + if (isData && exportEntries[i].type != 1) { + return OS_DYNLOAD_INVALID_MODULE_NAME; + } + *outAddr = (void *) exportEntries[i].address; + DEBUG_FUNCTION_LINE("Set outAddr to %08X. It's from module %s function %s\n", + exportEntries[i].address, + gModuleData->module_data[modulehandle].module_export_name, + exportEntries[i].name); + return OS_DYNLOAD_OK; + } + } + } + return result; } hooks_magic_t method_hooks_hooks_static[] __attribute__((section(".data"))) = { - MAKE_MAGIC(OSDynLoad_Acquire, LIB_CORE_INIT, STATIC_FUNCTION), - MAKE_MAGIC(OSDynLoad_FindExport, LIB_CORE_INIT, STATIC_FUNCTION) + MAKE_MAGIC(OSDynLoad_Acquire, LIB_CORE_INIT, STATIC_FUNCTION), + MAKE_MAGIC(OSDynLoad_FindExport, LIB_CORE_INIT, STATIC_FUNCTION) }; uint32_t method_hooks_size_hooks_static __attribute__((section(".data"))) = sizeof(method_hooks_hooks_static) / sizeof(hooks_magic_t); diff --git a/source/common/export_defines.h b/source/common/export_defines.h new file mode 100644 index 0000000..6b007c7 --- /dev/null +++ b/source/common/export_defines.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +#define EXPORT_MAXIMUM_NAME_LENGTH 50 +typedef struct export_data_t { + uint32_t type; + char name[EXPORT_MAXIMUM_NAME_LENGTH]; + uint32_t address = 0; +} export_data_t; \ No newline at end of file diff --git a/source/common/module_defines.h b/source/common/module_defines.h index f44fe89..ac2a7d1 100644 --- a/source/common/module_defines.h +++ b/source/common/module_defines.h @@ -21,19 +21,23 @@ #include #include "dynamic_linking_defines.h" #include "relocation_defines.h" +#include "export_defines.h" #ifdef __cplusplus extern "C" { #endif #define MAXIMUM_MODULE_PATH_NAME_LENGTH 256 -#define MAXIMUM_MODULE_NAME_LENGTH 51 +#define MAXIMUM_EXPORT_MODULE_NAME_LENGTH 51 #define DYN_LINK_RELOCATION_LIST_LENGTH 500 +#define EXPORT_ENTRY_LIST_LENGTH 100 struct module_information_single_t { char path[MAXIMUM_MODULE_PATH_NAME_LENGTH] = ""; // Path where the module is stored dyn_linking_relocation_entry_t linking_entries[DYN_LINK_RELOCATION_LIST_LENGTH]; + char module_export_name[MAXIMUM_EXPORT_MODULE_NAME_LENGTH]; + export_data_t export_entries[EXPORT_ENTRY_LIST_LENGTH]; int32_t priority; // Priority of this module uint32_t bssAddr; uint32_t bssSize; diff --git a/source/main.cpp b/source/main.cpp index 4b70a67..373e932 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -114,7 +114,7 @@ int main(int argc, char **argv) { memset((void *) gModuleData, 0, sizeof(module_information_t)); - DirList modules("fs:/vol/external01/wiiu/modules", ".rpx", DirList::Files, 1); + DirList modules("fs:/vol/external01/wiiu/modules", ".wms", DirList::Files, 1); modules.SortList(); for (int i = 0; i < modules.GetFilecount(); i++) { diff --git a/source/module/ExportData.h b/source/module/ExportData.h new file mode 100644 index 0000000..80b571b --- /dev/null +++ b/source/module/ExportData.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +class ExportData { + +public: + ExportData(wums_entry_type_t type, const std::string &name, const void *address) { + this->type = type; + this->name = name; + this->address = address; + } + + const wums_entry_type_t getType() const { + return type; + } + + const void *getAddress() const { + return address; + } + + const std::string getName() const { + return name; + } + +private: + wums_entry_type_t type; + std::string name; + const void *address; +}; \ No newline at end of file diff --git a/source/module/ModuleData.h b/source/module/ModuleData.h index 9b7e117..c5f193e 100644 --- a/source/module/ModuleData.h +++ b/source/module/ModuleData.h @@ -22,6 +22,7 @@ #include #include "RelocationData.h" #include "SectionInfo.h" +#include "ExportData.h" class ModuleData { public: @@ -61,6 +62,14 @@ public: return relocation_data_list; } + void addExportData(const ExportData &data) { + export_data_list.push_back(data); + } + + const std::vector &getExportDataList() const { + return export_data_list; + } + void addSectionInfo(const SectionInfo §ionInfo) { section_info_list[sectionInfo.getName()] = sectionInfo; } @@ -106,10 +115,21 @@ public: std::string toString() const; + void setExportName(const std::string &name) { + this->export_name = name; + } + + std::string getExportName() const { + return this->export_name; + } + private: std::vector relocation_data_list; + std::vector export_data_list; std::map section_info_list; + std::string export_name; + uint32_t bssAddr = 0; uint32_t bssSize = 0; uint32_t sbssAddr = 0; diff --git a/source/module/ModuleDataFactory.cpp b/source/module/ModuleDataFactory.cpp index 5616698..acdb0c9 100644 --- a/source/module/ModuleDataFactory.cpp +++ b/source/module/ModuleDataFactory.cpp @@ -19,11 +19,13 @@ #include #include #include +#include #include "ModuleDataFactory.h" #include "elfio/elfio.hpp" #include "utils/utils.h" #include "ElfUtils.h" #include "SectionInfo.h" +#include "ExportData.h" using namespace ELFIO; @@ -104,7 +106,6 @@ std::optional ModuleDataFactory::load(std::string path, uint32_t des moduleData.addSectionInfo(SectionInfo(psec->get_name(), destination, sectionSize)); DEBUG_FUNCTION_LINE("Saved %s section info. Location: %08X size: %08X", psec->get_name().c_str(), destination, sectionSize); - totalSize += sectionSize; if (endAddress < destination + sectionSize) { @@ -133,8 +134,55 @@ std::optional ModuleDataFactory::load(std::string path, uint32_t des moduleData.addRelocationData(reloc); } - DCFlushRange((void *) destination_address, totalSize); - ICInvalidateRange((void *) destination_address, totalSize); + std::optional secInfo = moduleData.getSectionInfo(".wums.exports"); + if (secInfo && secInfo->getSize() > 0) { + size_t entries_count = secInfo->getSize() / sizeof(wums_entry_t); + wums_entry_t *entries = (wums_entry_t *) secInfo->getAddress(); + if (entries != NULL) { + for (size_t j = 0; j < entries_count; j++) { + wums_entry_t * exp = &entries[j]; + DEBUG_FUNCTION_LINE("Saving export of type %08X, name %s, target: %08X"/*,pluginData.getPluginInformation()->getName().c_str()*/, exp->type, exp->name, (void *) exp->address); + ExportData export_data(exp->type, exp->name, exp->address); + moduleData.addExportData(export_data); + } + } + } + + secInfo = moduleData.getSectionInfo(".wums.meta"); + if (secInfo && secInfo->getSize() > 0) { + wums_entry_t *entries = (wums_entry_t *) secInfo->getAddress(); + if (entries != NULL) { + + char *curEntry = (char *) secInfo->getAddress(); + while ((uint32_t) curEntry < (uint32_t) secInfo->getAddress() + secInfo->getSize()) { + if (*curEntry == '\0') { + curEntry++; + continue; + } + + auto firstFound = std::string(curEntry).find_first_of("="); + if (firstFound != std::string::npos) { + curEntry[firstFound] = '\0'; + std::string key(curEntry); + std::string value(curEntry + firstFound + 1); + + if (key.compare("export_name") == 0) { + DEBUG_FUNCTION_LINE("export_name = %s", value.c_str()); + moduleData.setExportName(value); + }else if (key.compare("wums") == 0) { + if (value.compare("0.1") != 0) { + DEBUG_FUNCTION_LINE("Warning: Ignoring module - Unsupported WUMS version: %s.\n", value.c_str()); + return std::nullopt; + } + } + } + curEntry += strlen(curEntry) + 1; + } + } + } + + DCFlushRange((void*)destination_address, totalSize); + ICInvalidateRange((void*)destination_address, totalSize); free(destinations); diff --git a/source/module/ModuleDataPersistence.cpp b/source/module/ModuleDataPersistence.cpp index cf44576..65be88e 100644 --- a/source/module/ModuleDataPersistence.cpp +++ b/source/module/ModuleDataPersistence.cpp @@ -26,6 +26,27 @@ bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformati } } + std::vector exportData = module.getExportDataList(); + + for (auto const &curExport : exportData) { + bool found = false; + for (uint32_t j = 0; j < EXPORT_ENTRY_LIST_LENGTH; j++) { + export_data_t *export_entry = &(module_data->export_entries[j]); + if (export_entry->address == NULL) { + export_entry->type = curExport.getType(); + strncpy(export_entry->name, curExport.getName().c_str(), EXPORT_MAXIMUM_NAME_LENGTH); + export_entry->address = (uint32_t) curExport.getAddress(); + found = true; + break; + } + } + if (!found) { + DEBUG_FUNCTION_LINE("Failed to found enough exports slots"); + } + } + + strncpy(module_data->module_export_name, module.getExportName().c_str(), MAXIMUM_EXPORT_MODULE_NAME_LENGTH); + module_data->bssAddr = module.getBSSAddr(); module_data->bssSize = module.getBSSSize(); module_data->sbssAddr = module.getSBSSAddr(); @@ -67,6 +88,14 @@ std::vector ModuleDataPersistence::loadModuleData(module_information moduleData.setStartAddress(module_data->startAddress); moduleData.setEndAddress(module_data->endAddress); + for (uint32_t j = 0; j < EXPORT_ENTRY_LIST_LENGTH; i++) { + export_data_t *export_entry = &(module_data->export_entries[j]); + if (export_entry->address == NULL) { + continue; + } + moduleData.addExportData(ExportData(static_cast(export_entry->type), export_entry->name, reinterpret_cast(export_entry->address))); + } + for (uint32_t j = 0; j < DYN_LINK_RELOCATION_LIST_LENGTH; j++) { dyn_linking_relocation_entry_t *linking_entry = &(module_data->linking_entries[j]); if (linking_entry->destination == NULL) {