From 5d230cb542b4cfd69c9be8b924e79f53cfcf4a25 Mon Sep 17 00:00:00 2001 From: raphaelthegreat <47210458+raphaelthegreat@users.noreply.github.com> Date: Wed, 5 Jun 2024 20:50:02 +0300 Subject: [PATCH] kernel: Implement module loading * Now it's easy to do anyway with new module rework --- src/core/libraries/kernel/libkernel.cpp | 38 +++++++++++++++++++ src/core/linker.cpp | 2 + src/core/loader/symbols_resolver.cpp | 4 +- src/core/loader/symbols_resolver.h | 1 + src/core/module.cpp | 6 +-- src/core/module.h | 13 ++++++- src/core/tls.cpp | 6 ++- .../renderer_vulkan/vk_rasterizer.cpp | 1 - .../renderer_vulkan/vk_rasterizer.h | 1 - .../texture_cache/texture_cache.cpp | 2 +- 10 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index 96f7c429d..a215fcb4e 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -6,6 +6,7 @@ #include "common/assert.h" #include "common/logging/log.h" #include "common/singleton.h" +#include "core/file_sys/fs.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/cpu_management.h" #include "core/libraries/kernel/event_flag/event_flag.h" @@ -199,6 +200,41 @@ s64 PS4_SYSV_ABI ps4__read(int d, void* buf, u64 nbytes) { strlen(std::fgets(static_cast(buf), static_cast(nbytes), stdin))); } +s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, size_t args, const void* argp, + u32 flags, const void* pOpt, int* pRes) { + LOG_INFO(Lib_Kernel, "called filename = {}, args = {}", moduleFileName, args); + + if (flags != 0) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + + auto* mnt = Common::Singleton::Instance(); + const auto path = mnt->GetHostFile(moduleFileName); + + // Load PRX module. + auto* linker = Common::Singleton::Instance(); + u32 handle = linker->LoadModule(path); + auto* module = linker->GetModule(handle); + linker->Relocate(module); + + // Retrieve and verify proc param according to libkernel. + u64* param = module->GetProcParam(); + ASSERT_MSG(!param || param[0] >= 0x18, "Invalid module param size: {}", param[0]); + module->Start(args, argp, param); + + return handle; +} + +s32 PS4_SYSV_ABI sceKernelDlsym(s32 handle, const char* symbol, void** addrp) { + auto* linker = Common::Singleton::Instance(); + auto* module = linker->GetModule(handle); + *addrp = module->FindByName(symbol); + if (*addrp == nullptr) { + return ORBIS_KERNEL_ERROR_ESRCH; + } + return ORBIS_OK; +} + void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { // obj LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); @@ -216,6 +252,8 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("IWIBBdTHit4", "libkernel", 1, "libkernel", 1, 1, sceKernelMapFlexibleMemory); LIB_FUNCTION("p5EcQeEeJAE", "libkernel", 1, "libkernel", 1, 1, _sceKernelRtldSetApplicationHeapAPI); + LIB_FUNCTION("wzvqT4UqKX8", "libkernel", 1, "libkernel", 1, 1, sceKernelLoadStartModule); + LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym); // equeue LIB_FUNCTION("D0OdFMjp46I", "libkernel", 1, "libkernel", 1, 1, sceKernelCreateEqueue); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 8cae916d8..7867b1807 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -252,6 +252,8 @@ void Linker::Resolve(const std::string& name, Loader::SymbolType sym_type, Modul } void* Linker::TlsGetAddr(u64 module_index, u64 offset) { + std::scoped_lock lk{mutex}; + DtvEntry* dtv_table = GetTcbBase()->tcb_dtv; ASSERT_MSG(dtv_table[0].counter == dtv_generation_counter, "Reallocation of DTV table is not supported"); diff --git a/src/core/loader/symbols_resolver.cpp b/src/core/loader/symbols_resolver.cpp index 9a8c95845..0b09a0201 100644 --- a/src/core/loader/symbols_resolver.cpp +++ b/src/core/loader/symbols_resolver.cpp @@ -11,9 +11,7 @@ namespace Core::Loader { void SymbolsResolver::AddSymbol(const SymbolResolver& s, u64 virtual_addr) { - SymbolRecord& r = m_symbols.emplace_back(); - r.name = GenerateName(s); - r.virtual_address = virtual_addr; + m_symbols.emplace_back(GenerateName(s), s.nidName, virtual_addr); } std::string SymbolsResolver::GenerateName(const SymbolResolver& s) { diff --git a/src/core/loader/symbols_resolver.h b/src/core/loader/symbols_resolver.h index 4feb32668..80ea46f2e 100644 --- a/src/core/loader/symbols_resolver.h +++ b/src/core/loader/symbols_resolver.h @@ -21,6 +21,7 @@ enum class SymbolType { struct SymbolRecord { std::string name; + std::string nid_name; u64 virtual_address; }; diff --git a/src/core/module.cpp b/src/core/module.cpp index cb266a2f3..102fbe1be 100644 --- a/src/core/module.cpp +++ b/src/core/module.cpp @@ -13,7 +13,7 @@ namespace Core { -using EntryFunc = PS4_SYSV_ABI int (*)(size_t args, const void* argp, ModuleFunc func); +using EntryFunc = PS4_SYSV_ABI int (*)(size_t args, const void* argp, void* param); static u64 LoadAddress = SYSTEM_RESERVED + CODE_BASE_OFFSET; static constexpr u64 CODE_BASE_INCR = 0x010000000u; @@ -64,10 +64,10 @@ Module::Module(const std::filesystem::path& file_) : file{file_} { Module::~Module() = default; -void Module::Start(size_t args, const void* argp, ModuleFunc func) { +void Module::Start(size_t args, const void* argp, void* param) { LOG_INFO(Core_Linker, "Module started : {}", file.filename().string()); const VAddr addr = dynamic_info.init_virtual_addr + GetBaseAddress(); - reinterpret_cast(addr)(args, argp, func); + reinterpret_cast(addr)(args, argp, param); } void Module::LoadModuleToMemory() { diff --git a/src/core/module.h b/src/core/module.h index 34feab412..bb11439eb 100644 --- a/src/core/module.h +++ b/src/core/module.h @@ -119,8 +119,17 @@ public: return elf.IsSharedLib(); } + void* FindByName(std::string_view name) { + const auto symbols = export_sym.GetSymbols(); + const auto it = std::ranges::find(symbols, name, &Loader::SymbolRecord::nid_name); + if (it != symbols.end()) { + return reinterpret_cast(it->virtual_address); + } + return nullptr; + } + template - const T GetProcParam() const noexcept { + T GetProcParam() const noexcept { return reinterpret_cast(proc_param_virtual_addr); } @@ -149,7 +158,7 @@ public: } } - void Start(size_t args, const void* argp, ModuleFunc func); + void Start(size_t args, const void* argp, void* param); void LoadModuleToMemory(); void LoadDynamicInfo(); void LoadSymbols(); diff --git a/src/core/tls.cpp b/src/core/tls.cpp index de0ba9bfd..151477882 100644 --- a/src/core/tls.cpp +++ b/src/core/tls.cpp @@ -135,7 +135,11 @@ void PatchTLS(u64 segment_addr, u64 segment_size, Xbyak::CodeGenerator& c) { #else -void SetTLSStorage(u64 image_address) { +void SetTcbBase(void* image_address) { + UNREACHABLE_MSG("Thread local storage is unimplemented on posix platforms!"); +} + +Tcb* GetTcbBase() { UNREACHABLE_MSG("Thread local storage is unimplemented on posix platforms!"); } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index e3b38ca48..37d6f72b5 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -85,7 +85,6 @@ void Rasterizer::Draw(bool is_indexed) { } void Rasterizer::DispatchDirect() { - compute_done = true; return; const auto cmdbuf = scheduler.CommandBuffer(); const auto& cs_program = liverpool->regs.cs_program; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 8f365f658..a1b6a5a66 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -49,7 +49,6 @@ private: Core::MemoryManager* memory; PipelineCache pipeline_cache; StreamBuffer vertex_index_buffer; - bool compute_done{}; }; } // namespace Vulkan diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 3e2a7deaf..26e70dbed 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -58,7 +58,7 @@ LONG WINAPI GuestFaultSignalHandler(EXCEPTION_POINTERS* pExp) noexcept { } #endif -static constexpr u64 StreamBufferSize = 128_MB; +static constexpr u64 StreamBufferSize = 512_MB; static constexpr u64 PageShift = 12; TextureCache::TextureCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_)