mirror of
https://github.com/wiiu-env/WiiUPluginLoaderBackend.git
synced 2024-11-05 20:45:07 +01:00
Try to allocate memory for the plugins via the memory mapping module
This commit is contained in:
parent
f11649bc36
commit
b48a53b63d
@ -11,6 +11,7 @@
|
||||
#include "utils/ElfUtils.h"
|
||||
#include "PluginManagement.h"
|
||||
#include "hooks.h"
|
||||
#include "globals.h"
|
||||
|
||||
bool PluginManagement::doRelocation(const std::vector<RelocationData> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length, uint32_t trampolinID) {
|
||||
std::map<std::string, OSDynLoad_Module> moduleHandleCache;
|
||||
@ -139,10 +140,11 @@ void PluginManagement::unloadPlugins(plugin_information_t *gPluginInformation, M
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Deleted allocated .data section for plugin %s [%08X]", plugin->meta.name, plugin->info.allocatedDataMemoryAddress);
|
||||
}
|
||||
|
||||
for (auto &trampoline : gPluginInformation->trampolines) {
|
||||
if (trampoline.id == plugin->info.trampolinId) {
|
||||
trampoline.id = 0;
|
||||
trampoline.status = RELOC_TRAMP_FREE;
|
||||
for (uint32_t i = 0; i < gTrampolineDataSize; i++) {
|
||||
auto trampoline = &(gTrampolineData[i]);
|
||||
if (trampoline->id == plugin->info.trampolinId) {
|
||||
trampoline->id = 0;
|
||||
trampoline->status = RELOC_TRAMP_FREE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,13 +40,13 @@ extern "C" {
|
||||
|
||||
#define PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH 1000
|
||||
|
||||
#define MAXIMUM_HOOKS_PER_PLUGIN 25
|
||||
#define MAXIMUM_FUNCTION_PER_PLUGIN 100
|
||||
#define MAXIMUM_HOOKS_PER_PLUGIN 25
|
||||
#define MAXIMUM_FUNCTION_PER_PLUGIN 100
|
||||
|
||||
struct plugin_section_info_t {
|
||||
char name[MAXIMUM_PLUGIN_SECTION_NAME_LENGTH] = "";
|
||||
uint32_t addr;
|
||||
uint32_t size;
|
||||
char name[MAXIMUM_PLUGIN_SECTION_NAME_LENGTH] = "";
|
||||
uint32_t addr;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
struct plugin_meta_info_t {
|
||||
@ -95,7 +95,6 @@ struct plugin_information_single_t {
|
||||
struct plugin_information_t {
|
||||
int32_t number_used_plugins = 0; // Number of used plugins. Maximum is MAXIMUM_PLUGINS
|
||||
plugin_information_single_t plugin_data[MAXIMUM_PLUGINS];
|
||||
relocation_trampolin_entry_t trampolines[DYN_LINK_TRAMPOLIN_LIST_LENGTH];
|
||||
dyn_linking_relocation_data_t linking_data; // RPL and function name list
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,12 @@
|
||||
#include "globals.h"
|
||||
|
||||
MEMHeapHandle pluginDataHeap __attribute__((section(".data"))) = nullptr;
|
||||
MEMHeapHandle gPluginDataHeap __attribute__((section(".data"))) = nullptr;
|
||||
MEMHeapHandle gPluginInformationHeap __attribute__((section(".data"))) = nullptr;
|
||||
plugin_information_t *gPluginInformation __attribute__((section(".data"))) = nullptr;
|
||||
plugin_information_on_reload_t gLinkOnReload __attribute__((section(".data")));
|
||||
module_information_t *gModuleData __attribute__((section(".data"))) = nullptr;
|
||||
relocation_trampolin_entry_t *gTrampolineData __attribute__((section(".data"))) = nullptr;
|
||||
|
||||
uint32_t gPluginDataHeapSize = 0;
|
||||
uint32_t gPluginDataHeapSize = 0;
|
||||
uint32_t gPluginInformationHeapSize = 0;
|
||||
uint32_t gTrampolineDataSize = 0;
|
@ -6,7 +6,14 @@
|
||||
#include "common/plugin_defines.h"
|
||||
|
||||
extern plugin_information_t *gPluginInformation;
|
||||
extern MEMHeapHandle pluginDataHeap;
|
||||
extern MEMHeapHandle gPluginDataHeap;
|
||||
extern MEMHeapHandle gPluginInformationHeap;
|
||||
extern uint32_t gPluginDataHeapSize;
|
||||
extern uint32_t gPluginInformationHeapSize;
|
||||
extern plugin_information_on_reload_t gLinkOnReload;
|
||||
extern module_information_t *gModuleData;
|
||||
extern module_information_t *gModuleData;
|
||||
extern relocation_trampolin_entry_t *gTrampolineData;
|
||||
extern uint32_t gTrampolineDataSize;
|
||||
|
||||
#define PLUGIN_DATA_HEAP_SIZE (8 * 1024 * 1024)
|
||||
#define NUMBER_OF_TRAMPS 1024
|
@ -2,6 +2,8 @@
|
||||
#include <wums.h>
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/cache.h>
|
||||
#include <coreinit/dynload.h>
|
||||
#include <coreinit/memdefaultheap.h>
|
||||
#include "plugin/PluginContainer.h"
|
||||
#include "globals.h"
|
||||
#include "plugin/PluginDataFactory.h"
|
||||
@ -43,6 +45,8 @@ WUMS_APPLICATION_ENDS() {
|
||||
FunctionPatcherRestoreDynamicFunctions(method_hooks_hooks_static, method_hooks_size_hooks_static);
|
||||
}
|
||||
|
||||
void *allocOnCustomHeap(int alignment, int size);
|
||||
|
||||
WUMS_APPLICATION_STARTS() {
|
||||
WHBLogUdpInit();
|
||||
uint32_t upid = OSGetUPID();
|
||||
@ -50,11 +54,9 @@ WUMS_APPLICATION_STARTS() {
|
||||
return;
|
||||
}
|
||||
bool initNeeded = false;
|
||||
if (pluginDataHeap == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("gModuleData = %08X", gModuleData);
|
||||
if (gPluginDataHeap == nullptr) {
|
||||
DCFlushRange((void *) gModuleData, sizeof(module_information_t));
|
||||
uint32_t endAddress = 0;
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Using %d modules", gModuleData->number_used_modules);
|
||||
for (int i = 0; i < gModuleData->number_used_modules; i++) {
|
||||
uint32_t curEndAddr = gModuleData->module_data[i].endAddress;
|
||||
if (curEndAddr > endAddress) {
|
||||
@ -67,26 +69,50 @@ WUMS_APPLICATION_STARTS() {
|
||||
// in the SetupPayload repo. (I know that's a bad idea)
|
||||
endAddress = (endAddress + 0x100) & 0xFFFFFF00;
|
||||
|
||||
gPluginDataHeapSize = 0x00FFF000 - endAddress;
|
||||
gPluginInformationHeapSize = 0x00FFF000 - endAddress;
|
||||
|
||||
DEBUG_FUNCTION_LINE("Create heap to store plugins");
|
||||
pluginDataHeap = MEMCreateExpHeapEx((void *) (endAddress), gPluginDataHeapSize, 0);
|
||||
DEBUG_FUNCTION_LINE("Create heap for plugins information");
|
||||
gPluginInformationHeap = MEMCreateExpHeapEx((void *) (endAddress), gPluginInformationHeapSize, 0);
|
||||
|
||||
if (pluginDataHeap != nullptr) {
|
||||
if (gPluginInformationHeap == nullptr) {
|
||||
OSFatal("PluginBackend: Failed to allocate memory for plugin information");
|
||||
}
|
||||
|
||||
void *pluginHeapMemory = allocOnCustomHeap(0x1000, PLUGIN_DATA_HEAP_SIZE);
|
||||
if (pluginHeapMemory == nullptr) {
|
||||
DEBUG_FUNCTION_LINE("Use plugins information heap as fallback");
|
||||
gPluginDataHeap = gPluginInformationHeap;
|
||||
gPluginDataHeapSize = gPluginInformationHeapSize;
|
||||
} else {
|
||||
gPluginDataHeap = MEMCreateExpHeapEx(pluginHeapMemory, PLUGIN_DATA_HEAP_SIZE, 0);
|
||||
gPluginDataHeapSize = PLUGIN_DATA_HEAP_SIZE;
|
||||
}
|
||||
|
||||
if (gPluginDataHeap != nullptr) {
|
||||
if (gPluginInformation == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Allocate gPluginInformation on heap %08X (size: %d bytes)", pluginDataHeap, sizeof(plugin_information_t));
|
||||
gPluginInformation = (plugin_information_t *) MEMAllocFromExpHeapEx(pluginDataHeap, sizeof(plugin_information_t), 4);
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Allocate gPluginInformation on heap %08X (size: %d bytes)", gPluginInformationHeap, sizeof(plugin_information_t));
|
||||
gPluginInformation = (plugin_information_t *) MEMAllocFromExpHeapEx(gPluginInformationHeap, sizeof(plugin_information_t), 4);
|
||||
if (gPluginInformation == nullptr) {
|
||||
DEBUG_FUNCTION_LINE("Failed to allocate global plugin information");
|
||||
OSFatal("PluginBackend: Failed to allocate global plugin information");
|
||||
return;
|
||||
}
|
||||
memset((void *) gPluginInformation, 0, sizeof(plugin_information_t));
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Available memory for storing plugins: %d kb", MEMGetAllocatableSizeForExpHeapEx(pluginDataHeap, 4) / 1024);
|
||||
std::vector<PluginData> pluginList = PluginDataFactory::loadDir("fs:/vol/external01/wiiu/plugins/", pluginDataHeap);
|
||||
if (gTrampolineData == nullptr) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Allocate gTrampolineData on heap %08X (size: %d bytes)", gPluginDataHeap, sizeof(relocation_trampolin_entry_t) * NUMBER_OF_TRAMPS);
|
||||
gTrampolineData = (relocation_trampolin_entry_t *) MEMAllocFromExpHeapEx(gPluginDataHeap, sizeof(relocation_trampolin_entry_t) * NUMBER_OF_TRAMPS, 4);
|
||||
if (gTrampolineData == nullptr) {
|
||||
OSFatal("PluginBackend: Failed to allocate gTrampolineData");
|
||||
return;
|
||||
}
|
||||
gTrampolineDataSize = NUMBER_OF_TRAMPS;
|
||||
memset((void *) gTrampolineData, 0, sizeof(relocation_trampolin_entry_t) * NUMBER_OF_TRAMPS);
|
||||
}
|
||||
DEBUG_FUNCTION_LINE("Available memory for storing plugins: %d kb", MEMGetAllocatableSizeForExpHeapEx(gPluginDataHeap, 4) / 1024);
|
||||
std::vector<PluginData> pluginList = PluginDataFactory::loadDir("fs:/vol/external01/wiiu/plugins/", gPluginDataHeap);
|
||||
DEBUG_FUNCTION_LINE("Loaded data for %d plugins.", pluginList.size());
|
||||
|
||||
std::vector<PluginContainer> plugins = PluginManagement::loadPlugins(pluginList, pluginDataHeap, gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH);
|
||||
std::vector<PluginContainer> plugins = PluginManagement::loadPlugins(pluginList, gPluginDataHeap, gTrampolineData, gTrampolineDataSize);
|
||||
|
||||
for (auto &pluginContainer : plugins) {
|
||||
for (const auto &kv : pluginContainer.getPluginInformation().getSectionInfoList()) {
|
||||
@ -138,9 +164,9 @@ WUMS_APPLICATION_STARTS() {
|
||||
}
|
||||
}
|
||||
|
||||
PluginManagement::unloadPlugins(gPluginInformation, pluginDataHeap, false);
|
||||
PluginManagement::unloadPlugins(gPluginInformation, gPluginDataHeap, false);
|
||||
|
||||
std::vector<PluginContainer> plugins = PluginManagement::loadPlugins(pluginDataList, pluginDataHeap, gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH);
|
||||
std::vector<PluginContainer> plugins = PluginManagement::loadPlugins(pluginDataList, gPluginDataHeap, gTrampolineData, gTrampolineDataSize);
|
||||
|
||||
for (auto &pluginContainer : plugins) {
|
||||
DEBUG_FUNCTION_LINE("Stored information for plugin %s ; %s", pluginContainer.getMetaInformation().getName().c_str(), pluginContainer.getMetaInformation().getAuthor().c_str());
|
||||
@ -152,13 +178,15 @@ WUMS_APPLICATION_STARTS() {
|
||||
initNeeded = true;
|
||||
}
|
||||
|
||||
if (pluginDataHeap != nullptr) {
|
||||
if (gPluginDataHeap != nullptr) {
|
||||
std::vector<PluginContainer> plugins = PluginContainerPersistence::loadPlugins(gPluginInformation);
|
||||
PluginManagement::doRelocations(plugins, gPluginInformation->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH);
|
||||
PluginManagement::doRelocations(plugins, gTrampolineData, DYN_LINK_TRAMPOLIN_LIST_LENGTH);
|
||||
// PluginManagement::memsetBSS(plugins);
|
||||
|
||||
DCFlushRange((void *) pluginDataHeap, gPluginDataHeapSize);
|
||||
ICInvalidateRange((void *) pluginDataHeap, gPluginDataHeapSize);
|
||||
DCFlushRange((void *) gPluginDataHeap, gPluginDataHeapSize);
|
||||
ICInvalidateRange((void *) gPluginDataHeap, gPluginDataHeapSize);
|
||||
DCFlushRange((void *) gPluginInformation, sizeof(plugin_information_t));
|
||||
ICInvalidateRange((void *) gPluginInformation, sizeof(plugin_information_t));
|
||||
|
||||
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_MALLOC);
|
||||
CallHook(gPluginInformation, WUPS_LOADER_HOOK_INIT_WUT_NEWLIB);
|
||||
@ -172,3 +200,19 @@ WUMS_APPLICATION_STARTS() {
|
||||
PluginManagement::PatchFunctionsAndCallHooks(gPluginInformation);
|
||||
}
|
||||
}
|
||||
|
||||
void *allocOnCustomHeap(int alignment, int size) {
|
||||
OSDynLoad_Module module;
|
||||
OSDynLoad_Error dyn_res = OSDynLoad_Acquire("homebrew_memorymapping", &module);
|
||||
if (dyn_res != OS_DYNLOAD_OK) {
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t *custom_memalign;
|
||||
dyn_res = OSDynLoad_FindExport(module, true, "MEMAllocFromMappedMemoryEx", reinterpret_cast<void **>(&custom_memalign));
|
||||
void *(*customMEMAllocFromDefaultHeapEx)(uint32_t size, int align) = (void *(*)(uint32_t, int)) *custom_memalign;
|
||||
|
||||
if (dyn_res != OS_DYNLOAD_OK) {
|
||||
return nullptr;
|
||||
}
|
||||
return customMEMAllocFromDefaultHeapEx(size, alignment);
|
||||
}
|
||||
|
@ -96,19 +96,17 @@ bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t des
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (freeSlot != NULL) {
|
||||
if (freeSlot == NULL) {
|
||||
DEBUG_FUNCTION_LINE("***24-bit relative branch cannot hit target. Trampolin data list is full");
|
||||
DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X", value, target, distance);
|
||||
DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X", value, target, target - (uint32_t) &(freeSlot->trampolin[0]));
|
||||
return false;
|
||||
}
|
||||
if (target - (uint32_t) &(freeSlot->trampolin[0]) > 0x1FFFFFC) {
|
||||
DEBUG_FUNCTION_LINE("**Cannot link 24-bit jump (too far to tramp buffer).");
|
||||
DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X", value, target, distance);
|
||||
DEBUG_FUNCTION_LINE("***value %08X - target %08X = distance %08X", value, target, (target - (uint32_t) &(freeSlot->trampolin[0])));
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE("freeSlot = %08X", freeSlot);
|
||||
|
||||
freeSlot->trampolin[0] = 0x3D600000 | ((((uint32_t) value) >> 16) & 0x0000FFFF); // lis r11, real_addr@h
|
||||
freeSlot->trampolin[1] = 0x616B0000 | (((uint32_t) value) & 0x0000ffff); // ori r11, r11, real_addr@l
|
||||
freeSlot->trampolin[2] = 0x7D6903A6; // mtctr r11
|
||||
@ -124,12 +122,11 @@ bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t des
|
||||
freeSlot->status = RELOC_TRAMP_FIXED;
|
||||
} else {
|
||||
// Relocations for the imports may be overridden
|
||||
freeSlot->status = RELOC_TRAMP_IMPORT_IN_PROGRESS;
|
||||
freeSlot->status = RELOC_TRAMP_IMPORT_DONE;
|
||||
}
|
||||
uint32_t symbolValue = (uint32_t) &(freeSlot->trampolin[0]);
|
||||
value = symbolValue + addend;
|
||||
distance = static_cast<int32_t>(value) - static_cast<int32_t>(target);
|
||||
DEBUG_FUNCTION_LINE("Created tramp");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,11 +67,11 @@ extern "C" int32_t WUPSDeletePluginData(const plugin_data_handle *plugin_data_ha
|
||||
extern "C" int32_t WUPSLoadPluginAsData(GetPluginInformationInputType inputType, const char *path, char *buffer, size_t size, plugin_data_handle *out) {
|
||||
std::optional<PluginData> pluginData;
|
||||
if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_PATH && path != nullptr) {
|
||||
pluginData = PluginDataFactory::load(path, pluginDataHeap);
|
||||
pluginData = PluginDataFactory::load(path, gPluginDataHeap);
|
||||
} else if (inputType == PLUGIN_INFORMATION_INPUT_TYPE_BUFFER && buffer != nullptr && size > 0) {
|
||||
std::vector<uint8_t> data(size);
|
||||
memcpy(&data[0], buffer, size);
|
||||
pluginData = PluginDataFactory::load(data, pluginDataHeap);
|
||||
pluginData = PluginDataFactory::load(data, gPluginDataHeap);
|
||||
} else {
|
||||
return ERROR_INVALID_ARG;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user