Fix resetting the trampoline data to avoid a crash when re-loading plugins 50+ times

This commit is contained in:
Maschell 2022-10-03 21:58:11 +02:00
parent 5303e05508
commit 0a254e59f4
3 changed files with 11 additions and 7 deletions

View File

@ -75,6 +75,11 @@ bool PluginManagement::doRelocation(const std::vector<std::unique_ptr<Relocation
bool PluginManagement::doRelocations(const std::vector<std::unique_ptr<PluginContainer>> &plugins, relocation_trampoline_entry_t *trampData, uint32_t tramp_size) { bool PluginManagement::doRelocations(const std::vector<std::unique_ptr<PluginContainer>> &plugins, relocation_trampoline_entry_t *trampData, uint32_t tramp_size) {
for (uint32_t i = 0; i < tramp_size; i++) {
if (trampData[i].status == RELOC_TRAMP_IMPORT_DONE) {
trampData[i].status = RELOC_TRAMP_FREE;
}
}
for (auto &pluginContainer : plugins) { for (auto &pluginContainer : plugins) {
DEBUG_FUNCTION_LINE_VERBOSE("Doing relocations for plugin: %s", pluginContainer->getMetaInformation()->getName().c_str()); DEBUG_FUNCTION_LINE_VERBOSE("Doing relocations for plugin: %s", pluginContainer->getMetaInformation()->getName().c_str());
if (!PluginManagement::doRelocation(pluginContainer->getPluginInformation()->getRelocationDataList(), trampData, tramp_size, pluginContainer->getPluginInformation()->getTrampolineId())) { if (!PluginManagement::doRelocation(pluginContainer->getPluginInformation()->getRelocationDataList(), trampData, tramp_size, pluginContainer->getPluginInformation()->getTrampolineId())) {

View File

@ -48,6 +48,7 @@ WUMS_APPLICATION_STARTS() {
if (upid != 2 && upid != 15) { if (upid != 2 && upid != 15) {
return; return;
} }
OSReport("Running WiiUPluginLoaderBackend " VERSION_FULL "\n"); OSReport("Running WiiUPluginLoaderBackend " VERSION_FULL "\n");
initLogging(); initLogging();
bool initNeeded = false; bool initNeeded = false;
@ -60,6 +61,7 @@ WUMS_APPLICATION_STARTS() {
DEBUG_FUNCTION_LINE_ERR("Failed to allocated the memory for the trampoline data"); DEBUG_FUNCTION_LINE_ERR("Failed to allocated the memory for the trampoline data");
OSFatal("Failed to allocated the memory for the trampoline data"); OSFatal("Failed to allocated the memory for the trampoline data");
} }
memset(gTrampData, 0, sizeof(relocation_trampoline_entry_t) * TRAMP_DATA_SIZE);
} }
if (gLoadedPlugins.empty()) { if (gLoadedPlugins.empty()) {
@ -68,7 +70,6 @@ WUMS_APPLICATION_STARTS() {
DEBUG_FUNCTION_LINE("Load plugins from %s", pluginPath.c_str()); DEBUG_FUNCTION_LINE("Load plugins from %s", pluginPath.c_str());
auto pluginData = PluginDataFactory::loadDir(pluginPath); auto pluginData = PluginDataFactory::loadDir(pluginPath);
gLoadedPlugins = PluginManagement::loadPlugins(pluginData, gTrampData, TRAMP_DATA_SIZE); gLoadedPlugins = PluginManagement::loadPlugins(pluginData, gTrampData, TRAMP_DATA_SIZE);
initNeeded = true; initNeeded = true;
@ -80,8 +81,9 @@ WUMS_APPLICATION_STARTS() {
CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_DEINIT_PLUGIN); CallHook(gLoadedPlugins, WUPS_LOADER_HOOK_DEINIT_PLUGIN);
DEBUG_FUNCTION_LINE("Unload existing plugins."); DEBUG_FUNCTION_LINE("Unload existing plugins.");
gLoadedPlugins.clear(); gLoadedPlugins.clear();
DEBUG_FUNCTION_LINE("Load new plugins"); memset(gTrampData, 0, sizeof(relocation_trampoline_entry_t) * TRAMP_DATA_SIZE);
DEBUG_FUNCTION_LINE("Load new plugins");
gLoadedPlugins = PluginManagement::loadPlugins(gLoadOnNextLaunch, gTrampData, TRAMP_DATA_SIZE); gLoadedPlugins = PluginManagement::loadPlugins(gLoadOnNextLaunch, gTrampData, TRAMP_DATA_SIZE);
initNeeded = true; initNeeded = true;
} }

View File

@ -89,8 +89,7 @@ bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t des
// so they can be overridden/updated/reused on the next application launch. // so they can be overridden/updated/reused on the next application launch.
// //
// Relocations that won't change will have the status RELOC_TRAMP_FIXED and are set to free when the module is unloaded. // Relocations that won't change will have the status RELOC_TRAMP_FIXED and are set to free when the module is unloaded.
if (trampoline_data[i].status == RELOC_TRAMP_FREE || if (trampoline_data[i].status == RELOC_TRAMP_FREE) {
trampoline_data[i].status == RELOC_TRAMP_IMPORT_DONE) {
freeSlot = &(trampoline_data[i]); freeSlot = &(trampoline_data[i]);
break; break;
} }
@ -117,11 +116,9 @@ bool ElfUtils::elfLinkOne(char type, size_t offset, int32_t addend, uint32_t des
freeSlot->trampoline[1] = 0x616B0000 | (((uint32_t) value) & 0x0000ffff); // ori r11, r11, real_addr@l freeSlot->trampoline[1] = 0x616B0000 | (((uint32_t) value) & 0x0000ffff); // ori r11, r11, real_addr@l
freeSlot->trampoline[2] = 0x7D6903A6; // mtctr r11 freeSlot->trampoline[2] = 0x7D6903A6; // mtctr r11
freeSlot->trampoline[3] = 0x4E800420; // bctr freeSlot->trampoline[3] = 0x4E800420; // bctr
DCFlushRange((void *) freeSlot->trampoline, sizeof(freeSlot->trampoline));
ICInvalidateRange((unsigned char *) freeSlot->trampoline, sizeof(freeSlot->trampoline)); ICInvalidateRange((unsigned char *) freeSlot->trampoline, sizeof(freeSlot->trampoline));
freeSlot->id = trampolineId; freeSlot->id = trampolineId;
DCFlushRange((void *) &freeSlot->id, sizeof(freeSlot->id));
ICInvalidateRange((unsigned char *) &freeSlot->id, sizeof(freeSlot->id)); ICInvalidateRange((unsigned char *) &freeSlot->id, sizeof(freeSlot->id));
if (reloc_type == RELOC_TYPE_FIXED) { if (reloc_type == RELOC_TYPE_FIXED) {