Tier0: pattern searching code improvements

Eliminate extraneous type promotion/demotion.
This commit is contained in:
Kawe Mazidjatari 2025-01-01 21:33:02 +01:00
parent 2a357914da
commit 26f48507f4
4 changed files with 39 additions and 32 deletions

View File

@ -69,9 +69,9 @@ void FourCCToString(FourCCString_t& buf, const int n);
/////////////////////////////////////////////////////////////////////////////
// Bytes
vector<int> StringToBytes(const char* const szInput, const bool bNullTerminator);
vector<uint8_t> StringToBytes(const char* const szInput, const bool bNullTerminator);
pair<vector<uint8_t>, string> StringToMaskedBytes(const char* const szInput, const bool bNullTerminator);
vector<int> PatternToBytes(const char* const szInput);
vector<uint16_t> PatternToBytes(const char* const szInput);
pair<vector<uint8_t>, string> PatternToMaskedBytes(const char* const szInput);
vector<int> IntToDigits(int iValue);

View File

@ -78,22 +78,24 @@ CMemory CMemory::FindPattern(const char* szPattern, const Direction searchDirect
{
uint8_t* pScanBytes = reinterpret_cast<uint8_t*>(ptr); // Get the base of the module.
const vector<int> PatternBytes = PatternToBytes(szPattern); // Convert our pattern to a byte array.
const pair<size_t, const int*> bytesInfo = std::make_pair<size_t, const int*>(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
const vector<uint16_t> PatternBytes = PatternToBytes(szPattern); // Convert our pattern to a byte array.
const pair<size_t, const uint16_t*> bytesInfo = std::make_pair<size_t, const uint16_t*>(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
ptrdiff_t occurrences = 0;
for (long i = 01; i < opCodesToScan + bytesInfo.first; i++)
{
bool bFound = true;
int nMemOffset = searchDirect == Direction::DOWN ? i : -i;
const int nMemOffset = searchDirect == Direction::DOWN ? i : -i;
for (DWORD j = 0ul; j < bytesInfo.first; j++)
for (size_t j = 0ull; j < bytesInfo.first; j++)
{
// If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard
// our if clause will be false.
uint8_t* const pCurrentAddr = (pScanBytes + nMemOffset + j);
_mm_prefetch(reinterpret_cast<const char*>(pCurrentAddr + 64), _MM_HINT_T0); // precache some data in L1.
if (*pCurrentAddr != bytesInfo.second[j] && bytesInfo.second[j] != -1)
if (*pCurrentAddr != bytesInfo.second[j] && bytesInfo.second[j] != 0xffff)
{
bFound = false;
break;
@ -125,8 +127,9 @@ CMemory CMemory::FindPatternSelf(const char* szPattern, const Direction searchDi
{
uint8_t* pScanBytes = reinterpret_cast<uint8_t*>(ptr); // Get the base of the module.
const vector<int> PatternBytes = PatternToBytes(szPattern); // Convert our pattern to a byte array.
const pair<size_t, const int*> bytesInfo = std::make_pair<size_t, const int*>(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
const vector<uint16_t> PatternBytes = PatternToBytes(szPattern); // Convert our pattern to a byte array.
const pair<size_t, const uint16_t*> bytesInfo = std::make_pair<size_t, const uint16_t*>(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
ptrdiff_t occurrences = 0;
for (long i = 01; i < opCodesToScan + bytesInfo.first; i++)
@ -134,13 +137,13 @@ CMemory CMemory::FindPatternSelf(const char* szPattern, const Direction searchDi
bool bFound = true;
int nMemOffset = searchDirect == Direction::DOWN ? i : -i;
for (DWORD j = 0ul; j < bytesInfo.first; j++)
for (size_t j = 0ull; j < bytesInfo.first; j++)
{
// If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard
// our if clause will be false.
uint8_t* const pCurrentAddr = (pScanBytes + nMemOffset + j);
_mm_prefetch(reinterpret_cast<const char*>(pCurrentAddr + 64), _MM_HINT_T0); // precache some data in L1.
if (*pCurrentAddr != bytesInfo.second[j] && bytesInfo.second[j] != -1)
if (*pCurrentAddr != bytesInfo.second[j] && bytesInfo.second[j] != 0xffff)
{
bFound = false;
break;

View File

@ -296,9 +296,8 @@ CMemory CModule::FindStringReadOnly(const char* szString, bool bNullTerminator)
}
// Convert our string to a byte array.
const vector<int> vBytes = StringToBytes(szString, bNullTerminator);
const pair<size_t, const int*> bytesInfo = std::make_pair<
size_t, const int*>(vBytes.size(), vBytes.data()); // Get the size and data of our bytes.
const vector<uint8_t> vBytes = StringToBytes(szString, bNullTerminator);
const pair<size_t, const uint8_t*> bytesInfo = std::make_pair<size_t, const uint8_t*>(vBytes.size(), vBytes.data()); // Get the size and data of our bytes.
// Get start of .rdata section.
const uint8_t* pBase = reinterpret_cast<uint8_t*>(readOnlyData.m_pSectionBase);

View File

@ -912,10 +912,10 @@ string& StringTrim(string& svInput, const char* const pszToTrim, const bool bTri
///////////////////////////////////////////////////////////////////////////////
// For converting a string to an array of bytes.
vector<int> StringToBytes(const char* const szInput, const bool bNullTerminator)
vector<uint8_t> StringToBytes(const char* const szInput, const bool bNullTerminator)
{
const char* const pszStringEnd = szInput + strlen(szInput);
vector<int> vBytes;
vector<uint8_t> vBytes;
for (const char* pszCurrentByte = szInput; pszCurrentByte < pszStringEnd; ++pszCurrentByte)
{
@ -933,14 +933,14 @@ vector<int> StringToBytes(const char* const szInput, const bool bNullTerminator)
///////////////////////////////////////////////////////////////////////////////
// For converting a string to an array of bytes.
pair<vector<uint8_t>, string> StringToMaskedBytes(const char* szInput, bool bNullTerminator)
pair<vector<uint8_t>, string> StringToMaskedBytes(const char* const szInput, const bool bNullTerminator)
{
const char* pszStringStart = const_cast<char*>(szInput);
const char* pszStringEnd = pszStringStart + strlen(szInput);
vector<uint8_t> vBytes;
string svMask;
for (const char* pszCurrentByte = pszStringStart; pszCurrentByte < pszStringEnd; ++pszCurrentByte)
const char* pszStringEnd = szInput + strlen(szInput);
for (const char* pszCurrentByte = szInput; pszCurrentByte < pszStringEnd; ++pszCurrentByte)
{
// Dereference character and push back the byte.
vBytes.push_back(*pszCurrentByte);
@ -952,6 +952,7 @@ pair<vector<uint8_t>, string> StringToMaskedBytes(const char* szInput, bool bNul
vBytes.push_back(0x0);
svMask += 'x';
}
return make_pair(vBytes, svMask);
};
@ -968,50 +969,53 @@ void FourCCToString(FourCCString_t& buf, const int n)
///////////////////////////////////////////////////////////////////////////////
// For converting a string pattern with wildcards to an array of bytes.
vector<int> PatternToBytes(const char* szInput)
vector<uint16_t> PatternToBytes(const char* const szInput)
{
const char* pszPatternStart = const_cast<char*>(szInput);
const char* pszPatternEnd = pszPatternStart + strlen(szInput);
vector<int> vBytes;
vector<uint16_t> vBytes;
const char* const pszPatternEnd = szInput + strlen(szInput);
for (const char* pszCurrentByte = pszPatternStart; pszCurrentByte < pszPatternEnd; ++pszCurrentByte)
for (const char* pszCurrentByte = szInput; pszCurrentByte < pszPatternEnd; ++pszCurrentByte)
{
if (*pszCurrentByte == '?')
{
++pszCurrentByte;
if (*pszCurrentByte == '?')
{
++pszCurrentByte; // Skip double wildcard.
}
vBytes.push_back(-1); // Push the byte back as invalid.
vBytes.push_back(0xffff); // Push the byte back as invalid.
}
else
{
vBytes.push_back(strtoul(pszCurrentByte, const_cast<char**>(&pszCurrentByte), 16));
vBytes.push_back(static_cast<uint16_t>(strtoul(pszCurrentByte, const_cast<char**>(&pszCurrentByte), 16)));
}
}
return vBytes;
};
///////////////////////////////////////////////////////////////////////////////
// For converting a string pattern with wildcards to an array of bytes and mask.
pair<vector<uint8_t>, string> PatternToMaskedBytes(const char* szInput)
pair<vector<uint8_t>, string> PatternToMaskedBytes(const char* const szInput)
{
const char* pszPatternStart = const_cast<char*>(szInput);
const char* pszPatternEnd = pszPatternStart + strlen(szInput);
vector<uint8_t> vBytes;
string svMask;
for (const char* pszCurrentByte = pszPatternStart; pszCurrentByte < pszPatternEnd; ++pszCurrentByte)
const char* const pszPatternEnd = szInput + strlen(szInput);
for (const char* pszCurrentByte = szInput; pszCurrentByte < pszPatternEnd; ++pszCurrentByte)
{
if (*pszCurrentByte == '?')
{
++pszCurrentByte;
if (*pszCurrentByte == '?')
{
++pszCurrentByte; // Skip double wildcard.
}
vBytes.push_back(0); // Push the byte back as invalid.
svMask += '?';
}
@ -1021,6 +1025,7 @@ pair<vector<uint8_t>, string> PatternToMaskedBytes(const char* szInput)
svMask += 'x';
}
}
return make_pair(vBytes, svMask);
};