2020-04-28 14:43:07 +02:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <coreinit/dynload.h>
|
|
|
|
#include <coreinit/cache.h>
|
|
|
|
#include <nsysnet/socket.h>
|
2020-05-17 13:14:19 +02:00
|
|
|
#include <coreinit/memorymap.h>
|
|
|
|
#include <map>
|
2020-04-29 12:05:39 +02:00
|
|
|
#include "../../source/common/dynamic_linking_defines.h"
|
|
|
|
#include "../../source/common/module_defines.h"
|
2020-04-29 12:35:13 +02:00
|
|
|
#include "../../source/module/RelocationData.h"
|
|
|
|
#include "../../source/module/ModuleData.h"
|
2020-04-28 14:43:07 +02:00
|
|
|
#include "ModuleDataPersistence.h"
|
|
|
|
#include "ElfUtils.h"
|
2020-04-29 12:05:39 +02:00
|
|
|
#include "../../source/common/relocation_defines.h"
|
2020-05-17 13:14:19 +02:00
|
|
|
#include "kernel/kernel_utils.h"
|
|
|
|
#include "hooks_patcher_static.h"
|
2020-04-28 14:43:07 +02:00
|
|
|
|
2020-04-29 12:35:13 +02:00
|
|
|
#include "utils/logger.h"
|
|
|
|
#include "utils/dynamic.h"
|
2020-04-28 14:43:07 +02:00
|
|
|
|
2020-04-29 11:43:45 +02:00
|
|
|
#define gModuleData ((module_information_t *) (0x00880000))
|
2020-04-28 14:43:07 +02:00
|
|
|
|
2020-05-17 13:14:19 +02:00
|
|
|
uint8_t gFunctionsPatched __attribute__((section(".data"))) = 0;
|
|
|
|
|
2020-04-28 14:43:07 +02:00
|
|
|
extern "C" void doStart(int argc, char **argv);
|
|
|
|
// We need to wrap it to make sure the main function is called AFTER our code.
|
|
|
|
// The compiler tries to optimize this otherwise and calling the main function earlier
|
|
|
|
extern "C" int _start(int argc, char **argv) {
|
|
|
|
InitFunctionPointers();
|
|
|
|
socket_lib_init();
|
|
|
|
log_init();
|
2020-05-17 13:11:52 +02:00
|
|
|
|
2020-05-17 19:05:51 +02:00
|
|
|
doStart(argc, argv);
|
2020-04-28 14:43:07 +02:00
|
|
|
|
|
|
|
DEBUG_FUNCTION_LINE("Call real one\n");
|
2020-05-17 19:05:51 +02:00
|
|
|
return ((int (*)(int, char **)) (*(unsigned int *) 0x1005E040))(argc, argv);
|
2020-04-28 14:43:07 +02:00
|
|
|
}
|
|
|
|
|
2020-05-17 19:05:51 +02:00
|
|
|
bool doRelocation(std::vector<RelocationData> &relocData, relocation_trampolin_entry_t *tramp_data, uint32_t tramp_length) {
|
|
|
|
std::map<std::string, OSDynLoad_Module> moduleCache;
|
|
|
|
for (auto const &curReloc : relocData) {
|
2020-05-17 13:11:52 +02:00
|
|
|
std::string functionName = curReloc.getName();
|
|
|
|
std::string rplName = curReloc.getImportRPLInformation().getName();
|
|
|
|
int32_t isData = curReloc.getImportRPLInformation().isData();
|
2020-04-28 14:43:07 +02:00
|
|
|
OSDynLoad_Module rplHandle = 0;
|
2020-05-17 19:05:51 +02:00
|
|
|
if (moduleCache.count(rplName) == 0) {
|
2020-05-17 13:14:19 +02:00
|
|
|
OSDynLoad_Acquire(rplName.c_str(), &rplHandle);
|
|
|
|
moduleCache[rplName] = rplHandle;
|
|
|
|
}
|
|
|
|
rplHandle = moduleCache.at(rplName);
|
2020-04-28 14:43:07 +02:00
|
|
|
uint32_t functionAddress = 0;
|
2020-05-28 21:45:44 +02:00
|
|
|
|
2020-05-17 19:05:51 +02:00
|
|
|
OSDynLoad_FindExport(rplHandle, isData, functionName.c_str(), (void **) &functionAddress);
|
|
|
|
if (functionAddress == 0) {
|
2020-05-28 20:26:02 +02:00
|
|
|
OSFatal_printf("Failed to find export %s of %s", functionName.c_str(), rplName.c_str());
|
2020-04-28 14:43:07 +02:00
|
|
|
return false;
|
|
|
|
}
|
2020-05-17 19:05:51 +02:00
|
|
|
if (!ElfUtils::elfLinkOne(curReloc.getType(), curReloc.getOffset(), curReloc.getAddend(), (uint32_t) curReloc.getDestination(), functionAddress, tramp_data, tramp_length, RELOC_TYPE_IMPORT)) {
|
2020-04-28 14:43:07 +02:00
|
|
|
DEBUG_FUNCTION_LINE("Relocation failed\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DCFlushRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t));
|
|
|
|
ICInvalidateRange(tramp_data, tramp_length * sizeof(relocation_trampolin_entry_t));
|
|
|
|
return true;
|
|
|
|
}
|
2020-05-17 19:05:51 +02:00
|
|
|
|
2020-04-28 14:43:07 +02:00
|
|
|
bool ResolveRelocations() {
|
2020-05-17 13:11:52 +02:00
|
|
|
std::vector<ModuleData> loadedModules = ModuleDataPersistence::loadModuleData(gModuleData);
|
2020-04-28 14:43:07 +02:00
|
|
|
bool wasSuccessful = true;
|
|
|
|
uint32_t count = 0;
|
2020-05-17 19:05:51 +02:00
|
|
|
for (auto const &curModule : loadedModules) {
|
|
|
|
if (wasSuccessful) {
|
2020-05-17 13:11:52 +02:00
|
|
|
std::vector<RelocationData> relocData = curModule.getRelocationDataList();
|
2020-05-17 19:05:51 +02:00
|
|
|
if (!doRelocation(relocData, gModuleData->trampolines, DYN_LINK_TRAMPOLIN_LIST_LENGTH)) {
|
2020-04-28 14:43:07 +02:00
|
|
|
DEBUG_FUNCTION_LINE("FAIL\n");
|
|
|
|
wasSuccessful = false;
|
|
|
|
}
|
|
|
|
}
|
2020-05-17 19:05:51 +02:00
|
|
|
if (curModule.getBSSAddr() != 0) {
|
2020-05-17 13:11:52 +02:00
|
|
|
DEBUG_FUNCTION_LINE("memset .bss %08X (%d)\n", curModule.getBSSAddr(), curModule.getBSSSize());
|
2020-05-17 19:05:51 +02:00
|
|
|
memset((void *) curModule.getBSSAddr(), 0, curModule.getBSSSize());
|
2020-04-28 14:43:07 +02:00
|
|
|
}
|
2020-05-17 19:05:51 +02:00
|
|
|
if (curModule.getSBSSAddr() != 0) {
|
2020-05-17 13:11:52 +02:00
|
|
|
DEBUG_FUNCTION_LINE("memset .sbss %08X (%d)\n", curModule.getSBSSAddr(), curModule.getSBSSSize());
|
2020-05-17 19:05:51 +02:00
|
|
|
memset((void *) curModule.getSBSSAddr(), 0, curModule.getSBSSSize());
|
2020-04-28 14:43:07 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-17 19:05:51 +02:00
|
|
|
if (count > 0) {
|
|
|
|
DCFlushRange((void *) 0x00800000, 0x00800000);
|
|
|
|
ICInvalidateRange((void *) 0x00800000, 0x00800000);
|
2020-04-28 14:43:07 +02:00
|
|
|
}
|
|
|
|
return wasSuccessful;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void doStart(int argc, char **argv) {
|
2020-05-17 19:05:51 +02:00
|
|
|
if (!gFunctionsPatched) {
|
2020-05-17 13:14:19 +02:00
|
|
|
gFunctionsPatched = 1;
|
|
|
|
kernelInitialize();
|
|
|
|
PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static);
|
|
|
|
}
|
2020-04-29 12:06:47 +02:00
|
|
|
DEBUG_FUNCTION_LINE("Resolve relocations\n");
|
|
|
|
DEBUG_FUNCTION_LINE("Number of modules %d\n", gModuleData->number_used_modules);
|
2020-04-28 14:43:07 +02:00
|
|
|
ResolveRelocations();
|
2020-05-17 19:05:51 +02:00
|
|
|
for (int i = 0; i < gModuleData->number_used_modules; i++) {
|
|
|
|
DEBUG_FUNCTION_LINE("About to call %08X\n", gModuleData->module_data[i].entrypoint);
|
|
|
|
int ret = ((int (*)(int, char **)) (gModuleData->module_data[i].entrypoint))(argc, argv);
|
2020-04-28 14:43:07 +02:00
|
|
|
DEBUG_FUNCTION_LINE("return code was %d\n", ret);
|
|
|
|
}
|
|
|
|
}
|