From 39c8cbbde1da0bc99c72fdbd639f059f39c0953a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 28 Jul 2026 00:15:41 +0200 Subject: [PATCH] Use the new kernel module description thing to annotate GPRs in the register viewer --- Core/Core.cpp | 8 +++++--- Core/HLE/sceKernelModule.cpp | 29 ++++++++++++++++++----------- Core/HLE/sceKernelModule.h | 2 +- Core/MemFault.cpp | 6 +++--- UI/ImDebugger/ImDebugger.cpp | 34 ++++++++++++++++++++++++++++++++-- 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index ae73aff5da..e8c0000a01 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -561,10 +561,12 @@ static ExceptionAction ResolveExceptionAction(ExceptionAction action) { // Looks up which loaded module (and section) an address falls in, formatted for appending // straight after an address in a log line, e.g. " [EBOOT.BIN.text+1234]". Empty if no match. static std::string ModuleAddressSuffix(u32 address) { - std::string desc = KernelModuleAddressDescription(address); - if (desc.empty()) + char desc[96]; + if (DescribeKernelModuleAddress(address, desc, sizeof(desc))) { + return std::string(" [") + desc + "]"; + } else { return std::string(); - return " [" + desc + "]"; + } } void Core_MemoryException(u32 address, u32 accessSize, u32 pc, MemoryExceptionType type, std::string_view additionalInfo, bool forceReport) { diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index cb8e640628..5f43e9d273 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -2647,7 +2647,7 @@ static u32 sceKernelGetModuleIdList(u32 resultBuffer, u32 resultBufferSize, u32 return hleNoLog(0); } -std::string KernelModuleAddressDescription(u32 address) { +bool DescribeKernelModuleAddress(u32 address, char *buffer, size_t bufferSize) { u32 error; for (SceUID moduleId : loadedModules) { PSPModule *module = kernelObjects.Get(moduleId, error); @@ -2657,19 +2657,26 @@ std::string KernelModuleAddressDescription(u32 address) { const NativeModule &nm = module->nm; u32 dataAddr = module->GetDataAddr(); u32 bssAddr = module->GetBSSAddr(); - - if (nm.text_size != 0 && address >= nm.text_addr && address < nm.text_addr + nm.text_size) - return StringFromFormat("%s.text+%x", nm.name, address - nm.text_addr); - if (nm.data_size != 0 && address >= dataAddr && address < dataAddr + nm.data_size) - return StringFromFormat("%s.data+%x", nm.name, address - dataAddr); - if (nm.bss_size != 0 && address >= bssAddr && address < bssAddr + nm.bss_size) - return StringFromFormat("%s.bss+%x", nm.name, address - bssAddr); + if (nm.text_size != 0 && address >= nm.text_addr && address < nm.text_addr + nm.text_size) { + snprintf(buffer, bufferSize, "%s.text+%x", nm.name, address - nm.text_addr); + return true; + } + if (nm.data_size != 0 && address >= dataAddr && address < dataAddr + nm.data_size) { + snprintf(buffer, bufferSize, "%s.data+%x", nm.name, address - dataAddr); + return true; + } + if (nm.bss_size != 0 && address >= bssAddr && address < bssAddr + nm.bss_size) { + snprintf(buffer, bufferSize, "%s.bss+%x", nm.name, address - bssAddr); + return true; + } for (int i = 0; i < (int)nm.nsegment && i < 4; i++) { - if (nm.segmentsize[i] != 0 && address >= nm.segmentaddr[i] && address < nm.segmentaddr[i] + nm.segmentsize[i]) - return StringFromFormat("%s.seg%d+%x", nm.name, i, address - nm.segmentaddr[i]); + if (nm.segmentsize[i] != 0 && address >= nm.segmentaddr[i] && address < nm.segmentaddr[i] + nm.segmentsize[i]) { + snprintf(buffer, bufferSize, "%s.seg%d+%x", nm.name, i, address - nm.segmentaddr[i]); + return true; + } } } - return std::string(); + return false; } //fix for tiger x dragon diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 4212a04868..2a2d39dd20 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -238,7 +238,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str bool KernelFindImportByStubAddr(u32 stubAddr, std::string *importModuleName, u32 *nid, std::string *importingModuleName); // Describes which loaded module (and section within it) an address falls in, e.g. "EBOOT.BIN.text+1234". // Returns an empty string if the address isn't inside any currently loaded module. -std::string KernelModuleAddressDescription(u32 address); +bool DescribeKernelModuleAddress(u32 address, char *buffer, size_t bufferSize); int __KernelGPUReplay(); void __KernelReturnFromModuleFunc(); SceUID KernelLoadModule(const std::string &filename, std::string *error_string); diff --git a/Core/MemFault.cpp b/Core/MemFault.cpp index 31029d1a3c..29d5927a55 100644 --- a/Core/MemFault.cpp +++ b/Core/MemFault.cpp @@ -374,9 +374,9 @@ std::string FormatStackTrace(const std::vector &frame std::stringstream str; for (const auto &frame : frames) { std::string desc = g_symbolMap->GetDescription(frame.entry); - std::string moduleDesc = KernelModuleAddressDescription(frame.pc); - if (!moduleDesc.empty()) { - str << StringFromFormat("%s [%s] (%08x+%03x, pc: %08x sp: %08x)\n", desc.c_str(), moduleDesc.c_str(), frame.entry, frame.pc - frame.entry, frame.pc, frame.sp); + char moduleDesc[96]; + if (DescribeKernelModuleAddress(frame.entry, moduleDesc, sizeof(moduleDesc))) { + str << StringFromFormat("%s [%s] (%08x+%03x, pc: %08x sp: %08x)\n", desc.c_str(), moduleDesc, frame.entry, frame.pc - frame.entry, frame.pc, frame.sp); } else { str << StringFromFormat("%s (%08x+%03x, pc: %08x sp: %08x)\n", desc.c_str(), frame.entry, frame.pc - frame.entry, frame.pc, frame.sp); } diff --git a/UI/ImDebugger/ImDebugger.cpp b/UI/ImDebugger/ImDebugger.cpp index 2db1dc8d8e..4672d6439f 100644 --- a/UI/ImDebugger/ImDebugger.cpp +++ b/UI/ImDebugger/ImDebugger.cpp @@ -213,6 +213,31 @@ void DrawSchedulerView(ImConfig &cfg) { ImGui::End(); } +static void DescribeGPRValue(u32 value, char *buffer, size_t bufferSize) { + if (Memory::IsValidAddress(value)) { + char moduleName[64]; + const char *kernel = (value & 0x80000000) ? " (kernel)" : ""; + const char *uncached = (value & 0x40000000) ? " (uncached)" : ""; + + if (DescribeKernelModuleAddress(value, moduleName, sizeof(moduleName))) { + snprintf(buffer, bufferSize, "[%s]%s%s", moduleName, kernel, uncached); + return; + } else if (Memory::IsVRAMAddress(value)) { + snprintf(buffer, bufferSize, "[VRAM]%s", uncached); // can't be kernel + return; + } else if (Memory::IsScratchpadAddress(value)) { + snprintf(buffer, bufferSize, "[SCRATCH]%s%s", kernel, uncached); + return; + } else { + // TODO: Symbol lookup + snprintf(buffer, bufferSize, "[RAM]%s%s", kernel, uncached); + return; + } + } else { + snprintf(buffer, bufferSize, "(value)"); + } +} + static void DrawGPRs(ImConfig &config, ImControl &control, const MIPSDebugInterface *mipsDebug, const ImSnapshotState &prev) { ImGui::SetNextWindowSize(ImVec2(320, 600), ImGuiCond_FirstUseEver); if (!ImGui::Begin("GPRs", &config.gprOpen)) { @@ -236,10 +261,11 @@ static void DrawGPRs(ImConfig &config, ImControl &control, const MIPSDebugInterf delete[] buffer; } - if (ImGui::BeginTable("gpr", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { + if (ImGui::BeginTable("gpr", 4, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersH)) { ImGui::TableSetupColumn("Reg", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("Decimal", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("Dec", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Desc", ImGuiTableColumnFlags_WidthStretch); ImGui::TableHeadersRow(); @@ -261,6 +287,10 @@ static void DrawGPRs(ImConfig &config, ImControl &control, const MIPSDebugInterf if (value >= -1000000 && value <= 1000000) { ImGui::Text("%d", value); } + ImGui::TableNextColumn(); + char temp[72]; + DescribeGPRValue(value, temp, sizeof(temp)); + ImGui::TextUnformatted(temp); if (diff || disabled) { ImGui::PopStyleColor(); }