From 124774fecbe741032400f4a3e5f377fd2c786f06 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 21:27:30 -0700 Subject: [PATCH] Debugger: Provide memory mapping ranges. Most of these are entirely static, but introspection is good for APIs. --- .../WebSocket/MemoryInfoSubscriber.cpp | 69 +++++++++++++++++++ Core/MemMap.h | 20 +++--- 2 files changed, 79 insertions(+), 10 deletions(-) diff --git a/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp index e81fa2d44d..ee2f34cd75 100644 --- a/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp +++ b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp @@ -18,6 +18,7 @@ #include "Core/Debugger/MemBlockInfo.h" #include "Core/Debugger/WebSocket/MemoryInfoSubscriber.h" #include "Core/Debugger/WebSocket/WebSocketUtils.h" +#include "Core/MemMap.h" class WebSocketMemoryInfoState : public DebuggerSubscriber { public: @@ -27,6 +28,7 @@ public: UpdateOverride(false); } + void Mapping(DebuggerRequest &req); void Config(DebuggerRequest &req); protected: @@ -37,6 +39,7 @@ protected: DebuggerSubscriber *WebSocketMemoryInfoInit(DebuggerEventHandlerMap &map) { auto p = new WebSocketMemoryInfoState(); + map["memory.mapping"] = std::bind(&WebSocketMemoryInfoState::Mapping, p, std::placeholders::_1); map["memory.info.config"] = std::bind(&WebSocketMemoryInfoState::Config, p, std::placeholders::_1); return p; @@ -50,6 +53,72 @@ void WebSocketMemoryInfoState::UpdateOverride(bool flag) { detailOverride_ = flag; } +// List memory map data (memory.mapping) +// +// No parameters. +// +// Response (same event name): +// - ranges: array of objects: +// - type: one of "ram", "vram", "sram". +// - subtype: "primary" or "mirror". +// - name: string, friendly name. +// - address: number, start address of range. +// - size: number, in bytes. +// +// Note: Even if you set false, may stay enabled if set by user or another debug session. +void WebSocketMemoryInfoState::Mapping(DebuggerRequest &req) { + struct MemRange { + const char *type; + const char *subtype; + const char *name; + const uint32_t address; + const uint32_t size; + }; + constexpr uint32_t kernelMemorySize = PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase(); + constexpr uint32_t volatileMemorySize = PSP_GetVolatileMemoryEnd() - PSP_GetVolatileMemoryStart(); + static constexpr MemRange ranges[] = { + { "sram", "primary", "Scratchpad", PSP_GetScratchpadMemoryBase(), Memory::SCRATCHPAD_SIZE }, + { "vram", "primary", "VRAM", PSP_GetVidMemBase(), Memory::VRAM_SIZE }, + { "vram", "mirror", "VRAM (Swizzled)", PSP_GetVidMemBase() + Memory::VRAM_SIZE * 1, Memory::VRAM_SIZE }, + { "vram", "mirror", "VRAM (Mirror)", PSP_GetVidMemBase() + Memory::VRAM_SIZE * 2, Memory::VRAM_SIZE }, + { "vram", "mirror", "VRAM (Swizzled + Interleaved)", PSP_GetVidMemBase() + Memory::VRAM_SIZE * 3, Memory::VRAM_SIZE }, + { "ram", "primary", "Kernel Memory", 0x80000000 | PSP_GetKernelMemoryBase(), kernelMemorySize }, + { "ram", "primary", "Volatile Memory", PSP_GetVolatileMemoryStart(), volatileMemorySize }, + // Size is specially calculated. + { "ram", "primary", "User Memory", PSP_GetUserMemoryBase(), 0 }, + }; + + JsonWriter &json = req.Respond(); + json.pushArray("ranges"); + for (auto range : ranges) { + uint32_t size = range.size; + if (size == 0) { + size = Memory::g_MemorySize; + if (size == 0) { + size = Memory::RAM_NORMAL_SIZE; + } + size -= kernelMemorySize + volatileMemorySize; + } + json.pushDict(); + json.writeString("type", range.type); + json.writeString("subtype", range.subtype); + json.writeString("name", range.name); + json.writeUint("address", range.address); + json.writeUint("size", size); + json.pop(); + + // Also write the uncached range. + json.pushDict(); + json.writeString("type", range.type); + json.writeString("subtype", "mirror"); + json.writeString("name", std::string("Uncached ") + range.name); + json.writeUint("address", 0x40000000 | range.address); + json.writeUint("size", size); + json.pop(); + } + json.pop(); +} + // Update memory info tracking config (memory.info.config) // // Parameters: diff --git a/Core/MemMap.h b/Core/MemMap.h index b9afe2ea35..a70d1510e8 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -459,22 +459,22 @@ struct PSPPointer }; -inline u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;} -inline u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;} +constexpr u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;} +constexpr u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;} -inline u32 PSP_GetKernelMemoryBase() { return 0x08000000;} +constexpr u32 PSP_GetKernelMemoryBase() { return 0x08000000;} inline u32 PSP_GetUserMemoryEnd() { return PSP_GetKernelMemoryBase() + Memory::g_MemorySize;} -inline u32 PSP_GetKernelMemoryEnd() { return 0x08400000;} +constexpr u32 PSP_GetKernelMemoryEnd() { return 0x08400000;} // "Volatile" RAM is between 0x08400000 and 0x08800000, can be requested by the // game through sceKernelVolatileMemTryLock. -inline u32 PSP_GetVolatileMemoryStart() { return 0x08400000; } -inline u32 PSP_GetVolatileMemoryEnd() { return 0x08800000; } +constexpr u32 PSP_GetVolatileMemoryStart() { return 0x08400000; } +constexpr u32 PSP_GetVolatileMemoryEnd() { return 0x08800000; } -inline u32 PSP_GetUserMemoryBase() { return 0x08800000;} -inline u32 PSP_GetDefaultLoadAddress() { return 0;} -inline u32 PSP_GetVidMemBase() { return 0x04000000;} -inline u32 PSP_GetVidMemEnd() { return 0x04800000;} +constexpr u32 PSP_GetUserMemoryBase() { return 0x08800000; } +constexpr u32 PSP_GetDefaultLoadAddress() { return 0; } +constexpr u32 PSP_GetVidMemBase() { return 0x04000000; } +constexpr u32 PSP_GetVidMemEnd() { return 0x04800000; } template inline bool operator==(const PSPPointer &lhs, const PSPPointer &rhs) {