Commit Graph
130 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ård 68085804be Merge pull request #22093 from hrydgard/debugger-work
More websocket debugger features, per-module symbol maps
2026-08-17 23:20:11 +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årdandClaude Opus 5 ee8aaff6d2 Add SymbolMap unit tests, fix absolute symbols vanishing with no module loaded
SymbolMap had no coverage. It stores symbols relative to a module so they
survive that module being unloaded and reloaded elsewhere, and only symbols
belonging to a loaded module count as active - that indirection is where the
surprises are, so the tests concentrate on module lifetime and the shared label
table.

Writing them turned up a real bug. UpdateActiveSymbols() bailed out early when
activeModuleEnds was empty, as a "tiny optimization" for startup and shutdown,
having already cleared the active maps. But symbols with module index 0 are
absolute by design - they belong to no module, which is how you label a heap or
stack address - and the loops it skipped are exactly what keeps those alive.
So an absolute symbol disappeared as soon as the last module was unloaded, and
didn't exist at all before the first one was loaded. Dropping activeModuleEnds
from the early-out condition fixes it; the symbol-count half still gives the
intended fast path when there's nothing to do.

Tests cover function and data lookup by containing address, SetFunctionSize,
RemoveFunction/RemoveData, symbols surviving an unload/reload at a different
address, absolute (module 0) symbols, GetSymbolInfo/GetDescription, and Clear.
Two of them pin down behaviour that catches people out rather than asserting
it's right: AddLabel deliberately won't overwrite an existing label, and because
functions and data share one label table, renaming or removing via one affects
the other.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 14:50:57 +02:00
Henrik Rydgård 14509b7815 Code style updates in SymbolMap.cpp, fix claudism 2026-08-14 13:19:12 +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 5aeb38412d Fix another valgrind warning 2026-02-19 11:46:14 +01:00
Henrik Rydgård 3a7911407b Assorted minor cleanups 2026-01-19 15:47:40 +01:00
刘皓 5716cbd41d Use the libretro VFS interface in libretro builds 2026-01-01 00:24:01 -05:00
Henrik Rydgård b304fbe0c9 Build armips in libretro builds (requirement for some lua functionality) 2025-10-08 09:45:44 -06: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
oltolm 02e767866a fix compiler warnings 2025-02-22 14:15:15 +01:00
Henrik Rydgård 3e198c53b2 More include cleanup 2024-12-18 13:57:26 +01:00
Henrik Rydgård 41eeb491e7 Replace a few more sprintf with snprintf 2024-10-15 15:45:19 +02:00
Henrik Rydgård e01ca5b057 Logging API change (refactor) (#19324)
* Rename LogType to Log

* Explicitly use the Log:: enum when logging. Allows for autocomplete when editing.

* Mac/ARM64 buildfix

* Do the same with the hle result log macros

* Rename the log names to mixed case while at it.

* iOS buildfix

* Qt buildfix attempt, ARM32 buildfix
2024-07-14 14:42:59 +02:00
Herman Semenov 309f0d97f2 [Common Data Net/Core Debugger HLE/GPU Debugger] Fixed reduction data type size to strict 32-bit integer 2023-12-14 19:26:10 +03:00
Unknown W. Brackets 9844422fc8 Debugger: Ignore func imports in ppmap files. 2023-09-30 15:25:48 -07:00
Henrik Rydgård 5a5779dcd6 Remove symbol-map related functions from Host 2023-03-24 18:08:31 +01:00
Unknown W. Brackets 21332c677b Build: Allow compiling without armips. 2022-12-17 10:08:46 -08:00
Unknown W. Brackets 9cfcbc46e6 Global: Cleanup initialization/pointer checks.
Cleaning up a lot of cases of uninitialized data, unchecked return values
for failures, and similar.
2022-12-10 21:13:36 -08:00
Herman Semenov 29b87e0c0b Merge branch 'master' into master 2022-10-03 07:49:13 +00:00
Unknown W. Brackets ac335ad61a armips: Update to UTF-8/c++17 armips. 2022-09-30 19:48:14 -07:00
lainon 3cdf72b68b Better readability and optimization insertion into container by replacing 'insert' -> 'emplace', 'push_back' -> 'emplace_back' 2022-09-30 12:35:28 +03:00
Unknown W. Brackets e2425a1e00 Debugger: Speed up GetFunctionSize().
Tested games with lots of functions, it's just never worth generating the
full active symbols.  Direct lookup saves 0.005s startup on desktop in a
typical game.
2021-12-04 14:49:50 -08:00
Henrik Rydgård bea9f67c02 Fix assorted path issues 2021-07-19 17:34:51 +02:00
Kingcom bb6f6051fc Transform labels to lower case for armips 2021-06-04 17:51:28 +02:00
Henrik Rydgård 4d344f556a Additional feedback. 2021-05-13 10:39:17 +02: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 13ec384dbe Build: Explicitly include ppsspp_config.h.
This adds it to all files that use it.  Not all our builds include the
file.
2021-03-02 21:04:03 -08:00
Unknown W. Brackets f32f89dd90 Global: Remove some unused variables. 2021-02-15 11:59:45 -08:00
Henrik Rydgård 4f43cff5ca Move fileutil, net, image loaders, ui to Common. (#13506)
* Move and rename file_util/fd_util to Common/File/FileUtil and DirListing

Let's also move net while we're at it.

Move the ZIM/PNG loaders over to Common.

Move the UI framework into Common

iOS buildfix

* Buildfix

* Buildfixes

* Apple buildfix

* This typo again..

* UWP buildfix

* Fix build of PPSSPPQt, such as it is (it's not in good condition...)

* Guess what? Another buildfix.
2020-10-04 20:48:47 +02:00
Henrik Rydgård 989e353482 Common.h shouldn't include Log.h.
Buildfixes

More buildfixes. Move JSON code to common.
2020-10-04 11:42:14 +02:00
Henrik Rydgård ff8148dd92 Move native/util, native/data and native/i18 to Common/Data.
Also move colorutil.cpp/h

linking build fix experiment

Delete a bunch of unused CMakeLists.txt files

CMakeLists.txt linking fix

Don't include NativeApp.h from any headers.

Android.mk buildfix

Half of the UWP fix

Buildfix

Minor project file cleanup

Buildfixes

Guess what? More buildfixes!
2020-10-04 07:28:29 +02:00
Unknown W. Brackets 8ae157e27f Debugger: Update to latest armips. 2018-06-30 14:18:26 -07: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 Rydgård 21fe73c8e7 Switch strncpy to truncate_cpy in a bunch of places. 2017-05-26 19:04:08 +02: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
Henrik Rydgard 03dab0fdbd More UWP prep 2017-02-25 09:57:22 +01:00
latot 7047ad2271 fix sscanf types 2016-12-02 22:46:52 -03:00
Henrik Rydgard 3ba911bf07 Replace some calls to fopen with File::OpenCFile (utf8). 2016-01-17 15:59:20 +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 936ccbf18a Fix symbolmap loading issue on MSVC 2015. 2015-09-07 09:24:15 -07:00
Unknown W. Brackets a191b9ac7f Fix a potentially not null terminated string. 2015-01-17 18:42:59 -08:00
Unknown W. Brackets ff59cd6e11 Fix a potential debug buffer overrun. 2015-01-17 18:21:03 -08: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