kernel: Implement module loading

* Now it's easy to do anyway with new module rework
This commit is contained in:
raphaelthegreat 2024-06-05 20:50:02 +03:00
parent dcaedc89a0
commit 5d230cb542
10 changed files with 62 additions and 12 deletions

View File

@ -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<char*>(buf), static_cast<int>(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<Core::FileSys::MntPoints>::Instance();
const auto path = mnt->GetHostFile(moduleFileName);
// Load PRX module.
auto* linker = Common::Singleton<Core::Linker>::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<u64*>();
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<Core::Linker>::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);

View File

@ -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");

View File

@ -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) {

View File

@ -21,6 +21,7 @@ enum class SymbolType {
struct SymbolRecord {
std::string name;
std::string nid_name;
u64 virtual_address;
};

View File

@ -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<EntryFunc>(addr)(args, argp, func);
reinterpret_cast<EntryFunc>(addr)(args, argp, param);
}
void Module::LoadModuleToMemory() {

View File

@ -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<void*>(it->virtual_address);
}
return nullptr;
}
template <typename T = VAddr>
const T GetProcParam() const noexcept {
T GetProcParam() const noexcept {
return reinterpret_cast<T>(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();

View File

@ -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!");
}

View File

@ -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;

View File

@ -49,7 +49,6 @@ private:
Core::MemoryManager* memory;
PipelineCache pipeline_cache;
StreamBuffer vertex_index_buffer;
bool compute_done{};
};
} // namespace Vulkan

View File

@ -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_)