#pragma once #include enum ValueType { ValueType_invalid = -1, ValueType_uint8, ValueType_int8, ValueType_uint16, ValueType_int16, ValueType_uint32, ValueType_int32, ValueType_uint64, ValueType_int64, ValueType_float, ValueType_double, // Non-primitives: ValueType_string, ValueType_istring, ValueType_unkstring }; enum AddressType { AddressType_Physical, AddressType_Virtual }; enum SearchType { SearchType_ExactValue, SearchType_LessThanValue, SearchType_GreaterThanValue, SearchType_LessThanOrEqualToValue, SearchType_GreaterThanOrEqualToValue, // First scan only: SearchType_UnknownValue, SearchType_JalTo, // Next scan only: SearchType_ChangedValue, SearchType_UnchangedValue, SearchType_IncreasedValue, SearchType_DecreasedValue }; enum DisplayFormat { DisplayDefault, DisplayHex }; typedef union { uint8_t _uint8; int8_t _sint8; uint16_t _uint16; int16_t _sint16; uint32_t _uint32; int32_t _sint32; uint64_t _uint64; int64_t _sint64; float _float; double _double; const wchar_t* _string; } MixedValue; class CMixed { protected: ValueType m_Type; int m_StrLength; public: MixedValue m_Value; CMixed() { m_StrLength = 0; m_Value._uint64 = 0; m_Type = ValueType_uint64; } inline void SetType(ValueType t) { m_Type = t; } inline ValueType GetType(void) { return m_Type; } inline void SetStrLength(int length) { m_StrLength = length; } inline int GetStrLength(void) { return m_StrLength; } inline void Set(uint8_t v) { SetType(ValueType_uint8); m_Value._uint8 = v; } inline void Set(int8_t v) { SetType(ValueType_int8); m_Value._sint8 = v; } inline void Set(uint16_t v) { SetType(ValueType_uint16); m_Value._uint16 = v; } inline void Set(int16_t v) { SetType(ValueType_int16); m_Value._sint16 = v; } inline void Set(uint32_t v) { SetType(ValueType_uint32); m_Value._uint32 = v; } inline void Set(int32_t v) { SetType(ValueType_int32); m_Value._sint32 = v; } inline void Set(uint64_t v) { SetType(ValueType_uint64); m_Value._uint64 = v; } inline void Set(int64_t v) { SetType(ValueType_int64); m_Value._sint64 = v; } inline void Set(float v) { SetType(ValueType_float); m_Value._float = v; } inline void Set(double v) { SetType(ValueType_double); m_Value._double = v; } inline void Set(const wchar_t* v) { SetType(ValueType_string); m_Value._string = v; } inline void Get(uint8_t* v) { *v = m_Value._uint8; } inline void Get(int8_t* v) { *v = m_Value._sint8; } inline void Get(uint16_t* v) { *v = m_Value._uint16; } inline void Get(int16_t* v) { *v = m_Value._sint16; } inline void Get(uint32_t* v) { *v = m_Value._uint32; } inline void Get(int32_t* v) { *v = m_Value._sint32; } inline void Get(uint64_t* v) { *v = m_Value._uint64; } inline void Get(int64_t* v) { *v = m_Value._sint64; } inline void Get(float* v) { *v = m_Value._float; } inline void Get(double* v) { *v = m_Value._double; } inline void Get(const wchar_t** v) { *v = m_Value._string; } const char* GetTypeName(void); int GetTypeSize(void); bool IsStringType(void); int ToString(char* buffer, bool bHex, size_t size); static ValueType GetTypeFromString(const char* name, int* typeArraySize); private: typedef struct { const char* name; ValueType type; } TypeNameEntry; static TypeNameEntry TypeNames[]; }; class CScanResult : public CMixed { public: CScanResult(AddressType addressType, DisplayFormat displayFormat); ~CScanResult(void); uint32_t m_Address; AddressType m_AddressType; DisplayFormat m_DisplayFormat; bool m_bSelected; char* m_Description; public: int GetValueString(char* buffer, size_t size); int GetMemoryValueString(char* buffer, size_t size, bool bIgnoreHex = false); int GetAddressString(char *buffer); uint32_t GetVirtualAddress(void); bool SetMemoryValueFromString(const char* str); //bool IsSelected(void); //void SetSelected(bool bSelected); void SetDescription(const char* str); const char* GetDescription(void); void DeleteDescription(void); bool GetMemoryValue(CMixed* v); bool SetAddressSafe(uint32_t address); bool SetStrLengthSafe(int length); }; class CMemoryScanner { public: CMemoryScanner(void); bool SetAddressRange(uint32_t startAddress, uint32_t endAddress); bool SetValueType(ValueType type); bool SetSearchType(SearchType searchType); void SetAddressType(AddressType addressType); static int ParseHexString(char* dst, const char* src); static bool AddrCheck(uint32_t addr, uint32_t rangeStart, uint32_t rangeEnd); static bool RangeCheck(uint32_t addrStart, uint32_t addrEnd, uint32_t rangeStart, uint32_t rangeEnd); static bool PAddrValid(uint32_t physAddr); static bool PAddrRangeValid(uint32_t physAddrStart, uint32_t physAddrEnd); template void SetValue(T value) { *(T*)&m_Value = value; } void SetStringValueLength(int length); void Reset(void); bool FirstScan(DisplayFormat resDisplayFormat = DisplayDefault); bool NextScan(void); bool DidFirstScan(void); size_t GetNumResults(void); CScanResult* GetResult(size_t index); void RemoveResult(size_t index); private: static int HexDigitVal(char c); uint8_t* m_Memory; bool m_DidFirstScan; uint32_t m_RangeStartAddress; uint32_t m_RangeEndAddress; ValueType m_ValueType; bool m_bDataTypePrimitive; SearchType m_SearchType; AddressType m_AddressType; uint32_t m_VAddrBits; std::vector m_Results; std::vector m_NewResults; MixedValue m_Value; int m_StringValueLength; friend class CScanResult; static uint8_t* GetMemoryPool(uint32_t physAddr); template static bool CompareLessThan(T a, T b) { return a < b; } template static bool CompareLessThanOrEqual(T a, T b) { return a <= b; } template static bool CompareGreaterThan(T a, T b) { return a > b; } template static bool CompareGreaterThanOrEqual(T a, T b) { return a >= b; } template static bool CompareEqual(T a, T b) { return a == b; } template static bool CompareNotEqual(T a, T b) { return a != b; } template static bool NoCompare(T /*a*/, T /*b*/) { return true; } void FirstScanLoopString(DisplayFormat resultDisplayFormat); void FirstScanLoopIString(DisplayFormat resultDisplayFormat); void FirstScanLoopUnkString(void); template void FirstScanLoopPrimitive(bool(*CompareFunc)(T, T), DisplayFormat resultDisplayFormat) { T searchValue = *(T*)&m_Value; uint32_t startAddr = ((m_RangeStartAddress - 1) | (sizeof(T) - 1)) + 1; uint32_t endAddr = m_RangeEndAddress; CScanResult result(m_AddressType, resultDisplayFormat); for (uint32_t addr = startAddr; addr <= endAddr; addr += sizeof(T)) { uint32_t leAddr = (addr ^ (4 - sizeof(T))); T memValue = *(T*)&m_Memory[leAddr]; if (CompareFunc(memValue, searchValue)) { result.m_Address = addr | m_VAddrBits; result.Set(memValue); m_Results.push_back(result); } } } // For int64 and double template void FirstScanLoopPrimitive64(bool(*CompareFunc)(T, T), DisplayFormat resultDisplayFormat) { T searchValue = *(T*)&m_Value; uint32_t startAddr = ((m_RangeStartAddress - 1) | (sizeof(T) - 1)) + 1; uint32_t endAddr = m_RangeEndAddress; CScanResult result(m_AddressType, resultDisplayFormat); for (uint32_t addr = startAddr; addr <= endAddr; addr += sizeof(T)) { T memValue; *((uint32_t*)(&memValue) + 1) = *(uint32_t*) &m_Memory[addr]; *((uint32_t*)(&memValue) + 0) = *(uint32_t*) &m_Memory[addr + 4]; if (CompareFunc(memValue, searchValue)) { result.m_Address = addr | m_VAddrBits; result.Set(memValue); m_Results.push_back(result); } } } // Compare result's current value in memory against m_Value template void NextScanLoopPrimitive(bool(*CompareFunc)(T, T)) { T searchValue = *(T*)&m_Value; for (size_t index = 0; index < m_Results.size(); index++) { CScanResult* presult = &m_Results[index]; uint32_t addr = presult->m_Address & 0x1FFFFFFF; uint32_t leAddr = (addr ^ (4 - sizeof(T))); T memValue = *(T*) &m_Memory[leAddr]; if (CompareFunc(memValue, searchValue)) { presult->Set(memValue); m_NewResults.push_back(*presult); } } m_Results.clear(); m_Results.swap(m_NewResults); } // Compare result's current value in memory against m_Value (for 64-bit types) template void NextScanLoopPrimitive64(bool(*CompareFunc)(T, T)) { T searchValue = *(T*)&m_Value; for (size_t index = 0; index < m_Results.size(); index++) { CScanResult* presult = &m_Results[index]; uint32_t addr = presult->m_Address & 0x1FFFFFFF; T memValue; *((uint32_t*)(&memValue) + 1) = *(uint32_t*) &m_Memory[addr]; *((uint32_t*)(&memValue) + 0) = *(uint32_t*) &m_Memory[addr + 4]; if (CompareFunc(memValue, searchValue)) { presult->Set(memValue); m_NewResults.push_back(*presult); } } m_Results.clear(); m_Results.swap(m_NewResults); } // Compare result's current value in memory against result's old value template void NextScanLoopPrimitiveResults(bool(*CompareFunc)(T, T)) { for (size_t index = 0; index < m_Results.size(); index++) { CScanResult* presult = &m_Results[index]; uint32_t addr = presult->m_Address & 0x1FFFFFFF; uint32_t leAddr = (addr ^ (4 - sizeof(T))); T memValue, oldValue; memValue = *(T*)&m_Memory[leAddr]; presult->Get(&oldValue); if (CompareFunc(memValue, oldValue)) { presult->Set(memValue); m_NewResults.push_back(*presult); } } m_Results.clear(); m_Results.swap(m_NewResults); } // Compare result's current value in memory against result's old value (for 64-bit types) template void NextScanLoopPrimitiveResults64(bool(*CompareFunc)(T, T)) { for (size_t index = 0; index < m_Results.size(); index++) { CScanResult* presult = &m_Results[index]; uint32_t addr = presult->m_Address & 0x1FFFFFFF; T memValue, oldValue; *((uint32_t*)(&memValue) + 1) = *(uint32_t*)&m_Memory[addr]; *((uint32_t*)(&memValue) + 0) = *(uint32_t*)&m_Memory[addr + 4]; presult->Get(&oldValue); if (CompareFunc(memValue, oldValue)) { presult->Set(memValue); m_NewResults.push_back(*presult); } } m_Results.clear(); m_Results.swap(m_NewResults); } };