Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #14358 from unknownbrackets/debugger
Add basic APIs for managing memory info tagging
  • Loading branch information
hrydgard committed Apr 17, 2021
2 parents 2ae5409 + 5904900 commit 8314a80
Show file tree
Hide file tree
Showing 17 changed files with 509 additions and 39 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Expand Up @@ -1501,6 +1501,8 @@ add_library(${CoreLibName} ${CoreLinkType}
Core/Debugger/WebSocket/InputSubscriber.h
Core/Debugger/WebSocket/LogBroadcaster.cpp
Core/Debugger/WebSocket/LogBroadcaster.h
Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp
Core/Debugger/WebSocket/MemoryInfoSubscriber.h
Core/Debugger/WebSocket/MemorySubscriber.cpp
Core/Debugger/WebSocket/MemorySubscriber.h
Core/Debugger/WebSocket/SteppingBroadcaster.cpp
Expand Down
2 changes: 2 additions & 0 deletions Core/Core.vcxproj
Expand Up @@ -442,6 +442,7 @@
<ClCompile Include="Debugger\WebSocket\InputSubscriber.cpp" />
<ClCompile Include="Debugger\WebSocket\LogBroadcaster.cpp" />
<ClCompile Include="Debugger\WebSocket\DisasmSubscriber.cpp" />
<ClCompile Include="Debugger\WebSocket\MemoryInfoSubscriber.cpp" />
<ClCompile Include="Debugger\WebSocket\MemorySubscriber.cpp" />
<ClCompile Include="Debugger\WebSocket\SteppingBroadcaster.cpp" />
<ClCompile Include="Debugger\WebSocket\SteppingSubscriber.cpp" />
Expand Down Expand Up @@ -988,6 +989,7 @@
<ClInclude Include="Debugger\WebSocket\HLESubscriber.h" />
<ClInclude Include="Debugger\WebSocket\InputBroadcaster.h" />
<ClInclude Include="Debugger\WebSocket\InputSubscriber.h" />
<ClInclude Include="Debugger\WebSocket\MemoryInfoSubscriber.h" />
<ClInclude Include="Debugger\WebSocket\SteppingSubscriber.h" />
<ClInclude Include="Debugger\WebSocket\WebSocketUtils.h" />
<ClInclude Include="Debugger\WebSocket\CPUCoreSubscriber.h" />
Expand Down
6 changes: 6 additions & 0 deletions Core/Core.vcxproj.filters
Expand Up @@ -980,6 +980,9 @@
<ClCompile Include="Debugger\MemBlockInfo.cpp">
<Filter>Debugger</Filter>
</ClCompile>
<ClCompile Include="Debugger\WebSocket\MemoryInfoSubscriber.cpp">
<Filter>Debugger\WebSocket</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ELF\ElfReader.h">
Expand Down Expand Up @@ -1676,6 +1679,9 @@
<ClInclude Include="Debugger\MemBlockInfo.h">
<Filter>Debugger</Filter>
</ClInclude>
<ClInclude Include="Debugger\WebSocket\MemoryInfoSubscriber.h">
<Filter>Debugger\WebSocket</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
Expand Down
26 changes: 21 additions & 5 deletions Core/Debugger/MemBlockInfo.cpp
Expand Up @@ -87,6 +87,7 @@ static MemSlabMap writeMap;
static MemSlabMap textureMap;
static std::vector<PendingNotifyMem> pendingNotifies;
static std::mutex pendingMutex;
static int detailedOverride;

MemSlabMap::MemSlabMap() {
Reset();
Expand Down Expand Up @@ -373,7 +374,7 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_

bool needFlush = false;
// When the setting is off, we skip smaller info to keep things fast.
if (g_Config.bDebugMemInfoDetailed || size >= 0x100) {
if (size >= 0x100 || MemBlockInfoDetailed()) {
PendingNotifyMem info{ flags, start, size };
info.ticks = CoreTiming::GetTicks();
info.pc = pc;
Expand All @@ -394,10 +395,12 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_
FlushPendingMemInfo();
}

if (flags & MemBlockFlags::WRITE) {
CBreakPoints::ExecMemCheck(start, true, size, pc, tagStr);
} else if (flags & MemBlockFlags::READ) {
CBreakPoints::ExecMemCheck(start, false, size, pc, tagStr);
if (!(flags & MemBlockFlags::SKIP_MEMCHECK)) {
if (flags & MemBlockFlags::WRITE) {
CBreakPoints::ExecMemCheck(start, true, size, pc, tagStr);
} else if (flags & MemBlockFlags::READ) {
CBreakPoints::ExecMemCheck(start, false, size, pc, tagStr);
}
}
}

Expand Down Expand Up @@ -472,3 +475,16 @@ void MemBlockInfoDoState(PointerWrap &p) {
writeMap.DoState(p);
textureMap.DoState(p);
}

// Used by the debugger.
void MemBlockOverrideDetailed() {
detailedOverride++;
}

void MemBlockReleaseDetailed() {
detailedOverride--;
}

bool MemBlockInfoDetailed() {
return g_Config.bDebugMemInfoDetailed || detailedOverride != 0;
}
9 changes: 8 additions & 1 deletion Core/Debugger/MemBlockInfo.h
Expand Up @@ -34,6 +34,8 @@ enum class MemBlockFlags {
READ = 0x0800,
FREE = 0x1000,
SUB_FREE = 0x2000,

SKIP_MEMCHECK = 0x00010000,
};
ENUM_CLASS_BITOPS(MemBlockFlags);

Expand All @@ -47,7 +49,8 @@ struct MemBlockInfo {
bool allocated;
};

void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const char *str, size_t strLength);
void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const char *tag, size_t tagLength);
void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const char *tag, size_t tagLength);

