Set breakpoints with the breakpoint!()
macro on many target architectures
and popular OSes like FreeBSD, macOS, iOS, Linux distro's, Windows without
using the nightly toolchain. Break into the debugger with an easy
breakpoint_if_debugging()
call, too!
Well, sure, but why?
- It might be more convinient to add the call to
breakpoint_if_debugging
from inside the comfort of your editor than to remember the incantion in the debugger, - Some callsites like lambdas and async routines/coroutines can be tricky to set a breakpoint to in the debugger due to name mangling or because the toolchain doesn't give them a name that is easily-discovered/human-friendly,
- Can add this to your
#[panic_handler]
to break into the debugger on a panic.
This model might be reminiscent of "semihosting" where the execution environment includes a host or a debugger who's services might be requested by the program.
Here is the example of how one can make use of this: runme.rs
.
Do exercise extreme caution when using any of this in the production environment, i.e.
out of the inner development loop. Heisenbugs and crashes might be sighted.
Platform- and target-specific notes follow.
The library provides breakpoint_if_debugging()
and breakpoint_if_debugging_seh()
The latter might be useful to detect the debugger if it is trying to hide its presence
via some cheap tricks.
The debugger detection logic will detect any tracer like strace
as the debugger, and
if the tracer isn't able to skip over the breakpoint CPU instruction, the program will
crash. That can be fixed by handling SIGTRAP
inside your program.
brk #imm16
is used for breakpoint on arm64.
Just FYI, the #imm16
value can be inside the Linux kernel 6.1
at the time of writing:
0x004
: for installing kprobes0x005
: for installing uprobes0x006
: for kprobe software single-step0x400
-0x7ff
: kgdb0x100
: for triggering a fault on purpose (reserved)0x400
: for dynamic BRK instruction0x401
: for compile time BRK instruction0x800
: kernel-mode BUG() and WARN() traps0x9xx
: tag-based KASAN trap (allowed values 0x900 - 0x9ff)0x8xxx
: Control-Flow Integrity traps
Here, we're talking the user mode yet the above illustrates the point
that the value supplied after brk
influences what to expect.
For __builtin_trap()
, gcc
produces brk #0x3e8
, clang
generates brk #1
.
This library uses 0xf000
as the debuggers on Windows and macOS skip over the debug
trap automatically in this case by advancing the instruction pointer behind the
curtain.
- C++'s "Debugging Support" paper.
dbg_breakpoint is free and open source. All code in this repository is dual-licensed under either:
- Unlicense (LICENSE-UNLICENSE or https://unlicense.org/)
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.