mirror of
https://github.com/wiiu-env/WUMSLoader.git
synced 2024-12-27 16:41:50 +01:00
Add support for WUMS, support for handling and resolving exports
This commit is contained in:
parent
2ee3011ae8
commit
51fc349237
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@ relocator.h
|
||||
*.layout
|
||||
.idea/
|
||||
cmake-build-debug/
|
||||
*.txt
|
||||
|
3
Makefile
3
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)
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -1,21 +1,60 @@
|
||||
#include "utils/logger.h"
|
||||
#include "utils/function_patcher.h"
|
||||
#include "../../source/common/module_defines.h"
|
||||
#include <malloc.h>
|
||||
#include <coreinit/dynload.h>
|
||||
|
||||
#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);
|
||||
|
10
source/common/export_defines.h
Normal file
10
source/common/export_defines.h
Normal 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;
|
@ -21,19 +21,23 @@
|
||||
#include <stddef.h>
|
||||
#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;
|
||||
|
@ -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++) {
|
||||
|
30
source/module/ExportData.h
Normal file
30
source/module/ExportData.h
Normal 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;
|
||||
};
|
@ -22,6 +22,7 @@
|
||||
#include <map>
|
||||
#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<ExportData> &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<RelocationData> relocation_data_list;
|
||||
std::vector<ExportData> export_data_list;
|
||||
std::map<std::string, SectionInfo> section_info_list;
|
||||
|
||||
std::string export_name;
|
||||
|
||||
uint32_t bssAddr = 0;
|
||||
uint32_t bssSize = 0;
|
||||
uint32_t sbssAddr = 0;
|
||||
|
@ -19,11 +19,13 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <coreinit/cache.h>
|
||||
#include <wums.h>
|
||||
#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<ModuleData> 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<ModuleData> ModuleDataFactory::load(std::string path, uint32_t des
|
||||
moduleData.addRelocationData(reloc);
|
||||
}
|
||||
|
||||
DCFlushRange((void *) destination_address, totalSize);
|
||||
ICInvalidateRange((void *) destination_address, totalSize);
|
||||
std::optional<SectionInfo> 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);
|
||||
|
||||
|
@ -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->bssSize = module.getBSSSize();
|
||||
module_data->sbssAddr = module.getSBSSAddr();
|
||||
@ -67,6 +88,14 @@ std::vector<ModuleData> 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<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++) {
|
||||
dyn_linking_relocation_entry_t *linking_entry = &(module_data->linking_entries[j]);
|
||||
if (linking_entry->destination == NULL) {
|
||||
|
Loading…
Reference in New Issue
Block a user