diff --git a/Dockerfile b/Dockerfile index 85fcb92..f418faf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM wiiuenv/devkitppc:20220917 +FROM wiiuenv/devkitppc:20221228 -COPY --from=wiiuenv/wiiumodulesystem:20221005 /artifacts $DEVKITPRO +COPY --from=wiiuenv/wiiumodulesystem:20230106 /artifacts $DEVKITPRO WORKDIR project \ No newline at end of file diff --git a/wumsloader/src/entry.cpp b/wumsloader/src/entry.cpp index a7be141..f7ae018 100644 --- a/wumsloader/src/entry.cpp +++ b/wumsloader/src/entry.cpp @@ -231,17 +231,13 @@ bool CheckModulesByDependencies(const std::vector> & for (auto const &curModule : loadedModules) { DEBUG_FUNCTION_LINE_VERBOSE("Check if we can load %s", curModule->getExportName().c_str()); - std::set importsFromOtherModules; - for (const auto &curReloc : curModule->getRelocationDataList()) { - std::string curRPL = curReloc->getImportRPLInformation()->getRPLName(); + for (auto &curRPL : curModule->getDependencies()) { + if (!curRPL.starts_with("homebrew")) { + continue; + } if (curRPL == "homebrew_wupsbackend") { OSFatal("Error: module depends on homebrew_wupsbackend, this is not supported"); } - if (curRPL.starts_with("homebrew")) { - importsFromOtherModules.insert(curRPL); - } - } - for (auto &curRPL : importsFromOtherModules) { if (!loaderModuleNames.contains(curRPL)) { DEBUG_FUNCTION_LINE_VERBOSE("%s requires %s which is not loaded yet", curModule->getExportName().c_str(), curRPL.c_str()); return false; @@ -256,35 +252,28 @@ bool CheckModulesByDependencies(const std::vector> & std::vector> OrderModulesByDependencies(const std::vector> &loadedModules) { std::vector> finalOrder; - std::vector loadedModulesExportNames; - std::vector loadedModulesEntrypoints; + std::set loadedModulesExportNames; + std::set loadedModulesEntrypoints; while (true) { bool canBreak = true; bool weDidSomething = false; for (auto const &curModule : loadedModules) { - if (std::find(loadedModulesEntrypoints.begin(), loadedModulesEntrypoints.end(), curModule->getEntrypoint()) != loadedModulesEntrypoints.end()) { + if (loadedModulesEntrypoints.contains(curModule->getEntrypoint())) { // DEBUG_FUNCTION_LINE("%s [%08X] is already loaded" curModule->getExportName().c_str(), curModule->getEntrypoint()); continue; } canBreak = false; DEBUG_FUNCTION_LINE_VERBOSE("Check if we can load %s", curModule->getExportName().c_str()); - std::vector importsFromOtherModules; - for (const auto &curReloc : curModule->getRelocationDataList()) { - std::string_view curRPL = curReloc->getImportRPLInformation()->getRPLName(); - if (curRPL == "homebrew_wupsbackend") { + bool canLoad = true; + for (auto &curImportRPL : curModule->getDependencies()) { + if (!curImportRPL.starts_with("homebrew")) { + continue; + } + if (curImportRPL == "homebrew_wupsbackend") { OSFatal("Error: module depends on homebrew_wupsbackend, this is not supported"); } - if (curRPL.starts_with("homebrew")) { - if (std::find(importsFromOtherModules.begin(), importsFromOtherModules.end(), curRPL) == importsFromOtherModules.end()) { - DEBUG_FUNCTION_LINE_VERBOSE("%s is importing from %s", curModule->getExportName().c_str(), curRPL.begin()); - importsFromOtherModules.push_back(curRPL); - } - } - } - bool canLoad = true; - for (auto &curImportRPL : importsFromOtherModules) { - if (std::find(loadedModulesExportNames.begin(), loadedModulesExportNames.end(), curImportRPL) == loadedModulesExportNames.end()) { + if (!loadedModulesExportNames.contains(curImportRPL)) { DEBUG_FUNCTION_LINE_VERBOSE("We can't load the module, because %s is not loaded yet", curImportRPL.begin()); canLoad = false; break; @@ -294,8 +283,8 @@ std::vector> OrderModulesByDependencies(const std::v weDidSomething = true; DEBUG_FUNCTION_LINE_VERBOSE("We can load: %s", curModule->getExportName().c_str()); finalOrder.push_back(curModule); - loadedModulesExportNames.emplace_back(curModule->getExportName()); - loadedModulesEntrypoints.push_back(curModule->getEntrypoint()); + loadedModulesExportNames.insert(curModule->getExportName()); + loadedModulesEntrypoints.insert(curModule->getEntrypoint()); } } if (canBreak) { diff --git a/wumsloader/src/module/ModuleData.h b/wumsloader/src/module/ModuleData.h index c09b260..7dbbbdc 100644 --- a/wumsloader/src/module/ModuleData.h +++ b/wumsloader/src/module/ModuleData.h @@ -55,6 +55,7 @@ public: } void addRelocationData(std::unique_ptr relocation_data) { + addDependency(relocation_data->getImportRPLInformation()->getRPLName()); relocation_data_list.push_back(std::move(relocation_data)); } @@ -78,6 +79,14 @@ public: return hook_data_list; } + void addDependency(std::string module_name) { + dependency_list.insert(std::move(module_name)); + } + + [[nodiscard]] const std::set &getDependencies() const { + return dependency_list; + } + void addSectionInfo(std::shared_ptr sectionInfo) { section_info_list[sectionInfo->getName()] = std::move(sectionInfo); } @@ -168,6 +177,7 @@ private: std::vector> relocation_data_list; std::vector> export_data_list; std::vector> hook_data_list; + std::set dependency_list; std::set, FunctionSymbolDataComparator> symbol_data_list; std::map> section_info_list; diff --git a/wumsloader/src/module/ModuleDataFactory.cpp b/wumsloader/src/module/ModuleDataFactory.cpp index 92a2ec3..d93e14a 100644 --- a/wumsloader/src/module/ModuleDataFactory.cpp +++ b/wumsloader/src/module/ModuleDataFactory.cpp @@ -79,7 +79,7 @@ std::optional> ModuleDataFactory::load(const std::st } else if ((address >= 0x10000000) && address < 0xC0000000) { data_size += sectionSize; } - if (psec->get_name().rfind(".wums.", 0) == 0) { + if (psec->get_name().starts_with(".wums.")) { data_size += sectionSize; } } @@ -196,6 +196,21 @@ std::optional> ModuleDataFactory::load(const std::st } } + secInfo = moduleData->getSectionInfo(".wums.dependencies"); + if (secInfo && secInfo.value()->getSize() > 0) { + if (secInfo.value()->getAddress() != 0) { + char *curEntry = (char *) secInfo.value()->getAddress(); + while ((uint32_t) curEntry < (uint32_t) secInfo.value()->getAddress() + secInfo.value()->getSize()) { + if (*curEntry == '\0') { + curEntry++; + continue; + } + moduleData->addDependency(curEntry); + curEntry += strlen(curEntry) + 1; + } + } + } + secInfo = moduleData->getSectionInfo(".wums.hooks"); if (secInfo && secInfo.value()->getSize() > 0) { size_t entries_count = secInfo.value()->getSize() / sizeof(wums_hook_t); @@ -251,7 +266,7 @@ std::optional> ModuleDataFactory::load(const std::st } } else if (key == "wums" || key == "wum") { checkedVersion = true; - if (value != "0.3.1") { + if (value != "0.3.1" && values != "0.3.2") { DEBUG_FUNCTION_LINE_WARN("Ignoring module - Unsupported WUMS version: %s.", value.c_str()); return std::nullopt; } diff --git a/wumsloader/src/utils/hooks.cpp b/wumsloader/src/utils/hooks.cpp index d535736..03749f2 100644 --- a/wumsloader/src/utils/hooks.cpp +++ b/wumsloader/src/utils/hooks.cpp @@ -25,7 +25,8 @@ static const char **hook_names = (const char *[]){ "WUMS_HOOK_APPLICATION_STARTS", "WUMS_HOOK_APPLICATION_ENDS", "WUMS_HOOK_RELOCATIONS_DONE", - "WUMS_HOOK_APPLICATION_REQUESTS_EXIT"}; + "WUMS_HOOK_APPLICATION_REQUESTS_EXIT", + "WUMS_HOOK_DEINIT"}; #endif void CallHook(const std::vector> &modules, wums_hook_type_t type, bool condition) { @@ -68,8 +69,10 @@ void CallHook(const std::shared_ptr &module, wums_hook_type_t type) type == WUMS_HOOK_FINI_WUT_DEVOPTAB || type == WUMS_HOOK_INIT_WUT_SOCKETS || type == WUMS_HOOK_FINI_WUT_SOCKETS || + type == WUMS_HOOK_FINI_WUT_SOCKETS || type == WUMS_HOOK_INIT_WRAPPER || - type == WUMS_HOOK_FINI_WRAPPER)) { + type == WUMS_HOOK_FINI_WRAPPER || + type == WUMS_HOOK_DEINIT)) { DEBUG_FUNCTION_LINE("Calling hook of type %s [%d] %d for %s: %08X", hook_names[type], type, curHook->getType(), module->getExportName().c_str(), curHook->getTarget()); ((void (*)())((uint32_t *) func_ptr))(); break;