Commit Graph
56 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5 daa18fc25a ImDebugger: fix stale symbol list after a game is reloaded
The disasm window cached the flattened symbol list and only rebuilt it when one
of three menu items said so. Nothing marked it dirty when a game booted or
exited, and a new SymbolMap is allocated per boot, so the list kept showing the
previous game's functions.

Give SymbolMap a version counter that every mutator bumps, and let the window
compare against it instead. The counter is process-wide rather than per-map, so
a fresh map can't hand out a version a cached copy already holds.

Also re-find the selected symbol by address after a rebuild (the index means
something else afterwards), and drop the unused symbol cache members in
ImMemWindow.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SfY7iFJEjmRXf1XGrTs4MF
2026-08-27 10:43:08 +02:00
Henrik RydgårdandClaude Opus 5 05f5668dfe Save symbols outside any module to a per-game file, and only save real names
Module symbols are keyed by module+crc so they're shared by every game that
loads that module. But symbols the user attaches to addresses that aren't in
any module - the heap, the stack, scratchpad, a hardware register, typically
after a memory.search - describe one game's own memory layout and are worthless
to any other game. Those now go to PSP/SYSTEM/SYMBOLS/<gameID>_syms.ppsym.

They're module index 0 ("absolute"), which already round-trips through the
existing per-module code: GetModuleRelativeAddr/GetModuleAbsoluteAddr are
identity for it, so the file format is unchanged, just with absolute addresses.
SaveModuleSymbols only needed to stop requiring a ModuleEntry. Auto-load/save
hang off CPU_Init/CPU_Shutdown rather than module load/unload, gated on the same
bAutoSaveLoadSymbols setting - and deliberately not on SYSPROP_HAS_DEBUGGER,
which only the Windows port reports true for, so LoadSymbolsIfSupported next to
it does nothing at all on headless. hle.game.saveSymbols/loadSymbols expose it.

Four things found while doing it:

- Symbols outside any module were being dropped on the floor. AddFunction/
  AddData/AddLabel take moduleIndex -1 as "work it out", pass it to
  GetModuleIndex(), and store whatever comes back - but that returns -1 when no
  module contains the address, and -1 is never an active module, so the symbol
  never reached the active maps: invisible to every lookup and to any save.
  hle.data.add had spotted this and normalized -1 to 0 locally; nothing else
  did, so e.g. hle.func.add outside a module silently did nothing. Fixed
  centrally in a new ResolveModuleIndex() the three of them share.
  (This only became reachable with the GetModuleIndex() fix in 29a38af37e -
  before that it returned a wrong-but-valid module index instead.)

- The saved files were almost entirely noise. Every function the analyzer finds
  is named z_un_<addr> and every import stub zz_<name>, both regenerated from
  scratch on each load. One real module wrote 13KB - 443 unnamed functions and
  64 stub names - for the four names a human had actually chosen. Worse, on the
  next run those were loaded back as authoritative and would beat the module's
  own symbols to the address. Now only names that aren't regenerated get saved,
  and a module with none writes no file at all (and removes a stale one, so
  deleting a symbol sticks). That module's file went 13020 -> 81 bytes.

- LoadModuleSymbols trusted the addresses in the file. It's meant to be
  hand-edited and can outlive the build it came from, so relative addresses past
  the end of the module are now skipped with a warning instead of landing at
  nonsense addresses.

- AddFunction and AddData both erased the map entry they were updating and then
  read back through the now-dangling iterator to refresh the active copy. Only
  latent: the refresh is guarded on the active copy's module matching the new
  one, which is false exactly when the erase happens. Re-point the iterator at
  the entry's new home instead, so it can't rot if that guard ever changes.
  AddLabel already did the equivalent correctly, via a local copy.

Filename sanitizing goes through SanitizeString with a new FileName restriction
rather than being open-coded; unlike the existing restrictions it substitutes
'_' instead of dropping, so two module names can't collapse onto one file.

