#include "prx/libkernel_sys/include/Api.hpp" #include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libkernel/KernelErrors.hpp" #include #include #include #include #include #include #include static void Require(bool value) { if (!value) std::abort(); } static std::vector List(int (APS5_VABI* list)(KernelModule*, std::size_t, std::size_t*)) { std::vector handles(256, -1); std::size_t count = 0; Require(list(handles.data(), handles.size(), &count) == 0); Require(count > 0 && count < handles.size()); handles.resize(count); return handles; } static void CheckList() { const auto internal = List(sceKernelGetModuleListInternal); Require(internal == List(sceKernelGetModuleList)); std::vector shorter(internal.size(), -1); std::size_t untouched = 99; Require(sceKernelGetModuleListInternal(shorter.data(), internal.size() - 1, &untouched) == SCE_KERNEL_ERROR_ENOMEM); Require(untouched == 99 && shorter.back() == -1); Require(sceKernelGetModuleListInternal(nullptr, 0, &untouched) == SCE_KERNEL_ERROR_EFAULT); Require(sceKernelGetModuleListInternal(shorter.data(), shorter.size(), nullptr) == SCE_KERNEL_ERROR_EFAULT); } static void CheckEachModule() { for (const auto handle : List(sceKernelGetModuleListInternal)) { ModuleInfoEx extended{}; extended.st_size = sizeof(ModuleInfoEx); Require(sceKernelGetModuleInfoInternal(handle, &extended) == 0); ModuleInfo basic{}; basic.st_size = sizeof(ModuleInfo); Require(sceKernelGetModuleInfo(handle, &basic) == 0); Require(extended.st_size == sizeof(ModuleInfoEx) && extended.id == handle); Require(std::string(extended.name) == basic.name && extended.segment_count == basic.segment_count); for (std::uint32_t i = 0; i < basic.segment_count; ++i) Require(extended.segments[i].address == basic.segments[i].address && extended.segments[i].size == basic.segments[i].size && extended.segments[i].prot == basic.segments[i].prot); } } static void CheckMatchesAddressLookup() { ModuleInfoEx byAddress{}; byAddress.st_size = sizeof(ModuleInfoEx); Require(sceKernelGetModuleInfoFromAddr(reinterpret_cast(&sceKernelGetModuleInfo), 1, &byAddress) == 0); ModuleInfoEx byHandle{}; byHandle.st_size = sizeof(ModuleInfoEx); Require(sceKernelGetModuleInfoInternal(byAddress.id, &byHandle) == 0); Require(byAddress.st_size == 0 && byHandle.st_size == sizeof(ModuleInfoEx)); Require(std::memcmp(byHandle.name, byAddress.name, sizeof(ModuleInfoEx) - offsetof(ModuleInfoEx, name)) == 0); } static void CheckRefusals() { const auto handle = List(sceKernelGetModuleListInternal).front(); for (const std::uint64_t size : {0x160, 0x1a4, 0x1b0, 0}) { ModuleInfoEx sized{}; sized.st_size = size; sized.name[0] = 'x'; Require(sceKernelGetModuleInfoInternal(handle, &sized) == SCE_KERNEL_ERROR_EINVAL); Require(sized.st_size == size && sized.name[0] == 'x'); } Require(sceKernelGetModuleInfoInternal(handle, nullptr) == SCE_KERNEL_ERROR_EFAULT); ModuleInfoEx unknown{}; unknown.st_size = sizeof(ModuleInfoEx); Require(sceKernelGetModuleInfoInternal(-1, &unknown) == SCE_KERNEL_ERROR_ESRCH && unknown.name[0] == '\0'); } int main() { CheckList(); CheckEachModule(); CheckMatchesAddressLookup(); CheckRefusals(); return 0; }