From 4975177c34506c61e1cd8dadb83afe01c7a012ee Mon Sep 17 00:00:00 2001 From: NovaRain Date: Mon, 9 Sep 2019 12:55:24 +0800 Subject: [PATCH] Added printing a list of all mem addrs in the log for debug version * for checking hidden memory conflicts. --- sfall/Modules/BugFixes.cpp | 1 + sfall/SafeWrite.cpp | 82 +++++++++++++++++++++++++------------- sfall/SafeWrite.h | 12 +++--- 3 files changed, 62 insertions(+), 33 deletions(-) diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index aacfb99a..0f4bf061 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -2294,6 +2294,7 @@ static void __declspec(naked) map_check_state_hook() { void BugFixes::init() { #ifndef NDEBUG + LoadGameHook::OnBeforeGameClose() += PrintAddrList; if (isDebug && (GetPrivateProfileIntA("Debugging", "BugFixes", 1, ::sfall::ddrawIni) == 0)) return; #endif diff --git a/sfall/SafeWrite.cpp b/sfall/SafeWrite.cpp index e6adf9d6..371707c0 100644 --- a/sfall/SafeWrite.cpp +++ b/sfall/SafeWrite.cpp @@ -1,7 +1,3 @@ -#ifndef NDEBUG -#include -#endif - #include "main.h" #pragma warning(disable:4996) @@ -16,21 +12,45 @@ enum CodeType : BYTE { }; #ifndef NDEBUG -std::list writeAddress; +std::multimap writeAddress; -void CheckConflict(DWORD addr) { - bool exist = false; +/* Checking for conflicts requires all options in ddraw.ini to be enabled */ +void PrintAddrList() { + unsigned long prev = 0, plen = 0; for (const auto &wa : writeAddress) { - if (addr == wa) { - exist = true; - char buf[256]; - dlog_f("Memory writing conflict at address: 0x%x\n", DL_MAIN, addr); - sprintf_s(buf, "Memory writing conflict at address 0x%x. The address has already been overwritten by other code.", addr); - MessageBoxA(0, buf, "Conflict Detected", MB_TASKMODAL); + unsigned long diff = (prev) ? (wa.first - prev) : -1; // length between two addresses + if (diff == 0 || diff < plen) { + dlog_f("0x%x L:%d [Conflict]\n", DL_MAIN, wa.first, wa.second); + } else if (diff == plen) { + dlog_f("0x%x L:%d [Warning] PL:%d\n", DL_MAIN, wa.first, wa.second, plen); + } else { + dlog_f("0x%x L:%d\n", DL_MAIN, wa.first, wa.second); } + prev = wa.first; + plen = wa.second; } - if (!exist) writeAddress.push_back(addr); } + +void CheckConflict(DWORD addr, long len) { + writeAddress.begin()->first; + if (writeAddress.find(addr) != writeAddress.cend()) { + char buf[64]; + sprintf_s(buf, "Memory writing conflict at address 0x%x.", addr); + //dlogr(buf, DL_MAIN); + MessageBoxA(0, buf, "", MB_TASKMODAL); + } + writeAddress.emplace(addr, len); +} + +void AddrAddToList(DWORD addr, long len) { + writeAddress.emplace(addr, len); +} + +#define _CheckConflict(addr, len) CheckConflict(addr, len); +#define _AddrAddToList(addr, len) AddrAddToList(addr, len); +#else +#define _CheckConflict(a, b) +#define _AddrAddToList(a, b) #endif static void _stdcall SafeWriteFunc(BYTE code, DWORD addr, void* func) { @@ -41,9 +61,7 @@ static void _stdcall SafeWriteFunc(BYTE code, DWORD addr, void* func) { *((DWORD*)(addr + 1)) = data; VirtualProtect((void *)addr, 5, oldProtect, &oldProtect); - #ifndef NDEBUG - CheckConflict(addr); - #endif + _CheckConflict(addr, 5); } static __declspec(noinline) void _stdcall SafeWriteFunc(BYTE code, DWORD addr, void* func, DWORD len) { @@ -61,9 +79,7 @@ static __declspec(noinline) void _stdcall SafeWriteFunc(BYTE code, DWORD addr, v } VirtualProtect((void *)addr, protectLen, oldProtect, &oldProtect); - #ifndef NDEBUG - CheckConflict(addr); - #endif + _CheckConflict(addr, protectLen); } void SafeWriteBytes(DWORD addr, BYTE* data, int count) { @@ -72,6 +88,8 @@ void SafeWriteBytes(DWORD addr, BYTE* data, int count) { VirtualProtect((void *)addr, count, PAGE_EXECUTE_READWRITE, &oldProtect); memcpy((void*)addr, data, count); VirtualProtect((void *)addr, count, oldProtect, &oldProtect); + + _AddrAddToList(addr, count) } void _stdcall SafeWrite8(DWORD addr, BYTE data) { @@ -80,6 +98,8 @@ void _stdcall SafeWrite8(DWORD addr, BYTE data) { VirtualProtect((void *)addr, 1, PAGE_EXECUTE_READWRITE, &oldProtect); *((BYTE*)addr) = data; VirtualProtect((void *)addr, 1, oldProtect, &oldProtect); + + _AddrAddToList(addr, 1) } void _stdcall SafeWrite16(DWORD addr, WORD data) { @@ -88,6 +108,8 @@ void _stdcall SafeWrite16(DWORD addr, WORD data) { VirtualProtect((void *)addr, 2, PAGE_EXECUTE_READWRITE, &oldProtect); *((WORD*)addr) = data; VirtualProtect((void *)addr, 2, oldProtect, &oldProtect); + + _AddrAddToList(addr, 2) } void _stdcall SafeWrite32(DWORD addr, DWORD data) { @@ -96,21 +118,25 @@ void _stdcall SafeWrite32(DWORD addr, DWORD data) { VirtualProtect((void *)addr, 4, PAGE_EXECUTE_READWRITE, &oldProtect); *((DWORD*)addr) = data; VirtualProtect((void *)addr, 4, oldProtect, &oldProtect); + + _AddrAddToList(addr, 4) } void _stdcall SafeWriteStr(DWORD addr, const char* data) { DWORD oldProtect; + long len = strlen(data) + 1; - VirtualProtect((void *)addr, strlen(data) + 1, PAGE_EXECUTE_READWRITE, &oldProtect); + VirtualProtect((void *)addr, len, PAGE_EXECUTE_READWRITE, &oldProtect); strcpy((char *)addr, data); - VirtualProtect((void *)addr, strlen(data) + 1, oldProtect, &oldProtect); + VirtualProtect((void *)addr, len, oldProtect, &oldProtect); + + _AddrAddToList(addr, len) } void HookCall(DWORD addr, void* func) { SafeWrite32(addr + 1, (DWORD)func - (addr + 5)); - #ifndef NDEBUG - CheckConflict(addr); - #endif + + _CheckConflict(addr, 1) } void MakeCall(DWORD addr, void* func) { @@ -147,6 +173,8 @@ void SafeMemSet(DWORD addr, BYTE val, int len) { VirtualProtect((void *)addr, len, PAGE_EXECUTE_READWRITE, &oldProtect); memset((void*)addr, val, len); VirtualProtect((void *)addr, len, oldProtect, &oldProtect); + + _AddrAddToList(addr, len) } void BlockCall(DWORD addr) { @@ -157,9 +185,7 @@ void BlockCall(DWORD addr) { *((BYTE*)(addr + 4)) = 0x00; VirtualProtect((void *)addr, 5, oldProtect, &oldProtect); - #ifndef NDEBUG - CheckConflict(addr); - #endif + _CheckConflict(addr, 5) } } diff --git a/sfall/SafeWrite.h b/sfall/SafeWrite.h index 8618f41a..e7e6ca8d 100644 --- a/sfall/SafeWrite.h +++ b/sfall/SafeWrite.h @@ -5,18 +5,20 @@ namespace sfall { + #ifndef NDEBUG -void CheckConflict(DWORD addr); +void AddrAddToList(DWORD addr, long len); +void PrintAddrList(); #endif template void _stdcall SafeWrite(DWORD addr, T data) { - DWORD oldProtect; - VirtualProtect((void *)addr, sizeof(T), PAGE_EXECUTE_READWRITE, &oldProtect); + DWORD oldProtect; + VirtualProtect((void*)addr, sizeof(T), PAGE_EXECUTE_READWRITE, &oldProtect); *((T*)addr) = data; - VirtualProtect((void *)addr, sizeof(T), oldProtect, &oldProtect); + VirtualProtect((void*)addr, sizeof(T), oldProtect, &oldProtect); #ifndef NDEBUG - if (GetPrivateProfileIntA("Debugging", "Enable", 0, ::sfall::ddrawIni) == 2) CheckConflict(addr); + AddrAddToList(addr, sizeof(T)); #endif }