Finish Signature Cache Map implementation

* Fixed bug where the system still added entries after we are initialized (file has already been written to the disk).
* Moved loading logic to CSigCache class.
* Dedicated and Host/Client now have their own cache files.
This commit is contained in:
Kawe Mazidjatari 2022-12-02 12:12:13 +01:00
parent 81fbf9ded7
commit b90d6f929c
3 changed files with 84 additions and 72 deletions

View File

@ -258,11 +258,6 @@ void Systems_Init()
spdlog::info("+-------------------------------------------------------------+\n");
ConVar::Init();
#ifdef DEDICATED
Dedicated_Init();
#endif // DEDICATED
SpdLog_PostInit();
std::thread fixed(&CEngineSDK::FixedFrame, g_EngineSDK);
@ -473,59 +468,12 @@ void CheckCPU() // Respawn's engine and our SDK utilize POPCNT, SSE3 and SSSE3 (
}
}
#include "protoc/sig_map.pb.h"
bool SigDB_Init()
{
CIOStream sigDbStream("bin\\startup.smap", CIOStream::Mode_t::READ);
if (!sigDbStream.IsReadable())
{
return false;
}
if (!sigDbStream.GetSize() > sizeof(SigDBHeader_t))
{
return false;
}
SigDBHeader_t sigDbHeader;
sigDbHeader.m_nMagic = sigDbStream.Read<int>();
if (sigDbHeader.m_nMagic != SIGDB_MAGIC)
{
return false;
}
sigDbHeader.m_nVersion = sigDbStream.Read<int>();
if (sigDbHeader.m_nVersion != SIGDB_VERSION)
{
return false;
}
sigDbHeader.m_FileTime = sigDbStream.Read<FILETIME>();
vector<uint8_t> vData;
size_t nSize = (static_cast<size_t>(sigDbStream.GetSize()) - sizeof(SigDBHeader_t));
vData.resize(nSize);
uint8_t* pBuf = vData.data();
sigDbStream.Read<uint8_t>(*pBuf, nSize);
if (!g_SigCache.m_Cache.ParseFromArray(pBuf, nSize))
{
return false;
}
return true;
}
void DetourInit() // Run the sigscan
{
bool bLogAdr = (strstr(GetCommandLineA(), "-sig_toconsole") != nullptr);
bool bInitDivider = false;
g_SigCache.m_bInitialized = SigDB_Init();
g_SigCache.LoadCache(SIGDB_FILE);
for (const IDetour* pDetour : vDetour)
{
@ -544,8 +492,14 @@ void DetourInit() // Run the sigscan
}
}
g_SigCache.WriteCache();
#ifdef DEDICATED
// Must be performed after detour init as we patch instructions which alters the function signatures.
Dedicated_Init();
#endif // DEDICATED
g_SigCache.WriteCache(SIGDB_FILE);
}
void DetourAddress() // Test the sigscan results
{
spdlog::debug("+----------------------------------------------------------------+\n");

View File

@ -14,10 +14,8 @@
//-----------------------------------------------------------------------------
void CSigCache::AddEntry(const string& svPattern, const uint64_t nRVA)
{
if (g_SigCache.m_bUseCache)
{
(*g_SigCache.m_Cache.mutable_smap())[svPattern] = nRVA;
}
Assert(!m_bInitialized);
(*m_Cache.mutable_smap())[svPattern] = nRVA;
}
//-----------------------------------------------------------------------------
@ -28,9 +26,9 @@ void CSigCache::AddEntry(const string& svPattern, const uint64_t nRVA)
//-----------------------------------------------------------------------------
bool CSigCache::FindEntry(const string& svPattern, uint64_t& nRVA) const
{
if (g_SigCache.m_bInitialized)
if (m_bInitialized)
{
google::protobuf::Map sMap = g_SigCache.m_Cache.smap();
google::protobuf::Map sMap = m_Cache.smap();
auto p = sMap.find(svPattern);
if (p != sMap.end())
@ -44,16 +42,72 @@ bool CSigCache::FindEntry(const string& svPattern, uint64_t& nRVA) const
}
//-----------------------------------------------------------------------------
// Purpose: writes the cache map to the disk
// Purpose: loads the cache map from the disk
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
void CSigCache::WriteCache()
bool CSigCache::LoadCache(const string& svCacheFile)
{
CIOStream writer("bin\\startup.smap", CIOStream::Mode_t::WRITE);
Assert(!m_bInitialized); // Recursive load.
CIOStream reader(svCacheFile, CIOStream::Mode_t::READ);
if (!reader.IsReadable())
{
return false;
}
if (!reader.GetSize() > sizeof(SigDBHeader_t))
{
return false;
}
SigDBHeader_t sigDbHeader;
sigDbHeader.m_nMagic = reader.Read<int>();
if (sigDbHeader.m_nMagic != SIGDB_MAGIC)
{
return false;
}
sigDbHeader.m_nVersion = reader.Read<int>();
if (sigDbHeader.m_nVersion != SIGDB_VERSION)
{
return false;
}
sigDbHeader.m_FileTime = reader.Read<FILETIME>();
vector<uint8_t> vData;
size_t nSize = (static_cast<size_t>(reader.GetSize()) - sizeof(SigDBHeader_t));
vData.resize(nSize);
uint8_t* pBuf = vData.data();
reader.Read<uint8_t>(*pBuf, nSize);
if (!m_Cache.ParseFromArray(pBuf, nSize))
{
return false;
}
m_bInitialized = true;
return true;
}
//-----------------------------------------------------------------------------
// Purpose: writes the cache map to the disk
// Output : true on success, false otherwise
//-----------------------------------------------------------------------------
bool CSigCache::WriteCache(const string& svCacheFile)
{
if (m_bInitialized)
{
// Only write when we don't have anything valid on the disk.
return false;
}
CIOStream writer(svCacheFile, CIOStream::Mode_t::WRITE);
if (!writer.IsWritable())
{
// Error message..
return;
return false;
}
SigDBHeader_t header;
@ -65,4 +119,6 @@ void CSigCache::WriteCache()
writer.Write(header);
writer.Write(svBuffer.data(), svBuffer.size());
}
return true;
}

View File

@ -6,21 +6,23 @@
#define SIGDB_MAGIC (('p'<<24)+('a'<<16)+('M'<<8)+'S')
#define SIGDB_VERSION 0x1
#ifdef DEDICATED
#define SIGDB_FILE "cfg\\server\\startup.bin"
#else
#define SIGDB_FILE "cfg\\client\\startup.bin"
#endif
class CSigCache
{
public:
// Save
// Load
// Clear
void AddEntry(const string& svPattern, const uint64_t nRVA);
bool FindEntry(const string& svPattern, uint64_t& nRVA) const;
void WriteCache();
bool LoadCache(const string& svCacheFile);
bool WriteCache(const string& svCacheFile);
SigMap_Pb m_Cache;
bool m_bInitialized;
bool m_bUseCache = true;
};
struct SigDBHeader_t