Skip to content

fix(aarch64): auto-skip brk instructions in user space#17

Open
yoinspiration wants to merge 11 commits intoarceos-org:devfrom
yoinspiration:fix/aarch64-breakpoint-handling
Open

fix(aarch64): auto-skip brk instructions in user space#17
yoinspiration wants to merge 11 commits intoarceos-org:devfrom
yoinspiration:fix/aarch64-breakpoint-handling

Conversation

@yoinspiration
Copy link
Copy Markdown

@yoinspiration yoinspiration commented Dec 21, 2025

Handle breakpoint exceptions (Brk64 and TrappedMsrMrs) by automatically skipping
the brk instruction (4 bytes) when the process is not being debugged. This matches
Linux behavior where brk instructions are silently ignored for processes without
a debugger attached.

Changes:

  • Handle Brk64 (EC=0x3C) exceptions in UserContext::run()
  • Handle TrappedMsrMrs (EC=0x18) exceptions that may be triggered by brk instructions
  • Skip instruction by incrementing elr by 4 bytes and recursively calling run()
  • Update ExceptionInfo::kind() to recognize TrappedMsrMrs as Breakpoint

Also fixes function pointer cast warnings in init.rs files across all architectures
by using the recommended 'as *const () as usize' pattern.

Handle BreakpointLowerEL exceptions by automatically skipping the brk
instruction (4 bytes) when the process is not being debugged. This matches
Linux behavior where brk instructions are silently ignored for processes
without a debugger attached.

The implementation skips the instruction by incrementing elr by 4 bytes
and recursively calling run() to continue execution immediately.
…owerEL

Use Brk64 exception type which is the correct ESR_EL1::EC value for
breakpoint exceptions in user space, matching the implementation in
trap.rs for kernel space breakpoint handling.
…andling

Enable interrupts before recursively calling run() to ensure proper
interrupt state management when continuing execution after skipping
the brk instruction.
Add debug output to print exception class (EC) values to help diagnose
why breakpoint exceptions might not be matching the Brk64 case.
Change debug! to warn! for exception logging to ensure we can see the
output with warn log level, helping diagnose the actual exception class
value when breakpoint exceptions occur.
Check both Brk64 (0x3C) and BreakpointLowerEL (0x08) exception class
values directly instead of relying only on enum matching, to ensure
we catch breakpoint exceptions from user space brk instructions.
Handle breakpoint exceptions in user space by automatically skipping
the breakpoint instruction when the process is not being debugged.
This matches Linux behavior where breakpoint instructions are silently
ignored for processes without a debugger attached.

Changes:
- aarch64: Handle both Brk64 (0x3C) and BreakpointLowerEL (0x08) exceptions,
  skip 4 bytes, and fix ExceptionInfo::kind() to correctly identify breakpoint
  exceptions from lower exception level
- riscv: Handle Breakpoint exception, skip 2 bytes
- loongarch64: Handle Breakpoint exception, skip 4 bytes
- x86_64: Handle Breakpoint exception (INT3), skip 1 byte

All architectures now recursively call run() after skipping the instruction
to continue execution immediately.
…gging

Add warn-level logging to diagnose why breakpoint exceptions are not
being handled correctly. These logs will show:
- All synchronous exceptions with EC, ISS, and ELR values
- When a breakpoint exception is detected and handled
- When exceptions don't match expected patterns

This is temporary debugging code to identify the actual EC values
being triggered by brk instructions.
Remove check for BreakpointLowerEL (0x08) as the correct exception
type for user space brk instructions is Brk64 (0x3C), not BreakpointLowerEL.
Also remove debug logging that was added for troubleshooting.

The fix ensures that brk instructions in user space are automatically
skipped (by incrementing elr by 4 bytes) and execution continues
immediately, matching Linux behavior where brk instructions are
silently ignored when no debugger is attached.
Handle BreakpointLowerEL exceptions by automatically skipping the brk
instruction (4 bytes) when the process is not being debugged. This matches
Linux behavior where brk instructions are silently ignored for processes
without a debugger attached.

- Handle Brk64 (EC=0x3C) exceptions in UserContext::run()
- Handle TrappedMsrMrs (EC=0x18) exceptions that may be triggered by brk
- Skip instruction by incrementing elr by 4 bytes and recursively calling run()
- Update ExceptionInfo::kind() to recognize TrappedMsrMrs as Breakpoint

Also fix function pointer cast warnings in init.rs files for all architectures:
- aarch64/init.rs: exception_vector_base
- riscv/init.rs: trap_vector_base
- loongarch64/init.rs: exception_entry_base and handle_tlb_refill

All casts now use 'as *const () as usize' pattern as recommended by the compiler.
Replace recursive self.run() calls with loop-based implementation
to avoid potential stack overflow when handling consecutive breakpoint
exceptions. This change applies to all architectures:
- aarch64: Brk64 and TrappedMsrMrs exceptions
- x86_64: BREAKPOINT_VECTOR
- loongarch64: Breakpoint exception
- riscv: Breakpoint exception

The new implementation uses a loop with continue statement instead
of recursive calls, maintaining the same behavior of silently skipping
breakpoint instructions when the process is not being debugged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant