From 012d47bcbf36dce5b61e8b0393b5b54096a8c085 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 21 Apr 2021 23:50:59 -0700 Subject: [PATCH] Debugger: Show string in status bar for li, etc. This is helpful when stepping through the debugger. Only shows likely UTF-8 or similar formatted text, but often names or error messages are. --- Core/Debugger/DisassemblyManager.cpp | 34 ++++++++++++++++++++ Core/Debugger/DisassemblyManager.h | 1 + Core/Debugger/WebSocket/DisasmSubscriber.cpp | 4 +++ Windows/Debugger/CtrlDisAsmView.cpp | 4 +++ 4 files changed, 43 insertions(+) diff --git a/Core/Debugger/DisassemblyManager.cpp b/Core/Debugger/DisassemblyManager.cpp index e113ef38d1..d950fb5357 100644 --- a/Core/Debugger/DisassemblyManager.cpp +++ b/Core/Debugger/DisassemblyManager.cpp @@ -23,6 +23,7 @@ #include "ext/xxhash.h" #include "Common/CommonTypes.h" +#include "Common/Data/Encoding/Utf8.h" #include "Core/MemMap.h" #include "Core/System.h" #include "Core/MIPS/MIPSCodeUtils.h" @@ -41,6 +42,39 @@ bool isInInterval(u32 start, u32 size, u32 value) return start <= value && value <= (start+size-1); } +bool IsLikelyStringAt(uint32_t addr) { + uint32_t maxLen = Memory::ValidSize(addr, 128); + if (maxLen <= 1) + return false; + const char *p = Memory::GetCharPointer(addr); + // If there's no terminator nearby, let's say no. + if (memchr(p, 0, maxLen) == nullptr) + return false; + + // Allow tabs and newlines. + static constexpr bool validControl[] = { + false, false, false, false, false, false, false, false, + false, true, true, true, false, true, false, false, + false, false, false, false, false, false, false, false, + false, false, false, false, false, false, false, false, + }; + + // Check that there's some bytes before the terminator that look like a string. + UTF8 utf(p); + if (utf.end()) + return false; + + while (!utf.end()) { + if (utf.invalid()) + return false; + + uint32_t c = utf.next(); + if (c < ARRAY_SIZE(validControl) && !validControl[c]) + return false; + } + + return true; +} static HashType computeHash(u32 address, u32 size) { diff --git a/Core/Debugger/DisassemblyManager.h b/Core/Debugger/DisassemblyManager.h index 51b1f1959e..00ff46c6fc 100644 --- a/Core/Debugger/DisassemblyManager.h +++ b/Core/Debugger/DisassemblyManager.h @@ -224,3 +224,4 @@ private: }; bool isInInterval(u32 start, u32 size, u32 value); +bool IsLikelyStringAt(uint32_t addr); diff --git a/Core/Debugger/WebSocket/DisasmSubscriber.cpp b/Core/Debugger/WebSocket/DisasmSubscriber.cpp index fdebe9a892..ab43655d56 100644 --- a/Core/Debugger/WebSocket/DisasmSubscriber.cpp +++ b/Core/Debugger/WebSocket/DisasmSubscriber.cpp @@ -188,6 +188,10 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi json.writeUint("uintValue", Memory::ReadUnchecked_U32(l.info.relevantAddress)); else json.writeNull("uintValue"); + if (IsLikelyStringAt(l.info.relevantAddress)) + json.writeString("stringValue", Memory::GetCharPointer(l.info.relevantAddress)); + else + json.writeNull("stringValue"); json.pop(); } else { json.writeNull("relevantData"); diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index afb032d755..4c3b13228f 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -1094,6 +1094,10 @@ void CtrlDisAsmView::updateStatusBarText() text[0] = 0; if (line.type == DISTYPE_OPCODE || line.type == DISTYPE_MACRO) { + if (line.info.hasRelevantAddress && IsLikelyStringAt(line.info.relevantAddress)) { + snprintf(text, sizeof(text), "[%08X] = \"%s\"", line.info.relevantAddress, Memory::GetCharPointer(line.info.relevantAddress)); + } + if (line.info.isDataAccess) { if (!Memory::IsValidAddress(line.info.dataAddress))