#include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include #include extern "C" { void* APS5_VABI dlopen_nid_postfix(const char*, int); void* APS5_VABI dlsym_nid_postfix(void*, const char*); int APS5_VABI dlclose_nid_postfix(void*); char* APS5_VABI dlerror_nid_postfix(); int APS5_VABI _sceKernelRtldThreadAtexitIncrement_nid_postfix(const void*); int APS5_VABI _sceKernelRtldThreadAtexitDecrement_nid_postfix(const void*); } static void Require(bool value) { if (!value) std::abort(); } template static bool ThrowsRuntimeError(TFunction function) { try { function(); } catch (const std::runtime_error&) { return true; } return false; } int main(int argc, char** argv) { Require(argc == 2); Require(dlerror_nid_postfix() == nullptr); Require(dlopen_nid_postfix(argv[1], 0x2000) == nullptr); Require(dlerror_nid_postfix() != nullptr); Require(dlerror_nid_postfix() == nullptr); Require(dlopen_nid_postfix("anyps5-missing-module-for-test.prx", 2) == nullptr); Require(dlerror_nid_postfix() != nullptr); void* executable = dlopen_nid_postfix(nullptr, 2); Require(executable != nullptr && dlclose_nid_postfix(executable) == 0); void* module = dlopen_nid_postfix(argv[1], 2 | 0x100); Require(module != nullptr); using Add = int (APS5_VABI *)(int, int); auto add = reinterpret_cast(dlsym_nid_postfix(module, "GuestModuleAdd")); Require(add && add(17, 25) == 42); Require(dlsym_nid_postfix(reinterpret_cast(-2), "GuestModuleAdd") == reinterpret_cast(add)); #ifndef _WIN32 auto mul = reinterpret_cast(dlsym_nid_postfix(module, "GuestModuleMul")); Require(mul && mul(6, 7) == 42); auto sub = reinterpret_cast(dlsym_nid_postfix(module, "GuestModuleSub")); Require(sub && sub(50, 8) == 42); #endif Require(dlsym_nid_postfix(module, "missing_symbol") == nullptr); std::thread other([] { Require(dlerror_nid_postfix() == nullptr); }); other.join(); Require(dlerror_nid_postfix() != nullptr); Require(dlerror_nid_postfix() == nullptr); void* second = dlopen_nid_postfix(argv[1], 1); Require(second && second != module); Require(dlclose_nid_postfix(module) == 0); Require(dlsym_nid_postfix(module, "GuestModuleAdd") == nullptr); add = reinterpret_cast(dlsym_nid_postfix(second, "GuestModuleAdd")); Require(add && add(2, 3) == 5); Require(dlclose_nid_postfix(second) == 0); Require(dlclose_nid_postfix(second) == -1); const std::filesystem::path guest = "anyps5-relinked-module-for-test.prx"; auto relinked = guest; relinked += ".guest.prx"; { std::ofstream elf(guest, std::ios::binary); elf.write("\x7f" "ELF", 4); } std::filesystem::copy_file(argv[1], relinked, std::filesystem::copy_options::overwrite_existing); void* redirected = dlopen_nid_postfix(guest.string().c_str(), 2); Require(redirected != nullptr); add = reinterpret_cast(dlsym_nid_postfix(redirected, "GuestModuleAdd")); Require(add && add(40, 2) == 42); Require(dlclose_nid_postfix(redirected) == 0); std::filesystem::remove(guest); std::filesystem::remove(relinked); void* pinned = dlopen_nid_postfix(argv[1], 2); add = reinterpret_cast(dlsym_nid_postfix(pinned, "GuestModuleAdd")); Require(add && _sceKernelRtldThreadAtexitIncrement_nid_postfix(reinterpret_cast(add)) == 0); Require(_sceKernelRtldThreadAtexitIncrement_nid_postfix(reinterpret_cast(add)) == 0); Require(dlclose_nid_postfix(pinned) == 0); Require(add(20, 22) == 42); Require(_sceKernelRtldThreadAtexitDecrement_nid_postfix(reinterpret_cast(add)) == 0); Require(add(40, 2) == 42); Require(_sceKernelRtldThreadAtexitDecrement_nid_postfix(reinterpret_cast(add)) == 0); Require(_sceKernelRtldThreadAtexitIncrement_nid_postfix(reinterpret_cast(&ThrowsRuntimeError)) == 0); Require(_sceKernelRtldThreadAtexitDecrement_nid_postfix(reinterpret_cast(&ThrowsRuntimeError)) == 0); Require(ThrowsRuntimeError([] { _sceKernelRtldThreadAtexitDecrement_nid_postfix(reinterpret_cast(&Require)); })); int local = 0; Require(ThrowsRuntimeError([&] { _sceKernelRtldThreadAtexitIncrement_nid_postfix(&local); })); }