Add support for WUMS, support for handling and resolving exports

This commit is contained in:
Maschell 2020-05-17 21:14:27 +02:00
parent 2ee3011ae8
commit 51fc349237
12 changed files with 201 additions and 16 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@ relocator.h
*.layout *.layout
.idea/ .idea/
cmake-build-debug/ cmake-build-debug/
*.txt

View File

@ -10,6 +10,7 @@ TOPDIR ?= $(CURDIR)
include $(DEVKITPRO)/wut/share/wut_rules include $(DEVKITPRO)/wut/share/wut_rules
WUMS_ROOT := $(DEVKITPRO)/wums
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# TARGET is the name of the output # TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed # 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 # list of directories containing libraries, this must be the top level
# containing include and lib # containing include and lib
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(WUT_ROOT) LIBDIRS := $(PORTLIBS) $(WUT_ROOT) $(WUMS_ROOT)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------

View File

@ -4,14 +4,14 @@ This is a payload that should be run with [CustomRPXLoader](https://github.com/w
## Usage ## Usage
Put the `payload.rpx` in the `sd:/wiiu/` folder of your sd card and use the `CustomRPXLoader` to run this setup payload. 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`. 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 (for example by using a custom crt instead of the wut one) - 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 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. The area between `0x00800000` and whereever this setup is loaded, will be used.
## Building ## 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 make install
``` ```

View File

@ -22,6 +22,8 @@ export CXX := $(PREFIX)g++
export AR := $(PREFIX)ar export AR := $(PREFIX)ar
export OBJCOPY := $(PREFIX)objcopy export OBJCOPY := $(PREFIX)objcopy
WUMS_ROOT := $(DEVKITPRO)/wums
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# TARGET is the name of the output # TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed # 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 # 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 # list of directories containing libraries, this must be the top level containing
@ -62,6 +64,7 @@ LIBS :=
LIBDIRS := $(CURDIR) \ LIBDIRS := $(CURDIR) \
$(DEVKITPPC)/lib \ $(DEVKITPPC)/lib \
$(DEVKITPRO)/wut \ $(DEVKITPRO)/wut \
$(WUMS_ROOT) \
$(DEVKITPPC)/lib/gcc/powerpc-eabi/$(GCC_VER) $(DEVKITPPC)/lib/gcc/powerpc-eabi/$(GCC_VER)

View File

@ -1,16 +1,55 @@
#include "utils/logger.h" #include "utils/logger.h"
#include "utils/function_patcher.h" #include "utils/function_patcher.h"
#include "../../source/common/module_defines.h"
#include <malloc.h> #include <malloc.h>
#include <coreinit/dynload.h> #include <coreinit/dynload.h>
#define gModuleData ((module_information_t *) (0x00880000))
DECL(OSDynLoad_Error, OSDynLoad_Acquire, char const *name, OSDynLoad_Module *outModule) { DECL(OSDynLoad_Error, OSDynLoad_Acquire, char const *name, OSDynLoad_Module *outModule) {
DEBUG_FUNCTION_LINE("%s\n", name); OSDynLoad_Error result = real_OSDynLoad_Acquire(name, outModule);
return 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) { DECL(OSDynLoad_Error, OSDynLoad_FindExport, OSDynLoad_Module module, BOOL isData, char const *name, void **outAddr) {
DEBUG_FUNCTION_LINE("%s\n", name); //DEBUG_FUNCTION_LINE("%08X\n", module);
return real_OSDynLoad_FindExport(module, isData, name, outAddr); 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"))) = { hooks_magic_t method_hooks_hooks_static[] __attribute__((section(".data"))) = {

View File

@ -0,0 +1,10 @@
#pragma once
#include <cstdint>
#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;

View File

@ -21,19 +21,23 @@
#include <stddef.h> #include <stddef.h>
#include "dynamic_linking_defines.h" #include "dynamic_linking_defines.h"
#include "relocation_defines.h" #include "relocation_defines.h"
#include "export_defines.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define MAXIMUM_MODULE_PATH_NAME_LENGTH 256 #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 DYN_LINK_RELOCATION_LIST_LENGTH 500
#define EXPORT_ENTRY_LIST_LENGTH 100
struct module_information_single_t { struct module_information_single_t {
char path[MAXIMUM_MODULE_PATH_NAME_LENGTH] = ""; // Path where the module is stored 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]; 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 int32_t priority; // Priority of this module
uint32_t bssAddr; uint32_t bssAddr;
uint32_t bssSize; uint32_t bssSize;

View File

@ -114,7 +114,7 @@ int main(int argc, char **argv) {
memset((void *) gModuleData, 0, sizeof(module_information_t)); 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(); modules.SortList();
for (int i = 0; i < modules.GetFilecount(); i++) { for (int i = 0; i < modules.GetFilecount(); i++) {

View File

@ -0,0 +1,30 @@
#pragma once
#include <wums.h>
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;
};

View File

@ -22,6 +22,7 @@
#include <map> #include <map>
#include "RelocationData.h" #include "RelocationData.h"
#include "SectionInfo.h" #include "SectionInfo.h"
#include "ExportData.h"
class ModuleData { class ModuleData {
public: public:
@ -61,6 +62,14 @@ public:
return relocation_data_list; return relocation_data_list;
} }
void addExportData(const ExportData &data) {
export_data_list.push_back(data);
}
const std::vector<ExportData> &getExportDataList() const {
return export_data_list;
}
void addSectionInfo(const SectionInfo &sectionInfo) { void addSectionInfo(const SectionInfo &sectionInfo) {
section_info_list[sectionInfo.getName()] = sectionInfo; section_info_list[sectionInfo.getName()] = sectionInfo;
} }
@ -106,10 +115,21 @@ public:
std::string toString() const; std::string toString() const;
void setExportName(const std::string &name) {
this->export_name = name;
}
std::string getExportName() const {
return this->export_name;
}
private: private:
std::vector<RelocationData> relocation_data_list; std::vector<RelocationData> relocation_data_list;
std::vector<ExportData> export_data_list;
std::map<std::string, SectionInfo> section_info_list; std::map<std::string, SectionInfo> section_info_list;
std::string export_name;
uint32_t bssAddr = 0; uint32_t bssAddr = 0;
uint32_t bssSize = 0; uint32_t bssSize = 0;
uint32_t sbssAddr = 0; uint32_t sbssAddr = 0;

View File

@ -19,11 +19,13 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <coreinit/cache.h> #include <coreinit/cache.h>
#include <wums.h>
#include "ModuleDataFactory.h" #include "ModuleDataFactory.h"
#include "elfio/elfio.hpp" #include "elfio/elfio.hpp"
#include "utils/utils.h" #include "utils/utils.h"
#include "ElfUtils.h" #include "ElfUtils.h"
#include "SectionInfo.h" #include "SectionInfo.h"
#include "ExportData.h"
using namespace ELFIO; using namespace ELFIO;
@ -104,7 +106,6 @@ std::optional<ModuleData> ModuleDataFactory::load(std::string path, uint32_t des
moduleData.addSectionInfo(SectionInfo(psec->get_name(), destination, sectionSize)); 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); DEBUG_FUNCTION_LINE("Saved %s section info. Location: %08X size: %08X", psec->get_name().c_str(), destination, sectionSize);
totalSize += sectionSize; totalSize += sectionSize;
if (endAddress < destination + sectionSize) { if (endAddress < destination + sectionSize) {
@ -133,8 +134,55 @@ std::optional<ModuleData> ModuleDataFactory::load(std::string path, uint32_t des
moduleData.addRelocationData(reloc); moduleData.addRelocationData(reloc);
} }
DCFlushRange((void *) destination_address, totalSize); std::optional<SectionInfo> secInfo = moduleData.getSectionInfo(".wums.exports");
ICInvalidateRange((void *) destination_address, totalSize); 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); free(destinations);

View File

@ -26,6 +26,27 @@ bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformati
} }
} }
std::vector<ExportData> 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->bssAddr = module.getBSSAddr();
module_data->bssSize = module.getBSSSize(); module_data->bssSize = module.getBSSSize();
module_data->sbssAddr = module.getSBSSAddr(); module_data->sbssAddr = module.getSBSSAddr();
@ -67,6 +88,14 @@ std::vector<ModuleData> ModuleDataPersistence::loadModuleData(module_information
moduleData.setStartAddress(module_data->startAddress); moduleData.setStartAddress(module_data->startAddress);
moduleData.setEndAddress(module_data->endAddress); 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<wums_entry_type_t>(export_entry->type), export_entry->name, reinterpret_cast<const void *>(export_entry->address)));
}
for (uint32_t j = 0; j < DYN_LINK_RELOCATION_LIST_LENGTH; j++) { for (uint32_t j = 0; j < DYN_LINK_RELOCATION_LIST_LENGTH; j++) {
dyn_linking_relocation_entry_t *linking_entry = &(module_data->linking_entries[j]); dyn_linking_relocation_entry_t *linking_entry = &(module_data->linking_entries[j]);
if (linking_entry->destination == NULL) { if (linking_entry->destination == NULL) {