From 525fc4fe8a94ecc1d2563fce68536687a4227340 Mon Sep 17 00:00:00 2001 From: spxtr Date: Wed, 30 Dec 2015 19:10:31 -0800 Subject: [PATCH] Allow MemoryWatcher to follow pointers --- Source/Core/Core/MemoryWatcher.cpp | 47 +++++++++++++++++++++++------- Source/Core/Core/MemoryWatcher.h | 21 +++++++++---- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/Source/Core/Core/MemoryWatcher.cpp b/Source/Core/Core/MemoryWatcher.cpp index ecce7aa714..39d355b048 100644 --- a/Source/Core/Core/MemoryWatcher.cpp +++ b/Source/Core/Core/MemoryWatcher.cpp @@ -11,7 +11,7 @@ #include "Core/HW/Memmap.h" // We don't want to kill the cpu, so sleep for this long after polling. -static const int SLEEP_DURATION = 10; // ms +static const int SLEEP_DURATION = 2; // ms MemoryWatcher::MemoryWatcher() { @@ -39,14 +39,25 @@ bool MemoryWatcher::LoadAddresses(const std::string& path) if (!locations) return false; - u32 data; - locations >> std::hex; - while (locations >> data) - m_values[data] = 0; + std::string line; + while (std::getline(locations, line)) + ParseLine(line); return m_values.size() > 0; } +void MemoryWatcher::ParseLine(const std::string& line) +{ + m_values[line] = 0; + m_addresses[line] = std::vector(); + + std::stringstream offsets(line); + offsets >> std::hex; + u32 offset; + while (offsets >> offset) + m_addresses[line].push_back(offset); +} + bool MemoryWatcher::OpenSocket(const std::string& path) { memset(&m_addr, 0, sizeof(m_addr)); @@ -57,24 +68,40 @@ bool MemoryWatcher::OpenSocket(const std::string& path) return m_fd >= 0; } +u32 MemoryWatcher::ChasePointer(const std::string& line) +{ + u32 value = 0; + for (u32 offset : m_addresses[line]) + value = Memory::Read_U32(value + offset); + return value; +} + +std::string MemoryWatcher::ComposeMessage(const std::string& line, u32 value) +{ + std::stringstream message_stream; + message_stream << line << '\n' << std::hex << value; + return message_stream.str(); +} + void MemoryWatcher::WatcherThread() { while (m_running) { for (auto& entry : m_values) { - u32 address = entry.first; + std::string address = entry.first; u32& current_value = entry.second; - u32 new_value = Memory::Read_U32(address); + u32 new_value = ChasePointer(address); if (new_value != current_value) { + // Update the value current_value = new_value; - u32 buf[2] = {address, current_value}; + std::string message = ComposeMessage(address, new_value); sendto( m_fd, - static_cast(buf), - sizeof(buf), + message.c_str(), + message.size() + 1, 0, reinterpret_cast(&m_addr), sizeof(m_addr)); diff --git a/Source/Core/Core/MemoryWatcher.h b/Source/Core/Core/MemoryWatcher.h index 8f2e36c1bc..ebe2b89c50 100644 --- a/Source/Core/Core/MemoryWatcher.h +++ b/Source/Core/Core/MemoryWatcher.h @@ -7,16 +7,18 @@ #include #include #include +#include #include #include // MemoryWatcher reads a file containing in-game memory addresses and outputs // changes to those memory addresses to a unix domain socket as the game runs. // -// The input file is a newline-separated list of hex memory addresses -// (without the "0x"). The output to the socket is two words long, the first -// containing the address, and the second containing the data as stored in -// game memory. +// The input file is a newline-separated list of hex memory addresses, without +// the "0x". To follow pointers, separate addresses with a space. For example, +// "ABCD EF" will watch the address at (*0xABCD) + 0xEF. +// The output to the socket is two lines. The first is the address from the +// input file, and the second is the new value in hex. class MemoryWatcher final { public: @@ -26,6 +28,11 @@ public: private: bool LoadAddresses(const std::string& path); bool OpenSocket(const std::string& path); + + void ParseLine(const std::string& line); + u32 ChasePointer(const std::string& line); + std::string ComposeMessage(const std::string& line, u32 value); + void WatcherThread(); std::thread m_watcher_thread; @@ -34,6 +41,8 @@ private: int m_fd; sockaddr_un m_addr; - // Address -> last value - std::map m_values; + // Address as stored in the file -> list of offsets to follow + std::map> m_addresses; + // Address as stored in the file -> current value + std::map m_values; };