Verified end to end on headless with cpu_alu.prx: named a function inside the
module and data/functions in scratchpad and the heap, let it exit, checked both
files, rebooted and confirmed all of it came back at the right addresses.
Unit tests 51/51, pspautotests 314/314.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 16:53:48 +02:00
Henrik RydgårdandClaude Sonnet 5 29a38af37e Per-module symbol save/load, module identity via crc, GetModuleIndex fix
SymbolMap:
- Fix GetModuleIndex(): it only checked the end of an active module's range
  (via activeModuleEnds.upper_bound), never the start, so an address sitting
  in the gap before a module was silently misattributed to it. Added
  GetModuleIndexByName() as a companion lookup.
- AddModule() gains an optional crc param, stored per ModuleEntry. Reactivating
  a module by name now also requires the crc to agree when both sides know it,
  so two unrelated binaries that happen to share a name no longer get merged
  into one symbol table (addresses the old TODO at the top of SymbolMap.h).
- AddLabel()/AddFunction() gain an updateName param (default false, preserving
  existing "first writer wins" behavior) so a trusted source - like a loaded
  symbol file - can be allowed to overwrite a name that a lower-confidence
  automatic pass already assigned.
- New SaveModuleSymbols()/LoadModuleSymbols()/GetModuleSymbolsPath(): save or
  restore one module's functions/data/labels to/from a small human-editable
  text file, addressed relative to the module (so the file stays valid however
  the module ends up positioned on a later run). Keyed by
  PSP/SYSTEM/SYMBOLS/<moduleName>_<crc>.ppsym - deliberately by module+crc
  rather than by game, so it's shared by every game/homebrew that loads the
  exact same module. A "# game <id> <title>" comment records who last saved
  it, informational only.

WebSocket debugger: hle.module.saveSymbols/loadSymbols expose the above.

sceKernelModule.cpp: auto-load a module's saved symbols right after it's
registered with the symbol map (both the real ELF-load path and the
savestate-load path), and auto-save on unload (before UnloadModule(), while
its symbols are still active) - gated behind the new bAutoSaveLoadSymbols
config setting (default off), with a matching Developer Tools checkbox and
a --auto-save-load-symbols command-line override for headless use.

Includes some in-progress cleanup already staged: DescribeAddress now calls
g_symbolMap->GetDescription() directly instead of through the now-removed
MIPSDebugInterface::getDescription() wrapper.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 16:01:23 +02:00
Henrik Rydgård 63ef2a7498 Hide savestate controls if you are running a frame dump 2026-08-09 19:03:08 +02:00
Henrik RydgårdandClaude Sonnet 5 3500293402 SymbolMap: route remaining GUI-thread callers, remove internal locking
Windows/MainWindowMenu.cpp's Load/Save/Clear Symbol Map menu actions
mutated g_symbolMap directly from the WinMain thread; route them through
Core_RunOnCPUThread like the rest of the debugger. Windows/MainWindow.cpp's
WM_USER_GET_MODULE_INFO handler read it directly too; guard with
g_frameMutex. Windows/main.cpp's SortSymbols() calls turn out to already be
safe as-is - both notifications that trigger them (BOOT_DONE,
SYMBOL_MAP_UPDATED) are only ever fired from the CPU/NativeFrame thread -
so just fix the stale comment claiming reliance on the (now removed)
internal lock.

With those covered, every remaining caller is either on the CPU/NativeFrame
thread already or routes through Core_RunOnCPUThread/g_frameMutex, so
SymbolMap's internal recursive_mutex is redundant - remove it and all ~40
lock_guard call sites. Qt's mainwindow.cpp still pokes at g_symbolMap
directly and unguarded (a pre-existing issue, out of scope - Qt isn't a
maintained backend), but removing the lock doesn't change its public API,
so it still builds.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hqm11k99viLfbJm2MkH4BH
2026-08-08 17:22:12 +02:00
Henrik RydgårdandClaude Opus 5 074c8ac523 Add memory.search and hle.data.* to the WebSocket debugger
Reverse-engineering workflows need to (1) find where an unknown value lives
in memory and (2) label what's found, neither of which the debugger API
could do before:

