mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-25 12:26:51 +01:00
Load packaged system modules through the native module lifecycle
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef EMULATOR_SRC_KERNEL_MODULE_H_
|
||||||
|
#define EMULATOR_SRC_KERNEL_MODULE_H_
|
||||||
|
|
||||||
|
#include "common/abi.h"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace Libs::LibKernel {
|
||||||
|
|
||||||
|
using KernelModule = int32_t;
|
||||||
|
struct KernelLoadModuleOpt;
|
||||||
|
struct KernelUnloadModuleOpt;
|
||||||
|
|
||||||
|
KernelModule KYTY_SYSV_ABI KernelLoadStartModule(const char* module_file_name, size_t args,
|
||||||
|
const void* argp, uint32_t flags,
|
||||||
|
const KernelLoadModuleOpt* opt, int* res);
|
||||||
|
int KYTY_SYSV_ABI KernelStopUnloadModule(KernelModule handle, size_t args, const void* argp,
|
||||||
|
uint32_t flags, const KernelUnloadModuleOpt* opt,
|
||||||
|
int* res);
|
||||||
|
|
||||||
|
} // namespace Libs::LibKernel
|
||||||
|
|
||||||
|
#endif // EMULATOR_SRC_KERNEL_MODULE_H_
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "kernel/eventQueue.h"
|
#include "kernel/eventQueue.h"
|
||||||
#include "kernel/fileSystem.h"
|
#include "kernel/fileSystem.h"
|
||||||
#include "kernel/memory.h"
|
#include "kernel/memory.h"
|
||||||
|
#include "kernel/module.h"
|
||||||
#include "kernel/pthread.h"
|
#include "kernel/pthread.h"
|
||||||
#include "kernel/semaphore.h"
|
#include "kernel/semaphore.h"
|
||||||
#include "kernel/syncOnAddress.h"
|
#include "kernel/syncOnAddress.h"
|
||||||
@@ -65,7 +66,6 @@ LIB_DEFINE(InitLibKernel_1_Apr);
|
|||||||
|
|
||||||
namespace LibKernel {
|
namespace LibKernel {
|
||||||
|
|
||||||
using KernelModule = int32_t;
|
|
||||||
using get_thread_atexit_count_func_t = KYTY_SYSV_ABI int (*)(KernelModule);
|
using get_thread_atexit_count_func_t = KYTY_SYSV_ABI int (*)(KernelModule);
|
||||||
using thread_atexit_report_func_t = KYTY_SYSV_ABI void (*)(KernelModule);
|
using thread_atexit_report_func_t = KYTY_SYSV_ABI void (*)(KernelModule);
|
||||||
|
|
||||||
@@ -1201,9 +1201,9 @@ static int KYTY_SYSV_ABI KernelRaiseException(Pthread thread, int signum) {
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static KYTY_SYSV_ABI KernelModule KernelLoadStartModule(const char* module_file_name, size_t args,
|
KernelModule KYTY_SYSV_ABI KernelLoadStartModule(const char* module_file_name, size_t args,
|
||||||
const void* argp, uint32_t flags,
|
const void* argp, uint32_t flags,
|
||||||
const KernelLoadModuleOpt* opt, int* res) {
|
const KernelLoadModuleOpt* opt, int* res) {
|
||||||
PRINT_NAME();
|
PRINT_NAME();
|
||||||
|
|
||||||
// EXIT_NOT_IMPLEMENTED(!Common::Thread::IsMainThread());
|
// EXIT_NOT_IMPLEMENTED(!Common::Thread::IsMainThread());
|
||||||
@@ -1255,9 +1255,9 @@ static KYTY_SYSV_ABI KernelModule KernelLoadStartModule(const char* module_file_
|
|||||||
return static_cast<KernelModule>(handle);
|
return static_cast<KernelModule>(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int KYTY_SYSV_ABI KernelStopUnloadModule(KernelModule handle, size_t args, const void* argp,
|
int KYTY_SYSV_ABI KernelStopUnloadModule(KernelModule handle, size_t args, const void* argp,
|
||||||
uint32_t flags, const KernelUnloadModuleOpt* opt,
|
uint32_t flags, const KernelUnloadModuleOpt* opt,
|
||||||
int* res) {
|
int* res) {
|
||||||
PRINT_NAME();
|
PRINT_NAME();
|
||||||
|
|
||||||
// EXIT_NOT_IMPLEMENTED(!Common::Thread::IsMainThread());
|
// EXIT_NOT_IMPLEMENTED(!Common::Thread::IsMainThread());
|
||||||
|
|||||||
+47
-16
@@ -3,6 +3,7 @@
|
|||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/stringUtils.h"
|
#include "common/stringUtils.h"
|
||||||
|
#include "kernel/module.h"
|
||||||
#include "libs/libs.h"
|
#include "libs/libs.h"
|
||||||
#include "loader/symbolDatabase.h"
|
#include "loader/symbolDatabase.h"
|
||||||
|
|
||||||
@@ -20,14 +21,40 @@ int KYTY_SYSV_ABI KernelGetModuleInfoForUnwind(uint64_t addr, int flags, ModuleI
|
|||||||
|
|
||||||
namespace Sysmodule {
|
namespace Sysmodule {
|
||||||
|
|
||||||
constexpr int SYSMODULE_ERROR_UNLOADED = static_cast<int>(0x805a1001u);
|
constexpr int SYSMODULE_ERROR_UNLOADED = static_cast<int>(0x805a1001u);
|
||||||
|
constexpr int SYSMODULE_ERROR_FATAL = static_cast<int>(0x805a10ffu);
|
||||||
|
|
||||||
static std::mutex g_module_mutex;
|
static constexpr struct NativeModule {
|
||||||
static std::unordered_map<uint16_t, uint32_t> g_module_refs;
|
uint16_t id;
|
||||||
|
const char* path;
|
||||||
|
} g_native_modules[] = {{0x0115, "/app0/sce_module/libSceNpCppWebApi.prx"}};
|
||||||
|
|
||||||
static void LoadModule(uint16_t id) {
|
struct Module {
|
||||||
|
uint32_t references = 0;
|
||||||
|
LibKernel::KernelModule handle = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::mutex g_module_mutex;
|
||||||
|
static std::unordered_map<uint16_t, Module> g_modules;
|
||||||
|
|
||||||
|
static int LoadModule(uint16_t id) {
|
||||||
std::scoped_lock lock(g_module_mutex);
|
std::scoped_lock lock(g_module_mutex);
|
||||||
++g_module_refs[id];
|
if (const auto module = g_modules.find(id); module != g_modules.end()) {
|
||||||
|
++module->second.references;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LibKernel::KernelModule handle = -1;
|
||||||
|
for (const auto& module: g_native_modules) {
|
||||||
|
if (module.id != id) continue;
|
||||||
|
handle = LibKernel::KernelLoadStartModule(module.path, 0, nullptr, 0, nullptr, nullptr);
|
||||||
|
if (handle < 0) {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_modules.emplace(id, Module {1, handle});
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static KYTY_SYSV_ABI int SysmoduleGetModuleInfoForUnwind(uint64_t addr, int flags,
|
static KYTY_SYSV_ABI int SysmoduleGetModuleInfoForUnwind(uint64_t addr, int flags,
|
||||||
@@ -40,8 +67,7 @@ static KYTY_SYSV_ABI int SysmoduleLoadModule(uint16_t id) {
|
|||||||
|
|
||||||
LOGF("\t id = %d\n", static_cast<int>(id));
|
LOGF("\t id = %d\n", static_cast<int>(id));
|
||||||
|
|
||||||
LoadModule(id);
|
return LoadModule(id);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static KYTY_SYSV_ABI int SysmoduleUnloadModule(uint16_t id) {
|
static KYTY_SYSV_ABI int SysmoduleUnloadModule(uint16_t id) {
|
||||||
@@ -50,12 +76,19 @@ static KYTY_SYSV_ABI int SysmoduleUnloadModule(uint16_t id) {
|
|||||||
LOGF("\t id = %d\n", static_cast<int>(id));
|
LOGF("\t id = %d\n", static_cast<int>(id));
|
||||||
|
|
||||||
std::scoped_lock lock(g_module_mutex);
|
std::scoped_lock lock(g_module_mutex);
|
||||||
const auto module = g_module_refs.find(id);
|
const auto module = g_modules.find(id);
|
||||||
if (module == g_module_refs.end()) {
|
if (module == g_modules.end()) {
|
||||||
return SYSMODULE_ERROR_UNLOADED;
|
return SYSMODULE_ERROR_UNLOADED;
|
||||||
}
|
}
|
||||||
if (--module->second == 0) {
|
if (module->second.references == 1) {
|
||||||
g_module_refs.erase(module);
|
if (module->second.handle >= 0 &&
|
||||||
|
LibKernel::KernelStopUnloadModule(module->second.handle, 0, nullptr, 0, nullptr,
|
||||||
|
nullptr) < 0) {
|
||||||
|
return SYSMODULE_ERROR_FATAL;
|
||||||
|
}
|
||||||
|
g_modules.erase(id);
|
||||||
|
} else {
|
||||||
|
--module->second.references;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -71,10 +104,8 @@ static KYTY_SYSV_ABI int SysmoduleLoadModuleInternalWithArg(uint16_t id, int arg
|
|||||||
EXIT_IF(arg3 != 0);
|
EXIT_IF(arg3 != 0);
|
||||||
EXIT_IF(ret == nullptr);
|
EXIT_IF(ret == nullptr);
|
||||||
|
|
||||||
LoadModule(id);
|
*ret = LoadModule(id);
|
||||||
*ret = 0;
|
return *ret;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static KYTY_SYSV_ABI int SysmoduleIsLoaded(uint16_t id) {
|
static KYTY_SYSV_ABI int SysmoduleIsLoaded(uint16_t id) {
|
||||||
@@ -83,7 +114,7 @@ static KYTY_SYSV_ABI int SysmoduleIsLoaded(uint16_t id) {
|
|||||||
LOGF("\t id = %d\n", static_cast<int>(id));
|
LOGF("\t id = %d\n", static_cast<int>(id));
|
||||||
|
|
||||||
std::scoped_lock lock(g_module_mutex);
|
std::scoped_lock lock(g_module_mutex);
|
||||||
return g_module_refs.contains(id) ? 0 : SYSMODULE_ERROR_UNLOADED;
|
return g_modules.contains(id) ? 0 : SYSMODULE_ERROR_UNLOADED;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Sysmodule
|
} // namespace Sysmodule
|
||||||
|
|||||||
@@ -235,6 +235,9 @@ void TestSysmoduleReferences() {
|
|||||||
const auto unload = resolve("eR2bZFAAU0Q");
|
const auto unload = resolve("eR2bZFAAU0Q");
|
||||||
const auto is_loaded = resolve("fMP5NHUOaMk");
|
const auto is_loaded = resolve("fMP5NHUOaMk");
|
||||||
constexpr int unloaded = static_cast<int>(0x805a1001u);
|
constexpr int unloaded = static_cast<int>(0x805a1001u);
|
||||||
|
Check(load(0x115) == Libs::LibKernel::KERNEL_ERROR_ENOENT && is_loaded(0x115) == unloaded &&
|
||||||
|
unload(0x115) == unloaded,
|
||||||
|
"missing packaged NpCppWebApi fails without recording a loaded module");
|
||||||
Check(load(0x113) == OK && is_loaded(0xb4) == unloaded,
|
Check(load(0x113) == OK && is_loaded(0xb4) == unloaded,
|
||||||
"loading entitlement access does not mark AppContent loaded");
|
"loading entitlement access does not mark AppContent loaded");
|
||||||
Check(unload(0x113) == OK, "release independent module reference");
|
Check(unload(0x113) == OK, "release independent module reference");
|
||||||
@@ -255,6 +258,9 @@ void TestSysmoduleReferences() {
|
|||||||
reinterpret_cast<int (KYTY_SYSV_ABI *)(uint16_t, int, int, int, int*)>(
|
reinterpret_cast<int (KYTY_SYSV_ABI *)(uint16_t, int, int, int, int*)>(
|
||||||
internal_symbol->vaddr);
|
internal_symbol->vaddr);
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
Check(internal_load(0x115, 0, 0, 0, &result) == Libs::LibKernel::KERNEL_ERROR_ENOENT &&
|
||||||
|
result == Libs::LibKernel::KERNEL_ERROR_ENOENT && is_loaded(0x115) == unloaded,
|
||||||
|
"internal module loading propagates missing native module failure");
|
||||||
Check(internal_load(0xb4, 0, 0, 0, &result) == OK && result == OK &&
|
Check(internal_load(0xb4, 0, 0, 0, &result) == OK && result == OK &&
|
||||||
is_loaded(0xb4) == OK && unload(0xb4) == OK && is_loaded(0xb4) == unloaded,
|
is_loaded(0xb4) == OK && unload(0xb4) == OK && is_loaded(0xb4) == unloaded,
|
||||||
"internal and public module operations share load state");
|
"internal and public module operations share load state");
|
||||||
|
|||||||
Reference in New Issue
Block a user