Commit Graph
47 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5 d385c86a98 Fix breakpoints being swallowed when you step onto them
Set two breakpoints four bytes apart, both logging, run into the first, then
press Next: the second one never logs, however many times you step. Reproduced
on both the interpreter and the JIT.

The skip-first mechanism was doing two different jobs with one marker. Every
resume and every step recorded the address it started from, and any breakpoint
check at that address was suppressed outright. That's right for the breakpoint
you're parked on - you have to be able to get off it - but stepping *onto* an
address is not the same as having reported the breakpoint there, and the next
step suppressed it before it ever logged.

Split into the two things that were being conflated:

- resumedFrom_ is where the current run or step started. It only drops the
  pause, not the log or the hit count. It still covers the temporary breakpoint,
  which is what makes "run to here" work when you're already on that address.
- reported_ is the breakpoint we already logged and counted. Reporting stops the
  CPU before the instruction runs, so the resume that follows arrives at the
  same pending execution and must not report it twice.

Both are (address, tick count) pairs, which identify one pending execution of
one instruction: ticks only move when the CPU retires an instruction, so the
marker stops matching as soon as it runs, and a breakpoint in a loop still fires
every iteration.

reported_ can't be armed where the report happens, though. Under a JIT that's
inside a compiled block whose cycles are already accounted for, so the tick
count there isn't the settled one we see on the way back in - arming it there
double-logged the breakpoint under -j. So the report just records the address,
and NotifyResumingFrom() turns it into a real marker once the CPU has stopped.
That also has to be idempotent: a step-over arms its temporary breakpoint and
then calls Core_Resume(), which notifies a second time.

MemCheck::Action() no longer pauses by itself - the caller decides, the same way
ExecBreakPoint() already did, so all three breakpoint kinds share the handling.

Verified on both backends: two adjacent breakpoints now log once each while
stepping (was one log total), stepping off a breakpoint still doesn't re-log it
(was two under -j), step-over still skips the call and logs a breakpoint at the
address it lands on, and a breakpoint in a loop reports once per iteration.
pspautotests 314/314.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 23:25:56 +02:00
Henrik RydgårdandClaude Opus 5 35a91b757a Move the temporary breakpoint out of the user's breakpoint list
step-over, step-out and run-until plant a one-shot breakpoint at the address
they want execution to return to. Keeping it in breakPoints_ alongside the
user's own meant the two kept colliding:

- Adding a log-only user breakpoint at the same address hijacked the temporary
  one. AddBreakPoint() didn't match across temp-ness so both existed, and then
  ChangeBreakPoint() looked up "the first enabled breakpoint at this address" -
  a log-only breakpoint isn't enabled, so the temporary one won and had its
  action overwritten to log-only. It lost PAUSE and the step never came back.
- RemoveBreakPoint() erased up to two entries per address to catch an
  overlapping temporary one, so deleting either deleted both - including the
  interpreter's cleanup path in CheckExecBreakpoints() taking the user's
  breakpoint with it.
- ExecBreakPoint() handled one breakpoint per address, so with both at the same
  address only one of them did anything: the step completed but the user's log
  line never printed.
- Nothing dropped it when something *else* stopped us first, so an interrupted
  step left a breakpoint armed at an address nobody was waiting for anymore,
  which later fired as a phantom stop.

It's a single TempBreakPoint member now, invisible to the breakpoint lists and
untouched by user edits. One is enough: step over/out and cross-thread step into
all require the CPU to already be stepping and resume it immediately, so only
one can be in flight, and run-until now replaces rather than stacking (two
pending run-untils had no coherent meaning, and the loser stayed armed).

Behavior follows what other debuggers do. Both breakpoints at an address are
evaluated independently and their actions combine, so a log-only breakpoint
logs without stopping and still lets the step finish. Core_Break() drops the
temporary breakpoint on any stop, whatever the reason - the same way gdb deletes
its step-resume breakpoint and lldb discards the thread plan.

Two things to be careful of, both covered by the new TempBreakpoints test:
HasBreakPoints() has to account for it, or the interpreter's checked run loop
and the JIT skip breakpoint checking entirely and a step with no user
breakpoints set never returns; and IsAddressBreakPoint() (user-facing, for the
lists and disassembly markers) is now separate from NeedsBreakCheckAt() (what
the JIT frontends and interpreter ask), since only the latter should see it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-17 00:29:26 +02:00
Henrik Rydgård 14405c08cf Remove the concept of stepSize from the debugger 2026-08-16 16:59:54 +02:00
Henrik Rydgård 9f90512ef6 Make instruction cache invalidation (for us, jit cache invalidation) clearer 2026-08-16 16:59:52 +02:00
Henrik Rydgård f5bd302694 Improve DescribeAddress, show the description of the currently selected line in disassembly 2026-08-14 14:38:33 +02:00
Henrik Rydgård 0596ee97f6 More memory access cleanup 2026-08-11 20:14:01 +02:00
Henrik Rydgård 4f8859d0ec Centralize a disassembly utility function between the debuggers 2026-08-11 09:08:52 +02:00
Henrik Rydgård 2be4d995f2 More Read_U32 cleanup 2026-08-10 11:23:23 +02:00
Henrik RydgårdandClaude Sonnet 5 b1f0112cef Debugger: Remove opcode-fusion display and fix cpu step size units
DisassemblyManager used to fuse lui+addiu/load/store into single pseudo-
instructions ("li", fused loads/stores) for display. This only applied to a
handful of opcodes, complicated DisassemblyManager, and was the root cause of
a stepping bug: Core_PerformCPUStep's Into/Over cases treated stepSize as a
byte count, while the WebSocket cpu.stepInto handler computed it as an
instruction count (needed to step over a whole fused macro in one go) - so a
plain, non-fused stepInto silently executed zero instructions.

