mirror of
https://github.com/wiiu-env/WUMSLoader.git
synced 2024-12-25 23:51:50 +01:00
Use std::shared_ptr
This commit is contained in:
parent
862363629e
commit
460c235430
@ -61,17 +61,17 @@ dyn_linking_import_t *DynamicLinkingHelper::getOrAddImport(dyn_linking_relocatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DynamicLinkingHelper::addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length,
|
bool DynamicLinkingHelper::addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length,
|
||||||
const RelocationData &relocationData) {
|
const std::shared_ptr<RelocationData> &relocationData) {
|
||||||
return addRelocationEntry(linking_data, linking_entries, linking_entry_length, relocationData.getType(),
|
return addRelocationEntry(linking_data, linking_entries, linking_entry_length, relocationData->getType(),
|
||||||
relocationData.getOffset(), relocationData.getAddend(), relocationData.getDestination(),
|
relocationData->getOffset(), relocationData->getAddend(), relocationData->getDestination(),
|
||||||
relocationData.getName(),
|
relocationData->getName(),
|
||||||
relocationData.getImportRPLInformation());
|
relocationData->getImportRPLInformation());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DynamicLinkingHelper::addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset,
|
bool DynamicLinkingHelper::addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset,
|
||||||
int32_t addend, void *destination,
|
int32_t addend, void *destination,
|
||||||
const std::string &name, const ImportRPLInformation &rplInfo) {
|
const std::string &name, const std::shared_ptr<ImportRPLInformation> &rplInfo) {
|
||||||
dyn_linking_import_t *importInfoGbl = DynamicLinkingHelper::getOrAddImport(linking_data, rplInfo.getName().c_str(), rplInfo.isData());
|
dyn_linking_import_t *importInfoGbl = DynamicLinkingHelper::getOrAddImport(linking_data, rplInfo->getName().c_str(), rplInfo->isData());
|
||||||
if (importInfoGbl == nullptr) {
|
if (importInfoGbl == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d rpl files to import reached.\n", DYN_LINK_IMPORT_LIST_LENGTH);
|
DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d rpl files to import reached.\n", DYN_LINK_IMPORT_LIST_LENGTH);
|
||||||
return false;
|
return false;
|
||||||
|
@ -47,12 +47,13 @@ public:
|
|||||||
**/
|
**/
|
||||||
static dyn_linking_import_t *getOrAddImport(dyn_linking_relocation_data_t *data, const char *importName, bool isData);
|
static dyn_linking_import_t *getOrAddImport(dyn_linking_relocation_data_t *data, const char *importName, bool isData);
|
||||||
|
|
||||||
static bool addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, const RelocationData &relocationData);
|
static bool addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length,
|
||||||
|
const std::shared_ptr<RelocationData> &relocationData);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend,
|
addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend,
|
||||||
void *destination, const std::string &name,
|
void *destination, const std::string &name,
|
||||||
const ImportRPLInformation &rplInfo);
|
const std::shared_ptr<ImportRPLInformation> &rplInfo);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
addRelocationEntry(dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, void *destination,
|
addRelocationEntry(dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, void *destination,
|
||||||
|
@ -34,19 +34,19 @@ public:
|
|||||||
return this->export_name;
|
return this->export_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addRelocationData(const RelocationData &relocation_data) {
|
void addRelocationData(const std::shared_ptr<RelocationData> &relocation_data) {
|
||||||
relocation_data_list.push_back(relocation_data);
|
relocation_data_list.push_back(relocation_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<RelocationData> &getRelocationDataList() const {
|
[[nodiscard]] const std::vector<std::shared_ptr<RelocationData>> &getRelocationDataList() const {
|
||||||
return relocation_data_list;
|
return relocation_data_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addHookData(const HookData &data) {
|
void addHookData(const std::shared_ptr<HookData> &data) {
|
||||||
hook_data_list.push_back(data);
|
hook_data_list.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<HookData> &getHookDataList() const {
|
[[nodiscard]] const std::vector<std::shared_ptr<HookData>> &getHookDataList() const {
|
||||||
return hook_data_list;
|
return hook_data_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,10 +68,9 @@ public:
|
|||||||
|
|
||||||
bool relocationsDone = false;
|
bool relocationsDone = false;
|
||||||
private:
|
private:
|
||||||
std::vector<RelocationData> relocation_data_list;
|
std::vector<std::shared_ptr<RelocationData>> relocation_data_list;
|
||||||
std::vector<HookData> hook_data_list;
|
std::vector<std::shared_ptr<HookData>> hook_data_list;
|
||||||
std::string export_name;
|
std::string export_name;
|
||||||
uint32_t entrypoint = 0;
|
uint32_t entrypoint = 0;
|
||||||
bool initBeforeRelocationDoneHook = false;
|
bool initBeforeRelocationDoneHook = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
#include <coreinit/cache.h>
|
#include <coreinit/cache.h>
|
||||||
#include <wums.h>
|
#include <wums.h>
|
||||||
|
|
||||||
std::vector<ModuleDataMinimal> ModuleDataPersistence::loadModuleData(module_information_t *moduleInformation) {
|
std::vector<std::shared_ptr<ModuleDataMinimal>> ModuleDataPersistence::loadModuleData(module_information_t *moduleInformation) {
|
||||||
std::vector<ModuleDataMinimal> result;
|
std::vector<std::shared_ptr<ModuleDataMinimal>> result;
|
||||||
if (moduleInformation == nullptr) {
|
if (moduleInformation == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE("moduleInformation == NULL\n");
|
DEBUG_FUNCTION_LINE("moduleInformation == NULL\n");
|
||||||
return result;
|
return result;
|
||||||
@ -22,17 +22,17 @@ std::vector<ModuleDataMinimal> ModuleDataPersistence::loadModuleData(module_info
|
|||||||
for (int32_t i = 0; i < module_count; i++) {
|
for (int32_t i = 0; i < module_count; i++) {
|
||||||
// Copy data from struct.
|
// Copy data from struct.
|
||||||
module_information_single_t *module_data = &(moduleInformation->module_data[i]);
|
module_information_single_t *module_data = &(moduleInformation->module_data[i]);
|
||||||
ModuleDataMinimal moduleData;
|
auto moduleData = std::make_shared<ModuleDataMinimal>();
|
||||||
|
|
||||||
moduleData.setEntrypoint(module_data->entrypoint);
|
moduleData->setEntrypoint(module_data->entrypoint);
|
||||||
moduleData.setInitBeforeRelocationDoneHook(module_data->initBeforeRelocationDoneHook);
|
moduleData->setInitBeforeRelocationDoneHook(module_data->initBeforeRelocationDoneHook);
|
||||||
moduleData.setExportName(module_data->module_export_name);
|
moduleData->setExportName(module_data->module_export_name);
|
||||||
|
|
||||||
for (auto &hook_entry: module_data->hook_entries) {
|
for (auto &hook_entry: module_data->hook_entries) {
|
||||||
if (hook_entry.target == 0) {
|
if (hook_entry.target == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
moduleData.addHookData(HookData(static_cast<wums_hook_type_t>(hook_entry.type), reinterpret_cast<const void *>(hook_entry.target)));
|
moduleData->addHookData(std::make_shared<HookData>(static_cast<wums_hook_type_t>(hook_entry.type), reinterpret_cast<const void *>(hook_entry.target)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &linking_entry: module_data->linking_entries) {
|
for (auto &linking_entry: module_data->linking_entries) {
|
||||||
@ -58,10 +58,10 @@ std::vector<ModuleDataMinimal> ModuleDataPersistence::loadModuleData(module_info
|
|||||||
DEBUG_FUNCTION_LINE("functionEntry->functionName was NULL, skipping relocation entry\n");
|
DEBUG_FUNCTION_LINE("functionEntry->functionName was NULL, skipping relocation entry\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ImportRPLInformation rplInfo(importEntry->importName, importEntry->isData);
|
auto rplInfo = std::make_shared<ImportRPLInformation>(importEntry->importName, importEntry->isData);
|
||||||
RelocationData reloc(linking_entry.type, linking_entry.offset, linking_entry.addend, linking_entry.destination, functionEntry->functionName, rplInfo);
|
auto reloc = std::make_shared<RelocationData>(linking_entry.type, linking_entry.offset, linking_entry.addend, linking_entry.destination, functionEntry->functionName, rplInfo);
|
||||||
|
|
||||||
moduleData.addRelocationData(reloc);
|
moduleData->addRelocationData(reloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.push_back(moduleData);
|
result.push_back(moduleData);
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
|
|
||||||
class ModuleDataPersistence {
|
class ModuleDataPersistence {
|
||||||
public:
|
public:
|
||||||
static std::vector<ModuleDataMinimal> loadModuleData(module_information_t *moduleInformation);
|
static std::vector<std::shared_ptr<ModuleDataMinimal>> loadModuleData(module_information_t *moduleInformation);
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,7 @@ uint8_t gInitCalled __attribute__((section(".data"))) = 0;
|
|||||||
|
|
||||||
extern "C" void socket_lib_init();
|
extern "C" void socket_lib_init();
|
||||||
|
|
||||||
std::vector<ModuleDataMinimal> OrderModulesByDependencies(const std::vector<ModuleDataMinimal> &loadedModules);
|
std::vector<std::shared_ptr<ModuleDataMinimal>> OrderModulesByDependencies(const std::vector<std::shared_ptr<ModuleDataMinimal>> &loadedModules);
|
||||||
|
|
||||||
extern "C" void doStart(int argc, char **argv);
|
extern "C" void doStart(int argc, char **argv);
|
||||||
// We need to wrap it to make sure the main function is called AFTER our code.
|
// We need to wrap it to make sure the main function is called AFTER our code.
|
||||||
@ -46,11 +46,11 @@ extern "C" int _start(int argc, char **argv) {
|
|||||||
return ((int (*)(int, char **)) (*(unsigned int *) 0x1005E040))(argc, argv);
|
return ((int (*)(int, char **)) (*(unsigned int *) 0x1005E040))(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool doRelocation(std::vector<RelocationData> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length, bool skipAllocReplacement) {
|
bool doRelocation(std::vector<std::shared_ptr<RelocationData>> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length, bool skipAllocReplacement) {
|
||||||
std::map<std::string, OSDynLoad_Module> moduleCache;
|
std::map<std::string, OSDynLoad_Module> moduleCache;
|
||||||
for (auto const &curReloc: relocData) {
|
for (auto const &curReloc: relocData) {
|
||||||
std::string functionName = curReloc.getName();
|
std::string functionName = curReloc->getName();
|
||||||
std::string rplName = curReloc.getImportRPLInformation().getName();
|
std::string rplName = curReloc->getImportRPLInformation()->getName();
|
||||||
uint32_t functionAddress = 0;
|
uint32_t functionAddress = 0;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < MAXIMUM_MODULES; i++) {
|
for (uint32_t i = 0; i < MAXIMUM_MODULES; i++) {
|
||||||
@ -75,7 +75,7 @@ bool doRelocation(std::vector<RelocationData> &relocData, relocation_trampolin_e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (functionAddress == 0) {
|
if (functionAddress == 0) {
|
||||||
int32_t isData = curReloc.getImportRPLInformation().isData();
|
int32_t isData = curReloc->getImportRPLInformation()->isData();
|
||||||
OSDynLoad_Module rplHandle = nullptr;
|
OSDynLoad_Module rplHandle = nullptr;
|
||||||
if (moduleCache.count(rplName) == 0) {
|
if (moduleCache.count(rplName) == 0) {
|
||||||
OSDynLoad_Error err = OSDynLoad_IsModuleLoaded(rplName.c_str(), &rplHandle);
|
OSDynLoad_Error err = OSDynLoad_IsModuleLoaded(rplName.c_str(), &rplHandle);
|
||||||
@ -98,7 +98,8 @@ bool doRelocation(std::vector<RelocationData> &relocData, relocation_trampolin_e
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ElfUtils::elfLinkOne(curReloc.getType(), curReloc.getOffset(), curReloc.getAddend(), (uint32_t) curReloc.getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT)) {
|
if (!ElfUtils::elfLinkOne(curReloc->getType(), curReloc->getOffset(), curReloc->getAddend(), (uint32_t) curReloc->getDestination(), functionAddress, tramp_data, tramp_length,
|
||||||
|
RELOC_TYPE_IMPORT)) {
|
||||||
DEBUG_FUNCTION_LINE("Relocation failed\n");
|
DEBUG_FUNCTION_LINE("Relocation failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -109,26 +110,26 @@ bool doRelocation(std::vector<RelocationData> &relocData, relocation_trampolin_e
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResolveRelocations(std::vector<ModuleDataMinimal> &loadedModules, bool skipMemoryMappingModule) {
|
bool ResolveRelocations(std::vector<std::shared_ptr<ModuleDataMinimal>> &loadedModules, bool skipMemoryMappingModule) {
|
||||||
bool wasSuccessful = true;
|
bool wasSuccessful = true;
|
||||||
|
|
||||||
for (auto &curModule: loadedModules) {
|
for (auto &curModule: loadedModules) {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Let's do the relocations for %s\n", curModule.getExportName().c_str());
|
DEBUG_FUNCTION_LINE_VERBOSE("Let's do the relocations for %s\n", curModule->getExportName().c_str());
|
||||||
if (wasSuccessful) {
|
if (wasSuccessful) {
|
||||||
std::vector<RelocationData> relocData = curModule.getRelocationDataList();
|
auto relocData = curModule->getRelocationDataList();
|
||||||
|
|
||||||
// On first usage we can't redirect the alloc functions to our custom heap
|
// On first usage we can't redirect the alloc functions to our custom heap
|
||||||
// because threads can't run it on it. In order to patch the kernel
|
// because threads can't run it on it. In order to patch the kernel
|
||||||
// to fully support our memory region, we have to run the FunctionPatcher and MemoryMapping
|
// to fully support our memory region, we have to run the FunctionPatcher and MemoryMapping
|
||||||
// once with the default heap. Afterwards we can just rely on the custom heap.
|
// once with the default heap. Afterwards we can just rely on the custom heap.
|
||||||
bool skipAllocFunction = skipMemoryMappingModule && (curModule.getExportName() == "homebrew_memorymapping" || curModule.getExportName() == "homebrew_functionpatcher");
|
bool skipAllocFunction = skipMemoryMappingModule && (curModule->getExportName() == "homebrew_memorymapping" || curModule->getExportName() == "homebrew_functionpatcher");
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Skip alloc replace? %d\n", skipAllocFunction);
|
DEBUG_FUNCTION_LINE_VERBOSE("Skip alloc replace? %d\n", skipAllocFunction);
|
||||||
if (!doRelocation(relocData, gModuleData->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH, skipAllocFunction)) {
|
if (!doRelocation(relocData, gModuleData->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH, skipAllocFunction)) {
|
||||||
DEBUG_FUNCTION_LINE("FAIL\n");
|
DEBUG_FUNCTION_LINE("FAIL\n");
|
||||||
wasSuccessful = false;
|
wasSuccessful = false;
|
||||||
curModule.relocationsDone = false;
|
curModule->relocationsDone = false;
|
||||||
}
|
}
|
||||||
curModule.relocationsDone = true;
|
curModule->relocationsDone = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,7 +148,7 @@ extern "C" void doStart(int argc, char **argv) {
|
|||||||
|
|
||||||
bool applicationEndHookLoaded = false;
|
bool applicationEndHookLoaded = false;
|
||||||
for (auto &curModule: loadedModules) {
|
for (auto &curModule: loadedModules) {
|
||||||
if (curModule.getExportName() == "homebrew_applicationendshook") {
|
if (curModule->getExportName() == "homebrew_applicationendshook") {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("We have ApplicationEndsHook Module!\n");
|
DEBUG_FUNCTION_LINE_VERBOSE("We have ApplicationEndsHook Module!\n");
|
||||||
applicationEndHookLoaded = true;
|
applicationEndHookLoaded = true;
|
||||||
break;
|
break;
|
||||||
@ -156,10 +157,10 @@ extern "C" void doStart(int argc, char **argv) {
|
|||||||
|
|
||||||
// Make sure WUMS_HOOK_APPLICATION_ENDS and WUMS_HOOK_FINI_WUT are called
|
// Make sure WUMS_HOOK_APPLICATION_ENDS and WUMS_HOOK_FINI_WUT are called
|
||||||
for (auto &curModule: loadedModules) {
|
for (auto &curModule: loadedModules) {
|
||||||
for (auto &curHook: curModule.getHookDataList()) {
|
for (auto &curHook: curModule->getHookDataList()) {
|
||||||
if (curHook.getType() == WUMS_HOOK_APPLICATION_ENDS || curHook.getType() == WUMS_HOOK_FINI_WUT_DEVOPTAB) {
|
if (curHook->getType() == WUMS_HOOK_APPLICATION_ENDS || curHook->getType() == WUMS_HOOK_FINI_WUT_DEVOPTAB) {
|
||||||
if (!applicationEndHookLoaded) {
|
if (!applicationEndHookLoaded) {
|
||||||
OSFatal_printf("%s requires module homebrew_applicationendshook", curModule.getExportName().c_str());
|
OSFatal_printf("%s requires module homebrew_applicationendshook", curModule->getExportName().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,7 +174,7 @@ extern "C" void doStart(int argc, char **argv) {
|
|||||||
ResolveRelocations(loadedModules, true);
|
ResolveRelocations(loadedModules, true);
|
||||||
|
|
||||||
for (auto &curModule: loadedModules) {
|
for (auto &curModule: loadedModules) {
|
||||||
if (curModule.isInitBeforeRelocationDoneHook()) {
|
if (curModule->isInitBeforeRelocationDoneHook()) {
|
||||||
CallHook(curModule, WUMS_HOOK_INIT_WUT_MALLOC);
|
CallHook(curModule, WUMS_HOOK_INIT_WUT_MALLOC);
|
||||||
CallHook(curModule, WUMS_HOOK_INIT_WUT_NEWLIB);
|
CallHook(curModule, WUMS_HOOK_INIT_WUT_NEWLIB);
|
||||||
CallHook(curModule, WUMS_HOOK_INIT_WUT_STDCPP);
|
CallHook(curModule, WUMS_HOOK_INIT_WUT_STDCPP);
|
||||||
@ -191,7 +192,6 @@ extern "C" void doStart(int argc, char **argv) {
|
|||||||
DEBUG_FUNCTION_LINE_VERBOSE("Relocations done\n");
|
DEBUG_FUNCTION_LINE_VERBOSE("Relocations done\n");
|
||||||
CallHook(loadedModules, WUMS_HOOK_RELOCATIONS_DONE);
|
CallHook(loadedModules, WUMS_HOOK_RELOCATIONS_DONE);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < gModuleData->number_used_modules; i++) {
|
for (int i = 0; i < gModuleData->number_used_modules; i++) {
|
||||||
if (!gModuleData->module_data[i].skipEntrypoint) {
|
if (!gModuleData->module_data[i].skipEntrypoint) {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("About to call %08X\n", gModuleData->module_data[i].entrypoint);
|
DEBUG_FUNCTION_LINE_VERBOSE("About to call %08X\n", gModuleData->module_data[i].entrypoint);
|
||||||
@ -201,7 +201,7 @@ extern "C" void doStart(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto &curModule: loadedModules) {
|
for (auto &curModule: loadedModules) {
|
||||||
if (!curModule.isInitBeforeRelocationDoneHook()) {
|
if (!curModule->isInitBeforeRelocationDoneHook()) {
|
||||||
CallHook(curModule, WUMS_HOOK_INIT_WUT_MALLOC);
|
CallHook(curModule, WUMS_HOOK_INIT_WUT_MALLOC);
|
||||||
CallHook(curModule, WUMS_HOOK_INIT_WUT_NEWLIB);
|
CallHook(curModule, WUMS_HOOK_INIT_WUT_NEWLIB);
|
||||||
CallHook(curModule, WUMS_HOOK_INIT_WUT_STDCPP);
|
CallHook(curModule, WUMS_HOOK_INIT_WUT_STDCPP);
|
||||||
@ -220,6 +220,7 @@ extern "C" void doStart(int argc, char **argv) {
|
|||||||
ResolveRelocations(loadedModules, false);
|
ResolveRelocations(loadedModules, false);
|
||||||
CallHook(loadedModules, WUMS_HOOK_RELOCATIONS_DONE);
|
CallHook(loadedModules, WUMS_HOOK_RELOCATIONS_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallHook(loadedModules, WUMS_HOOK_INIT_WUT_MALLOC);
|
CallHook(loadedModules, WUMS_HOOK_INIT_WUT_MALLOC);
|
||||||
CallHook(loadedModules, WUMS_HOOK_INIT_WUT_NEWLIB);
|
CallHook(loadedModules, WUMS_HOOK_INIT_WUT_NEWLIB);
|
||||||
CallHook(loadedModules, WUMS_HOOK_INIT_WUT_STDCPP);
|
CallHook(loadedModules, WUMS_HOOK_INIT_WUT_STDCPP);
|
||||||
@ -229,8 +230,8 @@ extern "C" void doStart(int argc, char **argv) {
|
|||||||
//CallHook(loadedModules, WUMS_HOOK_FINI_WUT);
|
//CallHook(loadedModules, WUMS_HOOK_FINI_WUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ModuleDataMinimal> OrderModulesByDependencies(const std::vector<ModuleDataMinimal> &loadedModules) {
|
std::vector<std::shared_ptr<ModuleDataMinimal>> OrderModulesByDependencies(const std::vector<std::shared_ptr<ModuleDataMinimal>> &loadedModules) {
|
||||||
std::vector<ModuleDataMinimal> finalOrder;
|
std::vector<std::shared_ptr<ModuleDataMinimal>> finalOrder;
|
||||||
std::vector<std::string> loadedModulesExportNames;
|
std::vector<std::string> loadedModulesExportNames;
|
||||||
std::vector<uint32_t> loadedModulesEntrypoints;
|
std::vector<uint32_t> loadedModulesEntrypoints;
|
||||||
|
|
||||||
@ -238,20 +239,20 @@ std::vector<ModuleDataMinimal> OrderModulesByDependencies(const std::vector<Modu
|
|||||||
bool canBreak = true;
|
bool canBreak = true;
|
||||||
bool weDidSomething = false;
|
bool weDidSomething = false;
|
||||||
for (auto const &curModule: loadedModules) {
|
for (auto const &curModule: loadedModules) {
|
||||||
if (std::find(loadedModulesEntrypoints.begin(), loadedModulesEntrypoints.end(), curModule.getEntrypoint()) != loadedModulesEntrypoints.end()) {
|
if (std::find(loadedModulesEntrypoints.begin(), loadedModulesEntrypoints.end(), curModule->getEntrypoint()) != loadedModulesEntrypoints.end()) {
|
||||||
// DEBUG_FUNCTION_LINE("%s [%08X] is already loaded\n", curModule.getExportName().c_str(), curModule.getEntrypoint());
|
// DEBUG_FUNCTION_LINE("%s [%08X] is already loaded\n", curModule->getExportName().c_str(), curModule->getEntrypoint());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
canBreak = false;
|
canBreak = false;
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Check if we can load %s\n", curModule.getExportName().c_str());
|
DEBUG_FUNCTION_LINE_VERBOSE("Check if we can load %s\n", curModule->getExportName().c_str());
|
||||||
std::vector<std::string> importsFromOtherModules;
|
std::vector<std::string> importsFromOtherModules;
|
||||||
for (const auto &curReloc: curModule.getRelocationDataList()) {
|
for (const auto &curReloc: curModule->getRelocationDataList()) {
|
||||||
std::string curRPL = curReloc.getImportRPLInformation().getName();
|
std::string curRPL = curReloc->getImportRPLInformation()->getName();
|
||||||
if (curRPL.rfind("homebrew", 0) == 0) {
|
if (curRPL.rfind("homebrew", 0) == 0) {
|
||||||
if (std::find(importsFromOtherModules.begin(), importsFromOtherModules.end(), curRPL) != importsFromOtherModules.end()) {
|
if (std::find(importsFromOtherModules.begin(), importsFromOtherModules.end(), curRPL) != importsFromOtherModules.end()) {
|
||||||
// is already in vector
|
// is already in vector
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("%s is importing from %s\n", curModule.getExportName().c_str(), curRPL.c_str());
|
DEBUG_FUNCTION_LINE_VERBOSE("%s is importing from %s\n", curModule->getExportName().c_str(), curRPL.c_str());
|
||||||
importsFromOtherModules.push_back(curRPL);
|
importsFromOtherModules.push_back(curRPL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,10 +269,10 @@ std::vector<ModuleDataMinimal> OrderModulesByDependencies(const std::vector<Modu
|
|||||||
}
|
}
|
||||||
if (canLoad) {
|
if (canLoad) {
|
||||||
weDidSomething = true;
|
weDidSomething = true;
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("We can load: %s\n", curModule.getExportName().c_str());
|
DEBUG_FUNCTION_LINE_VERBOSE("We can load: %s\n", curModule->getExportName().c_str());
|
||||||
finalOrder.push_back(curModule);
|
finalOrder.push_back(curModule);
|
||||||
loadedModulesExportNames.push_back(curModule.getExportName());
|
loadedModulesExportNames.push_back(curModule->getExportName());
|
||||||
loadedModulesEntrypoints.push_back(curModule.getEntrypoint());
|
loadedModulesEntrypoints.push_back(curModule->getEntrypoint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (canBreak) {
|
if (canBreak) {
|
||||||
|
@ -18,29 +18,30 @@ static const char **hook_names = (const char *[]) {
|
|||||||
"WUMS_HOOK_APPLICATION_STARTS",
|
"WUMS_HOOK_APPLICATION_STARTS",
|
||||||
"WUMS_HOOK_APPLICATION_ENDS",
|
"WUMS_HOOK_APPLICATION_ENDS",
|
||||||
"WUMS_HOOK_RELOCATIONS_DONE",
|
"WUMS_HOOK_RELOCATIONS_DONE",
|
||||||
"WUMS_HOOK_APPLICATION_REQUESTS_EXI"};
|
"WUMS_HOOK_APPLICATION_REQUESTS_EXIT"
|
||||||
|
};
|
||||||
|
|
||||||
void CallHook(const std::vector<ModuleDataMinimal> &modules, wums_hook_type_t type) {
|
void CallHook(const std::vector<std::shared_ptr<ModuleDataMinimal>> &modules, wums_hook_type_t type) {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s [%d] for all modules\n", hook_names[type], type);
|
DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s [%d] for all modules\n", hook_names[type], type);
|
||||||
for (auto &curModule: modules) {
|
for (auto &curModule: modules) {
|
||||||
CallHook(curModule, type);
|
CallHook(curModule, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallHook(const ModuleDataMinimal &module, wums_hook_type_t type) {
|
void CallHook(const std::shared_ptr<ModuleDataMinimal> &module, wums_hook_type_t type) {
|
||||||
if (!module.relocationsDone) {
|
if (!module->relocationsDone) {
|
||||||
DEBUG_FUNCTION_LINE("Hook not called because the relocations failed\n");
|
DEBUG_FUNCTION_LINE("Hook not called because the relocations failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &curHook: module.getHookDataList()) {
|
for (auto &curHook: module->getHookDataList()) {
|
||||||
auto func_ptr = (uint32_t) curHook.getTarget();
|
auto func_ptr = (uint32_t) curHook->getTarget();
|
||||||
if (func_ptr == 0) {
|
if (func_ptr == 0) {
|
||||||
DEBUG_FUNCTION_LINE("Hook ptr was NULL\n");
|
DEBUG_FUNCTION_LINE("Hook ptr was NULL\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == curHook.getType()) {
|
if (type == curHook->getType()) {
|
||||||
if ((type == WUMS_HOOK_APPLICATION_STARTS ||
|
if ((type == WUMS_HOOK_APPLICATION_STARTS ||
|
||||||
type == WUMS_HOOK_APPLICATION_ENDS ||
|
type == WUMS_HOOK_APPLICATION_ENDS ||
|
||||||
type == WUMS_HOOK_INIT_WUT_MALLOC ||
|
type == WUMS_HOOK_INIT_WUT_MALLOC ||
|
||||||
@ -54,12 +55,12 @@ void CallHook(const ModuleDataMinimal &module, wums_hook_type_t type) {
|
|||||||
type == WUMS_HOOK_INIT_WUT_SOCKETS ||
|
type == WUMS_HOOK_INIT_WUT_SOCKETS ||
|
||||||
type == WUMS_HOOK_FINI_WUT_SOCKETS
|
type == WUMS_HOOK_FINI_WUT_SOCKETS
|
||||||
)) {
|
)) {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s [%d] %d for %s: %08X\n", hook_names[type], type, curHook.getType(), module.getExportName().c_str(), curHook.getTarget());
|
DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s [%d] %d for %s: %08X\n", hook_names[type], type, curHook->getType(), module->getExportName().c_str(), curHook->getTarget());
|
||||||
((void (*)()) ((uint32_t *) func_ptr))();
|
((void (*)()) ((uint32_t *) func_ptr))();
|
||||||
break;
|
break;
|
||||||
} else if (type == WUMS_HOOK_INIT ||
|
} else if (type == WUMS_HOOK_INIT ||
|
||||||
type == WUMS_HOOK_RELOCATIONS_DONE) {
|
type == WUMS_HOOK_RELOCATIONS_DONE) {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s [%d] %d for %s: %08X\n", hook_names[type], type, curHook.getType(), module.getExportName().c_str(), curHook.getTarget());
|
DEBUG_FUNCTION_LINE_VERBOSE("Calling hook of type %s [%d] %d for %s: %08X\n", hook_names[type], type, curHook->getType(), module->getExportName().c_str(), curHook->getTarget());
|
||||||
wums_app_init_args_t args;
|
wums_app_init_args_t args;
|
||||||
args.module_information = gModuleData;
|
args.module_information = gModuleData;
|
||||||
((void (*)(wums_app_init_args_t *)) ((uint32_t *) func_ptr))(&args);
|
((void (*)(wums_app_init_args_t *)) ((uint32_t *) func_ptr))(&args);
|
||||||
|
@ -5,6 +5,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "ModuleDataMinimal.h"
|
#include "ModuleDataMinimal.h"
|
||||||
|
|
||||||
void CallHook(const std::vector<ModuleDataMinimal> &modules, wums_hook_type_t type);
|
void CallHook(const std::vector<std::shared_ptr<ModuleDataMinimal>> &modules, wums_hook_type_t type);
|
||||||
|
|
||||||
void CallHook(const ModuleDataMinimal &module, wums_hook_type_t type);
|
void CallHook(const std::shared_ptr<ModuleDataMinimal> &module, wums_hook_type_t type);
|
@ -11,6 +11,7 @@
|
|||||||
#include <whb/log_cafe.h>
|
#include <whb/log_cafe.h>
|
||||||
#include <whb/log_module.h>
|
#include <whb/log_module.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "fs/DirList.h"
|
#include "fs/DirList.h"
|
||||||
#include "module/ModuleDataPersistence.h"
|
#include "module/ModuleDataPersistence.h"
|
||||||
@ -42,11 +43,11 @@ extern "C" uint32_t textStart();
|
|||||||
|
|
||||||
extern "C" void _SYSLaunchMenuWithCheckingAccount(nn::act::SlotNo slot);
|
extern "C" void _SYSLaunchMenuWithCheckingAccount(nn::act::SlotNo slot);
|
||||||
|
|
||||||
bool doRelocation(std::vector<RelocationData> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length) {
|
bool doRelocation(std::vector<std::shared_ptr<RelocationData>> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length) {
|
||||||
for (auto const &curReloc: relocData) {
|
for (auto const &curReloc: relocData) {
|
||||||
std::string functionName = curReloc.getName();
|
std::string functionName = curReloc->getName();
|
||||||
std::string rplName = curReloc.getImportRPLInformation().getName();
|
std::string rplName = curReloc->getImportRPLInformation()->getName();
|
||||||
int32_t isData = curReloc.getImportRPLInformation().isData();
|
int32_t isData = curReloc->getImportRPLInformation()->isData();
|
||||||
OSDynLoad_Module rplHandle = nullptr;
|
OSDynLoad_Module rplHandle = nullptr;
|
||||||
|
|
||||||
if (OSDynLoad_IsModuleLoaded(rplName.c_str(), &rplHandle) != OS_DYNLOAD_OK) {
|
if (OSDynLoad_IsModuleLoaded(rplName.c_str(), &rplHandle) != OS_DYNLOAD_OK) {
|
||||||
@ -59,7 +60,8 @@ bool doRelocation(std::vector<RelocationData> &relocData, relocation_trampolin_e
|
|||||||
if (functionAddress == 0) {
|
if (functionAddress == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!ElfUtils::elfLinkOne(curReloc.getType(), curReloc.getOffset(), curReloc.getAddend(), (uint32_t) curReloc.getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT)) {
|
if (!ElfUtils::elfLinkOne(curReloc->getType(), curReloc->getOffset(), curReloc->getAddend(), (uint32_t) curReloc->getDestination(), functionAddress, tramp_data, tramp_length,
|
||||||
|
RELOC_TYPE_IMPORT)) {
|
||||||
DEBUG_FUNCTION_LINE("Relocation failed\n");
|
DEBUG_FUNCTION_LINE("Relocation failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -87,21 +89,22 @@ int main(int argc, char **argv) {
|
|||||||
uint32_t destination_address = ((uint32_t) gModuleData + (sizeof(module_information_t) + 0x0000FFFF)) & 0xFFFF0000;
|
uint32_t destination_address = ((uint32_t) gModuleData + (sizeof(module_information_t) + 0x0000FFFF)) & 0xFFFF0000;
|
||||||
memset((void *) gModuleData, 0, sizeof(module_information_t));
|
memset((void *) gModuleData, 0, sizeof(module_information_t));
|
||||||
DEBUG_FUNCTION_LINE("Trying to run %s", setupModules.GetFilepath(i));
|
DEBUG_FUNCTION_LINE("Trying to run %s", setupModules.GetFilepath(i));
|
||||||
std::optional<ModuleData> moduleData = ModuleDataFactory::load(setupModules.GetFilepath(i), &destination_address, textSectionStart - destination_address, gModuleData->trampolines,
|
auto moduleData = ModuleDataFactory::load(setupModules.GetFilepath(i), &destination_address, textSectionStart - destination_address, gModuleData->trampolines,
|
||||||
DYN_LINK_TRAMPOLIN_LIST_LENGTH);
|
DYN_LINK_TRAMPOLIN_LIST_LENGTH);
|
||||||
if (!moduleData) {
|
if (!moduleData) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to load %s", setupModules.GetFilepath(i));
|
DEBUG_FUNCTION_LINE("Failed to load %s", setupModules.GetFilepath(i));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
DEBUG_FUNCTION_LINE("Loaded module data");
|
DEBUG_FUNCTION_LINE("Loaded module data");
|
||||||
std::vector<RelocationData> relocData = moduleData->getRelocationDataList();
|
auto relocData = moduleData.value()->getRelocationDataList();
|
||||||
if (!doRelocation(relocData, gModuleData->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH)) {
|
if (!doRelocation(relocData, gModuleData->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH)) {
|
||||||
DEBUG_FUNCTION_LINE("relocations failed\n");
|
DEBUG_FUNCTION_LINE("relocations failed\n");
|
||||||
}
|
}
|
||||||
DCFlushRange((void *) moduleData->getStartAddress(), moduleData->getEndAddress() - moduleData->getStartAddress());
|
|
||||||
ICInvalidateRange((void *) moduleData->getStartAddress(), moduleData->getEndAddress() - moduleData->getStartAddress());
|
DCFlushRange((void *) moduleData.value()->getStartAddress(), moduleData.value()->getEndAddress() - moduleData.value()->getStartAddress());
|
||||||
DEBUG_FUNCTION_LINE("Calling entrypoint @%08X", moduleData->getEntrypoint());
|
ICInvalidateRange((void *) moduleData.value()->getStartAddress(), moduleData.value()->getEndAddress() - moduleData.value()->getStartAddress());
|
||||||
((int (*)(int, char **)) moduleData->getEntrypoint())(argc, argv);
|
DEBUG_FUNCTION_LINE("Calling entrypoint @%08X", moduleData.value()->getEntrypoint());
|
||||||
|
((int (*)(int, char **)) moduleData.value()->getEntrypoint())(argc, argv);
|
||||||
DEBUG_FUNCTION_LINE("Back from module");
|
DEBUG_FUNCTION_LINE("Back from module");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +118,7 @@ int main(int argc, char **argv) {
|
|||||||
for (int i = 0; i < modules.GetFilecount(); i++) {
|
for (int i = 0; i < modules.GetFilecount(); i++) {
|
||||||
DEBUG_FUNCTION_LINE("Loading module %s", modules.GetFilepath(i));
|
DEBUG_FUNCTION_LINE("Loading module %s", modules.GetFilepath(i));
|
||||||
auto moduleData = ModuleDataFactory::load(modules.GetFilepath(i), &destination_address, MEMORY_REGION_USABLE_END - destination_address, gModuleData->trampolines,
|
auto moduleData = ModuleDataFactory::load(modules.GetFilepath(i), &destination_address, MEMORY_REGION_USABLE_END - destination_address, gModuleData->trampolines,
|
||||||
DYN_LINK_TRAMPOLIN_LIST_LENGTH);
|
DYN_LINK_TRAMPOLIN_LIST_LENGTH);
|
||||||
|
|
||||||
if (moduleData) {
|
if (moduleData) {
|
||||||
DEBUG_FUNCTION_LINE("Successfully loaded %s", modules.GetFilepath(i));
|
DEBUG_FUNCTION_LINE("Successfully loaded %s", modules.GetFilepath(i));
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
#include "DynamicLinkingHelper.h"
|
#include "DynamicLinkingHelper.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <coreinit/dynload.h>
|
#include <coreinit/dynload.h>
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
|
||||||
dyn_linking_function_t *DynamicLinkingHelper::getOrAddFunctionEntryByName(dyn_linking_relocation_data_t *data, const char *functionName) {
|
dyn_linking_function_t *DynamicLinkingHelper::getOrAddFunctionEntryByName(dyn_linking_relocation_data_t *data, const char *functionName) {
|
||||||
if (data == NULL) {
|
if (data == nullptr) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (functionName == NULL) {
|
if (functionName == nullptr) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
dyn_linking_function_t *result = NULL;
|
dyn_linking_function_t *result = nullptr;
|
||||||
for (int32_t i = 0; i < DYN_LINK_FUNCTION_LIST_LENGTH; i++) {
|
for (auto &function: data->functions) {
|
||||||
dyn_linking_function_t *curEntry = &(data->functions[i]);
|
dyn_linking_function_t *curEntry = &function;
|
||||||
if (strlen(curEntry->functionName) == 0) {
|
if (strlen(curEntry->functionName) == 0) {
|
||||||
if (strlen(functionName) > DYN_LINK_FUNCTION_NAME_LENGTH) {
|
if (strlen(functionName) > DYN_LINK_FUNCTION_NAME_LENGTH) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to add function name, it's too long.\n");
|
DEBUG_FUNCTION_LINE("Failed to add function name, it's too long.\n");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
strncpy(curEntry->functionName, functionName, DYN_LINK_FUNCTION_NAME_LENGTH);
|
strncpy(curEntry->functionName, functionName, DYN_LINK_FUNCTION_NAME_LENGTH);
|
||||||
result = curEntry;
|
result = curEntry;
|
||||||
@ -41,16 +41,16 @@ dyn_linking_import_t *DynamicLinkingHelper::getOrAddDataImportByName(dyn_linking
|
|||||||
}
|
}
|
||||||
|
|
||||||
dyn_linking_import_t *DynamicLinkingHelper::getOrAddImport(dyn_linking_relocation_data_t *data, const char *importName, bool isData) {
|
dyn_linking_import_t *DynamicLinkingHelper::getOrAddImport(dyn_linking_relocation_data_t *data, const char *importName, bool isData) {
|
||||||
if (importName == NULL || data == NULL) {
|
if (importName == nullptr || data == nullptr) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
dyn_linking_import_t *result = NULL;
|
dyn_linking_import_t *result = nullptr;
|
||||||
for (int32_t i = 0; i < DYN_LINK_IMPORT_LIST_LENGTH; i++) {
|
for (auto &import: data->imports) {
|
||||||
dyn_linking_import_t *curEntry = &(data->imports[i]);
|
dyn_linking_import_t *curEntry = &import;
|
||||||
if (strlen(curEntry->importName) == 0) {
|
if (strlen(curEntry->importName) == 0) {
|
||||||
if (strlen(importName) > DYN_LINK_IMPORT_NAME_LENGTH) {
|
if (strlen(importName) > DYN_LINK_IMPORT_NAME_LENGTH) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to add Import, it's too long.\n");
|
DEBUG_FUNCTION_LINE("Failed to add Import, it's too long.\n");
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
strncpy(curEntry->importName, importName, DYN_LINK_IMPORT_NAME_LENGTH);
|
strncpy(curEntry->importName, importName, DYN_LINK_IMPORT_NAME_LENGTH);
|
||||||
curEntry->isData = isData;
|
curEntry->isData = isData;
|
||||||
@ -65,23 +65,23 @@ dyn_linking_import_t *DynamicLinkingHelper::getOrAddImport(dyn_linking_relocatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DynamicLinkingHelper::addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length,
|
bool DynamicLinkingHelper::addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length,
|
||||||
const RelocationData &relocationData) {
|
const std::shared_ptr<RelocationData> &relocationData) {
|
||||||
return addReloationEntry(linking_data, linking_entries, linking_entry_length, relocationData.getType(), relocationData.getOffset(), relocationData.getAddend(), relocationData.getDestination(),
|
return addReloationEntry(linking_data, linking_entries, linking_entry_length, relocationData->getType(), relocationData->getOffset(), relocationData->getAddend(), relocationData->getDestination(),
|
||||||
relocationData.getName(),
|
relocationData->getName(),
|
||||||
relocationData.getImportRPLInformation());
|
relocationData->getImportRPLInformation());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset,
|
bool DynamicLinkingHelper::addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset,
|
||||||
int32_t addend, void *destination,
|
int32_t addend, void *destination,
|
||||||
std::string name, const ImportRPLInformation &rplInfo) {
|
const std::string &name, const std::shared_ptr<ImportRPLInformation> &rplInfo) {
|
||||||
dyn_linking_import_t *importInfoGbl = DynamicLinkingHelper::getOrAddImport(linking_data, rplInfo.getName().c_str(), rplInfo.isData());
|
dyn_linking_import_t *importInfoGbl = DynamicLinkingHelper::getOrAddImport(linking_data, rplInfo->getName().c_str(), rplInfo->isData());
|
||||||
if (importInfoGbl == NULL) {
|
if (importInfoGbl == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d rpl files to import reached.\n", DYN_LINK_IMPORT_LIST_LENGTH);
|
DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d rpl files to import reached.\n", DYN_LINK_IMPORT_LIST_LENGTH);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dyn_linking_function_t *functionInfo = DynamicLinkingHelper::getOrAddFunctionEntryByName(linking_data, name.c_str());
|
dyn_linking_function_t *functionInfo = DynamicLinkingHelper::getOrAddFunctionEntryByName(linking_data, name.c_str());
|
||||||
if (functionInfo == NULL) {
|
if (functionInfo == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d function to be relocated reached.\n", DYN_LINK_FUNCTION_LIST_LENGTH);
|
DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d function to be relocated reached.\n", DYN_LINK_FUNCTION_LIST_LENGTH);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ bool DynamicLinkingHelper::addRelocationEntry(dyn_linking_relocation_entry_t *li
|
|||||||
dyn_linking_import_t *importInfo) {
|
dyn_linking_import_t *importInfo) {
|
||||||
for (uint32_t i = 0; i < linking_entry_length; i++) {
|
for (uint32_t i = 0; i < linking_entry_length; i++) {
|
||||||
dyn_linking_relocation_entry_t *curEntry = &(linking_entries[i]);
|
dyn_linking_relocation_entry_t *curEntry = &(linking_entries[i]);
|
||||||
if (curEntry->functionEntry != NULL) {
|
if (curEntry->functionEntry != nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
curEntry->type = type;
|
curEntry->type = type;
|
||||||
|
@ -47,11 +47,11 @@ public:
|
|||||||
**/
|
**/
|
||||||
static dyn_linking_import_t *getOrAddImport(dyn_linking_relocation_data_t *data, const char *importName, bool isData);
|
static dyn_linking_import_t *getOrAddImport(dyn_linking_relocation_data_t *data, const char *importName, bool isData);
|
||||||
|
|
||||||
static bool addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, const RelocationData &relocationData);
|
static bool addRelocationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, const std::shared_ptr<RelocationData> &relocationData);
|
||||||
|
|
||||||
static bool addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend,
|
static bool addReloationEntry(dyn_linking_relocation_data_t *linking_data, dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend,
|
||||||
void *destination, std::string name,
|
void *destination, const std::string& name,
|
||||||
const ImportRPLInformation &rplInfo);
|
const std::shared_ptr<ImportRPLInformation> &rplInfo);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
addRelocationEntry(dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, void *destination,
|
addRelocationEntry(dyn_linking_relocation_entry_t *linking_entries, uint32_t linking_entry_length, char type, size_t offset, int32_t addend, void *destination,
|
||||||
|
@ -19,19 +19,20 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
|
||||||
class ImportRPLInformation {
|
class ImportRPLInformation {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ImportRPLInformation(std::string name, bool isData = false) {
|
explicit ImportRPLInformation(std::string name, bool isData = false) {
|
||||||
this->name = name;
|
this->name = std::move(name);
|
||||||
this->_isData = isData;
|
this->_isData = isData;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ImportRPLInformation() = default;
|
~ImportRPLInformation() = default;
|
||||||
|
|
||||||
static std::optional<ImportRPLInformation> createImportRPLInformation(std::string rawSectionName) {
|
static std::optional<std::shared_ptr<ImportRPLInformation>> createImportRPLInformation(std::string rawSectionName) {
|
||||||
std::string fimport = ".fimport_";
|
std::string fimport = ".fimport_";
|
||||||
std::string dimport = ".dimport_";
|
std::string dimport = ".dimport_";
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ public:
|
|||||||
DEBUG_FUNCTION_LINE("invalid section name\n");
|
DEBUG_FUNCTION_LINE("invalid section name\n");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return ImportRPLInformation(rplName, data);
|
return std::make_shared<ImportRPLInformation>(rplName, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::string getName() const {
|
[[nodiscard]] std::string getName() const {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
std::string ModuleData::toString() const {
|
std::string ModuleData::toString() const {
|
||||||
std::string res = StringTools::strfmt("Entrypoint %08X, bss: %08X (%d), bss: %08X (%d)\n", getEntrypoint(), getBSSAddr(), getBSSSize(), getSBSSAddr(), getSBSSSize());
|
std::string res = StringTools::strfmt("Entrypoint %08X, bss: %08X (%d), bss: %08X (%d)\n", getEntrypoint(), getBSSAddr(), getBSSSize(), getSBSSAddr(), getSBSSSize());
|
||||||
for (auto const &reloc: relocation_data_list) {
|
for (auto const &reloc: relocation_data_list) {
|
||||||
res += reloc.toString();
|
res += reloc->toString();
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,14 @@
|
|||||||
#include "HookData.h"
|
#include "HookData.h"
|
||||||
#include "FunctionSymbolData.h"
|
#include "FunctionSymbolData.h"
|
||||||
|
|
||||||
|
struct FunctionSymbolDataComparator {
|
||||||
|
bool operator()(const std::shared_ptr<FunctionSymbolData>& lhs,
|
||||||
|
const std::shared_ptr<FunctionSymbolData>& rhs) const
|
||||||
|
{
|
||||||
|
return (uint32_t) lhs->getAddress() < (uint32_t) rhs->getAddress();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ModuleData {
|
class ModuleData {
|
||||||
public:
|
public:
|
||||||
ModuleData() = default;
|
ModuleData() = default;
|
||||||
@ -55,47 +63,47 @@ public:
|
|||||||
this->endAddress = _endAddress;
|
this->endAddress = _endAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addRelocationData(const RelocationData &relocation_data) {
|
void addRelocationData(const std::shared_ptr<RelocationData> &relocation_data) {
|
||||||
relocation_data_list.push_back(relocation_data);
|
relocation_data_list.push_back(relocation_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<RelocationData> &getRelocationDataList() const {
|
[[nodiscard]] const std::vector<std::shared_ptr<RelocationData>> &getRelocationDataList() const {
|
||||||
return relocation_data_list;
|
return relocation_data_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addExportData(const ExportData &data) {
|
void addExportData(const std::shared_ptr<ExportData> &data) {
|
||||||
export_data_list.push_back(data);
|
export_data_list.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<ExportData> &getExportDataList() const {
|
[[nodiscard]] const std::vector<std::shared_ptr<ExportData>> &getExportDataList() const {
|
||||||
return export_data_list;
|
return export_data_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addHookData(const HookData &data) {
|
void addHookData(const std::shared_ptr<HookData> &data) {
|
||||||
hook_data_list.push_back(data);
|
hook_data_list.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<HookData> &getHookDataList() const {
|
[[nodiscard]] const std::vector<std::shared_ptr<HookData>> &getHookDataList() const {
|
||||||
return hook_data_list;
|
return hook_data_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addSectionInfo(const SectionInfo §ionInfo) {
|
void addSectionInfo(const std::shared_ptr<SectionInfo> §ionInfo) {
|
||||||
section_info_list[sectionInfo.getName()] = sectionInfo;
|
section_info_list[sectionInfo->getName()] = sectionInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addFunctionSymbolData(const FunctionSymbolData &symbol_data) {
|
void addFunctionSymbolData(const std::shared_ptr<FunctionSymbolData> &symbol_data) {
|
||||||
symbol_data_list.insert(symbol_data);
|
symbol_data_list.insert(symbol_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const std::set<FunctionSymbolData> &getFunctionSymbolDataList() const {
|
[[nodiscard]] const std::set<std::shared_ptr<FunctionSymbolData>, FunctionSymbolDataComparator> &getFunctionSymbolDataList() const {
|
||||||
return symbol_data_list;
|
return symbol_data_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const std::map<std::string, SectionInfo> &getSectionInfoList() const {
|
[[nodiscard]] const std::map<std::string, std::shared_ptr<SectionInfo>> &getSectionInfoList() const {
|
||||||
return section_info_list;
|
return section_info_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::optional<SectionInfo> getSectionInfo(const std::string §ionName) const {
|
[[nodiscard]] std::optional<std::shared_ptr<SectionInfo>> getSectionInfo(const std::string §ionName) const {
|
||||||
if (getSectionInfoList().count(sectionName) > 0) {
|
if (getSectionInfoList().count(sectionName) > 0) {
|
||||||
return section_info_list.at(sectionName);
|
return section_info_list.at(sectionName);
|
||||||
}
|
}
|
||||||
@ -158,11 +166,11 @@ public:
|
|||||||
|
|
||||||
bool relocationsDone = false;
|
bool relocationsDone = false;
|
||||||
private:
|
private:
|
||||||
std::vector<RelocationData> relocation_data_list;
|
std::vector<std::shared_ptr<RelocationData>> relocation_data_list;
|
||||||
std::vector<ExportData> export_data_list;
|
std::vector<std::shared_ptr<ExportData>> export_data_list;
|
||||||
std::vector<HookData> hook_data_list;
|
std::vector<std::shared_ptr<HookData>> hook_data_list;
|
||||||
std::set<FunctionSymbolData> symbol_data_list;
|
std::set<std::shared_ptr<FunctionSymbolData>, FunctionSymbolDataComparator> symbol_data_list;
|
||||||
std::map<std::string, SectionInfo> section_info_list;
|
std::map<std::string, std::shared_ptr<SectionInfo>> section_info_list;
|
||||||
|
|
||||||
std::string export_name;
|
std::string export_name;
|
||||||
|
|
||||||
|
@ -27,10 +27,10 @@
|
|||||||
|
|
||||||
using namespace ELFIO;
|
using namespace ELFIO;
|
||||||
|
|
||||||
std::optional<ModuleData>
|
std::optional<std::shared_ptr<ModuleData>>
|
||||||
ModuleDataFactory::load(const std::string &path, uint32_t *destination_address_ptr, uint32_t maximum_size, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length) {
|
ModuleDataFactory::load(const std::string &path, uint32_t *destination_address_ptr, uint32_t maximum_size, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length) {
|
||||||
elfio reader;
|
elfio reader;
|
||||||
ModuleData moduleData;
|
std::shared_ptr<ModuleData> moduleData = std::make_shared<ModuleData>();
|
||||||
|
|
||||||
// Load ELF data
|
// Load ELF data
|
||||||
if (!reader.load(path)) {
|
if (!reader.load(path)) {
|
||||||
@ -101,14 +101,14 @@ ModuleDataFactory::load(const std::string &path, uint32_t *destination_address_p
|
|||||||
|
|
||||||
//nextAddress = ROUNDUP(destination + sectionSize, 0x100);
|
//nextAddress = ROUNDUP(destination + sectionSize, 0x100);
|
||||||
if (psec->get_name() == ".bss") {
|
if (psec->get_name() == ".bss") {
|
||||||
moduleData.setBSSLocation(destination, sectionSize);
|
moduleData->setBSSLocation(destination, sectionSize);
|
||||||
memset(reinterpret_cast<void *>(destination), 0, sectionSize);
|
memset(reinterpret_cast<void *>(destination), 0, sectionSize);
|
||||||
} else if (psec->get_name() == ".sbss") {
|
} else if (psec->get_name() == ".sbss") {
|
||||||
moduleData.setSBSSLocation(destination, sectionSize);
|
moduleData->setSBSSLocation(destination, sectionSize);
|
||||||
memset(reinterpret_cast<void *>(destination), 0, sectionSize);
|
memset(reinterpret_cast<void *>(destination), 0, sectionSize);
|
||||||
}
|
}
|
||||||
|
auto sectionInfo = std::make_shared<SectionInfo>(psec->get_name(), destination, sectionSize);
|
||||||
moduleData.addSectionInfo(SectionInfo(psec->get_name(), destination, sectionSize));
|
moduleData->addSectionInfo(sectionInfo);
|
||||||
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);
|
||||||
|
|
||||||
if (endAddress < destination + sectionSize) {
|
if (endAddress < destination + sectionSize) {
|
||||||
@ -131,47 +131,47 @@ ModuleDataFactory::load(const std::string &path, uint32_t *destination_address_p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<RelocationData> relocationData = getImportRelocationData(reader, destinations);
|
auto relocationData = getImportRelocationData(reader, destinations);
|
||||||
|
|
||||||
for (auto const &reloc: relocationData) {
|
for (auto const &reloc: relocationData) {
|
||||||
moduleData.addRelocationData(reloc);
|
moduleData->addRelocationData(reloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<SectionInfo> secInfo = moduleData.getSectionInfo(".wums.exports");
|
auto secInfo = moduleData->getSectionInfo(".wums.exports");
|
||||||
if (secInfo && secInfo->getSize() > 0) {
|
if (secInfo && secInfo.value()->getSize() > 0) {
|
||||||
size_t entries_count = secInfo->getSize() / sizeof(wums_entry_t);
|
size_t entries_count = secInfo.value()->getSize() / sizeof(wums_entry_t);
|
||||||
auto *entries = (wums_entry_t *) secInfo->getAddress();
|
auto *entries = (wums_entry_t *) secInfo.value()->getAddress();
|
||||||
if (entries != nullptr) {
|
if (entries != nullptr) {
|
||||||
for (size_t j = 0; j < entries_count; j++) {
|
for (size_t j = 0; j < entries_count; j++) {
|
||||||
wums_entry_t *exp = &entries[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);
|
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);
|
auto exportData = std::make_shared<ExportData>(exp->type, exp->name, exp->address);
|
||||||
moduleData.addExportData(export_data);
|
moduleData->addExportData(exportData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
secInfo = moduleData.getSectionInfo(".wums.hooks");
|
secInfo = moduleData->getSectionInfo(".wums.hooks");
|
||||||
if (secInfo && secInfo->getSize() > 0) {
|
if (secInfo && secInfo.value()->getSize() > 0) {
|
||||||
size_t entries_count = secInfo->getSize() / sizeof(wums_hook_t);
|
size_t entries_count = secInfo.value()->getSize() / sizeof(wums_hook_t);
|
||||||
auto *hooks = (wums_hook_t *) secInfo->getAddress();
|
auto *hooks = (wums_hook_t *) secInfo.value()->getAddress();
|
||||||
if (hooks != nullptr) {
|
if (hooks != nullptr) {
|
||||||
for (size_t j = 0; j < entries_count; j++) {
|
for (size_t j = 0; j < entries_count; j++) {
|
||||||
wums_hook_t *hook = &hooks[j];
|
wums_hook_t *hook = &hooks[j];
|
||||||
DEBUG_FUNCTION_LINE("Saving hook of type %08X, target: %08X"/*,pluginData.getPluginInformation()->getName().c_str()*/, hook->type, hook->target);
|
DEBUG_FUNCTION_LINE("Saving hook of type %08X, target: %08X"/*,pluginData.getPluginInformation()->getName().c_str()*/, hook->type, hook->target);
|
||||||
HookData hook_data(hook->type, hook->target);
|
auto hookData = std::make_shared<HookData>(hook->type, hook->target);
|
||||||
moduleData.addHookData(hook_data);
|
moduleData->addHookData(hookData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
secInfo = moduleData.getSectionInfo(".wums.meta");
|
secInfo = moduleData->getSectionInfo(".wums.meta");
|
||||||
if (secInfo && secInfo->getSize() > 0) {
|
if (secInfo && secInfo.value()->getSize() > 0) {
|
||||||
auto *entries = (wums_entry_t *) secInfo->getAddress();
|
auto *entries = (wums_entry_t *) secInfo.value()->getAddress();
|
||||||
if (entries != nullptr) {
|
if (entries != nullptr) {
|
||||||
|
|
||||||
char *curEntry = (char *) secInfo->getAddress();
|
char *curEntry = (char *) secInfo.value()->getAddress();
|
||||||
while ((uint32_t) curEntry < (uint32_t) secInfo->getAddress() + secInfo->getSize()) {
|
while ((uint32_t) curEntry < (uint32_t) secInfo.value()->getAddress() + secInfo.value()->getSize()) {
|
||||||
if (*curEntry == '\0') {
|
if (*curEntry == '\0') {
|
||||||
curEntry++;
|
curEntry++;
|
||||||
continue;
|
continue;
|
||||||
@ -185,20 +185,20 @@ ModuleDataFactory::load(const std::string &path, uint32_t *destination_address_p
|
|||||||
|
|
||||||
if (key == "export_name") {
|
if (key == "export_name") {
|
||||||
DEBUG_FUNCTION_LINE("export_name = %s", value.c_str());
|
DEBUG_FUNCTION_LINE("export_name = %s", value.c_str());
|
||||||
moduleData.setExportName(value);
|
moduleData->setExportName(value);
|
||||||
} else if (key == "skipEntrypoint") {
|
} else if (key == "skipEntrypoint") {
|
||||||
if (value == "true") {
|
if (value == "true") {
|
||||||
DEBUG_FUNCTION_LINE("skipEntrypoint = %s", value.c_str());
|
DEBUG_FUNCTION_LINE("skipEntrypoint = %s", value.c_str());
|
||||||
moduleData.setSkipEntrypoint(true);
|
moduleData->setSkipEntrypoint(true);
|
||||||
} else {
|
} else {
|
||||||
moduleData.setSkipEntrypoint(false);
|
moduleData->setSkipEntrypoint(false);
|
||||||
}
|
}
|
||||||
} else if (key == "initBeforeRelocationDoneHook") {
|
} else if (key == "initBeforeRelocationDoneHook") {
|
||||||
if (value == "true") {
|
if (value == "true") {
|
||||||
DEBUG_FUNCTION_LINE("initBeforeRelocationDoneHook = %s", value.c_str());
|
DEBUG_FUNCTION_LINE("initBeforeRelocationDoneHook = %s", value.c_str());
|
||||||
moduleData.setInitBeforeRelocationDoneHook(true);
|
moduleData->setInitBeforeRelocationDoneHook(true);
|
||||||
} else {
|
} else {
|
||||||
moduleData.setInitBeforeRelocationDoneHook(false);
|
moduleData->setInitBeforeRelocationDoneHook(false);
|
||||||
}
|
}
|
||||||
} else if (key == "wums") {
|
} else if (key == "wums") {
|
||||||
if (value != "0.3") {
|
if (value != "0.3") {
|
||||||
@ -235,15 +235,15 @@ ModuleDataFactory::load(const std::string &path, uint32_t *destination_address_p
|
|||||||
if (type == STT_FUNC) { // We only care about functions.
|
if (type == STT_FUNC) { // We only care about functions.
|
||||||
auto sectionVal = reader.sections[section];
|
auto sectionVal = reader.sections[section];
|
||||||
auto offsetVal = value - sectionVal->get_address();
|
auto offsetVal = value - sectionVal->get_address();
|
||||||
auto sectionOpt = moduleData.getSectionInfo(sectionVal->get_name());
|
auto sectionOpt = moduleData->getSectionInfo(sectionVal->get_name());
|
||||||
if (!sectionOpt.has_value()) {
|
if (!sectionOpt.has_value()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto finalAddress = offsetVal + sectionOpt->getAddress();
|
auto finalAddress = offsetVal + sectionOpt.value()->getAddress();
|
||||||
|
|
||||||
uint32_t stringSize = name.size() + 1;
|
uint32_t stringSize = name.size() + 1;
|
||||||
memcpy(strTable + strOffset, name.c_str(), stringSize);
|
memcpy(strTable + strOffset, name.c_str(), stringSize);
|
||||||
moduleData.addFunctionSymbolData(FunctionSymbolData(strTable + strOffset, (void *) finalAddress, (uint32_t) size));
|
moduleData->addFunctionSymbolData(std::make_shared<FunctionSymbolData>(strTable + strOffset, (void *) finalAddress, (uint32_t) size));
|
||||||
strOffset += stringSize;
|
strOffset += stringSize;
|
||||||
totalSize += stringSize;
|
totalSize += stringSize;
|
||||||
endAddress += stringSize;
|
endAddress += stringSize;
|
||||||
@ -260,9 +260,9 @@ ModuleDataFactory::load(const std::string &path, uint32_t *destination_address_p
|
|||||||
|
|
||||||
free(destinations);
|
free(destinations);
|
||||||
|
|
||||||
moduleData.setEntrypoint(entrypoint);
|
moduleData->setEntrypoint(entrypoint);
|
||||||
moduleData.setStartAddress(*destination_address_ptr);
|
moduleData->setStartAddress(*destination_address_ptr);
|
||||||
moduleData.setEndAddress(endAddress);
|
moduleData->setEndAddress(endAddress);
|
||||||
DEBUG_FUNCTION_LINE("Saved entrypoint as %08X", entrypoint);
|
DEBUG_FUNCTION_LINE("Saved entrypoint as %08X", entrypoint);
|
||||||
DEBUG_FUNCTION_LINE("Saved startAddress as %08X", *destination_address_ptr);
|
DEBUG_FUNCTION_LINE("Saved startAddress as %08X", *destination_address_ptr);
|
||||||
DEBUG_FUNCTION_LINE("Saved endAddress as %08X", endAddress);
|
DEBUG_FUNCTION_LINE("Saved endAddress as %08X", endAddress);
|
||||||
@ -272,8 +272,8 @@ ModuleDataFactory::load(const std::string &path, uint32_t *destination_address_p
|
|||||||
return moduleData;
|
return moduleData;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RelocationData> ModuleDataFactory::getImportRelocationData(elfio &reader, uint8_t **destinations) {
|
std::vector<std::shared_ptr<RelocationData>> ModuleDataFactory::getImportRelocationData(elfio &reader, uint8_t **destinations) {
|
||||||
std::vector<RelocationData> result;
|
std::vector<std::shared_ptr<RelocationData>> result;
|
||||||
std::map<uint32_t, std::string> infoMap;
|
std::map<uint32_t, std::string> infoMap;
|
||||||
|
|
||||||
uint32_t sec_num = reader.sections.size();
|
uint32_t sec_num = reader.sections.size();
|
||||||
@ -307,7 +307,7 @@ std::vector<RelocationData> ModuleDataFactory::getImportRelocationData(elfio &re
|
|||||||
if (infoMap.count(sym_section_index) == 0) {
|
if (infoMap.count(sym_section_index) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::optional<ImportRPLInformation> rplInfo = ImportRPLInformation::createImportRPLInformation(infoMap[sym_section_index]);
|
auto rplInfo = ImportRPLInformation::createImportRPLInformation(infoMap[sym_section_index]);
|
||||||
if (!rplInfo) {
|
if (!rplInfo) {
|
||||||
DEBUG_FUNCTION_LINE("Failed to create import information");
|
DEBUG_FUNCTION_LINE("Failed to create import information");
|
||||||
break;
|
break;
|
||||||
@ -316,7 +316,7 @@ std::vector<RelocationData> ModuleDataFactory::getImportRelocationData(elfio &re
|
|||||||
uint32_t section_index = psec->get_info();
|
uint32_t section_index = psec->get_info();
|
||||||
|
|
||||||
// When these relocations are performed, we don't need the 0xC0000000 offset anymore.
|
// When these relocations are performed, we don't need the 0xC0000000 offset anymore.
|
||||||
RelocationData relocationData(type, offset - 0x02000000, addend, (void *) (destinations[section_index] + 0x02000000), sym_name, rplInfo.value());
|
auto relocationData = std::make_shared<RelocationData>(type, offset - 0x02000000, addend, (void *) (destinations[section_index] + 0x02000000), sym_name, rplInfo.value());
|
||||||
//relocationData->printInformation();
|
//relocationData->printInformation();
|
||||||
result.push_back(relocationData);
|
result.push_back(relocationData);
|
||||||
}
|
}
|
||||||
|
@ -26,11 +26,11 @@
|
|||||||
|
|
||||||
class ModuleDataFactory {
|
class ModuleDataFactory {
|
||||||
public:
|
public:
|
||||||
static std::optional<ModuleData>
|
static std::optional<std::shared_ptr<ModuleData>>
|
||||||
load(const std::string &path, uint32_t *destination_address_ptr, uint32_t maximum_size, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length);
|
load(const std::string &path, uint32_t *destination_address_ptr, uint32_t maximum_size, relocation_trampolin_entry_t *trampolin_data, uint32_t trampolin_data_length);
|
||||||
|
|
||||||
static bool linkSection(ELFIO::elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampolin_entry_t *trampolin_data,
|
static bool linkSection(ELFIO::elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampolin_entry_t *trampolin_data,
|
||||||
uint32_t trampolin_data_length);
|
uint32_t trampolin_data_length);
|
||||||
|
|
||||||
static std::vector<RelocationData> getImportRelocationData(ELFIO::elfio &reader, uint8_t **destinations);
|
static std::vector<std::shared_ptr<RelocationData>> getImportRelocationData(ELFIO::elfio &reader, uint8_t **destinations);
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#include <coreinit/cache.h>
|
#include <coreinit/cache.h>
|
||||||
|
|
||||||
#include "ModuleDataPersistence.h"
|
#include "ModuleDataPersistence.h"
|
||||||
#include "DynamicLinkingHelper.h"
|
#include "DynamicLinkingHelper.h"
|
||||||
|
|
||||||
bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformation, const ModuleData &module) {
|
bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformation, const std::shared_ptr<ModuleData> &module) {
|
||||||
int32_t module_count = moduleInformation->number_used_modules;
|
int32_t module_count = moduleInformation->number_used_modules;
|
||||||
|
|
||||||
if (module_count >= MAXIMUM_MODULES) {
|
if (module_count >= MAXIMUM_MODULES) {
|
||||||
@ -13,9 +12,9 @@ bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformati
|
|||||||
// Copy data to global struct.
|
// Copy data to global struct.
|
||||||
module_information_single_t *module_data = &(moduleInformation->module_data[module_count]);
|
module_information_single_t *module_data = &(moduleInformation->module_data[module_count]);
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Saving relocation data for module at %08X", module.getEntrypoint());
|
DEBUG_FUNCTION_LINE("Saving relocation data for module at %08X", module->getEntrypoint());
|
||||||
// Relocation
|
// Relocation
|
||||||
std::vector<RelocationData> relocationData = module.getRelocationDataList();
|
auto relocationData = module->getRelocationDataList();
|
||||||
for (auto const &reloc: relocationData) {
|
for (auto const &reloc: relocationData) {
|
||||||
if (!DynamicLinkingHelper::addRelocationEntry(&(moduleInformation->linking_data), module_data->linking_entries,
|
if (!DynamicLinkingHelper::addRelocationEntry(&(moduleInformation->linking_data), module_data->linking_entries,
|
||||||
DYN_LINK_RELOCATION_LIST_LENGTH, reloc)) {
|
DYN_LINK_RELOCATION_LIST_LENGTH, reloc)) {
|
||||||
@ -24,15 +23,15 @@ bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ExportData> exportData = module.getExportDataList();
|
auto exportData = module->getExportDataList();
|
||||||
for (auto const &curExport: exportData) {
|
for (auto const &curExport: exportData) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto &export_entry: module_data->export_entries) {
|
for (auto &export_entry: module_data->export_entries) {
|
||||||
if (export_entry.address == 0) {
|
if (export_entry.address == 0) {
|
||||||
export_entry.type = curExport.getType();
|
export_entry.type = curExport->getType();
|
||||||
export_entry.name[0] = '\0';
|
export_entry.name[0] = '\0';
|
||||||
strncat(export_entry.name, curExport.getName().c_str(), sizeof(export_entry.name) - 1);
|
strncat(export_entry.name, curExport->getName().c_str(), sizeof(export_entry.name) - 1);
|
||||||
export_entry.address = (uint32_t) curExport.getAddress();
|
export_entry.address = (uint32_t) curExport->getAddress();
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -43,13 +42,13 @@ bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<HookData> hookData = module.getHookDataList();
|
auto hookData = module->getHookDataList();
|
||||||
for (auto const &curHook: hookData) {
|
for (auto const &curHook: hookData) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto &hook_entry: module_data->hook_entries) {
|
for (auto &hook_entry: module_data->hook_entries) {
|
||||||
if (hook_entry.target == 0) {
|
if (hook_entry.target == 0) {
|
||||||
hook_entry.type = curHook.getType();
|
hook_entry.type = curHook->getType();
|
||||||
hook_entry.target = (uint32_t) curHook.getTarget();
|
hook_entry.target = (uint32_t) curHook->getTarget();
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -60,22 +59,22 @@ bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(module_data->module_export_name, module.getExportName().c_str(), MAXIMUM_EXPORT_MODULE_NAME_LENGTH);
|
strncpy(module_data->module_export_name, module->getExportName().c_str(), MAXIMUM_EXPORT_MODULE_NAME_LENGTH);
|
||||||
|
|
||||||
uint32_t entryCount = module.getFunctionSymbolDataList().size();
|
uint32_t entryCount = module->getFunctionSymbolDataList().size();
|
||||||
if (entryCount > 0) {
|
if (entryCount > 0) {
|
||||||
auto ptr = &moduleInformation->function_symbols[moduleInformation->number_used_function_symbols];
|
auto ptr = &moduleInformation->function_symbols[moduleInformation->number_used_function_symbols];
|
||||||
module_data->function_symbol_entries = ptr;
|
module_data->function_symbol_entries = ptr;
|
||||||
|
|
||||||
uint32_t sym_offset = 0;
|
uint32_t sym_offset = 0;
|
||||||
for (auto &curFuncSym: module.getFunctionSymbolDataList()) {
|
for (auto &curFuncSym: module->getFunctionSymbolDataList()) {
|
||||||
if (moduleInformation->number_used_function_symbols >= FUNCTION_SYMBOL_LIST_LENGTH) {
|
if (moduleInformation->number_used_function_symbols >= FUNCTION_SYMBOL_LIST_LENGTH) {
|
||||||
DEBUG_FUNCTION_LINE("Function symbol list is full");
|
DEBUG_FUNCTION_LINE("Function symbol list is full");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
module_data->function_symbol_entries[sym_offset].address = curFuncSym.getAddress();
|
module_data->function_symbol_entries[sym_offset].address = curFuncSym->getAddress();
|
||||||
module_data->function_symbol_entries[sym_offset].name = (char *) curFuncSym.getName();
|
module_data->function_symbol_entries[sym_offset].name = (char *) curFuncSym->getName();
|
||||||
module_data->function_symbol_entries[sym_offset].size = curFuncSym.getSize();
|
module_data->function_symbol_entries[sym_offset].size = curFuncSym->getSize();
|
||||||
|
|
||||||
sym_offset++;
|
sym_offset++;
|
||||||
moduleInformation->number_used_function_symbols++;
|
moduleInformation->number_used_function_symbols++;
|
||||||
@ -86,15 +85,15 @@ bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformati
|
|||||||
module_data->number_used_function_symbols = 0;
|
module_data->number_used_function_symbols = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
module_data->sbssSize = module.getSBSSSize();
|
module_data->sbssSize = module->getSBSSSize();
|
||||||
module_data->startAddress = module.getStartAddress();
|
module_data->startAddress = module->getStartAddress();
|
||||||
module_data->endAddress = module.getEndAddress();
|
module_data->endAddress = module->getEndAddress();
|
||||||
module_data->entrypoint = module.getEntrypoint();
|
module_data->entrypoint = module->getEntrypoint();
|
||||||
module_data->skipEntrypoint = module.isSkipEntrypoint();
|
module_data->skipEntrypoint = module->isSkipEntrypoint();
|
||||||
module_data->initBeforeRelocationDoneHook = module.isInitBeforeRelocationDoneHook();
|
module_data->initBeforeRelocationDoneHook = module->isInitBeforeRelocationDoneHook();
|
||||||
|
|
||||||
moduleInformation->number_used_modules++;
|
moduleInformation->number_used_modules++;
|
||||||
|
|
||||||
@ -104,8 +103,8 @@ bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformati
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ModuleData> ModuleDataPersistence::loadModuleData(module_information_t *moduleInformation) {
|
std::vector<std::shared_ptr<ModuleData>> ModuleDataPersistence::loadModuleData(module_information_t *moduleInformation) {
|
||||||
std::vector<ModuleData> result;
|
std::vector<std::shared_ptr<ModuleData>> result;
|
||||||
if (moduleInformation == nullptr) {
|
if (moduleInformation == nullptr) {
|
||||||
DEBUG_FUNCTION_LINE("moduleInformation == NULL\n");
|
DEBUG_FUNCTION_LINE("moduleInformation == NULL\n");
|
||||||
return result;
|
return result;
|
||||||
@ -121,29 +120,31 @@ std::vector<ModuleData> ModuleDataPersistence::loadModuleData(module_information
|
|||||||
for (int32_t i = 0; i < module_count; i++) {
|
for (int32_t i = 0; i < module_count; i++) {
|
||||||
// Copy data from struct.
|
// Copy data from struct.
|
||||||
module_information_single_t *module_data = &(moduleInformation->module_data[i]);
|
module_information_single_t *module_data = &(moduleInformation->module_data[i]);
|
||||||
ModuleData moduleData;
|
auto moduleData = std::make_shared<ModuleData>();
|
||||||
moduleData.setBSSLocation(module_data->bssAddr, module_data->bssSize);
|
moduleData->setBSSLocation(module_data->bssAddr, module_data->bssSize);
|
||||||
moduleData.setSBSSLocation(module_data->sbssAddr, module_data->sbssSize);
|
moduleData->setSBSSLocation(module_data->sbssAddr, module_data->sbssSize);
|
||||||
moduleData.setEntrypoint(module_data->entrypoint);
|
moduleData->setEntrypoint(module_data->entrypoint);
|
||||||
moduleData.setStartAddress(module_data->startAddress);
|
moduleData->setStartAddress(module_data->startAddress);
|
||||||
moduleData.setEndAddress(module_data->endAddress);
|
moduleData->setEndAddress(module_data->endAddress);
|
||||||
moduleData.setExportName(module_data->module_export_name);
|
moduleData->setExportName(module_data->module_export_name);
|
||||||
moduleData.setSkipEntrypoint(module_data->skipEntrypoint);
|
moduleData->setSkipEntrypoint(module_data->skipEntrypoint);
|
||||||
moduleData.setInitBeforeRelocationDoneHook(module_data->initBeforeRelocationDoneHook);
|
moduleData->setInitBeforeRelocationDoneHook(module_data->initBeforeRelocationDoneHook);
|
||||||
|
|
||||||
for (auto &export_entrie: module_data->export_entries) {
|
for (auto &export_entrie: module_data->export_entries) {
|
||||||
export_data_t *export_entry = &export_entrie;
|
export_data_t *export_entry = &export_entrie;
|
||||||
if (export_entry->address == 0) {
|
if (export_entry->address == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
moduleData.addExportData(ExportData(static_cast<wums_entry_type_t>(export_entry->type), export_entry->name, reinterpret_cast<const void *>(export_entry->address)));
|
auto exportData = std::make_shared<ExportData>(static_cast<wums_entry_type_t>(export_entry->type), export_entry->name, reinterpret_cast<const void *>(export_entry->address));
|
||||||
|
moduleData->addExportData(exportData);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &hook_entry: module_data->hook_entries) {
|
for (auto &hook_entry: module_data->hook_entries) {
|
||||||
if (hook_entry.target == 0) {
|
if (hook_entry.target == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
moduleData.addHookData(HookData(static_cast<wums_hook_type_t>(hook_entry.type), reinterpret_cast<const void *>(hook_entry.target)));
|
auto hookData = std::make_shared<HookData>(static_cast<wums_hook_type_t>(hook_entry.type), reinterpret_cast<const void *>(hook_entry.target));
|
||||||
|
moduleData->addHookData(hookData);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &linking_entry: module_data->linking_entries) {
|
for (auto &linking_entry: module_data->linking_entries) {
|
||||||
@ -161,16 +162,17 @@ std::vector<ModuleData> ModuleDataPersistence::loadModuleData(module_information
|
|||||||
DEBUG_FUNCTION_LINE("functionEntry was NULL, skipping relocation entry\n");
|
DEBUG_FUNCTION_LINE("functionEntry was NULL, skipping relocation entry\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ImportRPLInformation rplInfo(importEntry->importName, importEntry->isData);
|
auto rplInfo = std::make_shared<ImportRPLInformation>(importEntry->importName, importEntry->isData);
|
||||||
RelocationData reloc(linking_entry.type, linking_entry.offset, linking_entry.addend, linking_entry.destination, functionEntry->functionName, rplInfo);
|
auto reloc = std::make_shared<RelocationData>(linking_entry.type, linking_entry.offset, linking_entry.addend, linking_entry.destination, functionEntry->functionName, rplInfo);
|
||||||
|
|
||||||
moduleData.addRelocationData(reloc);
|
moduleData->addRelocationData(reloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (module_data->function_symbol_entries != nullptr && module_data->number_used_function_symbols > 0) {
|
if (module_data->function_symbol_entries != nullptr && module_data->number_used_function_symbols > 0) {
|
||||||
for (uint32_t j = 0; j < module_data->number_used_function_symbols; j++) {
|
for (uint32_t j = 0; j < module_data->number_used_function_symbols; j++) {
|
||||||
auto symbol = &module_data->function_symbol_entries[j];
|
auto symbol = &module_data->function_symbol_entries[j];
|
||||||
moduleData.addFunctionSymbolData(FunctionSymbolData(symbol->name, symbol->address, symbol->size));
|
auto functionSymbolData = std::make_shared<FunctionSymbolData>(symbol->name, symbol->address, symbol->size);
|
||||||
|
moduleData->addFunctionSymbolData(functionSymbolData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.push_back(moduleData);
|
result.push_back(moduleData);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
class ModuleDataPersistence {
|
class ModuleDataPersistence {
|
||||||
public:
|
public:
|
||||||
static bool saveModuleData(module_information_t *moduleInformation, const ModuleData &module);
|
static bool saveModuleData(module_information_t *moduleInformation, const std::shared_ptr<ModuleData> &module);
|
||||||
|
|
||||||
static std::vector<ModuleData> loadModuleData(module_information_t *moduleInformation);
|
static std::vector<std::shared_ptr<ModuleData>> loadModuleData(module_information_t *moduleInformation);
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
#include "utils/StringTools.h"
|
#include "utils/StringTools.h"
|
||||||
|
|
||||||
std::string RelocationData::toString() const {
|
std::string RelocationData::toString() const {
|
||||||
return StringTools::strfmt("%s destination: %08X offset: %08X type: %02X addend: %d rplName: %s isData: %d \n", name.c_str(), destination, offset, type, addend, rplInfo.getName().c_str(),
|
return StringTools::strfmt("%s destination: %08X offset: %08X type: %02X addend: %d rplName: %s isData: %d \n", name.c_str(), destination, offset, type, addend, rplInfo->getName().c_str(),
|
||||||
rplInfo.isData());
|
rplInfo->isData());
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
#include "ImportRPLInformation.h"
|
#include "ImportRPLInformation.h"
|
||||||
|
|
||||||
class RelocationData {
|
class RelocationData {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RelocationData(char type, size_t offset, int32_t addend, void *destination, std::string name, const ImportRPLInformation &rplInfo) : rplInfo(rplInfo) {
|
RelocationData(char type, size_t offset, int32_t addend, void *destination, std::string name, std::shared_ptr<ImportRPLInformation> rplInfo) : rplInfo(std::move(rplInfo)) {
|
||||||
this->type = type;
|
this->type = type;
|
||||||
this->offset = offset;
|
this->offset = offset;
|
||||||
this->addend = addend;
|
this->addend = addend;
|
||||||
this->destination = destination;
|
this->destination = destination;
|
||||||
this->name = name;
|
this->name = std::move(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
~RelocationData() = default;
|
~RelocationData() = default;
|
||||||
@ -53,7 +55,7 @@ public:
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] ImportRPLInformation getImportRPLInformation() const {
|
[[nodiscard]] std::shared_ptr<ImportRPLInformation> getImportRPLInformation() const {
|
||||||
return rplInfo;
|
return rplInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,5 +67,5 @@ private:
|
|||||||
int32_t addend;
|
int32_t addend;
|
||||||
void *destination;
|
void *destination;
|
||||||
std::string name;
|
std::string name;
|
||||||
const ImportRPLInformation rplInfo;
|
const std::shared_ptr<ImportRPLInformation> rplInfo;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user