Breakpoints
Set a breakpoint with lazydap break file:line. It is written to .lazydap/state.toml in
your project and applied to every session you launch afterwards, whether or not one is
running when you set it.
lazydap break hello.c:6They are project state, not session state
Section titled “They are project state, not session state”This is the part that differs from most debuggers. A breakpoint set today applies to the program you launch tomorrow, and to the one you launch after restarting the daemon. There is no separate “save breakpoints” step, and no session to attach them to first.
$ cat .lazydap/state.tomlversion = 1next_breakpoint_id = 3
[[breakpoints]]id = 2source = "hello.c"line = 6condition = "i == 7"enabled = trueTOML rather than a database, so it diffs, greps, and can be written by anything. Commit it if
your team wants shared breakpoints; the repository’s own .gitignore leaves that choice to
you.
Verified means bound
Section titled “Verified means bound”verified is the field to read. When you set a breakpoint with nothing running, nothing has
checked whether the line exists:
$ lazydap break hello.c:6 --format json{ "action": "added", "applied_to_session": false, "breakpoints": [ { "enabled": true, "id": 1, "line": 6, "source": "/Users/you/lazydap-demo/hello.c", "verified": false } ], "dry_run": false, "not_found": []}launch applies it and the adapter decides. Watch it change in breakpoint_updates on the
next --wait reply:
"breakpoint_updates": [ { "adapter_id": 1, "id": 1, "line": 6, "message": "Resolved locations: 1", "verified": true }]“Resolved locations: 1” is the good case. A breakpoint that stays verified: false will
never stop anything, and lazydap reports it rather than failing, per DAP. If a program runs
straight past a line you know it reaches, read verified first —
the troubleshooting page lists the
three usual causes.
Conditions
Section titled “Conditions”--condition takes an expression in the debuggee’s language, evaluated at the breakpoint. The
program only stops when it is true.
$ lazydap break hello.c:6 --condition 'i == 7' --format json{ "action": "added", "breakpoints": [ { "condition": "i == 7", "enabled": true, "id": 2, "line": 6, "source": "/Users/you/lazydap-demo/hello.c", "verified": false } ], "dry_run": false, "not_found": []}Launching and continuing then stops on the seventh iteration and nowhere else:
$ lazydap variables --reference 1003 --format tableNAME VALUE TYPE REFERENCEn 10 int 0sum 21 int 0i 7 int 0sum is 21, which is 1+2+3+4+5+6 — the condition held exactly once, before the seventh
addition.
--hit-condition counts hits instead of testing a value: --hit-condition '>= 10' stops on
the tenth arrival and after.
--log turns a breakpoint into a log point. The program does not stop; the message is emitted
instead, with braces interpolated from the debuggee’s scope:
lazydap break hello.c:6 --log "i = {i}, sum = {sum}"Log-point output arrives in captured_output on the next
--wait reply, like anything else the program produced.
Conditions can be set from the CLI but not yet from the TUI.
Listing and selecting
Section titled “Listing and selecting”$ lazydap break --list --format tableID LOCATION ENABLED VERIFIED CONDITION1 hello.c:6 true true ---format ids prints bare ids for piping:
$ lazydap break --list --format ids1Selection for --remove and --toggle is by --id (repeatable) or --all:
lazydap break --toggle --id 1 # disable, or re-enablelazydap break --remove --id 1 --id 2lazydap break --remove --allDry-run first
Section titled “Dry-run first”Every mutation takes --dry-run and reports what it would have done:
$ lazydap break --remove --all --dry-run --format json{ "action": "removed", "breakpoints": [ { "enabled": true, "id": 1, "line": 6, "message": "Resolved locations: 1", "source": "/Users/you/lazydap-demo/hello.c", "verified": true } ], "dry_run": true, "not_found": []}The breakpoints array is the set that would be removed, chosen by the same selection code
the real removal uses — not a second implementation that could disagree with it. Drop
--dry-run and that is what goes.
not_found lists ids you asked for that do not exist, so a script can tell “removed nothing
because there was nothing” from “removed nothing because I typo’d the id”.
Paths are relative to your shell, and lazydap canonicalises them before sending them on. That
is what keeps the daemon and the adapter agreeing about a file regardless of anyone’s working
directory, and it is why a typo fails immediately instead of as a silent verified: false
later.
The exception is symlinked directories, where canonicalising is the thing that breaks it —
see quirk 8 and
keep debuggees out of /tmp on macOS.
See also
Section titled “See also”lazydap break— every flag- Quickstart — a breakpoint end to end
- Troubleshooting — when one does not bind