Removed the fusion logic entirely (DisassemblyMacro, DISTYPE_MACRO) - every
disassembly line is now exactly one 4-byte instruction. With that,
"how many instructions does this line span" is always 1, so the
getInstructionSizeAt() byte-size queries in the legacy Windows and ImGui
debuggers are gone too; step requests just pass 1. Core_RequestCPUStep's
stepSize is now consistently in instructions everywhere.

Also fixes the PPSSPPHeadless build, broken since 0ed1f3e added
OpenWebDebugger() (which calls System_LaunchUrl) without a headless stub.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hqm11k99viLfbJm2MkH4BH
2026-08-08 11:16:36 +02:00
Henrik Rydgård 330a638281 Add ability to copy function hash from the disassembly view
See #4179
2026-02-09 19:26:43 +01:00
Henrik Rydgård c20be71c10 Fix the API for MIPSAssembleOpcode to remove a global 2025-11-03 16:08:07 +01:00
Henrik Rydgård 1c49ad7b29 Support screen rotation on iOS (unrestricted) 2025-10-22 15:13:21 +02:00
Henrik Rydgård 5751e202a5 Remove redundant .c_str() 2025-08-31 13:37:43 +02:00
Henrik Rydgård bc688d83b1 ImDebugger: Replace the Skim button by adding hold-shift functionality to "Into"
That is, you can hold shift to repeatedly click the button.
2025-06-12 10:23:00 +02:00
Henrik Rydgård ff37cbe184 Minor memory safety fixes 2025-05-14 09:39:09 +02:00
Henrik Rydgård a97ea04827 ImGui: Add "repeatshift" buttons that auto-repeat if you hold shift. 2025-04-09 11:58:31 +02:00
Henrik Rydgård ad17ec5fc8 Minor reorganization in ImDebugger 2025-04-09 11:58:31 +02:00
Henrik Rydgård 088a02bfdb Cleanup a lot of the bootup state management. 2025-03-30 14:02:29 +02:00
Henrik Rydgård 23954f5403 Implement the disassembly mode too 2025-01-09 13:35:29 +01:00
Henrik Rydgård 08d251b5bc Add a memory dump window 2025-01-09 13:14:13 +01:00
Henrik Rydgård 3e198c53b2 More include cleanup 2024-12-18 13:57:26 +01:00
Henrik Rydgård 3cc7d6ef7a ImDebugger: Assorted UI improvements 2024-12-13 22:06:56 +01:00
Henrik Rydgård 597be1c9bc Stop pretending that DisassemblyManager isn't a singleton - it currently is. 2024-12-12 19:25:04 +01:00
Henrik Rydgård c85266359f More memory view work 2024-12-12 17:47:37 +01:00
Henrik Rydgård 39ffe92e0a LR->RA rename, fixes 2024-12-12 17:47:37 +01:00
Henrik Rydgård 11e858f0f1 Add input to memview. Use step counters to control updates. 2024-12-12 17:47:37 +01:00
Henrik Rydgård 20c19f96e0 More memview work 2024-12-12 17:47:37 +01:00
Henrik Rydgård 637d15434e Minor code cleanup. Add Goto LR button 2024-12-10 22:56:03 +01:00
Henrik Rydgård 474e7acf54 Hook up the new (bare-bones) ImGui debug window to GPU stepping, fix stepping. 2024-12-05 00:51:59 +01:00
Henrik Rydgård 7f13bc1a34 Add new log category for texture replacements 2024-12-01 14:17:01 +01:00
Henrik Rydgård f665878b3c Fix crash with mismatched pushfont/popfont 2024-11-28 09:50:29 +01:00
Henrik Rydgård 1eadea2589 Show the filesystem types and origins in the list (except ISO) 2024-11-26 00:36:58 +01:00
Henrik Rydgård e95d9b15b4 Add kernel object viewer, reimpl "Run to here" 2024-11-26 00:13:37 +01:00
Henrik Rydgård 28f1a7d45d Slightly better right-click behavior in disasm view 2024-11-25 23:52:31 +01:00
Henrik Rydgård 9801f4c810 Add "Rename function" functionality. Fix some input and stepping bugs. 2024-11-25 10:18:56 +01:00
Henrik Rydgård 7992ff4627 Make CBreakpoints an object 2024-11-25 00:22:53 +01:00
Henrik Rydgård e31636caec Still use a fixed-width font for the disassembly (might change this) 2024-11-25 00:03:06 +01:00
Henrik Rydgård 2a1cda05b0 ImGui: Fix DPI scale, disable unneeded logging 2024-11-24 23:41:27 +01:00
Henrik Rydgård e66516eb50 ImDebugger: Add ability to rename function symbols 2024-11-23 23:23:52 +01:00
Henrik Rydgård 6b11ebfb9f ImDebugger: Fix a bunch of keyboard shortcuts 2024-11-23 23:23:52 +01:00
Henrik Rydgård c5eb600044 Add search functionality to disassembler 2024-11-23 23:23:52 +01:00
Henrik Rydgård 194b2ce076 Ge Debugger: Add a framebuffer listing, along with some plumbing 2024-11-23 23:23:48 +01:00
Henrik Rydgård 80474fd0f0 Some cosmetic fixes to the ImGui debugger 2024-11-07 20:11:23 +01:00
Henrik Rydgård 99eb0bbd64 Improve register view, fix follow PC, some cleanup 2024-11-07 11:10:16 +01:00
Henrik Rydgård 9c92978fcc ImGui debugger: assorted work 2024-11-07 11:10:16 +01:00
Henrik Rydgård 84a0293e54 Add basic register view 2024-11-07 11:10:16 +01:00
Henrik Rydgård cf6d06c56a Start work on imdbg 2024-11-07 11:10:12 +01:00