Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debugger: Add conditional data breakpoints, and a few minor bug fixes #2473

Open
wants to merge 40 commits into
base: master
Choose a base branch
from

Conversation

mateusfavarin
Copy link

I've implemented conditional data breakpoints for variable memory sizes. Duckstation was storing the address of each breakpoint as the information to check for when an execution breakpoint is valid. I expanded this idea by creating the struct DebugAddress, which encapsulates an address, a size and a debug_mode. The user can create a DebugAddress by adding a breakpoint using the UI, and select multiple conditions for the breakpoint: read, write, changed value or execution.

The execution breakpoint that was implemented on duck had to be modified by adding an extra check for the debug_mode, so only execution breakpoints can trigger that event. The data breakpoint was implemented by adding a function that looks ahead of what the next CPU instruction is going to be, and if the next instruction matches the conditions of any DebugAddress, then the emulation is paused before the CPU executes that instruction. The UI had to be changed in order for the user to create such breakpoints.

A few minor bug fixes unrelated to that:

  • Change breakpoint list ID to reset at 1, just like it's constructed.
  • When a breakpoint is removed, decrement the ID of every other breakpoint with an ID greater than the one that were removed.
  • When breakpoints are cleared, update the breakpoint list UI to give a visual feedback to the user.
  • Fix the breakpoint not disabling when you toggle the checkbox in the breakpoint list.
  • Change instruction format to always display hexadecimal values for consistency, and also change the sll zero, zero to nop.
  • Add the possibility to edit and delete breakpoints by interacting with the mouse in the breakpoint list.

This PR addresses some of the issues mentioned at #2179.

@mateusfavarin mateusfavarin changed the title Debugger: Add conditional data breakpoints, and few minor bug fixes Debugger: Add conditional data breakpoints, and a few minor bug fixes Aug 3, 2021
@stenzek
Copy link
Owner

stenzek commented Aug 4, 2021

Thanks! I'll get around to reviewing this soon, super busy with work this week :(

Copy link
Owner

@stenzek stenzek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only looked at the CPU side for now, I'm a little concerned about the performance impact given the fact that this code can potentially execute up to 33.8 million times per second.

{
const u32 pc = g_state.regs.pc;
Instruction inst = g_state.current_instruction;
inst.bits = inst_bits;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant assignment

if (inst.bits == 0)
return false;

switch (inst.op)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just read g_state.current_instruction

// continue is measurably faster than break on msvc for some reason
continue;
}
if (ExecutionBreakpointCheck())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (ExecutionBreakpointCheck() || ConditionalBreakpointLookAhead())

case InstructionOp::lw:
{
const VirtualMemoryAddress addr = ReadReg(inst.i.rs) + inst.i.imm_sext32();
DataBreakpointCheck<MemoryAccessType::Read>(addr);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to get very slow. It would probably be better to align the test address down, and do a single range check in DataBreakpointCheck.

@@ -17,6 +17,21 @@ enum class MemoryAccessSize : u32
Word
};

struct DebugAddress
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than combining the breakpoints, it'd be better to store the execution and data breakpoints in separate arrays (fewer loops/comparisons for every guest instruction).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants