From 8fa898fe9a6ac5a090320613957ed5d511d05a28 Mon Sep 17 00:00:00 2001 From: Sepalani Date: Mon, 21 May 2018 18:46:03 +0400 Subject: DebugInterface: MemoryPatches methods added CodeView: Restore instruction added --- Source/Core/Common/CMakeLists.txt | 1 + Source/Core/Common/Common.vcxproj | 2 + Source/Core/Common/Common.vcxproj.filters | 8 ++- Source/Core/Common/Debug/MemoryPatches.cpp | 99 ++++++++++++++++++++++++++++++ Source/Core/Common/Debug/MemoryPatches.h | 52 ++++++++++++++++ Source/Core/Common/DebugInterface.h | 13 +++- 6 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 Source/Core/Common/Debug/MemoryPatches.cpp create mode 100644 Source/Core/Common/Debug/MemoryPatches.h (limited to 'Source/Core/Common') diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index c0e3e94462..0feb950b91 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -9,6 +9,7 @@ add_library(common Crypto/AES.cpp Crypto/bn.cpp Crypto/ec.cpp + Debug/MemoryPatches.cpp Debug/Watches.cpp ENetUtil.cpp File.cpp diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index c03dd0b6ac..995c6e733e 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -60,6 +60,7 @@ + @@ -176,6 +177,7 @@ + diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index b26498b90b..dd041d490b 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -269,6 +269,9 @@ Debug + + Debug + @@ -292,7 +295,6 @@ - @@ -344,6 +346,10 @@ Debug + + + Debug + diff --git a/Source/Core/Common/Debug/MemoryPatches.cpp b/Source/Core/Common/Debug/MemoryPatches.cpp new file mode 100644 index 0000000000..db7a40c58b --- /dev/null +++ b/Source/Core/Common/Debug/MemoryPatches.cpp @@ -0,0 +1,99 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Common/Debug/MemoryPatches.h" + +#include +#include + +namespace Common::Debug +{ +MemoryPatch::MemoryPatch(u32 address_, std::vector value_) + : address(address_), value(value_), is_enabled(State::Enabled) +{ +} + +MemoryPatch::MemoryPatch(u32 address, u32 value) + : MemoryPatch(address, {static_cast(value >> 24), static_cast(value >> 16), + static_cast(value >> 8), static_cast(value)}) +{ +} + +MemoryPatches::MemoryPatches() = default; +MemoryPatches::~MemoryPatches() = default; + +void MemoryPatches::SetPatch(u32 address, u32 value) +{ + const std::size_t index = m_patches.size(); + m_patches.emplace_back(address, value); + Patch(index); +} + +void MemoryPatches::SetPatch(u32 address, std::vector value) +{ + const std::size_t index = m_patches.size(); + m_patches.emplace_back(address, std::move(value)); + Patch(index); +} + +const std::vector& MemoryPatches::GetPatches() const +{ + return m_patches; +} + +void MemoryPatches::UnsetPatch(u32 address) +{ + const auto it = std::remove_if(m_patches.begin(), m_patches.end(), + [address](const auto& patch) { return patch.address == address; }); + + if (it == m_patches.end()) + return; + + const std::size_t size = m_patches.size(); + std::size_t index = size - std::distance(it, m_patches.end()); + while (index < size) + { + DisablePatch(index); + ++index; + } + m_patches.erase(it, m_patches.end()); +} + +void MemoryPatches::EnablePatch(std::size_t index) +{ + if (m_patches[index].is_enabled == MemoryPatch::State::Enabled) + return; + m_patches[index].is_enabled = MemoryPatch::State::Enabled; + Patch(index); +} + +void MemoryPatches::DisablePatch(std::size_t index) +{ + if (m_patches[index].is_enabled == MemoryPatch::State::Disabled) + return; + m_patches[index].is_enabled = MemoryPatch::State::Disabled; + Patch(index); +} + +bool MemoryPatches::HasEnabledPatch(u32 address) const +{ + return std::any_of(m_patches.begin(), m_patches.end(), [address](const MemoryPatch& patch) { + return patch.address == address && patch.is_enabled == MemoryPatch::State::Enabled; + }); +} + +void MemoryPatches::RemovePatch(std::size_t index) +{ + DisablePatch(index); + m_patches.erase(m_patches.begin() + index); +} + +void MemoryPatches::ClearPatches() +{ + const std::size_t size = m_patches.size(); + for (std::size_t index = 0; index < size; ++index) + DisablePatch(index); + m_patches.clear(); +} +} // namespace Common::Debug diff --git a/Source/Core/Common/Debug/MemoryPatches.h b/Source/Core/Common/Debug/MemoryPatches.h new file mode 100644 index 0000000000..cee814c6b5 --- /dev/null +++ b/Source/Core/Common/Debug/MemoryPatches.h @@ -0,0 +1,52 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include + +#include "Common/CommonTypes.h" + +namespace Common::Debug +{ +struct MemoryPatch +{ + enum class State + { + Enabled, + Disabled + }; + + u32 address; + std::vector value; + State is_enabled; + + MemoryPatch(u32 address, std::vector value); + MemoryPatch(u32 address, u32 value); +}; + +class MemoryPatches +{ +public: + MemoryPatches(); + virtual ~MemoryPatches(); + + void SetPatch(u32 address, u32 value); + void SetPatch(u32 address, std::vector value); + const std::vector& GetPatches() const; + void UnsetPatch(u32 address); + void EnablePatch(std::size_t index); + void DisablePatch(std::size_t index); + bool HasEnabledPatch(u32 address) const; + void RemovePatch(std::size_t index); + void ClearPatches(); + +protected: + virtual void Patch(std::size_t index) = 0; + + std::vector m_patches; +}; +} // namespace Common::Debug diff --git a/Source/Core/Common/DebugInterface.h b/Source/Core/Common/DebugInterface.h index 363c8743e4..0d1ea6159a 100644 --- a/Source/Core/Common/DebugInterface.h +++ b/Source/Core/Common/DebugInterface.h @@ -10,6 +10,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/Debug/MemoryPatches.h" #include "Common/Debug/Watches.h" class DebugInterface @@ -34,6 +35,17 @@ public: virtual std::vector SaveWatchesToStrings() const = 0; virtual void ClearWatches() = 0; + // Memory Patches + virtual void SetPatch(u32 address, u32 value) = 0; + virtual void SetPatch(u32 address, std::vector value) = 0; + virtual const std::vector& GetPatches() const = 0; + virtual void UnsetPatch(u32 address) = 0; + virtual void EnablePatch(std::size_t index) = 0; + virtual void DisablePatch(std::size_t index) = 0; + virtual bool HasEnabledPatch(u32 address) const = 0; + virtual void RemovePatch(std::size_t index) = 0; + virtual void ClearPatches() = 0; + virtual std::string Disassemble(unsigned int /*address*/) { return "NODEBUGGER"; } virtual std::string GetRawMemoryString(int /*memory*/, unsigned int /*address*/) { @@ -59,7 +71,6 @@ public: virtual void SetPC(unsigned int /*address*/) {} virtual void Step() {} virtual void RunToBreakpoint() {} - virtual void Patch(unsigned int /*address*/, unsigned int /*value*/) {} virtual int GetColor(unsigned int /*address*/) { return 0xFFFFFFFF; } virtual std::string GetDescription(unsigned int /*address*/) = 0; virtual void Clear() = 0; -- cgit v1.2.3