- memory.search (MemorySubscriber.cpp): Cheat-Engine-style scan of a memory
  range for a u8/u16/u32/float value, or a byte pattern with an optional
  wildcard mask.
- hle.data.list/add/remove/rename (HLESubscriber.cpp): manage ST_DATA
  symbols (structs, tables, buffers), mirroring the existing hle.func.*
  commands for functions. Needed a new SymbolMap::RemoveData, since only
  RemoveFunction existed - added following the same pattern.

Verified live against a running PPSSPP instance (game.status, cpu.stepping,
memory.search in u32/bytes/masked-bytes modes, and the full
add/list/rename/remove data-symbol lifecycle) via Tools/wsdbg.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDNwPPuidmNxQGRJxBuRL6
2026-07-26 21:17:09 +02:00
Henrik Rydgård 644f5e4e6c Expose PSPModule (so the debugger can access it later) 2025-03-31 09:56:08 +02:00
Henrik Rydgård c1828f69b9 Add an option to compress .ppsym files when saving or not (was always on before). 2025-03-29 18:17:41 +01:00
Henrik Rydgård 1a93d8a1f9 Some work on symbol export, minor cleanups 2025-03-29 14:23:59 +01:00
Henrik Rydgård 3e198c53b2 More include cleanup 2024-12-18 13:57:26 +01:00
Henrik Rydgård dd26bcf1af Cache symbols and use a clipper to speed up the symbol list. 2024-11-07 11:11:47 +01:00
Henrik Rydgård cf6d06c56a Start work on imdbg 2024-11-07 11:10:12 +01:00
Henrik Rydgård 5a5779dcd6 Remove symbol-map related functions from Host 2023-03-24 18:08:31 +01:00
Henrik Rydgård 025bcb1673 Introduce Path, start using it all over the place.
Still lots left to convert!

Convert GetSysDirectory to return Path.

More buildfixing

