mirror of
https://github.com/Inori/GPCS4.git
synced 2024-06-02 19:38:19 -04:00
Improved module system (#59)
* Add a couple of new components for module system * Bridge new code * Add some docs. * Remove old code * Docs and Naming * Add symbol source log * Minor changes
This commit is contained in:
parent
6244e15907
commit
a675be9384
|
@ -31,7 +31,7 @@ void CEmulator::Unit()
|
|||
modManager->clearModules();
|
||||
}
|
||||
|
||||
bool CEmulator::Run(MemoryMappedModule const &mod)
|
||||
bool CEmulator::Run(NativeModule const &mod)
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
|
|
|
@ -20,21 +20,13 @@ public:
|
|||
|
||||
void Unit();
|
||||
|
||||
bool LoadEboot(const std::string& strEbtPath);
|
||||
|
||||
bool Run();
|
||||
|
||||
bool Run(MemoryMappedModule const &mod);
|
||||
bool Run(NativeModule const &mod);
|
||||
|
||||
private:
|
||||
bool registerModules();
|
||||
|
||||
bool registerLibC(CSceModuleSystem* pModuleSystem);
|
||||
bool registerLibKernel(CSceModuleSystem* pModuleSystem);
|
||||
|
||||
static void PS4API LastExitHandler(void);
|
||||
private:
|
||||
//CEbootObject m_oEboot;
|
||||
std::shared_ptr<CLinker> m_pLinker;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,35 +8,8 @@ LOG_CHANNEL(Linker);
|
|||
|
||||
CLinker::CLinker() : m_modSystem{*CSceModuleSystem::GetInstance()} {}
|
||||
|
||||
bool CLinker::ResolveSymbol(const std::string &strModName,
|
||||
const std::string &strLibName,
|
||||
uint64_t nNid,
|
||||
void **ppAddress) const
|
||||
{
|
||||
bool bRet = false;
|
||||
do
|
||||
{
|
||||
if (!ppAddress)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
void *pFunc = CSceModuleSystem::GetInstance()->findFunction(
|
||||
strModName, strLibName, nNid);
|
||||
if (!pFunc)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*ppAddress = pFunc;
|
||||
|
||||
bRet = true;
|
||||
} while (false);
|
||||
return bRet;
|
||||
}
|
||||
|
||||
// resolveSymbol always returns true
|
||||
bool CLinker::resolveSymbol(MemoryMappedModule const &mod,
|
||||
bool CLinker::resolveSymbol(NativeModule const &mod,
|
||||
std::string const &name,
|
||||
uint64_t *addrOut) const
|
||||
{
|
||||
|
@ -45,8 +18,8 @@ bool CLinker::resolveSymbol(MemoryMappedModule const &mod,
|
|||
do
|
||||
{
|
||||
const SymbolInfo *info = nullptr;
|
||||
void *address = nullptr;
|
||||
bool overridden = false;
|
||||
void *address = nullptr;
|
||||
bool useNative = false;
|
||||
|
||||
if (addrOut == nullptr)
|
||||
{
|
||||
|
@ -63,22 +36,33 @@ bool CLinker::resolveSymbol(MemoryMappedModule const &mod,
|
|||
|
||||
if (!info->isEncoded)
|
||||
{
|
||||
address = m_modSystem.findSymbol(info->moduleName, info->libraryName,
|
||||
info->symbolName);
|
||||
address = getSymbolAddress(info->moduleName,
|
||||
info->libraryName,
|
||||
info->symbolName);
|
||||
|
||||
auto policy = m_modSystem.getSymbolPolicy(info->moduleName,
|
||||
info->libraryName,
|
||||
info->symbolName);
|
||||
|
||||
useNative = (policy == Policy::UseNative);
|
||||
}
|
||||
else
|
||||
{
|
||||
address = m_modSystem.findFunction(info->moduleName, info->libraryName,
|
||||
info->nid);
|
||||
address = getSymbolAddress(info->moduleName,
|
||||
info->libraryName,
|
||||
info->nid);
|
||||
|
||||
// overridden == true, means the function is native
|
||||
overridden = m_modSystem.isFunctionOverridable(info->moduleName,
|
||||
info->libraryName,
|
||||
info->nid);
|
||||
auto policy = m_modSystem.getSymbolPolicy(info->moduleName,
|
||||
info->libraryName,
|
||||
info->nid);
|
||||
|
||||
useNative = (policy == Policy::UseNative);
|
||||
}
|
||||
|
||||
LOG_ERR_IF(address == nullptr, "fail to resolve symbol: %s from %s for module %s",
|
||||
name.c_str(), info->moduleName.c_str(), mod.fileName.c_str());
|
||||
const char* source = useNative? "NATIVE":"BUILTIN";
|
||||
|
||||
LOG_ERR_IF(address == nullptr, "fail to resolve symbol: %s[%s] from %s for module %s",
|
||||
name.c_str(), source, info->moduleName.c_str(), mod.fileName.c_str());
|
||||
|
||||
#ifdef MODSYS_STUB_DISABLE
|
||||
|
||||
|
@ -90,12 +74,12 @@ bool CLinker::resolveSymbol(MemoryMappedModule const &mod,
|
|||
|
||||
#else // MODSYS_STUB_DISABLE
|
||||
|
||||
if (address != nullptr && !overridden)
|
||||
if (address != nullptr && !useNative)
|
||||
{
|
||||
// builtin function
|
||||
*addrOut = reinterpret_cast<uint64_t>(address);
|
||||
}
|
||||
else if (address != nullptr && overridden)
|
||||
else if (address != nullptr && useNative)
|
||||
{
|
||||
// native function
|
||||
|
||||
|
@ -168,7 +152,7 @@ void* CLinker::generateStubFunction(const SymbolInfo* sybInfo, void* oldFunc) co
|
|||
|
||||
bool CLinker::relocateModules()
|
||||
{
|
||||
auto &mods = m_modSystem.getMemoryMappedModules();
|
||||
auto &mods = m_modSystem.getAllNativeModules();
|
||||
bool retVal = false;
|
||||
|
||||
for (auto &mod : mods)
|
||||
|
@ -184,7 +168,33 @@ bool CLinker::relocateModules()
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool CLinker::relocateModule(MemoryMappedModule &mod)
|
||||
void* CLinker::getSymbolAddress(std::string const& modName,
|
||||
std::string const& libName,
|
||||
uint64_t nid) const
|
||||
{
|
||||
auto pointer = m_modSystem.getSymbolAddress(modName, libName, nid);
|
||||
return const_cast<void*>(pointer);
|
||||
}
|
||||
|
||||
void* CLinker::getSymbolAddress(std::string const& modName, std::string const& libName, std::string const& symbName) const
|
||||
{
|
||||
auto symbolManager = m_modSystem.getSymbolManager();
|
||||
auto policy = m_modSystem.getSymbolPolicy(modName, libName, symbName);
|
||||
const void* pointer = nullptr;
|
||||
|
||||
if (policy == Policy::UseBuiltin)
|
||||
{
|
||||
pointer = symbolManager.findBuiltinSymbol(modName, libName, symbName);
|
||||
}
|
||||
else // Policy::UseNative
|
||||
{
|
||||
pointer = symbolManager.findNativeSymbol(modName, libName, symbName);
|
||||
}
|
||||
|
||||
return const_cast<void*>(pointer);
|
||||
}
|
||||
|
||||
bool CLinker::relocateModule(NativeModule& mod)
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
|
@ -196,7 +206,7 @@ bool CLinker::relocateModule(MemoryMappedModule &mod)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool CLinker::relocateRela(MemoryMappedModule &mod)
|
||||
bool CLinker::relocateRela(NativeModule &mod)
|
||||
{
|
||||
bool retVal = false;
|
||||
do
|
||||
|
@ -293,7 +303,7 @@ bool CLinker::relocateRela(MemoryMappedModule &mod)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool CLinker::relocatePltRela(MemoryMappedModule &mod)
|
||||
bool CLinker::relocatePltRela(NativeModule &mod)
|
||||
{
|
||||
bool bRet = false;
|
||||
do
|
||||
|
|
|
@ -11,21 +11,18 @@ public:
|
|||
CLinker();
|
||||
CLinker(CSceModuleSystem &modSystem) : m_modSystem{modSystem} {};
|
||||
|
||||
bool ResolveSymbol(const std::string &strModName,
|
||||
const std::string &strLibName,
|
||||
uint64_t nNid,
|
||||
void **ppAddress) const;
|
||||
|
||||
bool resolveSymbol(MemoryMappedModule const &mod,
|
||||
bool resolveSymbol(NativeModule const &mod,
|
||||
std::string const &name,
|
||||
uint64_t *addr) const;
|
||||
|
||||
bool relocateModules();
|
||||
|
||||
private:
|
||||
bool relocateModule(MemoryMappedModule &mod);
|
||||
bool relocateRela(MemoryMappedModule &mod);
|
||||
bool relocatePltRela(MemoryMappedModule &mod);
|
||||
void* getSymbolAddress(std::string const &modName, std::string const& libName, uint64_t nid) const;
|
||||
void* getSymbolAddress(std::string const& modName, std::string const& libName, std::string const& symbName) const;
|
||||
bool relocateModule(NativeModule &mod);
|
||||
bool relocateRela(NativeModule &mod);
|
||||
bool relocatePltRela(NativeModule &mod);
|
||||
void* generateStubFunction(const SymbolInfo* sybInfo, void* oldFunc) const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -8,40 +8,40 @@
|
|||
|
||||
LOG_CHANNEL(Module);
|
||||
|
||||
const MODULE_INFO &MemoryMappedModule::getModuleInfo() const { return m_moduleInfo; }
|
||||
MODULE_INFO &MemoryMappedModule::getModuleInfo() { return m_moduleInfo; }
|
||||
const MODULE_INFO &NativeModule::getModuleInfo() const { return m_moduleInfo; }
|
||||
MODULE_INFO &NativeModule::getModuleInfo() { return m_moduleInfo; }
|
||||
|
||||
const ByteArray &MemoryMappedModule::getFileMemory() const { return m_fileMemory; }
|
||||
ByteArray &MemoryMappedModule::getFileMemory() { return m_fileMemory; }
|
||||
const ByteArray &NativeModule::getFileMemory() const { return m_fileMemory; }
|
||||
ByteArray &NativeModule::getFileMemory() { return m_fileMemory; }
|
||||
|
||||
bool MemoryMappedModule::isModule() const
|
||||
bool NativeModule::isModule() const
|
||||
{
|
||||
return m_elfHeader->e_type == ET_SCE_DYNAMIC ? true : false;
|
||||
}
|
||||
|
||||
const FileList &MemoryMappedModule::getNeededFiles() const { return m_neededFiles; }
|
||||
const FileList &NativeModule::getNeededFiles() const { return m_neededFiles; }
|
||||
|
||||
const std::vector<size_t> &MemoryMappedModule::getExportSymbols() const
|
||||
const std::vector<size_t> &NativeModule::getExportSymbols() const
|
||||
{
|
||||
return m_exportSymbols;
|
||||
}
|
||||
|
||||
std::vector<size_t> &MemoryMappedModule::getExportSymbols()
|
||||
std::vector<size_t> &NativeModule::getExportSymbols()
|
||||
{
|
||||
return m_exportSymbols;
|
||||
}
|
||||
|
||||
const UtilMemory::memory_uptr &MemoryMappedModule::getMappedMemory() const
|
||||
const UtilMemory::memory_uptr &NativeModule::getMappedMemory() const
|
||||
{
|
||||
return m_mappedMemory;
|
||||
}
|
||||
|
||||
UtilMemory::memory_uptr &MemoryMappedModule::getMappedMemory()
|
||||
UtilMemory::memory_uptr &NativeModule::getMappedMemory()
|
||||
{
|
||||
return m_mappedMemory;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getImportSymbolInfo(std::string const &encSymbol,
|
||||
bool NativeModule::getImportSymbolInfo(std::string const &encSymbol,
|
||||
std::string *modName,
|
||||
std::string *libName,
|
||||
uint64_t *nid) const
|
||||
|
@ -50,7 +50,7 @@ bool MemoryMappedModule::getImportSymbolInfo(std::string const &encSymbol,
|
|||
libName, nid);
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getExportSymbolInfo(std::string const &encSymbol,
|
||||
bool NativeModule::getExportSymbolInfo(std::string const &encSymbol,
|
||||
std::string *modName,
|
||||
std::string *libName,
|
||||
uint64_t *nid) const
|
||||
|
@ -59,7 +59,7 @@ bool MemoryMappedModule::getExportSymbolInfo(std::string const &encSymbol,
|
|||
libName, nid);
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getSymbol(std::string const &encName,
|
||||
bool NativeModule::getSymbol(std::string const &encName,
|
||||
SymbolInfo const **symbolInfo) const
|
||||
{
|
||||
bool retVal = false;
|
||||
|
@ -77,7 +77,7 @@ bool MemoryMappedModule::getSymbol(std::string const &encName,
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getSymbolInfo(std::string const &encSymbol,
|
||||
bool NativeModule::getSymbolInfo(std::string const &encSymbol,
|
||||
ModuleList const &mods,
|
||||
LibraryList const &libs,
|
||||
std::string *modName,
|
||||
|
@ -132,7 +132,7 @@ bool MemoryMappedModule::getSymbolInfo(std::string const &encSymbol,
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getModNameFromId(uint64_t id,
|
||||
bool NativeModule::getModNameFromId(uint64_t id,
|
||||
ModuleList const &mods,
|
||||
std::string *modName) const
|
||||
{
|
||||
|
@ -161,7 +161,7 @@ bool MemoryMappedModule::getModNameFromId(uint64_t id,
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getLibNameFromId(uint64_t id,
|
||||
bool NativeModule::getLibNameFromId(uint64_t id,
|
||||
LibraryList const &libs,
|
||||
std::string *libName) const
|
||||
{
|
||||
|
@ -191,7 +191,7 @@ bool MemoryMappedModule::getLibNameFromId(uint64_t id,
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::decodeValue(std::string const &encodedStr,
|
||||
bool NativeModule::decodeValue(std::string const &encodedStr,
|
||||
uint64_t &value) const
|
||||
{
|
||||
bool bRet = false;
|
||||
|
@ -252,7 +252,7 @@ bool MemoryMappedModule::decodeValue(std::string const &encodedStr,
|
|||
return bRet;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::decodeSymbol(std::string const &strEncName,
|
||||
bool NativeModule::decodeSymbol(std::string const &strEncName,
|
||||
uint32_t *modId,
|
||||
uint32_t *libId,
|
||||
uint64_t *funcNid) const
|
||||
|
@ -301,7 +301,7 @@ bool MemoryMappedModule::decodeSymbol(std::string const &strEncName,
|
|||
return bRet;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::isEncodedSymbol(std::string const &symbolName) const
|
||||
bool NativeModule::isEncodedSymbol(std::string const &symbolName) const
|
||||
{
|
||||
bool retVal = false;
|
||||
if (symbolName.length() != 15)
|
||||
|
@ -320,7 +320,7 @@ bool MemoryMappedModule::isEncodedSymbol(std::string const &symbolName) const
|
|||
return retVal;
|
||||
}
|
||||
|
||||
int MemoryMappedModule::initialize()
|
||||
int NativeModule::initialize()
|
||||
{
|
||||
int retVal = 0;
|
||||
|
||||
|
@ -336,7 +336,7 @@ int MemoryMappedModule::initialize()
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getTLSInfo(void **pTls,
|
||||
bool NativeModule::getTLSInfo(void **pTls,
|
||||
uint32_t *initSize,
|
||||
uint32_t *totalSize,
|
||||
uint32_t *align) const
|
||||
|
@ -361,9 +361,9 @@ bool MemoryMappedModule::getTLSInfo(void **pTls,
|
|||
return retVal;
|
||||
}
|
||||
|
||||
void *MemoryMappedModule::getEntryPoint() const { return m_moduleInfo.pEntryPoint; }
|
||||
void *NativeModule::getEntryPoint() const { return m_moduleInfo.pEntryPoint; }
|
||||
|
||||
bool MemoryMappedModule::getSymbol(size_t index, SymbolInfo const **symbolInfo) const
|
||||
bool NativeModule::getSymbol(size_t index, SymbolInfo const **symbolInfo) const
|
||||
{
|
||||
bool retVal = false;
|
||||
if (index > m_symbols.size() - 1)
|
||||
|
@ -379,7 +379,7 @@ bool MemoryMappedModule::getSymbol(size_t index, SymbolInfo const **symbolInfo)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getImportSymbols(SymbolList *importSymbols) const
|
||||
bool NativeModule::getImportSymbols(SymbolList *importSymbols) const
|
||||
{
|
||||
LOG_ASSERT(importSymbols != nullptr, "%s", "null pointer error");
|
||||
|
||||
|
@ -391,7 +391,7 @@ bool MemoryMappedModule::getImportSymbols(SymbolList *importSymbols) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getExportSymbols(SymbolList *exportSymbols) const
|
||||
bool NativeModule::getExportSymbols(SymbolList *exportSymbols) const
|
||||
{
|
||||
LOG_ASSERT(exportSymbols != nullptr, "%s", "null pointer error");
|
||||
|
||||
|
@ -403,7 +403,7 @@ bool MemoryMappedModule::getExportSymbols(SymbolList *exportSymbols) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::getUnresolvedSymbols(SymbolList *symbolList) const
|
||||
bool NativeModule::getUnresolvedSymbols(SymbolList *symbolList) const
|
||||
{
|
||||
LOG_ASSERT(symbolList != nullptr, "%s", "null pointer error");
|
||||
auto modSystem = CSceModuleSystem::GetInstance();
|
||||
|
@ -411,9 +411,9 @@ bool MemoryMappedModule::getUnresolvedSymbols(SymbolList *symbolList) const
|
|||
for (auto index : m_importSymbols)
|
||||
{
|
||||
auto &symbol = m_symbols[index];
|
||||
auto addr = modSystem->findFunction(symbol.moduleName,
|
||||
symbol.libraryName,
|
||||
symbol.nid);
|
||||
auto addr = modSystem->getSymbolAddress(symbol.moduleName,
|
||||
symbol.libraryName,
|
||||
symbol.nid);
|
||||
if (addr == nullptr)
|
||||
{
|
||||
symbolList->emplace_back(symbol);
|
||||
|
@ -423,7 +423,7 @@ bool MemoryMappedModule::getUnresolvedSymbols(SymbolList *symbolList) const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MemoryMappedModule::outputUnresolvedSymbols(std::string const &fileName) const
|
||||
bool NativeModule::outputUnresolvedSymbols(std::string const &fileName) const
|
||||
{
|
||||
bool retVal = false;
|
||||
do
|
||||
|
|
|
@ -133,7 +133,7 @@ using SymbolAddrMap = std::map<std::string, void *>;
|
|||
using ByteArray = std::vector<uint8_t>;
|
||||
|
||||
class ELFMapper;
|
||||
struct MemoryMappedModule
|
||||
struct NativeModule
|
||||
{
|
||||
friend ELFMapper;
|
||||
|
||||
|
|
59
GPCS4/Emulator/ModuleManger.cpp
Normal file
59
GPCS4/Emulator/ModuleManger.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "Util/UtilContainer.h"
|
||||
#include "ModuleManger.h"
|
||||
|
||||
void ModuleManager::registerBuiltinModule(std::string const& modName)
|
||||
{
|
||||
m_builtinModules.emplace_back(modName);
|
||||
}
|
||||
|
||||
void ModuleManager::registerNativeModule(std::string const& modName,
|
||||
NativeModule&& mod)
|
||||
{
|
||||
auto index = m_nativeModules.size();
|
||||
|
||||
m_nativeModuleNameIndexMap.emplace(std::make_pair(modName, index));
|
||||
m_nativeModules.emplace_back(std::move(mod));
|
||||
}
|
||||
|
||||
bool ModuleManager::isBuiltinModuleDefined(std::string const& modName) const
|
||||
{
|
||||
return util::contains(m_builtinModules, modName);
|
||||
}
|
||||
|
||||
bool ModuleManager::isNativeModuleLoaded(std::string const& modName)
|
||||
{
|
||||
return util::contains(m_nativeModuleNameIndexMap, modName);
|
||||
}
|
||||
|
||||
bool ModuleManager::getNativeModule(std::string const& modName,
|
||||
NativeModule** modOut)
|
||||
{
|
||||
bool ret = false;
|
||||
do
|
||||
{
|
||||
auto iter = m_nativeModuleNameIndexMap.find(modName);
|
||||
if (iter == m_nativeModuleNameIndexMap.end())
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
auto &mod = m_nativeModules.at(iter->second);
|
||||
*modOut = &mod;
|
||||
ret = true;
|
||||
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<NativeModule>& ModuleManager::getNativeModules()
|
||||
{
|
||||
return m_nativeModules;
|
||||
}
|
||||
const std::vector<NativeModule>& ModuleManager::getNativeModules() const
|
||||
{
|
||||
return m_nativeModules;
|
||||
}
|
||||
|
||||
|
26
GPCS4/Emulator/ModuleManger.h
Normal file
26
GPCS4/Emulator/ModuleManger.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
#include "Module.h"
|
||||
|
||||
struct SCE_EXPORT_FUNCTION;
|
||||
struct SCE_EXPORT_LIBRARY;
|
||||
struct SCE_EXPORT_MODULE;
|
||||
|
||||
class ModuleManager
|
||||
{
|
||||
public:
|
||||
void registerBuiltinModule(std::string const &modName);
|
||||
void registerNativeModule(std::string const& modName, NativeModule&& mod);
|
||||
|
||||
bool isBuiltinModuleDefined(std::string const& modName) const;
|
||||
|
||||
bool isNativeModuleLoaded(std::string const& modName);
|
||||
bool getNativeModule(std::string const& modName, NativeModule** modOut);
|
||||
std::vector<NativeModule>& getNativeModules();
|
||||
|
||||
const std::vector<NativeModule>& getNativeModules() const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_builtinModules;
|
||||
std::vector<NativeModule> m_nativeModules;
|
||||
std::map<std::string, uint64_t> m_nativeModuleNameIndexMap;
|
||||
};
|
311
GPCS4/Emulator/PolicyManager.cpp
Normal file
311
GPCS4/Emulator/PolicyManager.cpp
Normal file
|
@ -0,0 +1,311 @@
|
|||
#include "GPCS4Common.h"
|
||||
|
||||
#include "Util/UtilContainer.h"
|
||||
#include "PolicyManager.h"
|
||||
|
||||
|
||||
void LibraryPolicy::excludeSymbol(uint64_t nid)
|
||||
{
|
||||
auto pair = std::make_pair(nid, true);
|
||||
m_excludeNids.insert(pair);
|
||||
}
|
||||
|
||||
|
||||
void LibraryPolicy::excludeSymbol(std::string const &name)
|
||||
{
|
||||
m_excludeNames.insert(std::make_pair(name, true));
|
||||
}
|
||||
|
||||
void LibraryPolicy::setPolicy(Policy policy)
|
||||
{
|
||||
m_policy = policy;
|
||||
}
|
||||
|
||||
|
||||
Policy LibraryPolicy::getSymbolPolicy(uint64_t nid) const
|
||||
{
|
||||
Policy ret = Policy::UseBuiltin;
|
||||
do
|
||||
{
|
||||
if (m_policy == Policy::UseBuiltin)
|
||||
{
|
||||
if (util::contains(m_excludeNids, nid))
|
||||
{
|
||||
ret = Policy::UseNative;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = Policy::UseBuiltin;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (util::contains(m_excludeNids, nid))
|
||||
{
|
||||
ret = Policy::UseBuiltin;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = Policy::UseNative;
|
||||
}
|
||||
}
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Policy LibraryPolicy::getSymoblPolicy(std::string const& name) const
|
||||
{
|
||||
Policy ret = Policy::UseBuiltin;
|
||||
do
|
||||
{
|
||||
if (m_policy == Policy::UseBuiltin)
|
||||
{
|
||||
if (util::contains(m_excludeNames, name))
|
||||
{
|
||||
ret = Policy::UseNative;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = Policy::UseBuiltin;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (util::contains(m_excludeNames, name))
|
||||
{
|
||||
ret = Policy::UseBuiltin;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = Policy::UseNative;
|
||||
}
|
||||
}
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
LibraryPolicy& ModulePolicy::addLibraryPolicy(std::string const & name,
|
||||
LibraryPolicy && lp)
|
||||
{
|
||||
m_libPolicyTable.emplace(std::make_pair(name, std::move(lp)));
|
||||
return m_libPolicyTable.at(name);
|
||||
}
|
||||
|
||||
bool ModulePolicy::getLibraryPolicy(std::string const & name,
|
||||
const LibraryPolicy ** p) const
|
||||
{
|
||||
bool ret = false;
|
||||
do {
|
||||
auto lib = m_libPolicyTable.find(name);
|
||||
if (lib == m_libPolicyTable.end())
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p = &lib->second;
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ModulePolicy::setPolicy(Policy policy)
|
||||
{
|
||||
m_policy = policy;
|
||||
}
|
||||
|
||||
Policy ModulePolicy::getPolicy() const
|
||||
{
|
||||
return m_policy;
|
||||
}
|
||||
|
||||
|
||||
PolicyManager::PolicyManager(ModuleManager& modMgr):
|
||||
m_modManager{modMgr}
|
||||
{
|
||||
}
|
||||
|
||||
bool PolicyManager::isModuleLoadable(std::string const &modName) const
|
||||
{
|
||||
bool ret = false;
|
||||
do
|
||||
{
|
||||
if (m_useNativeImplsWhenBuiltinModuleNotDefined &&
|
||||
!m_modManager.isBuiltinModuleDefined(modName))
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_defaultPolicy == Policy::UseNative)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (util::contains(m_modPolicyTable, modName))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Policy PolicyManager::getModulePolicy(std::string const& modName) const
|
||||
{
|
||||
Policy ret = m_defaultPolicy;
|
||||
do
|
||||
{
|
||||
auto modIter = m_modPolicyTable.find(modName);
|
||||
if (modIter == m_modPolicyTable.end())
|
||||
{
|
||||
if (m_useNativeImplsWhenBuiltinModuleNotDefined &&
|
||||
!m_modManager.isBuiltinModuleDefined(modName))
|
||||
{
|
||||
ret = Policy::UseNative;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = m_defaultPolicy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = modIter->second.getPolicy();
|
||||
break;
|
||||
}
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Policy PolicyManager::getSymbolPolicy(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid) const
|
||||
{
|
||||
Policy ret = m_defaultPolicy;
|
||||
do
|
||||
{
|
||||
auto modIter = m_modPolicyTable.find(modName);
|
||||
if (modIter == m_modPolicyTable.end())
|
||||
{
|
||||
if (m_useNativeImplsWhenBuiltinModuleNotDefined &&
|
||||
!m_modManager.isBuiltinModuleDefined(modName))
|
||||
{
|
||||
ret = Policy::UseNative;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = m_defaultPolicy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const LibraryPolicy *libPolicy = nullptr;
|
||||
auto found = modIter->second.getLibraryPolicy(libName, &libPolicy);
|
||||
if (!found)
|
||||
{
|
||||
ret = getModulePolicy(modName);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = libPolicy->getSymbolPolicy(nid);
|
||||
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Policy PolicyManager::getSymbolPolicy(std::string const& modName, std::string const& libName, std::string const& name) const
|
||||
{
|
||||
Policy ret = m_defaultPolicy;
|
||||
do
|
||||
{
|
||||
auto modIter = m_modPolicyTable.find(modName);
|
||||
if (modIter == m_modPolicyTable.end())
|
||||
{
|
||||
if (m_useNativeImplsWhenBuiltinModuleNotDefined &&
|
||||
!m_modManager.isBuiltinModuleDefined(modName))
|
||||
{
|
||||
ret = Policy::UseNative;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = m_defaultPolicy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const LibraryPolicy *libPolicy = nullptr;
|
||||
auto found = modIter->second.getLibraryPolicy(libName, &libPolicy);
|
||||
if (!found)
|
||||
{
|
||||
ret = m_defaultPolicy;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = libPolicy->getSymoblPolicy(name);
|
||||
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ModulePolicyAdder PolicyManager::declareModule(std::string const & name)
|
||||
{
|
||||
m_modPolicyTable.emplace(std::make_pair(name, ModulePolicy{}));
|
||||
return { m_modPolicyTable.at(name) };
|
||||
}
|
||||
|
||||
|
||||
LibrayNameAdder ModulePolicyAdder::withDefault(Policy policy)
|
||||
{
|
||||
m_modPolicy.setPolicy(policy);
|
||||
return { m_modPolicy };
|
||||
}
|
||||
|
||||
|
||||
LibraryPolicyAdder LibrayNameAdder::declareSubLibrary(std::string const & name)
|
||||
{
|
||||
auto &lp = m_modPolicy.addLibraryPolicy(name, LibraryPolicy{});
|
||||
return { m_modPolicy, lp };
|
||||
}
|
||||
|
||||
|
||||
LibrarySymbolExcluder LibraryPolicyAdder::with(Policy policy)
|
||||
{
|
||||
m_policy.setPolicy(policy);
|
||||
return { m_modPolicy, m_policy };
|
||||
}
|
||||
|
||||
|
||||
LibrayNameAdder LibrarySymbolExcluder::except(std::initializer_list<uint64_t> nids)
|
||||
{
|
||||
for (auto nid : nids)
|
||||
{
|
||||
m_policy.excludeSymbol(nid);
|
||||
}
|
||||
|
||||
return { m_modPolicy };
|
||||
}
|
168
GPCS4/Emulator/PolicyManager.h
Normal file
168
GPCS4/Emulator/PolicyManager.h
Normal file
|
@ -0,0 +1,168 @@
|
|||
#include "ModuleManger.h"
|
||||
|
||||
#include <map>
|
||||
#include <cstdint>
|
||||
|
||||
enum class Policy
|
||||
{
|
||||
UseBuiltin = 0,
|
||||
UseNative = 1,
|
||||
};
|
||||
|
||||
class LibraryPolicy
|
||||
{
|
||||
public:
|
||||
using NidList = std::initializer_list<uint64_t>;
|
||||
|
||||
LibraryPolicy() = default;
|
||||
void excludeSymbol(uint64_t nid);
|
||||
void excludeSymbol(std::string const &name);
|
||||
void setPolicy(Policy policy);
|
||||
|
||||
Policy getSymbolPolicy(uint64_t nid) const;
|
||||
Policy getSymoblPolicy(std::string const& name) const;
|
||||
|
||||
private:
|
||||
Policy m_policy;
|
||||
std::map<uint64_t, bool> m_excludeNids;
|
||||
std::map<std::string, bool> m_excludeNames;
|
||||
};
|
||||
|
||||
|
||||
class ModulePolicy
|
||||
{
|
||||
public:
|
||||
using LibPolicyEntry = std::pair<std::string, LibraryPolicy>;
|
||||
using LibraryPolicyList = std::initializer_list<LibPolicyEntry>;
|
||||
|
||||
ModulePolicy() = default;
|
||||
LibraryPolicy& addLibraryPolicy(std::string const &name, LibraryPolicy &&lp);
|
||||
bool getLibraryPolicy(std::string const &name, const LibraryPolicy **p) const;
|
||||
void setPolicy(Policy policy);
|
||||
Policy getPolicy() const;
|
||||
|
||||
private:
|
||||
Policy m_policy;
|
||||
std::map<std::string, LibraryPolicy> m_libPolicyTable;
|
||||
};
|
||||
|
||||
|
||||
class ModulePolicyAdder;
|
||||
class LibrayNameAdder;
|
||||
|
||||
class PolicyManager
|
||||
{
|
||||
public:
|
||||
using ModulePolicyEntry = std::pair<std::string, ModulePolicy>;
|
||||
PolicyManager(ModuleManager& modMgr);
|
||||
|
||||
/**
|
||||
* @brief Retireves the policy of a module
|
||||
*
|
||||
* @param modName module name
|
||||
* @return Policy
|
||||
*/
|
||||
Policy getModulePolicy(std::string const &modName) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the policy of a symbol
|
||||
*
|
||||
* @param modName module name
|
||||
* @param libName library name
|
||||
* @param nid symbol NID
|
||||
* @return Policy
|
||||
*/
|
||||
Policy getSymbolPolicy(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the policy of a symbol
|
||||
*
|
||||
* @param modName module name
|
||||
* @param libName library name
|
||||
* @param name symbol name
|
||||
* @return Policy
|
||||
*/
|
||||
Policy getSymbolPolicy(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const& name) const;
|
||||
|
||||
/**
|
||||
* @brief Checks if a native module is loadable.
|
||||
*
|
||||
* @param modName module name
|
||||
* @return true if the module if loadable
|
||||
* @return false if the module is not loadable
|
||||
*/
|
||||
bool isModuleLoadable(std::string const &modName) const;
|
||||
|
||||
/**
|
||||
* @brief Declares policy for a module
|
||||
*
|
||||
* @param name module name
|
||||
* @return ModulePolicyAdder
|
||||
*/
|
||||
ModulePolicyAdder declareModule(std::string const &name);
|
||||
|
||||
private:
|
||||
const Policy m_defaultPolicy = Policy::UseBuiltin;
|
||||
const bool m_useNativeImplsWhenBuiltinModuleNotDefined = true;
|
||||
std::map<std::string, ModulePolicy> m_modPolicyTable;
|
||||
ModuleManager& m_modManager;
|
||||
};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LibrarySymbolExcluder
|
||||
{
|
||||
public:
|
||||
LibrarySymbolExcluder(ModulePolicy &mp, LibraryPolicy &lp) :
|
||||
m_policy{ lp }, m_modPolicy{ mp }{};
|
||||
|
||||
LibrayNameAdder except(std::initializer_list<uint64_t> nids);
|
||||
private:
|
||||
LibraryPolicy &m_policy;
|
||||
ModulePolicy &m_modPolicy;
|
||||
};
|
||||
|
||||
class LibraryPolicyAdder
|
||||
{
|
||||
public:
|
||||
LibraryPolicyAdder(ModulePolicy &mp, LibraryPolicy &lp)
|
||||
: m_policy{ lp }, m_modPolicy{ mp } {};
|
||||
|
||||
LibrarySymbolExcluder with(Policy policy);
|
||||
|
||||
private:
|
||||
LibraryPolicy &m_policy;
|
||||
ModulePolicy &m_modPolicy;
|
||||
};
|
||||
|
||||
class LibrayNameAdder
|
||||
{
|
||||
public:
|
||||
LibrayNameAdder(ModulePolicy &mp):
|
||||
m_modPolicy{mp} {}
|
||||
|
||||
LibraryPolicyAdder declareSubLibrary(std::string const &name);
|
||||
|
||||
private:
|
||||
ModulePolicy &m_modPolicy;
|
||||
};
|
||||
|
||||
class ModulePolicyAdder
|
||||
{
|
||||
public:
|
||||
ModulePolicyAdder(ModulePolicy &mp):
|
||||
m_modPolicy{ mp } {}
|
||||
|
||||
LibrayNameAdder withDefault(Policy policy);
|
||||
|
||||
private:
|
||||
ModulePolicy &m_modPolicy;
|
||||
};
|
||||
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
LOG_CHANNEL(Emulator);
|
||||
|
||||
using Policy = CSceModuleSystem::LibraryRecord::OverridingPolicy;
|
||||
|
||||
#define REGISTER_MODULE(name) \
|
||||
if (!pModuleSystem->registerBuiltinModule(name)) \
|
||||
|
@ -13,54 +12,61 @@ using Policy = CSceModuleSystem::LibraryRecord::OverridingPolicy;
|
|||
break; \
|
||||
}
|
||||
|
||||
#define USE_NATIVE_MODULE(name) \
|
||||
if (!pModuleSystem->setModuleOverridability(name, true)) \
|
||||
{ \
|
||||
LOG_ERR("Fail to set overridability for module %s", name); \
|
||||
break; \
|
||||
}\
|
||||
static bool registerLibC(CSceModuleSystem* pModuleSystem)
|
||||
{
|
||||
bool ret = false;
|
||||
do
|
||||
{
|
||||
if (!pModuleSystem)
|
||||
{
|
||||
break;
|
||||
}
|
||||
auto& policyManager = pModuleSystem->getPolicyManager();
|
||||
|
||||
/**
|
||||
* Defines policy for libc.
|
||||
*
|
||||
* The default policy for this module is Policy::UseBuitlin,
|
||||
* which means when a sub-library of libc is not defined,
|
||||
* it applies the Policy::UseBuiltin by default.
|
||||
*
|
||||
* The libc sub-library uses implementations from native modules
|
||||
* except the symbols listed below.
|
||||
*/
|
||||
policyManager.declareModule("libc").withDefault(Policy::UseBuiltin)
|
||||
.declareSubLibrary("libc").with(Policy::UseNative).except
|
||||
({
|
||||
0xC5E60EE2EEEEC89DULL, // fopen
|
||||
0xAD0155057A7F0B18ULL, // fssek
|
||||
0x41ACF2F0B9974EFCULL, // ftell
|
||||
0x95B07E52566A546DULL, // fread
|
||||
0xBA874B632522A76DULL, // fclose
|
||||
0x8105FEE060D08E93ULL, // malloc
|
||||
0x63B689D6EC9D3CCAULL, // realloc
|
||||
0xD97E5A8058CAC4C7ULL, // calloc
|
||||
0xB4886CAA3D2AB051ULL, // free
|
||||
0x5CA45E82C1691299ULL, // catchReturnFromMain
|
||||
0xB8C7A2D56F6EC8DAULL, // exit
|
||||
0xC0B9459301BD51C4ULL, // time
|
||||
0x80D435576BDF5C31ULL, // setjmp
|
||||
0x94A10DD8879B809DULL // longjmp
|
||||
});
|
||||
|
||||
/*
|
||||
* Defines policy for libSceLibcInternal
|
||||
*
|
||||
* We load all of its symbols
|
||||
*/
|
||||
policyManager
|
||||
.declareModule("libSceLibcInternal").withDefault(Policy::UseNative);
|
||||
|
||||
|
||||
// Define a builtin function preference list.
|
||||
// The linker will use builtin functions in this list over native functions in firmware modules.
|
||||
#define BUILTIN_LIST_BEGIN(mod, lib) \
|
||||
if (!pModuleSystem->setLibraryOverridability(mod, lib, true, Policy::DisallowList)) \
|
||||
{ \
|
||||
LOG_ERR("Fail to begin builtin list for library %s", lib); \
|
||||
break; \
|
||||
}
|
||||
ret = true;
|
||||
}while(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define USE_BUILTIN_FUNCTION(mod, lib, nid) \
|
||||
if (!pModuleSystem->setFunctionOverridability(mod, lib, nid, false)) \
|
||||
{ \
|
||||
LOG_ERR("Fail to add function in builtin list %llx", nid); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define BUILTIN_LIST_END()
|
||||
|
||||
|
||||
// Define a native function preference list.
|
||||
// The linker will use native functions (in firmware modules.) in this list over builtin functions we HLEed in SceModules.
|
||||
#define NATIVE_LIST_BEGIN(mod, lib) \
|
||||
if (!pModuleSystem->setLibraryOverridability(mod, lib, true, Policy::AllowList)) \
|
||||
{ \
|
||||
LOG_ERR("Fail to set overridability for library %s", lib); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define USE_NATIVE_FUNCTION(mod, lib, nid) \
|
||||
if (!pModuleSystem->setFunctionOverridability(mod, lib, nid, true)) \
|
||||
{ \
|
||||
LOG_ERR("Fail to add function in native list %llx", nid); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define NATIVE_LIST_END()
|
||||
|
||||
|
||||
|
||||
bool CEmulator::registerLibC(CSceModuleSystem* pModuleSystem)
|
||||
static bool registerLibKernel(CSceModuleSystem* pModuleSystem)
|
||||
{
|
||||
bool ret = false;
|
||||
do
|
||||
|
@ -70,31 +76,35 @@ bool CEmulator::registerLibC(CSceModuleSystem* pModuleSystem)
|
|||
break;
|
||||
}
|
||||
|
||||
BUILTIN_LIST_BEGIN("libc", "libc");
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0xC5E60EE2EEEEC89DULL); // fopen
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0xAD0155057A7F0B18ULL); // fseek
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0x41ACF2F0B9974EFCULL); // ftell
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0x95B07E52566A546DULL); // fread
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0xBA874B632522A76DULL); // fclose
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0x8105FEE060D08E93ULL); // malloc
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0x63B689D6EC9D3CCAULL); // realloc
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0xD97E5A8058CAC4C7ULL); // calloc
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0xB4886CAA3D2AB051ULL); // free
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0x5CA45E82C1691299ULL); // catchReturnFromMain
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0xB8C7A2D56F6EC8DAULL); // exit
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0xC0B9459301BD51C4ULL); // time
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0x80D435576BDF5C31ULL); // setjmp
|
||||
USE_BUILTIN_FUNCTION("libc", "libc", 0x94A10DD8879B809DULL); // longjmp
|
||||
BUILTIN_LIST_END();
|
||||
auto& policyManager = pModuleSystem->getPolicyManager();
|
||||
|
||||
/**
|
||||
* Defines policy for libkernel.
|
||||
*
|
||||
* The default policy for this module is Policy::UseBuitlin,
|
||||
* which means when a sub-library of libkernel is not defined,
|
||||
* it applies the Policy::UseBuiltin policy by default.
|
||||
*
|
||||
* The libc sub-library uses implementations from builtin modules
|
||||
* except the symbols listed below.
|
||||
*/
|
||||
policyManager.declareModule("libkernel").withDefault(Policy::UseBuiltin)
|
||||
.declareSubLibrary("libkernel").with(Policy::UseBuiltin).except
|
||||
({
|
||||
0xF41703CA43E6A352, // __error
|
||||
0x581EBA7AFBBC6EC5 // sceKernelGetCompiledSdkVersion
|
||||
});
|
||||
|
||||
|
||||
ret = true;
|
||||
}while(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CEmulator::registerLibKernel(CSceModuleSystem* pModuleSystem)
|
||||
static bool registerOtherModules(CSceModuleSystem *pModuleSystem)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
do
|
||||
{
|
||||
if (!pModuleSystem)
|
||||
|
@ -102,18 +112,18 @@ bool CEmulator::registerLibKernel(CSceModuleSystem* pModuleSystem)
|
|||
break;
|
||||
}
|
||||
|
||||
NATIVE_LIST_BEGIN("libkernel", "libkernel");
|
||||
USE_NATIVE_FUNCTION("libkernel", "libkernel", 0xF41703CA43E6A352); // __error
|
||||
USE_NATIVE_FUNCTION("libkernel", "libkernel", 0x581EBA7AFBBC6EC5); // sceKernelGetCompiledSdkVersion
|
||||
USE_NATIVE_FUNCTION("libkernel", "libkernel", 0x8E1FBC5E22B82DE1); // sceKernelIsAddressSanitizerEnabled
|
||||
USE_NATIVE_FUNCTION("libkernel", "libkernel", 0x0F8CA56B7BF1E2D6); // sceKernelError
|
||||
NATIVE_LIST_END();
|
||||
auto& policyManager = pModuleSystem->getPolicyManager();
|
||||
|
||||
policyManager
|
||||
.declareModule("libSceNpCommon").withDefault(Policy::UseNative);
|
||||
|
||||
ret = true;
|
||||
} while (false);
|
||||
|
||||
ret = true;
|
||||
}while(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool CEmulator::registerModules()
|
||||
{
|
||||
bool bRet = false;
|
||||
|
@ -171,11 +181,7 @@ bool CEmulator::registerModules()
|
|||
REGISTER_MODULE(g_ExpModuleSceVideoOut);
|
||||
REGISTER_MODULE(g_ExpModuleSceVideoRecording);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
USE_NATIVE_MODULE("libSceLibcInternal");
|
||||
USE_NATIVE_MODULE("libSceNpCommon");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//USE_NATIVE_MODULE("libSceNpCommon");
|
||||
if (!registerLibKernel(pModuleSystem))
|
||||
{
|
||||
break;
|
||||
|
@ -186,6 +192,31 @@ bool CEmulator::registerModules()
|
|||
break;
|
||||
}
|
||||
|
||||
if (!registerOtherModules(pModuleSystem))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Yes, the policy is testable now, although we should not put the
|
||||
// test code here
|
||||
auto testPolicy = [&]() {
|
||||
auto pm = pModuleSystem->getPolicyManager();
|
||||
|
||||
auto p1 = pm.getSymbolPolicy("libc", "libc", 0xC5E60EE2EEEEC89DULL);
|
||||
LOG_ASSERT(p1 == Policy::UseBuiltin, "policy error");
|
||||
|
||||
auto p2 = pm.getSymbolPolicy("libkernel", "libkernel", 0xF41703CA43E6A352);
|
||||
LOG_ASSERT(p2 == Policy::UseNative, "policy error2");
|
||||
|
||||
auto p3 = pm.getSymbolPolicy("libSceNgs2", "libSceNgs2", 0xDE908D6D5335D540);
|
||||
LOG_ASSERT(p3 == Policy::UseNative, "policy error3");
|
||||
|
||||
auto p4 = pm.getSymbolPolicy("libSceLibcInternal", "libSceLibcInternal", 0x80D435576BDF5C31);
|
||||
LOG_ASSERT(p4 == Policy::UseNative, "policy error4");
|
||||
};
|
||||
|
||||
testPolicy();
|
||||
|
||||
bRet = true;
|
||||
} while (false);
|
||||
return bRet;
|
||||
|
|
|
@ -5,200 +5,19 @@
|
|||
|
||||
LOG_CHANNEL(Emulator);
|
||||
|
||||
CSceModuleSystem::CSceModuleSystem() {}
|
||||
CSceModuleSystem::CSceModuleSystem():m_policyManager{m_moduleManager} {}
|
||||
|
||||
CSceModuleSystem::~CSceModuleSystem() {}
|
||||
|
||||
bool CSceModuleSystem::IsEndLibraryEntry(const SCE_EXPORT_LIBRARY *pLib)
|
||||
{
|
||||
return (pLib->szLibraryName == NULL && pLib->pFunctionEntries == NULL);
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isNativeModuleLoadable(std::string const &modName) const
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
if (m_moduleSymbNameMap.count(modName) == 0)
|
||||
{
|
||||
retVal = true;
|
||||
}
|
||||
else if (isModuleOverridable(modName))
|
||||
{
|
||||
retVal = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = false;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
return m_policyManager.isModuleLoadable(modName);
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isModuleOverridable(std::string const &modName) const
|
||||
std::vector<NativeModule>& CSceModuleSystem::getAllNativeModules()
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
do
|
||||
{
|
||||
if (util::contains(m_overridableModules, modName) == true)
|
||||
{
|
||||
ret = m_overridableModules.at(modName).overridable;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isBuitinModuleDefined(modName) == false)
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isLibraryOverridable(std::string const &modName,
|
||||
std::string const &libName) const
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
do
|
||||
{
|
||||
if (isModuleOverridable(modName) == false)
|
||||
{
|
||||
retVal = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isModuleOVRDDefinationEmpty(modName))
|
||||
{
|
||||
// If no library overridability defined for a overridable module,
|
||||
// All libraries in the module are overridable.
|
||||
retVal = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isLibraryOverridabilityDefined(modName, libName) == false)
|
||||
{
|
||||
retVal = false;
|
||||
break;
|
||||
}
|
||||
|
||||
auto &mr = m_overridableModules.at(modName);
|
||||
|
||||
retVal = util::contains(mr.libraries, libName)
|
||||
? mr.libraries.at(libName).overrideable
|
||||
: false;
|
||||
} while (false);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isFunctionOverridable(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid) const
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
do
|
||||
{
|
||||
if (!isLibraryOverridable(modName, libName))
|
||||
{
|
||||
retVal = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isModuleOVRDDefinationEmpty(modName))
|
||||
{
|
||||
retVal = true;
|
||||
break;
|
||||
}
|
||||
|
||||
auto &lr = m_overridableModules.at(modName).libraries.at(libName);
|
||||
if (lr.functions.empty())
|
||||
{
|
||||
retVal = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lr.mode == LibraryRecord::OverridingPolicy::AllowList)
|
||||
{
|
||||
retVal = util::contains(lr.functions, nid) ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = util::contains(lr.functions, nid) ? false : true;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isBuitinModuleDefined(std::string const& name) const
|
||||
{
|
||||
return util::contains(m_builtinModules, name);
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isModuleOVRDDefinationEmpty(std::string const& modName) const
|
||||
{
|
||||
bool ret = false;
|
||||
do
|
||||
{
|
||||
if (!util::contains(m_overridableModules, modName))
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_overridableModules.at(modName).libraries.empty())
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isLibraryOverridabilityDefined(std::string const& modName,
|
||||
std::string const& libName) const
|
||||
{
|
||||
bool ret = false;
|
||||
do
|
||||
{
|
||||
auto modIt = m_overridableModules.find(modName);
|
||||
if (modIt == m_overridableModules.end())
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
auto libIt = modIt->second.libraries.find(libName);
|
||||
if (libIt == modIt->second.libraries.end())
|
||||
{
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
} while (false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::IsEndFunctionEntry(const SCE_EXPORT_FUNCTION* pFunc)
|
||||
{
|
||||
return (pFunc->nNid == 0 && pFunc->szFunctionName == NULL &&
|
||||
pFunc->pFunction == NULL);
|
||||
return m_moduleManager.getNativeModules();
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::registerBuiltinModule(const SCE_EXPORT_MODULE &stModule)
|
||||
|
@ -213,415 +32,102 @@ bool CSceModuleSystem::registerBuiltinModule(const SCE_EXPORT_MODULE &stModule)
|
|||
|
||||
const char *szModName = stModule.szModuleName;
|
||||
const SCE_EXPORT_LIBRARY *pLib = stModule.pLibraries;
|
||||
SceLibMapNid libMapNid;
|
||||
SceLibMapName libMapName;
|
||||
|
||||
m_builtinModules.emplace_back(szModName);
|
||||
m_moduleManager.registerBuiltinModule(szModName);
|
||||
|
||||
while (!IsEndLibraryEntry(pLib))
|
||||
while (!pLib->isEndEntry())
|
||||
{
|
||||
const char *szLibName = pLib->szLibraryName;
|
||||
const SCE_EXPORT_FUNCTION *pFunc = pLib->pFunctionEntries;
|
||||
|
||||
NidFuncMap nidMap;
|
||||
NameFuncMap nameMap;
|
||||
while (!IsEndFunctionEntry(pFunc))
|
||||
|
||||
while (!pFunc->isEndEntry())
|
||||
{
|
||||
nidMap.insert(
|
||||
std::make_pair((uint64_t)pFunc->nNid, (void *)pFunc->pFunction));
|
||||
nameMap.insert(std::make_pair(std::string(pFunc->szFunctionName),
|
||||
(void *)pFunc->pFunction));
|
||||
++pFunc;
|
||||
m_symbolManager.registerBuiltinSymbol(szModName,
|
||||
szLibName,
|
||||
pFunc->nNid,
|
||||
pFunc->pFunction);
|
||||
|
||||
m_symbolManager.registerBuiltinSymbol(szModName,
|
||||
szLibName,
|
||||
pFunc->szFunctionName,
|
||||
pFunc->pFunction);
|
||||
|
||||
pFunc = pFunc->iterNext();
|
||||
}
|
||||
libMapNid.insert(std::make_pair((char *)szLibName, nidMap));
|
||||
libMapName.insert(std::make_pair((char *)szLibName, nameMap));
|
||||
++pLib;
|
||||
pLib = pLib->iterNext();
|
||||
}
|
||||
|
||||
m_moduleNidMap.insert(std::make_pair((char *)szModName, libMapNid));
|
||||
m_moduleSymbNameMap.insert(std::make_pair((char *)szModName, libMapName));
|
||||
|
||||
bRet = true;
|
||||
} while (false);
|
||||
return bRet;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::registerNativeFunction(std::string const &modName,
|
||||
bool CSceModuleSystem::registerNativeSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid,
|
||||
void *p)
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
do
|
||||
{
|
||||
if (isFunctionOverridable(modName, libName, nid) == false)
|
||||
{
|
||||
retVal = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isModuleLoaded(modName))
|
||||
{
|
||||
SceLibMapNid libMapNid = {};
|
||||
SceLibMapName libMapName = {};
|
||||
|
||||
m_moduleSymbNameMap.insert(std::make_pair(modName, libMapName));
|
||||
m_moduleNidMap.insert(std::make_pair(modName, libMapNid));
|
||||
}
|
||||
|
||||
if (!isLibraryLoaded(modName, libName))
|
||||
{
|
||||
NidFuncMap nidMap = {};
|
||||
|
||||
nidMap.insert(std::make_pair(nid, p));
|
||||
m_moduleNidMap.at(modName).insert(std::make_pair(libName, nidMap));
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_moduleNidMap.at(modName).at(libName).count(nid) != 0)
|
||||
{
|
||||
m_moduleNidMap.at(modName).at(libName).at(nid) = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_moduleNidMap.at(modName).at(libName).insert(std::make_pair(nid, p));
|
||||
}
|
||||
|
||||
retVal = true;
|
||||
|
||||
} while (false);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::registerSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const &symbolName,
|
||||
void *p)
|
||||
{
|
||||
bool retVal = false;
|
||||
if (m_moduleSymbNameMap.count(modName) == 0)
|
||||
{
|
||||
SceLibMapName libMapName = {};
|
||||
m_moduleSymbNameMap.emplace(std::make_pair(modName, libMapName));
|
||||
}
|
||||
|
||||
auto &mod = m_moduleSymbNameMap.at(modName);
|
||||
if (mod.count(libName) == 0)
|
||||
{
|
||||
NameFuncMap symbolNameMap = {};
|
||||
mod.emplace(std::make_pair(libName, symbolNameMap));
|
||||
}
|
||||
|
||||
auto &lib = mod.at(libName);
|
||||
if (lib.count(symbolName) != 0)
|
||||
{
|
||||
LOG_ERR("symbol %s has ready been registered", symbolName.c_str());
|
||||
retVal = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lib.emplace(std::make_pair(symbolName, p));
|
||||
retVal = true;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::registerMemoryMappedModule(std::string const &modName,
|
||||
MemoryMappedModule &&mod)
|
||||
{
|
||||
auto index = m_mappedModules.size();
|
||||
|
||||
m_mappedModuleNameIndexMap.insert(std::make_pair(modName, index));
|
||||
m_mappedModules.push_back(std::move(mod));
|
||||
|
||||
m_symbolManager.registerNativeSymbol(modName, libName, nid, p);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isMemoryMappedModuleLoaded(std::string const &modName)
|
||||
bool CSceModuleSystem::registerNativeSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const &symbolName,
|
||||
void *p)
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
if (m_mappedModuleNameIndexMap.count(modName) != 0)
|
||||
{
|
||||
retVal = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = false;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
m_symbolManager.registerNativeSymbol(modName, libName, symbolName, p);
|
||||
return true;
|
||||
}
|
||||
|
||||
CSceModuleSystem::SceMappedModuleList &CSceModuleSystem::getMemoryMappedModules()
|
||||
bool CSceModuleSystem::registerNativeModule(std::string const &modName,
|
||||
NativeModule &&mod)
|
||||
{
|
||||
return m_mappedModules;
|
||||
m_moduleManager.registerNativeModule(modName, std::move(mod));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::getMemoryMappedModule(std::string const &modName,
|
||||
MemoryMappedModule **ppMod)
|
||||
Policy CSceModuleSystem::getModulePolicy(std::string const& modName) const
|
||||
{
|
||||
bool retVal = true;
|
||||
|
||||
auto iter = m_mappedModuleNameIndexMap.find(modName);
|
||||
if (iter == m_mappedModuleNameIndexMap.end())
|
||||
{
|
||||
retVal = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppMod = &m_mappedModules.at(iter->second);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
return m_policyManager.getModulePolicy(modName);
|
||||
}
|
||||
|
||||
void *CSceModuleSystem::findFunction(const std::string &strModName,
|
||||
const std::string &strLibName,
|
||||
uint64_t nNid)
|
||||
Policy CSceModuleSystem::getSymbolPolicy(std::string const& modName,
|
||||
std::string const& libName,
|
||||
uint64_t nid) const
|
||||
{
|
||||
void *pFunction = NULL;
|
||||
do
|
||||
{
|
||||
SceModuleMapNid::iterator iter_mod = m_moduleNidMap.find(strModName);
|
||||
if (iter_mod == m_moduleNidMap.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
SceLibMapNid &libMap = iter_mod->second;
|
||||
SceLibMapNid::iterator iter_lib = libMap.find(strLibName);
|
||||
if (iter_lib == libMap.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
NidFuncMap &nidMap = iter_lib->second;
|
||||
NidFuncMap::iterator iter_func = nidMap.find(nNid);
|
||||
if (iter_func == nidMap.end())
|
||||
{
|
||||
// TODO: This is for experimental only. When a NID is not found,
|
||||
// we attempt to traversal all libs in the module to find that nid.
|
||||
//for (auto libIt : iter_mod->second)
|
||||
//{
|
||||
// auto nidIter = libIt.second.find(nNid);
|
||||
// if (nidIter != libIt.second.end())
|
||||
// {
|
||||
// pFunction = nidIter->second;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
break;
|
||||
}
|
||||
|
||||
pFunction = iter_func->second;
|
||||
} while (false);
|
||||
return pFunction;
|
||||
return m_policyManager.getSymbolPolicy(modName, libName, nid);
|
||||
}
|
||||
|
||||
void *CSceModuleSystem::findSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const &symbolName)
|
||||
Policy CSceModuleSystem::getSymbolPolicy(std::string const& modName,
|
||||
std::string const& libName,
|
||||
std::string const& name) const
|
||||
{
|
||||
void *pAddr = nullptr;
|
||||
do
|
||||
{
|
||||
auto iterMod = m_moduleSymbNameMap.find(modName);
|
||||
if (iterMod == m_moduleSymbNameMap.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
auto &libMap = iterMod->second;
|
||||
auto iterLib = libMap.find(libName);
|
||||
|
||||
if (iterLib == libMap.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
auto &nameMap = iterLib->second;
|
||||
auto iterSymbol = nameMap.find(symbolName);
|
||||
if (iterSymbol == nameMap.end())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pAddr = iterSymbol->second;
|
||||
} while (false);
|
||||
|
||||
return pAddr;
|
||||
return m_policyManager.getSymbolPolicy(modName, libName, name);
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isModuleLoaded(const std::string &modName)
|
||||
const SymbolManager& CSceModuleSystem::getSymbolManager() const
|
||||
{
|
||||
return (m_moduleNidMap.count(modName) != 0);
|
||||
return m_symbolManager;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isLibraryLoaded(std::string const &modName,
|
||||
std::string const &libName)
|
||||
PolicyManager& CSceModuleSystem::getPolicyManager()
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
if (!isModuleLoaded(modName))
|
||||
{
|
||||
retVal = false;
|
||||
}
|
||||
else if (m_moduleNidMap.at(modName).count(libName) > 0)
|
||||
{
|
||||
retVal = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = false;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
return m_policyManager;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::setModuleOverridability(const std::string &modName, bool ovrd)
|
||||
bool CSceModuleSystem::isNativeModuleLoaded(std::string const &modName)
|
||||
{
|
||||
bool retVal = false;
|
||||
do
|
||||
{
|
||||
if (ovrd)
|
||||
{
|
||||
if (m_overridableModules.count(modName) == 0)
|
||||
{
|
||||
ModuleRecord mr = {};
|
||||
m_overridableModules.insert(std::make_pair(modName, mr));
|
||||
}
|
||||
|
||||
m_overridableModules.at(modName).overridable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_overridableModules.count(modName) != 0)
|
||||
{
|
||||
m_overridableModules.at(modName).overridable = false;
|
||||
}
|
||||
}
|
||||
|
||||
retVal = true;
|
||||
|
||||
} while (false);
|
||||
|
||||
return retVal;
|
||||
return m_moduleManager.isNativeModuleLoaded(modName);
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::setLibraryOverridability(const std::string &modName,
|
||||
const std::string &libName,
|
||||
bool ovrd,
|
||||
LibraryRecord::OverridingPolicy mode)
|
||||
|
||||
bool CSceModuleSystem::getNativeModule(std::string const &modName,
|
||||
NativeModule **ppMod)
|
||||
{
|
||||
bool retVal = true;
|
||||
|
||||
do
|
||||
{
|
||||
if (m_overridableModules.count(modName) == 0)
|
||||
{
|
||||
if (ovrd == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ModuleRecord mr = {};
|
||||
mr.overridable = true;
|
||||
m_overridableModules.insert(std::make_pair(modName, mr));
|
||||
}
|
||||
|
||||
auto &mr = m_overridableModules.at(modName);
|
||||
|
||||
if (mr.libraries.count(libName) == 0)
|
||||
{
|
||||
if (ovrd == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
LibraryRecord lr = {};
|
||||
lr.mode = mode;
|
||||
lr.overrideable = true;
|
||||
mr.libraries.insert(std::make_pair(libName, lr));
|
||||
}
|
||||
|
||||
mr.libraries.at(libName).overrideable = ovrd;
|
||||
|
||||
} while (false);
|
||||
|
||||
return retVal;
|
||||
return m_moduleManager.getNativeModule(modName, ppMod);
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::setFunctionOverridability(const std::string &modName,
|
||||
const std::string &libName,
|
||||
uint64_t nid,
|
||||
bool ovrd)
|
||||
{
|
||||
bool retVal = false;
|
||||
|
||||
do
|
||||
{
|
||||
if (m_overridableModules.count(modName) == 0)
|
||||
{
|
||||
if (ovrd == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ModuleRecord mr = {};
|
||||
mr.overridable = true;
|
||||
m_overridableModules.insert(std::make_pair(modName, mr));
|
||||
}
|
||||
|
||||
auto &mr = m_overridableModules.at(modName);
|
||||
if (mr.libraries.count(libName) == 0)
|
||||
{
|
||||
if (ovrd == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
LibraryRecord lr = {};
|
||||
lr.overrideable = true;
|
||||
mr.libraries.insert(std::make_pair(libName, lr));
|
||||
}
|
||||
|
||||
auto &lr = mr.libraries.at(libName);
|
||||
if (ovrd)
|
||||
{
|
||||
if (lr.mode == LibraryRecord::OverridingPolicy::AllowList &&
|
||||
lr.functions.count(nid) == 0)
|
||||
{
|
||||
lr.functions.insert(std::make_pair(nid, true));
|
||||
}
|
||||
else if (lr.mode == LibraryRecord::OverridingPolicy::DisallowList &&
|
||||
lr.functions.count(nid) != 0)
|
||||
{
|
||||
lr.functions.erase(nid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lr.mode == LibraryRecord::OverridingPolicy::DisallowList &&
|
||||
lr.functions.count(nid) == 0)
|
||||
{
|
||||
lr.functions.insert(std::make_pair(nid, true));
|
||||
}
|
||||
else if (lr.mode == LibraryRecord::OverridingPolicy::AllowList &&
|
||||
lr.functions.count(nid) != 0)
|
||||
{
|
||||
lr.functions.erase(nid);
|
||||
}
|
||||
}
|
||||
|
||||
retVal = true;
|
||||
} while (false);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool CSceModuleSystem::isFileAllowedToLoad(std::string const &fileName)
|
||||
{
|
||||
|
@ -665,21 +171,38 @@ const MODULE_INFO* CSceModuleSystem::getEbootModuleInfo() const
|
|||
const MODULE_INFO* retVal = nullptr;
|
||||
do
|
||||
{
|
||||
if (m_mappedModules.size() == 0)
|
||||
auto &modules = m_moduleManager.getNativeModules();
|
||||
if (modules.size() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
const auto &ebootModule = m_mappedModules.at(0);
|
||||
|
||||
const auto &ebootModule = modules.at(0);
|
||||
retVal = &ebootModule.getModuleInfo();
|
||||
} while (false);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
const void* CSceModuleSystem::getSymbolAddress(std::string const& modName,
|
||||
std::string const& libName,
|
||||
uint64_t nid) const
|
||||
{
|
||||
auto policy = m_policyManager.getSymbolPolicy(modName, libName, nid);
|
||||
void* address = nullptr;
|
||||
|
||||
if (policy == Policy::UseBuiltin)
|
||||
{
|
||||
address = const_cast<void*>(m_symbolManager.findBuiltinSymbol(modName, libName, nid));
|
||||
}
|
||||
else
|
||||
{
|
||||
address = const_cast<void*>(m_symbolManager.findNativeSymbol(modName, libName, nid));
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
// TODO: To be done
|
||||
void CSceModuleSystem::clearModules()
|
||||
{
|
||||
m_moduleNidMap.clear();
|
||||
m_moduleSymbNameMap.clear();
|
||||
m_overridableModules.clear();
|
||||
m_mappedModules.clear();
|
||||
m_mappedModuleNameIndexMap.clear();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#include "GPCS4Common.h"
|
||||
#include "UtilSingleton.h"
|
||||
#include "PolicyManager.h"
|
||||
#include "SymbolManager.h"
|
||||
#include "ModuleManger.h"
|
||||
|
||||
#include "Module.h"
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
@ -10,125 +14,187 @@ struct SCE_EXPORT_FUNCTION;
|
|||
struct SCE_EXPORT_LIBRARY;
|
||||
struct SCE_EXPORT_MODULE;
|
||||
|
||||
// Note:
|
||||
// Here "override" always mean native over builtin
|
||||
|
||||
class CSceModuleSystem final : public Singleton<CSceModuleSystem>
|
||||
{
|
||||
friend class Singleton<CSceModuleSystem>;
|
||||
|
||||
public:
|
||||
struct LibraryRecord
|
||||
{
|
||||
enum class OverridingPolicy
|
||||
{
|
||||
DisallowList,
|
||||
AllowList,
|
||||
};
|
||||
/**
|
||||
* @brief Get symbol address according to the corresponding policy
|
||||
*
|
||||
* @param modName mmodule name
|
||||
* @param libName library name
|
||||
* @param nid symbol NID
|
||||
* @return const void* symbol address
|
||||
*/
|
||||
const void *getSymbolAddress(std::string const& modName,
|
||||
std::string const& libName,
|
||||
uint64_t nid) const;
|
||||
|
||||
OverridingPolicy mode;
|
||||
bool overrideable;
|
||||
std::unordered_map<uint64_t, bool> functions;
|
||||
};
|
||||
|
||||
struct ModuleRecord
|
||||
{
|
||||
bool overridable;
|
||||
std::unordered_map<std::string, LibraryRecord> libraries;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
//since we won't insert or remove item after initialization
|
||||
//we use unordered_map instead of map
|
||||
typedef std::unordered_map<uint64_t, void*> NidFuncMap;
|
||||
typedef std::unordered_map<std::string, void*> NameFuncMap;
|
||||
|
||||
typedef std::unordered_map<std::string, NidFuncMap> SceLibMapNid;
|
||||
typedef std::unordered_map<std::string, NameFuncMap> SceLibMapName;
|
||||
|
||||
typedef std::unordered_map<std::string, SceLibMapNid> SceModuleMapNid;
|
||||
typedef std::unordered_map<std::string, SceLibMapName> SceModuleMapName;
|
||||
|
||||
typedef std::unordered_map<std::string, bool> SceAllowedFileMap;
|
||||
typedef std::unordered_map<std::string, ModuleRecord> SceOverridableMapNid;
|
||||
typedef std::unordered_map<std::string, MemoryMappedModule> SceMappedModuleMap;
|
||||
|
||||
typedef std::vector<MemoryMappedModule> SceMappedModuleList;
|
||||
typedef std::unordered_map<std::string, size_t> SceModuleNameIndexMap;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Clear modules. TODO: NOT IMPLEMENTED
|
||||
*
|
||||
*/
|
||||
void clearModules();
|
||||
|
||||
bool registerBuiltinModule(const SCE_EXPORT_MODULE& stModule);
|
||||
|
||||
bool registerNativeFunction(std::string const &modName, std::string const &libName, uint64_t nid, void *p);
|
||||
|
||||
bool registerSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const &symbolName,
|
||||
void *p);
|
||||
|
||||
bool registerMemoryMappedModule(std::string const &modName, MemoryMappedModule &&mod);
|
||||
|
||||
bool isMemoryMappedModuleLoaded(std::string const &modName);
|
||||
|
||||
SceMappedModuleList &getMemoryMappedModules();
|
||||
|
||||
bool getMemoryMappedModule(std::string const &modName, MemoryMappedModule **ppMod);
|
||||
|
||||
void* findFunction(const std::string& strModName, const std::string& strLibName, uint64_t nNid);
|
||||
void *findSymbol(std::string const &modName, std::string const &libName, std::string const &symbolName);
|
||||
|
||||
bool isModuleLoaded(const std::string& modName);
|
||||
|
||||
bool isNativeModuleLoadable(std::string const &modName) const;
|
||||
|
||||
bool isLibraryLoaded(std::string const &modName, std::string const &libName);
|
||||
|
||||
bool setModuleOverridability(const std::string &modName, bool isOverridable);
|
||||
|
||||
bool setLibraryOverridability(const std::string &modName,
|
||||
const std::string &libName,
|
||||
bool isOverridable,
|
||||
LibraryRecord::OverridingPolicy mode = LibraryRecord::OverridingPolicy::DisallowList);
|
||||
|
||||
bool setFunctionOverridability(const std::string &modName,
|
||||
const std::string &libName,
|
||||
uint64_t nid, bool isOverridable);
|
||||
|
||||
bool isFileAllowedToLoad(std::string const &fileName);
|
||||
bool isModuleOverridable(std::string const &modName) const;
|
||||
bool isLibraryOverridable(std::string const &modName, std::string const &libName) const;
|
||||
bool isFunctionOverridable(std::string const &modName, std::string const &libName, uint64_t nid) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the module infomation of eboot object
|
||||
*
|
||||
* @return const MODULE_INFO*
|
||||
*/
|
||||
const MODULE_INFO* getEbootModuleInfo() const;
|
||||
|
||||
/**
|
||||
* @brief Checks if a file is allowd to load.
|
||||
*
|
||||
* @param fileName file name
|
||||
* @return true if the file is allowed to load
|
||||
* @return false if the file is not allowed to load
|
||||
*/
|
||||
bool isFileAllowedToLoad(std::string const &fileName);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Checks if a native module is loadable
|
||||
*
|
||||
* @param modName module name
|
||||
* @return true if the native module is loadable
|
||||
* @return false if the native module is not loadable
|
||||
*/
|
||||
bool isNativeModuleLoadable(std::string const &modName) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves all native modules that are loaded.
|
||||
*
|
||||
* @return std::vector<NativeModule>&
|
||||
*/
|
||||
std::vector<NativeModule> &getAllNativeModules();
|
||||
|
||||
/**
|
||||
* @brief Retrieves a native module
|
||||
*
|
||||
* @param modName module name
|
||||
* @param ppMod [out] returned module
|
||||
* @return true if found
|
||||
* @return false if not found
|
||||
*/
|
||||
bool getNativeModule(std::string const &modName,
|
||||
NativeModule **ppMod);
|
||||
/**
|
||||
* @brief Checks if a native module is loaded from firmware.
|
||||
*
|
||||
* @param modName module name
|
||||
* @return true when the native module is loaded.
|
||||
* @return false when the native module isn't loaded.
|
||||
*/
|
||||
bool isNativeModuleLoaded(std::string const &modName);
|
||||
|
||||
/**
|
||||
* @brief Registers a builtin module to the module system
|
||||
*
|
||||
* @param stModule module defination
|
||||
* @return true when succeeded
|
||||
* @return false when failed
|
||||
*/
|
||||
bool registerBuiltinModule(const SCE_EXPORT_MODULE& stModule);
|
||||
|
||||
/**
|
||||
* @brief Registers a native module to the module system.
|
||||
* The ownship of the module is transfered after calling
|
||||
* this method.
|
||||
*
|
||||
* @param modName module name
|
||||
* @param mod module
|
||||
* @return true when succeeded
|
||||
* @return false when failed
|
||||
*/
|
||||
bool registerNativeModule(std::string const &modName,
|
||||
NativeModule &&mod);
|
||||
|
||||
/**
|
||||
* @brief Registers a symbol from native module
|
||||
*
|
||||
* @param modName module name
|
||||
* @param libName library name
|
||||
* @param nid symbol NID
|
||||
* @param p address
|
||||
* @return true when succeeded
|
||||
* @return false when failed
|
||||
*/
|
||||
bool registerNativeSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid,
|
||||
void *p);
|
||||
/**
|
||||
* @brief Registers a symbol from native modue
|
||||
*
|
||||
* @param modName module name
|
||||
* @param libName library name
|
||||
* @param symbolName symbol name
|
||||
* @param p address
|
||||
* @return true when succeeded
|
||||
* @return false when failed
|
||||
*/
|
||||
bool registerNativeSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const &symbolName,
|
||||
void *p);
|
||||
|
||||
/**
|
||||
* @brief Retrieves policy of a module
|
||||
*
|
||||
* @param modName module name
|
||||
* @return Policy
|
||||
*/
|
||||
Policy getModulePolicy(std::string const& modName) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves policy of a symbol
|
||||
*
|
||||
* @param modName module name
|
||||
* @param libName library name
|
||||
* @param nid symbol NID
|
||||
* @return Policy
|
||||
*/
|
||||
Policy getSymbolPolicy(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieves policy of a symbol
|
||||
*
|
||||
* @param modName module name
|
||||
* @param libName library name
|
||||
* @param name symbol name
|
||||
* @return Policy
|
||||
*/
|
||||
Policy getSymbolPolicy(std::string const& modName,
|
||||
std::string const& libName,
|
||||
std::string const& name) const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Gets the Symbol Manager object
|
||||
*
|
||||
* @return const SymbolManager&
|
||||
*/
|
||||
const SymbolManager& getSymbolManager() const;
|
||||
|
||||
/**
|
||||
* @brief Gets the Policy Manager object
|
||||
*
|
||||
* @return PolicyManager&
|
||||
*/
|
||||
PolicyManager& getPolicyManager();
|
||||
private:
|
||||
// Check if a builtin module is defined
|
||||
bool isBuitinModuleDefined(std::string const& name) const;
|
||||
|
||||
// Check if a module overridability defination is empty(does not contain any
|
||||
// library definations). This function also returns true when the module
|
||||
// overridability does not exist.
|
||||
bool isModuleOVRDDefinationEmpty(std::string const& modName) const;
|
||||
bool isLibraryOverridabilityDefined(std::string const &modName, std::string const &libName) const;
|
||||
|
||||
bool IsEndFunctionEntry(const SCE_EXPORT_FUNCTION* pFunc);
|
||||
bool IsEndLibraryEntry(const SCE_EXPORT_LIBRARY* pLib);
|
||||
|
||||
CSceModuleSystem();
|
||||
~CSceModuleSystem();
|
||||
CSceModuleSystem(const CSceModuleSystem&);
|
||||
CSceModuleSystem(const CSceModuleSystem&) = delete;
|
||||
CSceModuleSystem& operator = (const CSceModuleSystem&) = delete;
|
||||
|
||||
private:
|
||||
SceModuleMapNid m_moduleNidMap;
|
||||
SceModuleMapName m_moduleSymbNameMap;
|
||||
SceOverridableMapNid m_overridableModules;
|
||||
|
||||
std::vector<std::string> m_builtinModules;
|
||||
SceMappedModuleList m_mappedModules;
|
||||
SceModuleNameIndexMap m_mappedModuleNameIndexMap;
|
||||
ModuleManager m_moduleManager;
|
||||
SymbolManager m_symbolManager;
|
||||
PolicyManager m_policyManager;
|
||||
};
|
||||
|
||||
|
|
79
GPCS4/Emulator/SymbolManager.cpp
Normal file
79
GPCS4/Emulator/SymbolManager.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
#include "SymbolManager.h"
|
||||
|
||||
const void *SymbolManager::findNativeSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid) const
|
||||
{
|
||||
return findSymbolGeneric(m_nativeModuleSymbolNidDir, modName, libName, nid);
|
||||
}
|
||||
|
||||
const void* SymbolManager::findNativeSymbol(std::string const& modName,
|
||||
std::string const& libName,
|
||||
std::string const& symbName) const
|
||||
{
|
||||
return findSymbolGeneric(m_nativeModuleSymbolNameDir, modName, libName, symbName);
|
||||
}
|
||||
|
||||
const void* SymbolManager::findBuiltinSymbol(std::string const& modName,
|
||||
std::string const& libName,
|
||||
uint64_t nid) const
|
||||
{
|
||||
return findSymbolGeneric(m_builtinModuleSymbolNidDir, modName, libName, nid);
|
||||
}
|
||||
|
||||
const void* SymbolManager::findBuiltinSymbol(std::string const& modName,
|
||||
std::string const& libName,
|
||||
std::string const& name) const
|
||||
{
|
||||
return findSymbolGeneric(m_builtinModuleSymbolNameDir, modName, libName, name);
|
||||
}
|
||||
|
||||
bool SymbolManager::registerNativeSymbol(std::string const& modName,
|
||||
std::string const& libName,
|
||||
uint64_t nid,
|
||||
const void* address)
|
||||
{
|
||||
return registerSymbolNidGeneric(m_nativeModuleSymbolNidDir,
|
||||
modName,
|
||||
libName,
|
||||
nid,
|
||||
address);
|
||||
}
|
||||
|
||||
bool SymbolManager::registerNativeSymbol(std::string const& modName,
|
||||
std::string const& libName,
|
||||
std::string const& name,
|
||||
const void* address)
|
||||
{
|
||||
return registerSymbolNidGeneric(m_nativeModuleSymbolNameDir,
|
||||
modName,
|
||||
libName,
|
||||
name,
|
||||
address);
|
||||
}
|
||||
|
||||
bool SymbolManager::registerBuiltinSymbol(std::string const& modName,
|
||||
std::string const& libName,
|
||||
uint64_t nid,
|
||||
const void* address)
|
||||
{
|
||||
return registerSymbolNidGeneric(m_builtinModuleSymbolNidDir,
|
||||
modName,
|
||||
libName,
|
||||
nid,
|
||||
address);
|
||||
}
|
||||
|
||||
bool SymbolManager::registerBuiltinSymbol(std::string const& modName,
|
||||
std::string const& libName,
|
||||
std::string const& name,
|
||||
const void* address)
|
||||
{
|
||||
return registerSymbolNidGeneric(m_builtinModuleSymbolNameDir,
|
||||
modName,
|
||||
libName,
|
||||
name,
|
||||
address);
|
||||
}
|
||||
|
||||
|
137
GPCS4/Emulator/SymbolManager.h
Normal file
137
GPCS4/Emulator/SymbolManager.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class SymbolManager
|
||||
{
|
||||
public:
|
||||
const void *findNativeSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid) const;
|
||||
|
||||
const void *findNativeSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const &symbName) const;
|
||||
|
||||
const void *findBuiltinSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid) const;
|
||||
|
||||
const void *findBuiltinSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const &name) const;
|
||||
|
||||
bool registerNativeSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid,
|
||||
const void *address);
|
||||
|
||||
bool registerNativeSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const &name,
|
||||
const void *address);
|
||||
|
||||
bool registerBuiltinSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
uint64_t nid,
|
||||
const void *address);
|
||||
|
||||
bool registerBuiltinSymbol(std::string const &modName,
|
||||
std::string const &libName,
|
||||
std::string const &name,
|
||||
const void *address);
|
||||
|
||||
private:
|
||||
using NidAddrMap = std::unordered_map<uint64_t, const void*>;
|
||||
using NameAddrMap = std::unordered_map<std::string, const void*>;
|
||||
using LibSymbNidMap = std::unordered_map<std::string, NidAddrMap>;
|
||||
using LibSymbNameMap = std::unordered_map<std::string, NameAddrMap>;
|
||||
using ModSymbNameMap = std::unordered_map<std::string, LibSymbNameMap>;
|
||||
using ModSymbNidMap = std::unordered_map<std::string, LibSymbNidMap>;
|
||||
|
||||
template<typename Table, typename KeyType>
|
||||
const void *findSymbolGeneric(Table &table,
|
||||
std::string const &modName,
|
||||
std::string const &libName,
|
||||
KeyType nid) const
|
||||
{
|
||||
auto &tab = table;
|
||||
const void *address = nullptr;
|
||||
|
||||
do
|
||||
{
|
||||
auto modIter = tab.find(modName);
|
||||
if (modIter == tab.end())
|
||||
{
|
||||
address = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
auto libIter = modIter->second.find(libName);
|
||||
if (libIter == modIter->second.end())
|
||||
{
|
||||
address = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
auto nidIter = libIter->second.find(nid);
|
||||
if (nidIter == libIter->second.end())
|
||||
{
|
||||
address = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
address = nidIter->second;
|
||||
} while (false);
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
template<typename Table, typename KeyType>
|
||||
bool registerSymbolNidGeneric(Table &table,
|
||||
std::string const &modName,
|
||||
std::string const &libName,
|
||||
KeyType nid,
|
||||
const void *addr)
|
||||
{
|
||||
using LibMapType = typename Table::mapped_type;
|
||||
using AddrMapType = typename Table::mapped_type::mapped_type;
|
||||
|
||||
bool ret = false;
|
||||
|
||||
auto& tab = table;
|
||||
auto modIter = tab.find(modName);
|
||||
if (modIter == tab.end())
|
||||
{
|
||||
typename Table::mapped_type libMap;
|
||||
tab.emplace(std::make_pair(modName, LibMapType{}));
|
||||
modIter = tab.find(modName);
|
||||
}
|
||||
|
||||
auto libIter = modIter->second.find(libName);
|
||||
if (libIter == modIter->second.end())
|
||||
{
|
||||
modIter->second.emplace(std::make_pair(libName, AddrMapType{}));
|
||||
libIter = modIter->second.find(libName);
|
||||
}
|
||||
|
||||
auto symbIter = libIter->second.find(nid);
|
||||
if (symbIter == libIter->second.end())
|
||||
{
|
||||
libIter->second.emplace(std::make_pair(nid, addr));
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// already registered
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ModSymbNidMap m_nativeModuleSymbolNidDir;
|
||||
ModSymbNidMap m_builtinModuleSymbolNidDir;
|
||||
|
||||
ModSymbNameMap m_nativeModuleSymbolNameDir;
|
||||
ModSymbNameMap m_builtinModuleSymbolNameDir;
|
||||
};
|
|
@ -26,6 +26,9 @@
|
|||
<ClInclude Include="Common\GPCS4Log.h" />
|
||||
<ClInclude Include="Common\GPCS4Types.h" />
|
||||
<ClInclude Include="Common\IntelliSenseClang.h" />
|
||||
<ClInclude Include="Emulator\ModuleManger.h" />
|
||||
<ClInclude Include="Emulator\PolicyManager.h" />
|
||||
<ClInclude Include="Emulator\SymbolManager.h" />
|
||||
<ClInclude Include="Graphic\Gnm\GnmGpuAddressTool.h" />
|
||||
<ClInclude Include="Graphic\Gnm\GnmTiler.h" />
|
||||
<ClInclude Include="Graphic\Gnm\GnmTilerSSE2.h" />
|
||||
|
@ -270,8 +273,11 @@
|
|||
<ClCompile Include="Emulator\GameThread.cpp" />
|
||||
<ClCompile Include="Emulator\Linker.cpp" />
|
||||
<ClCompile Include="Emulator\Module.cpp" />
|
||||
<ClCompile Include="Emulator\ModuleManger.cpp" />
|
||||
<ClCompile Include="Emulator\PolicyManager.cpp" />
|
||||
<ClCompile Include="Emulator\RegisterModules.cpp" />
|
||||
<ClCompile Include="Emulator\SceModuleSystem.cpp" />
|
||||
<ClCompile Include="Emulator\SymbolManager.cpp" />
|
||||
<ClCompile Include="Emulator\TLSHandler.cpp" />
|
||||
<ClCompile Include="GPCS4Main.cpp" />
|
||||
<ClCompile Include="Graphic\Gnm\GnmCmdStream.cpp" />
|
||||
|
|
|
@ -907,6 +907,15 @@
|
|||
<ClInclude Include="SceModules\SceAppContentUtil\sce_appcontentutil_error.h">
|
||||
<Filter>SceModules\SceAppContentUtil</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emulator\PolicyManager.h">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emulator\SymbolManager.h">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emulator\ModuleManger.h">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Loader\EbootObject.cpp">
|
||||
|
@ -1581,6 +1590,15 @@
|
|||
<ClCompile Include="Graphic\Gve\GveSharpResourceManager.cpp">
|
||||
<Filter>Source Files\Graphic\Gve</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emulator\PolicyManager.cpp">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emulator\SymbolManager.cpp">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emulator\ModuleManger.cpp">
|
||||
<Filter>Source Files\Emulator</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="Emulator\TLSStub.asm">
|
||||
|
|
|
@ -70,7 +70,7 @@ int main(int argc, char *argv[])
|
|||
ModuleLoader loader = { *CSceModuleSystem::GetInstance(), linker };
|
||||
|
||||
auto eboot = optResult["E"].as<std::string>();
|
||||
MemoryMappedModule *ebootModule = nullptr;
|
||||
NativeModule *ebootModule = nullptr;
|
||||
if (!loader.loadModule(eboot, &ebootModule))
|
||||
{
|
||||
break;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
LOG_CHANNEL(Loader.ELFMapper);
|
||||
|
||||
bool ELFMapper::loadFile(std::string const &filePath, MemoryMappedModule *mod)
|
||||
bool ELFMapper::loadFile(std::string const &filePath, NativeModule *mod)
|
||||
{
|
||||
UtilFile::file_uptr file = {};
|
||||
bool retVal = false;
|
||||
|
|
|
@ -17,7 +17,7 @@ public:
|
|||
ELFMapper(ELFMapper const &) = delete;
|
||||
void operator=(ELFMapper const &) = delete;
|
||||
|
||||
bool loadFile(std::string const &filePath, MemoryMappedModule *mod);
|
||||
bool loadFile(std::string const &filePath, NativeModule *mod);
|
||||
bool validateHeader();
|
||||
bool parseSegmentHeaders();
|
||||
bool parseDynamicSection();
|
||||
|
@ -36,5 +36,5 @@ private:
|
|||
bool mapSecReloSegment(Elf64_Phdr const &phdr);
|
||||
bool mapDataSegment(Elf64_Phdr const &phdr);
|
||||
|
||||
MemoryMappedModule *m_moduleData;
|
||||
NativeModule *m_moduleData;
|
||||
};
|
||||
|
|
|
@ -21,12 +21,12 @@ ModuleLoader::ModuleLoader(CSceModuleSystem &modSystem,
|
|||
}
|
||||
|
||||
bool ModuleLoader::loadModule(std::string const &fileName,
|
||||
MemoryMappedModule **modOut)
|
||||
NativeModule **modOut)
|
||||
{
|
||||
bool retVal = false;
|
||||
do
|
||||
{
|
||||
MemoryMappedModule mod = {};
|
||||
NativeModule mod = {};
|
||||
|
||||
bool exist = false;
|
||||
retVal = loadModuleFromFile(fileName, &mod, &exist);
|
||||
|
@ -40,7 +40,7 @@ bool ModuleLoader::loadModule(std::string const &fileName,
|
|||
mod.outputUnresolvedSymbols("unresolved_HLE.txt");
|
||||
#endif // MODSYS_OUTPUT_NOT_IMPLEMENTED_HLE
|
||||
|
||||
retVal = m_modSystem.registerMemoryMappedModule(mod.fileName, std::move(mod));
|
||||
retVal = m_modSystem.registerNativeModule(mod.fileName, std::move(mod));
|
||||
if (!retVal)
|
||||
{
|
||||
LOG_ERR("Failed to register module: %s", mod.fileName.c_str());
|
||||
|
@ -65,7 +65,7 @@ bool ModuleLoader::loadModule(std::string const &fileName,
|
|||
break;
|
||||
}
|
||||
|
||||
*modOut = &(m_modSystem.getMemoryMappedModules()[0]);
|
||||
*modOut = &(m_modSystem.getAllNativeModules()[0]);
|
||||
retVal = true;
|
||||
} while (false);
|
||||
|
||||
|
@ -73,7 +73,7 @@ bool ModuleLoader::loadModule(std::string const &fileName,
|
|||
}
|
||||
|
||||
bool ModuleLoader::loadModuleFromFile(std::string const &fileName,
|
||||
MemoryMappedModule *mod,
|
||||
NativeModule *mod,
|
||||
bool *exist)
|
||||
{
|
||||
LOG_ASSERT(mod != nullptr, "mod is nullpointer");
|
||||
|
@ -89,7 +89,7 @@ bool ModuleLoader::loadModuleFromFile(std::string const &fileName,
|
|||
break;
|
||||
}
|
||||
|
||||
bool isLoaded = m_modSystem.isMemoryMappedModuleLoaded(mod->fileName);
|
||||
bool isLoaded = m_modSystem.isNativeModuleLoaded(mod->fileName);
|
||||
if (isLoaded)
|
||||
{
|
||||
LOG_DEBUG("module %s has already been loaded", mod->fileName.c_str());
|
||||
|
@ -181,7 +181,7 @@ bool ModuleLoader::loadDependencies()
|
|||
}
|
||||
|
||||
bool exist = false;
|
||||
auto mod = MemoryMappedModule{};
|
||||
auto mod = NativeModule{};
|
||||
retVal = loadModuleFromFile(path, &mod, &exist);
|
||||
if (!retVal)
|
||||
{
|
||||
|
@ -197,7 +197,7 @@ bool ModuleLoader::loadDependencies()
|
|||
|
||||
if (!exist)
|
||||
{
|
||||
retVal = m_modSystem.registerMemoryMappedModule(mod.fileName, std::move(mod));
|
||||
retVal = m_modSystem.registerNativeModule(mod.fileName, std::move(mod));
|
||||
if (!retVal)
|
||||
{
|
||||
LOG_ERR("Failed to register module: %s", mod.fileName.c_str());
|
||||
|
@ -209,7 +209,7 @@ bool ModuleLoader::loadDependencies()
|
|||
return retVal || moduleNotFoundIgnore;
|
||||
}
|
||||
|
||||
bool ModuleLoader::addDepedenciesToLoad(MemoryMappedModule const &mod)
|
||||
bool ModuleLoader::addDepedenciesToLoad(NativeModule const &mod)
|
||||
{
|
||||
for (auto const &file : mod.getNeededFiles())
|
||||
{
|
||||
|
@ -274,7 +274,7 @@ bool ModuleLoader::mapFilePathToModuleName(std::string const &filePath,
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool ModuleLoader::registerSymbol(MemoryMappedModule const &mod,
|
||||
bool ModuleLoader::registerSymbol(NativeModule const &mod,
|
||||
std::string const &encName,
|
||||
void *pointer)
|
||||
{
|
||||
|
@ -291,7 +291,7 @@ bool ModuleLoader::registerSymbol(MemoryMappedModule const &mod,
|
|||
break;
|
||||
}
|
||||
|
||||
retVal = m_modSystem.registerNativeFunction(modName, libName, nid, pointer);
|
||||
retVal = m_modSystem.registerNativeSymbol(modName, libName, nid, pointer);
|
||||
if (!retVal)
|
||||
{
|
||||
break;
|
||||
|
@ -303,21 +303,21 @@ bool ModuleLoader::registerSymbol(MemoryMappedModule const &mod,
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool ModuleLoader::registerSymbol(MemoryMappedModule const &mod, size_t idx)
|
||||
bool ModuleLoader::registerSymbol(NativeModule const &mod, size_t idx)
|
||||
{
|
||||
const SymbolInfo *info = nullptr;
|
||||
mod.getSymbol(idx, &info);
|
||||
|
||||
if (info->isEncoded)
|
||||
{
|
||||
m_modSystem.registerNativeFunction(info->moduleName, info->libraryName, info->nid,
|
||||
m_modSystem.registerNativeSymbol(info->moduleName, info->libraryName, info->nid,
|
||||
reinterpret_cast<void *>(info->address));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_modSystem.registerSymbol(info->moduleName, info->libraryName,
|
||||
info->symbolName,
|
||||
reinterpret_cast<void *>(info->address));
|
||||
m_modSystem.registerNativeSymbol(info->moduleName, info->libraryName,
|
||||
info->symbolName,
|
||||
reinterpret_cast<void *>(info->address));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -326,7 +326,7 @@ bool ModuleLoader::registerSymbol(MemoryMappedModule const &mod, size_t idx)
|
|||
|
||||
bool ModuleLoader::initializeModules()
|
||||
{
|
||||
auto &mods = m_modSystem.getMemoryMappedModules();
|
||||
auto &mods = m_modSystem.getAllNativeModules();
|
||||
bool retVal = true;
|
||||
|
||||
auto tlsManager = TLSManager::GetInstance();
|
||||
|
|
|
@ -16,21 +16,21 @@ class ModuleLoader
|
|||
{
|
||||
public:
|
||||
ModuleLoader(CSceModuleSystem &modSystem, CLinker &linker);
|
||||
bool loadModule(std::string const &fileName, MemoryMappedModule **mod);
|
||||
bool loadModule(std::string const &fileName, NativeModule **mod);
|
||||
private:
|
||||
bool loadModuleFromFile(std::string const &fileName,
|
||||
MemoryMappedModule *mod,
|
||||
NativeModule *mod,
|
||||
bool *exist);
|
||||
bool loadDependencies();
|
||||
bool addDepedenciesToLoad(MemoryMappedModule const &mod);
|
||||
bool addDepedenciesToLoad(NativeModule const &mod);
|
||||
bool mapModuleNameToFilePath(std::string const &modName, std::string *path);
|
||||
bool mapFilePathToModuleName(std::string const &filePath,
|
||||
std::string *modName);
|
||||
|
||||
bool registerSymbol(MemoryMappedModule const &mod,
|
||||
bool registerSymbol(NativeModule const &mod,
|
||||
std::string const &encName,
|
||||
void *pointer);
|
||||
bool registerSymbol(MemoryMappedModule const &mod, size_t idx);
|
||||
bool registerSymbol(NativeModule const &mod, size_t idx);
|
||||
bool initializeModules();
|
||||
|
||||
private:
|
||||
|
|
|
@ -11,6 +11,18 @@ struct SCE_EXPORT_FUNCTION
|
|||
const uint64_t nNid;
|
||||
const char* szFunctionName;
|
||||
const void* pFunction;
|
||||
|
||||
bool isEndEntry() const
|
||||
{
|
||||
auto pFunc = this;
|
||||
return (pFunc->nNid == 0 && pFunc->szFunctionName == nullptr &&
|
||||
pFunc->pFunction == nullptr);
|
||||
}
|
||||
|
||||
const SCE_EXPORT_FUNCTION *iterNext() const
|
||||
{
|
||||
return this + 1;
|
||||
}
|
||||
};
|
||||
#define SCE_FUNCTION_ENTRY_END {0, NULL, NULL}
|
||||
|
||||
|
@ -19,6 +31,17 @@ struct SCE_EXPORT_LIBRARY
|
|||
{
|
||||
const char* szLibraryName;
|
||||
const SCE_EXPORT_FUNCTION *pFunctionEntries;
|
||||
|
||||
bool isEndEntry() const
|
||||
{
|
||||
auto pLib = this;
|
||||
return (pLib->szLibraryName == nullptr && pLib->pFunctionEntries == nullptr);
|
||||
}
|
||||
|
||||
const SCE_EXPORT_LIBRARY *iterNext() const
|
||||
{
|
||||
return this + 1;
|
||||
}
|
||||
};
|
||||
#define SCE_LIBRARY_ENTRY_END {NULL, NULL}
|
||||
|
||||
|
|
Loading…
Reference in a new issue