MemoryWatcher.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright 2015 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "Core/MemoryWatcher.h"
  4. #include <cstring>
  5. #include <fstream>
  6. #include <iostream>
  7. #include <sstream>
  8. #include <unistd.h>
  9. #include "Common/FileUtil.h"
  10. #include "Core/HW/SystemTimers.h"
  11. #include "Core/PowerPC/MMU.h"
  12. MemoryWatcher::MemoryWatcher()
  13. {
  14. m_running = false;
  15. if (!LoadAddresses(File::GetUserPath(F_MEMORYWATCHERLOCATIONS_IDX)))
  16. return;
  17. if (!OpenSocket(File::GetUserPath(F_MEMORYWATCHERSOCKET_IDX)))
  18. return;
  19. m_running = true;
  20. }
  21. MemoryWatcher::~MemoryWatcher()
  22. {
  23. if (!m_running)
  24. return;
  25. m_running = false;
  26. close(m_fd);
  27. }
  28. bool MemoryWatcher::LoadAddresses(const std::string& path)
  29. {
  30. std::ifstream locations;
  31. File::OpenFStream(locations, path, std::ios_base::in);
  32. if (!locations)
  33. return false;
  34. std::string line;
  35. while (std::getline(locations, line))
  36. ParseLine(line);
  37. return !m_values.empty();
  38. }
  39. void MemoryWatcher::ParseLine(const std::string& line)
  40. {
  41. m_values[line] = 0;
  42. m_addresses[line] = std::vector<u32>();
  43. std::istringstream offsets(line);
  44. offsets >> std::hex;
  45. u32 offset;
  46. while (offsets >> offset)
  47. m_addresses[line].push_back(offset);
  48. }
  49. bool MemoryWatcher::OpenSocket(const std::string& path)
  50. {
  51. m_addr.sun_family = AF_UNIX;
  52. strncpy(m_addr.sun_path, path.c_str(), sizeof(m_addr.sun_path) - 1);
  53. m_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
  54. return m_fd >= 0;
  55. }
  56. u32 MemoryWatcher::ChasePointer(const Core::CPUThreadGuard& guard, const std::string& line)
  57. {
  58. u32 value = 0;
  59. for (u32 offset : m_addresses[line])
  60. {
  61. value = PowerPC::MMU::HostRead_U32(guard, value + offset);
  62. if (!PowerPC::MMU::HostIsRAMAddress(guard, value))
  63. break;
  64. }
  65. return value;
  66. }
  67. std::string MemoryWatcher::ComposeMessages(const Core::CPUThreadGuard& guard)
  68. {
  69. std::ostringstream message_stream;
  70. message_stream << std::hex;
  71. for (auto& entry : m_values)
  72. {
  73. std::string address = entry.first;
  74. u32& current_value = entry.second;
  75. u32 new_value = ChasePointer(guard, address);
  76. if (new_value != current_value)
  77. {
  78. // Update the value
  79. current_value = new_value;
  80. message_stream << address << '\n' << new_value << '\n';
  81. }
  82. }
  83. return message_stream.str();
  84. }
  85. void MemoryWatcher::Step(const Core::CPUThreadGuard& guard)
  86. {
  87. if (!m_running)
  88. return;
  89. std::string message = ComposeMessages(guard);
  90. sendto(m_fd, message.c_str(), message.size() + 1, 0, reinterpret_cast<sockaddr*>(&m_addr),
  91. sizeof(m_addr));
  92. }