Show module.section+offset next to addresses in exception/stack-trace logs

Added KernelModuleAddressDescription() (Core/HLE/sceKernelModule.cpp),
which looks up which currently loaded module (and text/data/bss/segment
section within it) an address falls in, e.g. "EBOOT.BIN.text+1234".
Wired it into:

- Core_MemoryException/Core_ExecException/Core_BreakException
  (Core/Core.cpp), appended next to every address/pc/ra shown in their
  log lines.
- FormatStackTrace (Core/MemFault.cpp), appended per-frame next to the
  existing symbol description.

This makes crash/exception logs actionable even when there's no symbol
at the faulting address - you at least get which module and section
it's in, useful for reverse engineering unfamiliar code.

Verified live via headless: injected a MIPS break instruction at the
current PC (through Tools/wsdbg) and confirmed the log line changed from
"break instruction hit at 088040ac" to "break instruction hit at 088040ac
[sceDisplayWaitVblank Test.text+ac]".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDNwPPuidmNxQGRJxBuRL6
This commit is contained in:
Henrik Rydgård
2026-07-27 23:44:14 +02:00
co-authored by Claude Opus 5
parent 878d2aeb0e
commit 9b577b5f46
4 changed files with 56 additions and 8 deletions
+25
View File
@@ -2647,6 +2647,31 @@ static u32 sceKernelGetModuleIdList(u32 resultBuffer, u32 resultBufferSize, u32
return hleNoLog(0);
}
std::string KernelModuleAddressDescription(u32 address) {
u32 error;
for (SceUID moduleId : loadedModules) {
PSPModule *module = kernelObjects.Get<PSPModule>(moduleId, error);
if (!module)
continue;
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);
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]);
}
}
return std::string();
}
//fix for tiger x dragon
static u32 sceKernelLoadModuleForLoadExecVSHDisc(const char *name, u32 flags, u32 optionAddr) {
return sceKernelLoadModule(name, flags, optionAddr);