Remove unnecessary Path( constructors
2021-05-13 10:39:16 +02:00
Unknown W. Brackets 89f89ec749 Debugger: Defer active symbol updates.
This makes it faster when loading many modules/functions/etc., for example
when using the freeze debug feature.
2017-12-26 18:11:22 -08:00
Henrik Rydgard 26a2d42731 Big mutex overhaul - remove our custom ones, make them non-recursive where possible 2017-02-28 11:40:29 +01:00
Unknown W. Brackets 86127b3d0d Update armips to latest version.
The new version has some speed and other improvements.
2015-12-26 20:30:35 -08:00
Henrik Rydgard b998131581 Move the symbol map to the heap, deallocate it when no game is running. 2015-10-31 23:01:19 +01:00
Unknown W. Brackets e0f85a9c6b Native merge part 1: skip native/ in includes. 2015-09-06 12:19:33 -07:00
Unknown W. Brackets 58ff826b73 Cleanup to link assembler on arm unittest builds. 2014-12-07 15:41:11 -08:00
Kingcom f6cedcbff5 Replace assembler with a submodule 2014-11-23 21:09:40 +01:00
Kingcom dc80123b93 Add options to import/export .sym files from the menu 2014-06-30 00:02:22 +02:00
Unknown W. Brackets c3a6092e26 Upgrade symbolmaps with module address info.
This fixes some issues with jit replacement only if you had a map laying
around.
2014-05-04 01:24:18 -07:00
Unknown W. Brackets 8948990871 Optimize searching for existing symbols.
Checking every time is slow, we should just skip by the address.  Some is
just the locking overhead.
2014-02-14 22:26:35 -08:00
Unknown W. Brackets 04776c8125 Small optimization: avoid fallback if possible.
Speeds up symbol map loading a little bit (when inserting new items.)
2014-02-14 22:07:39 -08:00
Unknown W. Brackets 26b4335637 Optimize symbol map in debug mode a bit more.
Avoid UpdateActiveSymbols().
2014-02-14 21:49:20 -08:00
Unknown W. Brackets d279dcd454 Fix renaming a function from disassembly. 2014-02-11 07:45:13 -08:00
Henrik Rydgård b1d6eefb8a Call UpdateActiveSymbols only once from MIPSAnalyst instead of for every recognized function.
Reduces startup slowdown when using a function signature file drastically.
2014-02-11 11:21:56 +01:00
Kingcom 880be6d41d Module list in Windows debugger 2014-01-27 00:35:16 +01:00
Unknown W. Brackets 76afb2a8d5 Avoid returning points from the symbol map.
Now that it uses a lookup, this is even more dangerous.  But, the maps
could be reordered while it's trying to print the pointer and cause that
data to become invalid.

This should be safe from race conditions.
2014-01-25 21:40:23 -08:00
Unknown W. Brackets a2fa53d5c4 Track modules in the symbol map.
This makes it so things don't overlap confusingly, and also so that we can
replace funcs more correctly and sanely.

This is unfortunately a bunch more complicated...
2014-01-25 20:59:53 -08:00
Henrik Rydgård e5e17fbc6e More include cleanup. Hoping for very slightly faster compile times.. 2013-12-30 10:49:05 +01:00
Henrik Rydgård 00c32ddadb Mostly get rid of including "Globals.h" 2013-12-30 10:17:11 +01:00
Henrik Rydgard 2140892074 Initial preparations for ability to replace game functions with custom implementations.
Also auto-saves hashmap additions and reapplies the hashmap on function
rename so that if you rename a function that exists in several copies
they will all be labelled.

Note that actual function replacement is not activated yet.
2013-12-17 12:27:20 +01:00
Henrik Rydgård cfbd1b07e8 Some code reformatting in SymbolMap 2013-12-02 15:30:03 +01:00
Unknown W. Brackets dd2e996838 Fix some type comparison warnings. 2013-12-01 11:21:16 -08:00
Kingcom cca750aab5 Fix invalid memory access on start, remove combo box code from symbol map 2013-11-28 10:49:02 +01:00
Kingcom 561379f5c2 Create data directives in disassembler 2013-11-28 00:33:21 +01:00
Kingcom eeb9667726 Fix QT build (hopefully) 2013-11-27 15:06:41 +01:00
Kingcom 5844d0107b Rewrite SymbolTable 2013-11-27 13:33:30 +01:00
Kingcom 3d4bb3f20b Remove obsolete functions 2013-11-26 00:51:04 +01:00
Kingcom 00a801f6a3 Don't overwrite label name if it already exists, get label value 2013-11-26 00:43:31 +01:00
Kingcom 7c585485bb Save labels separately from symbols 2013-11-26 00:23:17 +01:00
Kingcom 9a29e8b0bf More efficient "loose" opcode detection, clear entries when symbols were loaded 2013-11-25 16:18:29 +01:00
Peter Tissen d8b4ec6680 added disasm debugger features to remove and add functions 2013-10-30 16:13:18 +01:00
Henrik Rydgård 07c818251c Some formatting cleanup.
Yeah, I said we shouldn't do big overhauls..
2013-10-18 14:39:04 +02:00
Unknown W. Brackets 8786ec74ca Fix some potential threading probs with SymbolMap.
Got some strange crashes.
2013-08-10 20:54:55 -07:00
Kingcom 862cf047da Basic .sym support 2013-07-29 13:06:01 +02:00
Unknown W. Brackets 0ca8f5c655 Improve performance of ScanForFunctions().
Mostly affects games with a lot of modules and exports.
2013-07-06 16:58:17 -07:00
Unknown W. Brackets c1834908b1 Keep the symbol map entries unique.
Duplicates are annoying, and we have hacks upstream to prevent them that
cause trouble.
2013-06-30 10:04:48 -07:00