// This lets us avoid calling strlen on string constants, instead the string length (including null,
// so we have to subtract 1) is computed at compile time.
Expand All @@ -68,3 +71,7 @@ std::string GetMemWriteTagAt(uint32_t start, uint32_t size);
void MemBlockInfoInit();
void MemBlockInfoShutdown();
void MemBlockInfoDoState(PointerWrap &p);

void MemBlockOverrideDetailed();
void MemBlockReleaseDetailed();
bool MemBlockInfoDetailed();
2 changes: 2 additions & 0 deletions Core/Debugger/WebSocket.cpp
Expand Up @@ -57,6 +57,7 @@
#include "Core/Debugger/WebSocket/GPURecordSubscriber.h"
#include "Core/Debugger/WebSocket/HLESubscriber.h"
#include "Core/Debugger/WebSocket/InputSubscriber.h"
#include "Core/Debugger/WebSocket/MemoryInfoSubscriber.h"
#include "Core/Debugger/WebSocket/MemorySubscriber.h"
#include "Core/Debugger/WebSocket/SteppingSubscriber.h"

Expand All @@ -70,6 +71,7 @@ static const std::vector<SubscriberInit> subscribers({
&WebSocketGPURecordInit,
&WebSocketHLEInit,
&WebSocketInputInit,
&WebSocketMemoryInfoInit,
&WebSocketMemoryInit,
&WebSocketSteppingInit,
});
Expand Down
35 changes: 15 additions & 20 deletions Core/Debugger/WebSocket/DisasmSubscriber.cpp
Expand Up @@ -47,7 +47,6 @@ class WebSocketDisasmState : public DebuggerSubscriber {
protected:
void WriteDisasmLine(JsonWriter &json, const DisassemblyLineInfo &l);
void WriteBranchGuide(JsonWriter &json, const BranchLine &l);
uint32_t RoundAddressUp(uint32_t addr);

DisassemblyManager disasm_;
};
Expand Down Expand Up @@ -135,12 +134,20 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi
json.writeNull("dataSymbol");
}

bool enabled;
bool enabled = false;
int breakpointOffset = -1;
for (u32 i = 0; i < l.totalSize; i += 4) {
if (CBreakPoints::IsAddressBreakPoint(addr + i, &enabled))
breakpointOffset = i;
if (breakpointOffset != -1 && enabled)
break;
}
// TODO: Account for bp inside macro?
if (CBreakPoints::IsAddressBreakPoint(addr, &enabled)) {
if (breakpointOffset != -1) {
json.pushDict("breakpoint");
json.writeBool("enabled", enabled);
auto cond = CBreakPoints::GetBreakPointCondition(addr);
json.writeUint("address", addr + breakpointOffset);
auto cond = CBreakPoints::GetBreakPointCondition(addr + breakpointOffset);
if (cond)
json.writeString("condition", cond->expressionString);
else
Expand Down Expand Up @@ -240,18 +247,6 @@ void WebSocketDisasmState::WriteBranchGuide(JsonWriter &json, const BranchLine &
json.pop();
}

uint32_t WebSocketDisasmState::RoundAddressUp(uint32_t addr) {
if (addr < PSP_GetScratchpadMemoryBase())
return PSP_GetScratchpadMemoryBase();
else if (addr >= PSP_GetScratchpadMemoryEnd() && addr < PSP_GetVidMemBase())
return PSP_GetVidMemBase();
else if (addr >= PSP_GetVidMemEnd() && addr < PSP_GetKernelMemoryBase())
return PSP_GetKernelMemoryBase();
else if (addr >= PSP_GetUserMemoryEnd())
return PSP_GetScratchpadMemoryBase();
return addr;
}

// Request the current PSP memory base address (memory.base)
//
// WARNING: Avoid this unless you have a good reason. Uses PPSSPP's address space.
Expand Down Expand Up @@ -375,7 +370,7 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) {
// Parameters:
// - thread: optional number indicating the thread id (may not affect search much.)
// - address: starting address as a number.
// - end: optional end address as a number (otherwise uses start.)
// - end: optional end address as a number (otherwise uses start address.)
// - match: string to search for.
// - displaySymbols: optional, specify false to hide symbols in the searched parameters.
//
Expand All @@ -402,7 +397,7 @@ void WebSocketDisasmState::SearchDisasm(DebuggerRequest &req) {
return;

bool loopSearch = end <= start;
start = RoundAddressUp(start);
start = RoundMemAddressUp(start);
if ((end <= start) != loopSearch) {
// We must've passed end by rounding up.
JsonWriter &json = req.Respond();
Expand All @@ -411,7 +406,7 @@ void WebSocketDisasmState::SearchDisasm(DebuggerRequest &req) {
}

// We do this after the check in case both were in unused memory.
end = RoundAddressUp(end);
end = RoundMemAddressUp(end);

std::transform(match.begin(), match.end(), match.begin(), ::tolower);

Expand Down Expand Up @@ -442,7 +437,7 @@ void WebSocketDisasmState::SearchDisasm(DebuggerRequest &req) {
break;
}

addr = RoundAddressUp(addr + line.totalSize);
addr = RoundMemAddressUp(addr + line.totalSize);
} while (addr != end);

JsonWriter &json = req.Respond();
Expand Down

0 comments on commit 8314a80

Please sign in to comment.