# Breakpoints when the debugger is attached 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`](src/bin/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. ## Windows 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. ## Linux, macOS and FreeBSD 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. ## arm64 `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 kprobes * `0x005`: for installing uprobes * `0x006`: for kprobe software single-step * `0x400` - `0x7ff`: kgdb * `0x100`: for triggering a fault on purpose (reserved) * `0x400`: for dynamic BRK instruction * `0x401`: for compile time BRK instruction * `0x800`: kernel-mode BUG() and WARN() traps * `0x9xx`: 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. ## See also * C++'s ["Debugging Support"](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2546r0.html) paper. ## License dbg_breakpoint is free and open source. All code in this repository is dual-licensed under either: - Unlicense ([LICENSE-UNLICENSE](/LICENSE-UNLICENSE) or ) - MIT License ([LICENSE-MIT](/LICENSE-MIT) or ) at your option.