AnyPS5/core/libs/prx/libSceSysmodule/Export.cpp

173 lines
5.3 KiB
C++

#include <cstdint>
#include <cstring>
#include <mutex>
#include <stdexcept>
#include <string>
#include <unordered_map>
#ifdef _WIN32
#include <windows.h>
#include <psapi.h>
#else
#include "prx/libc/include/specifics/linux/HostMapping.hpp"
#endif
#include "SceTypes.hpp"
#include "ModuleTable.hpp"
#include "prx/libc/include/General.hpp"
namespace {
constexpr int SCE_SYSMODULE_ERROR_UNLOADED = static_cast<int>(0x805A1001);
const char* findModuleName(const std::uint32_t id) {
const auto it = kModuleTable.find(id);
return it != kModuleTable.end() ? it->second : nullptr;
}
std::mutex gMutex;
std::unordered_map<std::uint32_t, std::int32_t> gLoadCount;
bool fillModuleInfoForUnwind(std::uint64_t addr, ModuleInfoForUnwind* info) {
#ifdef _WIN32
MEMORY_BASIC_INFORMATION mbi{};
if (!VirtualQuery(reinterpret_cast<LPCVOID>(addr), &mbi, sizeof(mbi))) {
return false;
}
info->st_size = sizeof(ModuleInfoForUnwind);
info->eh_frame_hdr_addr = 0;
info->eh_frame_addr = 0;
info->eh_frame_size = 0;
info->seg0_addr = reinterpret_cast<std::uint64_t>(mbi.BaseAddress);
info->seg0_size = mbi.RegionSize;
char path[4096] = {};
DWORD len = GetMappedFileNameA(GetCurrentProcess(), mbi.BaseAddress, path, sizeof(path) - 1);
path[len] = '\0';
std::strncpy(info->name, path, sizeof(info->name) - 1);
info->name[sizeof(info->name) - 1] = '\0';
return true;
#else
const auto mapping = HostMapping::Find(addr, "sceSysmoduleGetModuleInfoForUnwind");
if (!mapping) {
return false;
}
info->st_size = sizeof(ModuleInfoForUnwind);
std::strncpy(info->name, mapping->path.c_str(), sizeof(info->name) - 1);
info->name[sizeof(info->name) - 1] = '\0';
info->eh_frame_hdr_addr = 0;
info->eh_frame_addr = 0;
info->eh_frame_size = 0;
info->seg0_addr = mapping->start;
info->seg0_size = mapping->end - mapping->start;
return true;
#endif
}
}
extern "C" {
int APS5_VABI sceSysmoduleGetModuleInfoForUnwind(std::uint64_t addr, int flags, ModuleInfoForUnwind* info) {
(void)flags;
if (!fillModuleInfoForUnwind(addr, info)) {
throw std::runtime_error("sceSysmoduleGetModuleInfoForUnwind: address not found");
}
return 0;
}
int APS5_VABI sceSysmoduleIsLoaded(std::uint16_t id) {
if (id == 0) {
throw std::runtime_error("sceSysmoduleIsLoaded: invalid id 0");
}
if (!findModuleName(id)) {
APS5_LOG_OUT("unknown id: %u", static_cast<unsigned>(id));
// throw std::runtime_error(std::string("sceSysmoduleIsLoaded: unknown id ") + std::to_string(id));
return 0;
}
std::lock_guard<std::mutex> lock(gMutex);
auto it = gLoadCount.find(id);
if (it == gLoadCount.end() || it->second < 1) {
return SCE_SYSMODULE_ERROR_UNLOADED;
}
return 0;
}
int APS5_VABI sceSysmoduleLoadModule(std::uint16_t id) {
if (id == 0) {
throw std::runtime_error("sceSysmoduleLoadModule: invalid id 0");
}
if (!findModuleName(id)) {
APS5_LOG_OUT("unknown id: %u", static_cast<unsigned>(id));
// throw std::runtime_error(std::string("sceSysmoduleLoadModule: unknown id ") + std::to_string(id));
return 0;
}
std::lock_guard<std::mutex> lock(gMutex);
gLoadCount[id]++;
return 0;
}
int APS5_VABI sceSysmoduleLoadModuleInternalWithArg(std::uint32_t id, int argc, void* argv, std::uint64_t unk, int* ret) {
(void)argc;
(void)argv;
(void)unk;
if ((id & 0x7fffffffu) == 0) {
throw std::runtime_error("sceSysmoduleLoadModuleInternalWithArg: invalid id 0");
}
if (!findModuleName(id)) {
throw std::runtime_error(std::string("sceSysmoduleLoadModuleInternalWithArg: unknown id ") + std::to_string(id));
}
std::lock_guard<std::mutex> lock(gMutex);
gLoadCount[id]++;
if (ret) {
*ret = 0;
}
return 0;
}
int APS5_VABI sceSysmoduleUnloadModule(std::uint16_t id) {
if (id == 0) {
throw std::runtime_error("sceSysmoduleUnloadModule: invalid id 0");
}
if (!findModuleName(id)) {
APS5_LOG_OUT("unknown id: %u", static_cast<unsigned>(id));
return 0;
}
std::lock_guard<std::mutex> lock(gMutex);
auto it = gLoadCount.find(id);
if (it == gLoadCount.end() || it->second < 1) {
return SCE_SYSMODULE_ERROR_UNLOADED;
}
it->second--;
return 0;
}
int APS5_VABI sceSysmoduleLoadModuleInternal(std::uint32_t id) {
if ((id & 0x7fffffffu) == 0) {
throw std::runtime_error("sceSysmoduleLoadModuleInternal: invalid id 0");
}
if (!findModuleName(id)) {
throw std::runtime_error(std::string("sceSysmoduleLoadModuleInternal: unknown id ") + std::to_string(id));
}
std::lock_guard<std::mutex> lock(gMutex);
gLoadCount[id]++;
return 0;
}
int APS5_VABI sceSysmoduleUnloadModuleInternal(std::uint32_t id) {
if ((id & 0x7fffffffu) == 0) {
throw std::runtime_error("sceSysmoduleUnloadModuleInternal: invalid id 0");
}
if (!findModuleName(id)) {
throw std::runtime_error(std::string("sceSysmoduleUnloadModuleInternal: unknown id ") + std::to_string(id));
}
std::lock_guard<std::mutex> lock(gMutex);
auto it = gLoadCount.find(id);
if (it == gLoadCount.end() || it->second < 1) {
return SCE_SYSMODULE_ERROR_UNLOADED;
}
it->second--;
return 0;
}
}