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:
DummyCatz 2020-02-09 23:20:48 +08:00 committed by GitHub
parent 6244e15907
commit a675be9384
23 changed files with 1301 additions and 855 deletions

View file

@ -31,7 +31,7 @@ void CEmulator::Unit()
modManager->clearModules();
}
bool CEmulator::Run(MemoryMappedModule const &mod)
bool CEmulator::Run(NativeModule const &mod)
{
bool retVal = false;

View file

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

View file

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

View file

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

View file

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

View file

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

View 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;
}

View 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;
};

View 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 };
}

View 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;
};

View file

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

View file

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

View file

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

View 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);
}

View 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;
};

View file

@ -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" />

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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