textual-debugger 0.2.6__tar.gz → 0.2.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/PKG-INFO +294 -43
- {textual_debugger-0.2.6/src/tdb → textual_debugger-0.2.8}/README.md +293 -42
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/pyproject.toml +2 -1
- {textual_debugger-0.2.6 → textual_debugger-0.2.8/src/tdb}/README.md +293 -42
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/__init__.py +1 -1
- textual_debugger-0.2.8/src/tdb/adapters/ocaml/lldb_formatters.py +153 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/perl/server.py +21 -10
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/perl/session.py +9 -1
- textual_debugger-0.2.8/src/tdb/adapters/ruby/__init__.py +1 -0
- textual_debugger-0.2.8/src/tdb/adapters/ruby/__main__.py +23 -0
- textual_debugger-0.2.8/src/tdb/adapters/ruby/server.py +1120 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/app.py +28 -17
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/app_handlers/dap_events.py +3 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/app_handlers/inspection.py +101 -1
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/app_handlers/routing.py +36 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/app_handlers/ui_panels.py +39 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/cli.py +41 -10
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/dap/client.py +3 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/languages/base.py +63 -1
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/languages/bash.py +3 -1
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/languages/cpp.py +49 -6
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/languages/errors.py +216 -0
- textual_debugger-0.2.8/src/tdb/languages/ocaml.py +324 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/languages/perl.py +3 -1
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/languages/python.py +6 -4
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/languages/registry.py +71 -9
- textual_debugger-0.2.8/src/tdb/languages/ruby.py +117 -0
- textual_debugger-0.2.8/src/tdb/languages/rust.py +158 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/languages/tcsh.py +3 -1
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/mcp/server.py +41 -9
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/mcp/session.py +29 -5
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/replay.py +12 -2
- textual_debugger-0.2.8/src/tdb/rust_concurrency/__init__.py +41 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/analyzer.py +505 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/classifier.py +255 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/collector.py +337 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/models.py +269 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/probes/__init__.py +18 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/probes/base.py +166 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/probes/gdb.py +27 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/probes/gdb_script.py +238 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/probes/lldb.py +35 -0
- textual_debugger-0.2.8/src/tdb/rust_concurrency/probes/lldb_script.py +276 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/server/app.py +1 -1
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/server/handlers.py +21 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/server/rpc_types.py +17 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/server/runner.py +15 -3
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/controller.py +112 -14
- textual_debugger-0.2.8/src/tdb/session/errors.py +23 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/inspect_service.py +24 -15
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/recorder.py +3 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/state.py +2 -0
- textual_debugger-0.2.8/src/tdb/widgets/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/_inspection_modal.py +11 -2
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/modals.py +21 -10
- textual_debugger-0.2.8/src/tdb/widgets/rust_concurrency_modal.py +397 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/stack_view.py +6 -2
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/threads_modal.py +55 -8
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/textual_debugger.egg-info/PKG-INFO +294 -43
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/textual_debugger.egg-info/SOURCES.txt +21 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/LICENSE +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/setup.cfg +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/__main__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/_timeouts.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/bash/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/bash/__main__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/bash/declares.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/bash/server.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/bash/session.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/bash/tdb_harness.sh +0 -0
- {textual_debugger-0.2.6/src/tdb/adapters/perl → textual_debugger-0.2.8/src/tdb/adapters/ocaml}/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/perl/Devel/TdbCompile.pm +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/perl/Devel/TdbRemote.pm +0 -0
- {textual_debugger-0.2.6/src/tdb/dap → textual_debugger-0.2.8/src/tdb/adapters/perl}/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/perl/__main__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/perl/helpers.pl +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/perl/protocol.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/perl/refs.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/__main__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/breakpoints.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/cli.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/guardian.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/inspect.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/instrumenter.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/models.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/protocol.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/runtime.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/scanner.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/server.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/session.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/adapters/tcsh/transport.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/app_handlers/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/app_helpers.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/breakpoint_hook.py +0 -0
- {textual_debugger-0.2.6/src/tdb/server → textual_debugger-0.2.8/src/tdb/dap}/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/dap/messages.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/dap/protocol.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/dap/reverse.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/dap/types.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/inspection.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/inspection_full.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/keybindings/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/languages/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/mcp/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/mcp/__main__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/persist.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/post_mortem.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/processes_cache.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/run_mode.py +0 -0
- {textual_debugger-0.2.6/src/tdb/session → textual_debugger-0.2.8/src/tdb/server}/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/server/event_handler.py +0 -0
- {textual_debugger-0.2.6/src/tdb/widgets → textual_debugger-0.2.8/src/tdb/session}/__init__.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/child_processes.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/event_bus.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/messages.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/post_mortem_loader.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/statement_stepper.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/terminal.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/session/textual_handler.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/source_analysis.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/async_tasks_modal.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/breakpoint_view.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/code_view.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/console_view.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/evaluate_console.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/full_contents_modal.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/menu_bar.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/processes_modal.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/status_bar.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/tdb/widgets/variable_view.py +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/textual_debugger.egg-info/dependency_links.txt +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/textual_debugger.egg-info/entry_points.txt +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/textual_debugger.egg-info/requires.txt +0 -0
- {textual_debugger-0.2.6 → textual_debugger-0.2.8}/src/textual_debugger.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: textual-debugger
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: A TUI debugger for Python, Perl, and other languages. Based on textual.
|
|
5
5
|
Author-email: Al Danial <al.danial@gmail.com>
|
|
6
6
|
License: textual-debugger is licensed to you under the MIT/X Consortium license:
|
|
@@ -73,16 +73,16 @@ a full-featured terminal-based debugger for Python and other languages
|
|
|
73
73
|
with a Debug Adapter Protocol (DAP) implementation. In addition to Python,
|
|
74
74
|
`tdb` comes with built-in support for
|
|
75
75
|
- C and C++ (via `gdb` or `lldb-dap`)
|
|
76
|
+
- Rust (via `gdb` or `lldb-dap`, selected explicitly)
|
|
76
77
|
- Perl (via `perl -d`)
|
|
77
78
|
- Bash (via bash's own `DEBUG` trap; bash ≥ 4.4)
|
|
78
79
|
- Tcsh (via source instrumentation of a stock `tcsh`)
|
|
80
|
+
- Ruby (via the [debug gem](https://github.com/ruby/debug)'s `rdbg`; debug ≥ 1.9)
|
|
81
|
+
- OCaml (native via `lldb-dap`/`gdb`, bytecode via [ocamlearlybird](https://github.com/hackwaly/ocamlearlybird))
|
|
79
82
|
|
|
80
83
|
`tdb` is built with [textual](https://github.com/Textualize/textual) and speaks
|
|
81
|
-
DAP to a pluggable debug adapter
|
|
82
|
-
|
|
83
|
-
[GDB's DAP mode](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Debugger-Adapter-Protocol.html) or
|
|
84
|
-
[lldb-dap](https://lldb.llvm.org/resources/lldbdap.html)
|
|
85
|
-
for compiled code. It provides a rich interactive interface for stepping through
|
|
84
|
+
DAP to a pluggable debug adapter.
|
|
85
|
+
It provides a rich interactive interface for stepping through
|
|
86
86
|
code, inspecting variables, managing breakpoints, and evaluating expressions in
|
|
87
87
|
complex programs.
|
|
88
88
|
|
|
@@ -96,10 +96,13 @@ MIT License. Copyright 2026 by Al Danial.
|
|
|
96
96
|
`tdb`:
|
|
97
97
|
|
|
98
98
|
- debugs multiple languages through the Debug Adapter Protocol: Python (via `debugpy`,
|
|
99
|
-
the richest feature set), C/C++ (via `gdb -i dap` or `lldb-dap`),
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
the richest feature set), C/C++ (via `gdb -i dap` or `lldb-dap`), Rust (via `gdb` or
|
|
100
|
+
`lldb-dap`), Perl (via `perl -d`),
|
|
101
|
+
Bash (via bash's own `DEBUG` trap), Tcsh (via source instrumentation of a
|
|
102
|
+
stock `tcsh`), Ruby (via the debug gem's `rdbg`), and OCaml (native via
|
|
103
|
+
`lldb-dap`/`gdb`, bytecode via ocamlearlybird). Most languages are
|
|
104
|
+
auto-detected from the target; Rust intentionally requires `--lang rust`
|
|
105
|
+
(ref. [Multi-Language Debugging](#multi-language-debugging)).
|
|
103
106
|
|
|
104
107
|
- supports debugging of synchronous, asynchronous, multi-threaded, and multi-process Python code.
|
|
105
108
|
It specifically supports modules
|
|
@@ -107,7 +110,7 @@ It specifically supports modules
|
|
|
107
110
|
- `threading` (with a thread inspector)
|
|
108
111
|
- `multiprocessing` / `concurrent.futures` (with automatic child process attachment and a process inspector)
|
|
109
112
|
|
|
110
|
-
- supports remote attachment to
|
|
113
|
+
- supports remote attachment to Python, Perl, Ruby, Rust, and C/C++ programs
|
|
111
114
|
|
|
112
115
|
- includes a JSON-RPC server mode, an MCP mode, and a `SKILL.md` file that enable
|
|
113
116
|
programmatic debug control, making it suitable for
|
|
@@ -142,7 +145,8 @@ as open source.
|
|
|
142
145
|
- OpenAI, for providing access to Codex through the
|
|
143
146
|
[Codex for Open Source](https://developers.openai.com/community/codex-for-oss) program.
|
|
144
147
|
|
|
145
|
-
This project was inspired by Andreas Klöckner's excellent [pudb](https://pypi.org/project/pudb/)
|
|
148
|
+
This project was inspired by Andreas Klöckner's excellent [pudb](https://pypi.org/project/pudb/)
|
|
149
|
+
Python debugger.
|
|
146
150
|
|
|
147
151
|
## Gallery
|
|
148
152
|
<p align="center">
|
|
@@ -246,32 +250,49 @@ python -m tdb my_program.py
|
|
|
246
250
|
|
|
247
251
|
## Multi-Language Debugging
|
|
248
252
|
|
|
249
|
-
`tdb` debugs any language that has a Debug Adapter Protocol backend.
|
|
253
|
+
`tdb` debugs any language that has a Debug Adapter Protocol backend. Eight
|
|
250
254
|
languages are supported out of the box:
|
|
251
255
|
|
|
252
256
|
| Language | Adapter(s) | Dependencies | Feature level |
|
|
253
257
|
|----------|------------|------------------------|---------------|
|
|
254
258
|
| Python | `debugpy` (default) | Python ≥ 3.11 | everything in this README |
|
|
255
|
-
| C / C++ (any native binary) | `gdb` (default), `lldb-dap` (alternate) | `gdb -i dap` requires GDB ≥ 14; `lldb-dap` ships with LLVM ≥ 17 (e.g. `apt install lldb`) | core debugging: breakpoints, stepping, stack, variables, evaluate console |
|
|
259
|
+
| C / C++ (any native binary) | `gdb` (default), `lldb-dap` (alternate) | `gdb -i dap` requires GDB ≥ 14; `lldb-dap` ships with LLVM ≥ 17 (e.g. `apt install lldb`) | core debugging: breakpoints, stepping, stack, variables, evaluate console + remote attach (gdbserver/lldb-server, local symbol-bearing executable required) |
|
|
260
|
+
| Rust (explicit `--lang rust`) | `gdb` (Linux default), `lldb-dap` (macOS default) | any rustc building with debug info; GDB ≥ 14 or LLVM `lldb-dap` ≥ 17 (concurrency ownership evidence additionally requires stable Rust 1.98) | core debugging + best-effort Rust concurrency inspection + remote attach |
|
|
256
261
|
| Perl | perl-tdb (bundled) | perl ≥ 5.18 on PATH | core debugging + remote attach |
|
|
257
262
|
| Bash | bash-tdb (bundled) | bash ≥ 4.4 on PATH | core debugging (no remote attach) |
|
|
258
263
|
| Tcsh | tcsh-tdb (bundled) | tcsh on PATH | core debugging (no remote attach, no conditional breakpoints, no pause) |
|
|
264
|
+
| Ruby | `rdbg` (the [debug gem](https://github.com/ruby/debug)) | `rdbg` ≥ 1.9 on PATH | core debugging + remote attach |
|
|
265
|
+
| OCaml (native executable) | `lldb-dap` (default), `gdb` (alternate) | OCaml ≥ 4.12; `lldb-dap` ships with LLVM ≥ 17; `gdb -i dap` requires GDB ≥ 14 | core debugging + domains-as-threads; Variables view shows no OCaml locals (upstream DWARF limitation); evaluate console is lldb/C-level, not OCaml |
|
|
266
|
+
| OCaml (bytecode executable) | `ocamlearlybird` (default) | OCaml ≥ 4.12; `opam install earlybird` | core debugging + rich OCaml locals; no pause/`--run`, no evaluate responses, no fatal-error modal (ocamlearlybird 1.3.6 limitations); single-domain only |
|
|
259
267
|
|
|
260
268
|
### Language detection and selection
|
|
261
269
|
|
|
262
270
|
The language is auto-detected from the debug target:
|
|
263
271
|
|
|
264
272
|
1. File extension: `.py` → Python; `.pl` / `.pm` / `.t` → Perl; `.sh` / `.bash`
|
|
265
|
-
→ Bash; `.csh` / `.tcsh` → Tcsh.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
273
|
+
→ Bash; `.csh` / `.tcsh` → Tcsh; `.rb` → Ruby. (`.ml` / `.mli` do *not*
|
|
274
|
+
auto-select OCaml, see point 5.)
|
|
275
|
+
2. Native executables (ELF, Mach-O, PE magic bytes) → C/C++, unless
|
|
276
|
+
byte-sniffing finds an OCaml marker, either a native binary's
|
|
277
|
+
`caml_program`/`caml_startup` runtime symbols, a bytecode file's
|
|
278
|
+
trailing `Caml1999` marker, or a `#!...ocamlrun` shebang, in which case
|
|
279
|
+
→ OCaml (native or bytecode respectively). A stripped native OCaml
|
|
280
|
+
binary that byte-sniffing can't identify falls back to C/C++; force it
|
|
281
|
+
with `--lang ocaml`. Rust is never inferred from an executable; select
|
|
282
|
+
it explicitly with `--lang rust`.
|
|
283
|
+
3. A `#!...python`, `#!...perl`, `#!...bash`, `#!...csh`/`#!...tcsh`, or
|
|
284
|
+
`#!...ruby` shebang → Python / Perl / Bash / Tcsh / Ruby respectively.
|
|
269
285
|
4. C/C++/Rust *source* files (`.c`, `.cpp`, `.rs`, …) produce an error with a
|
|
270
286
|
hint: compile with debug info (`g++ -g -O0`) and debug the binary.
|
|
271
|
-
5.
|
|
287
|
+
5. `.ml` / `.mli` (OCaml source) produce an error too: build the project
|
|
288
|
+
first (dune's dev profile keeps debug info) and pass the **built
|
|
289
|
+
executable** to `tdb` (`tdb ./_build/default/bin/main.exe`), never the
|
|
290
|
+
`.ml` file.
|
|
291
|
+
6. Anything else produces an error naming the `--lang` override.
|
|
272
292
|
|
|
273
293
|
`--lang` forces the language; `--adapter` picks a non-default adapter within
|
|
274
|
-
it (`tdb --lang cpp --adapter lldb-dap ./myprog`).
|
|
294
|
+
it (`tdb --lang cpp --adapter lldb-dap ./myprog`). Rust always requires the
|
|
295
|
+
explicit language selection (`tdb --lang rust target/debug/app`).
|
|
275
296
|
|
|
276
297
|
> **Migration note:** extensionless Python scripts without a `python` shebang
|
|
277
298
|
> were previously assumed to be Python; they now require `--lang python`.
|
|
@@ -304,13 +325,17 @@ process inspectors and wait graph, the evaluate console's trailing-`?` help,
|
|
|
304
325
|
`--python`/`--pv`, `--no-subprocess`, automatic child-process attachment, and
|
|
305
326
|
the post-mortem / `tdb.breakpoint()` hooks (those hooks live inside Python
|
|
306
327
|
programs by nature). Remote attach (`-r`) also works for Perl (see
|
|
307
|
-
[Perl](#perl), `Devel::TdbRemote` in place of `debugpy.listen()`),
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
see [
|
|
328
|
+
[Perl](#perl), `Devel::TdbRemote` in place of `debugpy.listen()`), Ruby
|
|
329
|
+
(see [Ruby](#ruby), `rdbg --open` in place of `debugpy.listen()`), and for
|
|
330
|
+
Rust and C/C++ native binaries (against a gdbserver/lldb-server stub, with
|
|
331
|
+
a local symbol-bearing executable; see [Rust](#rust) — the same flags work
|
|
332
|
+
for a C/C++ target without `--lang`), but not for Bash, Tcsh, or OCaml. `--terminal` works for every launch-mode
|
|
333
|
+
language — Python, Perl, Bash, Tcsh, Ruby, and C/C++, OCaml native, or Rust
|
|
334
|
+
sessions via `--adapter lldb-dap` — see
|
|
335
|
+
[External Terminal Support](#external-terminal-support).
|
|
311
336
|
|
|
312
337
|
**Bash limitations (v1):** the bash adapter uses bash's own `DEBUG` trap and
|
|
313
|
-
has a smaller feature
|
|
338
|
+
has a smaller feature set than Python:
|
|
314
339
|
|
|
315
340
|
- Debuggee code that installs its own `DEBUG` trap clobbers the harness;
|
|
316
341
|
debugging silently degrades to free-running.
|
|
@@ -354,9 +379,30 @@ paths and line numbers are preserved in everything tdb displays):
|
|
|
354
379
|
|
|
355
380
|
See [Tcsh](#tcsh) below for launch details.
|
|
356
381
|
|
|
382
|
+
**OCaml limitations (v1):** OCaml has two independent adapters with
|
|
383
|
+
different, non-overlapping gaps; see [OCaml](#ocaml) below for the full
|
|
384
|
+
picture:
|
|
385
|
+
|
|
386
|
+
- **Native (`lldb-dap`/`gdb`):** the Variables view shows no named OCaml
|
|
387
|
+
locals in an OCaml frame (only a `Registers` scope). This is an
|
|
388
|
+
upstream OCaml/DWARF limitation on stock OCaml 5.4, not a `tdb` bug; use
|
|
389
|
+
the bytecode adapter when you need to inspect locals. The evaluate
|
|
390
|
+
console evaluates lldb/C-level expressions (runtime spelunking), not
|
|
391
|
+
OCaml expressions.
|
|
392
|
+
- **Bytecode (`ocamlearlybird`):** single-domain only (no multicore); no
|
|
393
|
+
`pause` while running (so `--run` is unavailable); the evaluate console
|
|
394
|
+
never gets a response for any expression (an `ocamlearlybird` 1.3.6
|
|
395
|
+
limitation); and the fatal-error modal doesn't appear for an uncaught
|
|
396
|
+
exception (`ocamlearlybird` swallows the real exception text before it
|
|
397
|
+
reaches `tdb`). Run the program outside the debugger to see the
|
|
398
|
+
backtrace instead.
|
|
399
|
+
- No Windows support, no remote attach, and a stripped native binary that
|
|
400
|
+
byte-sniffing can't identify needs `--lang ocaml`.
|
|
401
|
+
|
|
357
402
|
### C/C++ tips
|
|
358
403
|
|
|
359
|
-
- Compile with `-g` (ideally `-g -O0`
|
|
404
|
+
- Compile with `-g` (ideally `-g -O0` or `-g3 -O0`).
|
|
405
|
+
If no breakpoint in a file can be
|
|
360
406
|
bound, `tdb` prints a console warning suggesting the program may lack
|
|
361
407
|
debug info.
|
|
362
408
|
- Stack frames pointing into system libraries often have no source on disk;
|
|
@@ -373,6 +419,72 @@ See [Tcsh](#tcsh) below for launch details.
|
|
|
373
419
|
requires `--adapter lldb-dap`; GDB's DAP mode has no terminal integration
|
|
374
420
|
and `tdb` refuses `--terminal` with the default `gdb` adapter.
|
|
375
421
|
|
|
422
|
+
### Rust
|
|
423
|
+
|
|
424
|
+
Rust debugging is intentionally explicit: build a normal debug executable,
|
|
425
|
+
leave it unmodified, and pass that executable with `--lang rust`. Linux and
|
|
426
|
+
macOS are supported; Windows is not yet (MSVC-toolchain binaries carry PDB
|
|
427
|
+
debug info that neither `gdb -i dap` nor this release's probes read). `tdb` does
|
|
428
|
+
not compile, instrument, or auto-detect Rust programs. Core debugging
|
|
429
|
+
(breakpoints, stepping, stacks, variables, remote attach) works with any
|
|
430
|
+
rustc that emits debug info; the concurrency inspector's layout-specific
|
|
431
|
+
*ownership evidence* additionally requires the current stable Rust
|
|
432
|
+
**1.98** standard-library layout — on other versions the workspace still
|
|
433
|
+
opens with stack-based wait classification and a compatibility warning.
|
|
434
|
+
Build with debug information and no optimization for the most useful
|
|
435
|
+
source locations:
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
cargo rustc -- -C debuginfo=2 -C opt-level=0
|
|
439
|
+
# Equivalent direct rustc settings: rustc -C debuginfo=2 -C opt-level=0 src/main.rs
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
A panic that terminates the debuggee opens the error modal with the parsed
|
|
443
|
+
panic message and backtrace; `tdb` injects `RUST_BACKTRACE=1` into launched
|
|
444
|
+
programs (your own value wins if you set one) so the frames are present.
|
|
445
|
+
|
|
446
|
+
The common commands are:
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
cargo build
|
|
450
|
+
tdb --lang rust target/debug/app
|
|
451
|
+
tdb --lang rust --adapter lldb-dap --run target/debug/app
|
|
452
|
+
tdb --lang rust --adapter lldb-dap --terminal xterm target/debug/app
|
|
453
|
+
tdb --lang rust --adapter gdb --remote-attach host:2345 target/debug/app
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
`--run` and normal stopped-on-entry launch work with both adapters. On Linux,
|
|
457
|
+
use GDB (the default) or `lldb-dap`; on macOS, use `lldb-dap` (the default).
|
|
458
|
+
External terminals are LLDB-only: GDB's DAP mode cannot provide terminal
|
|
459
|
+
integration. The mode/platform matrix is:
|
|
460
|
+
|
|
461
|
+
| Platform | Normal / `--run` | `--terminal` | `--remote-attach` |
|
|
462
|
+
|----------|------------------|--------------|-------------------|
|
|
463
|
+
| Linux | GDB or `lldb-dap` | `lldb-dap` only | GDB or `lldb-dap` |
|
|
464
|
+
| macOS | `lldb-dap` | `lldb-dap` only | `lldb-dap` |
|
|
465
|
+
|
|
466
|
+
Remote attach connects to a GDB-remote server already running on the target.
|
|
467
|
+
Pass the matching **local, unmodified executable with debug symbols** as the
|
|
468
|
+
program argument; `tdb` requires it for symbols and Rust concurrency evidence.
|
|
469
|
+
When source paths differ, pair `--local-root` with `--remote-root`. Do not
|
|
470
|
+
expose the remote debug port to an untrusted network: prefer an SSH tunnel,
|
|
471
|
+
for example `ssh -L 2345:127.0.0.1:2345 host`, then attach to `127.0.0.1:2345`.
|
|
472
|
+
|
|
473
|
+
In a Rust session the Threads action (`Alt+T`, or the Threads menu entry)
|
|
474
|
+
opens the Rust Concurrency workspace while the debuggee is stopped — a
|
|
475
|
+
fresh, bounded snapshot of threads, wait edges, and findings. The graph is
|
|
476
|
+
best effort: `confirmed` evidence is directly observed by the debugger,
|
|
477
|
+
`probable` is a supported inference, and `unknown` means ownership could not
|
|
478
|
+
be established. A deadlock is confirmed only when every edge in its cycle is
|
|
479
|
+
confirmed. A suspected cycle or whole-program stall is a diagnostic lead, not
|
|
480
|
+
a proof: it means a cycle has incomplete evidence, or all observed application
|
|
481
|
+
threads are blocked while the graph cannot safely invent an owner. Refresh
|
|
482
|
+
after the next stop to collect a new snapshot.
|
|
483
|
+
|
|
484
|
+
The built-in evidence recognizes current `std` synchronization layouts. A
|
|
485
|
+
future helper crate may expose stable, application-provided synchronization
|
|
486
|
+
metadata for broader primitives and stronger ownership evidence.
|
|
487
|
+
|
|
376
488
|
### Perl
|
|
377
489
|
|
|
378
490
|
`tdb` bundles its own Perl adapter (`perl-tdb`) so only need
|
|
@@ -549,6 +661,119 @@ text directly in the paused shell. It can inspect *and mutate* state
|
|
|
549
661
|
(`set name = value` takes effect immediately), and a syntax error in
|
|
550
662
|
evaluated text can terminate the debuggee; there is no isolation.
|
|
551
663
|
|
|
664
|
+
### Ruby
|
|
665
|
+
|
|
666
|
+
tdb debugs Ruby via the [debug gem](https://github.com/ruby/debug)'s
|
|
667
|
+
`rdbg` (Ruby >= 3.1 ships it; otherwise `gem install debug`; tdb needs
|
|
668
|
+
debug >= 1.9). `rdbg` must be on PATH, or point tdb at it with
|
|
669
|
+
`{"adapters": {"rdbg": "/path/to/rdbg"}}` in config.json.
|
|
670
|
+
|
|
671
|
+
```bash
|
|
672
|
+
tdb script.rb # launch, stop at first line
|
|
673
|
+
tdb --run script.rb # run immediately, debug on demand
|
|
674
|
+
tdb --terminal script.rb # program I/O in its own terminal
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
Remote attach: start the program with
|
|
678
|
+
`rdbg --open --port 5678 --host 0.0.0.0 script.rb` (add `--nonstop` to
|
|
679
|
+
let it run before you attach), then `tdb -r HOST:5678 --lang ruby`.
|
|
680
|
+
Note: rdbg's `--cookie` authentication is not part of DAP and is not
|
|
681
|
+
supported; bind to localhost and tunnel over SSH instead.
|
|
682
|
+
`--local-root`/`--remote-root` path mappings are not supported for Ruby
|
|
683
|
+
yet. Bundler projects work when your environment resolves `rdbg`
|
|
684
|
+
(`gem install debug` into the project's Ruby); there is no `bundle
|
|
685
|
+
exec` integration yet.
|
|
686
|
+
|
|
687
|
+
> **Startup note:** the debug gem's `rdbg` has an occasional handshake
|
|
688
|
+
> race on launch; tdb detects a stalled/corrupted handshake and retries
|
|
689
|
+
> once automatically with a fresh `rdbg`, so this is usually invisible.
|
|
690
|
+
|
|
691
|
+
### OCaml
|
|
692
|
+
|
|
693
|
+
`tdb` debugs OCaml through two independent adapters, chosen automatically
|
|
694
|
+
from how the executable was built:
|
|
695
|
+
|
|
696
|
+
- **Native** (`ocamlopt`/dune's default build) → **`lldb-dap`** (default;
|
|
697
|
+
`--adapter gdb` also works). OCaml 5's domains show up as threads.
|
|
698
|
+
- **Bytecode** (`ocamlc -g`) → **`ocamlearlybird`** (`opam install
|
|
699
|
+
earlybird`). Single-domain only, but with rich, real OCaml locals.
|
|
700
|
+
|
|
701
|
+
**Build requirement:** compile with `-g` (dune's dev profile already
|
|
702
|
+
does). Always pass the **built executable** to `tdb`, never the `.ml`
|
|
703
|
+
source, as in `tdb ./_build/default/bin/main.exe`, not `tdb main.ml` (which
|
|
704
|
+
errors with this exact guidance).
|
|
705
|
+
|
|
706
|
+
**OCaml version:** tdb requires **OCaml ≥ 4.12**. Older runtimes print
|
|
707
|
+
`Printexc` backtraces without function names, which the fatal-error
|
|
708
|
+
modal's parser does not understand (frames would be dropped and the
|
|
709
|
+
modal would wrongly suggest recompiling with `-g`).
|
|
710
|
+
|
|
711
|
+
```bash
|
|
712
|
+
tdb ./_build/default/bin/main.exe # native, lldb-dap
|
|
713
|
+
tdb --adapter gdb ./_build/default/bin/main.exe # native, gdb
|
|
714
|
+
tdb ./_build/default/bin/main.byte # bytecode, ocamlearlybird
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
A stripped native binary that byte-sniffing can't identify as OCaml falls
|
|
718
|
+
back to C/C++; force it with `--lang ocaml`. Override the adapter or point
|
|
719
|
+
at a non-`PATH` install in `config.json` (see
|
|
720
|
+
[Configuration](#configuration)):
|
|
721
|
+
|
|
722
|
+
```json
|
|
723
|
+
{
|
|
724
|
+
"adapters": {"ocamlearlybird": "/path/to/ocamlearlybird"},
|
|
725
|
+
"default_adapters": {"ocaml": "gdb"}
|
|
726
|
+
}
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
**Domains as threads (native only):** OCaml 5's domains are presented in
|
|
730
|
+
the Threads modal (`Alt+T` or the **Threads (N)** menu label) as `Domain 0
|
|
731
|
+
(main)`, `Domain 1`, and so on, in creation order. The runtime's internal
|
|
732
|
+
"backup thread" (one per domain, used for I/O blocking) is hidden by
|
|
733
|
+
default since it's never running user code; press `a` in the Threads
|
|
734
|
+
modal to reveal it alongside the domains. Breakpoints, stepping, continue,
|
|
735
|
+
and pause all work normally against any domain. In both the Stack view
|
|
736
|
+
and the Threads modal, OCaml frame names are demangled from the
|
|
737
|
+
runtime's raw `camlModule__name_NNN` convention into readable
|
|
738
|
+
`Module.name` form (e.g. `camlOcaml_domains.worker_297` displays as
|
|
739
|
+
`Ocaml_domains.worker`); runtime C frames (`caml_start_program`,
|
|
740
|
+
`caml_callback_exn`, and the like) are shown as-is, unchanged.
|
|
741
|
+
|
|
742
|
+
**Variables view (native):** stock OCaml 5.4 native DWARF shows **no
|
|
743
|
+
named locals**. The `scopes`/`variables` round trip succeeds, but every
|
|
744
|
+
OCaml frame's `Locals` and `Globals` scopes come back empty; only a
|
|
745
|
+
`Registers` scope has data (the raw register file, not decoded OCaml
|
|
746
|
+
values). This is an upstream OCaml compiler/DWARF limitation on the
|
|
747
|
+
verified toolchain (OCaml 5.4.0 / lldb 21), not a `tdb` bug. If you need
|
|
748
|
+
to inspect local variables, use the bytecode adapter instead.
|
|
749
|
+
|
|
750
|
+
**Variables view (bytecode):** `ocamlearlybird` reports real local names
|
|
751
|
+
and values, exactly like Python locals.
|
|
752
|
+
|
|
753
|
+
**Evaluate console:** the two adapters give fundamentally different
|
|
754
|
+
consoles. Native (`lldb-dap`) evaluates **lldb/C-level expressions**.
|
|
755
|
+
This is runtime spelunking (registers, raw memory, C symbol names), not
|
|
756
|
+
OCaml expression evaluation. Bytecode (`ocamlearlybird`) is meant to
|
|
757
|
+
evaluate real OCaml expressions in scope, but in the verified
|
|
758
|
+
`ocamlearlybird` 1.3.6 release its `evaluate` request never responds (a
|
|
759
|
+
confirmed upstream limitation, not specific to `tdb`); the console
|
|
760
|
+
silently returns nothing for any expression.
|
|
761
|
+
|
|
762
|
+
**Uncaught exceptions:** native sessions set a breakpoint on
|
|
763
|
+
`caml_fatal_uncaught_exception` so the debugger stops there, and `tdb`
|
|
764
|
+
also parses the `OCAMLRUNPARAM=b` backtrace it injects into the debuggee's
|
|
765
|
+
environment once the process exits, opening the same error modal Python
|
|
766
|
+
tracebacks get. Bytecode sessions do **not** get this: `ocamlearlybird`
|
|
767
|
+
intercepts the uncaught exception itself and only reports a generic
|
|
768
|
+
"Program exited due to Uncaught_exc" message, so the real exception text
|
|
769
|
+
never reaches `tdb`. Run the program outside the debugger
|
|
770
|
+
(`OCAMLRUNPARAM=b ./main.byte`) to see its backtrace.
|
|
771
|
+
|
|
772
|
+
**Limitations (v1):** no Windows support; no remote attach; bytecode
|
|
773
|
+
sessions can't `pause` a running program (so `--run` is unavailable for
|
|
774
|
+
bytecode. Native sessions support `--run` normally); `Unix.fork` and Eio
|
|
775
|
+
fibers are out of scope (only OCaml 5 domains are presented as threads).
|
|
776
|
+
|
|
552
777
|
## Layout
|
|
553
778
|
|
|
554
779
|
```
|
|
@@ -604,6 +829,11 @@ A cursor line (blue) tracks your position; the current execution line is highlig
|
|
|
604
829
|
| `Alt+A` | Async Tasks |
|
|
605
830
|
| `Alt+H` | Help (Documentation, About) |
|
|
606
831
|
|
|
832
|
+
File > Open works for every supported language: the file picker filters to
|
|
833
|
+
the current session's language (by extension) and refuses a pick that
|
|
834
|
+
detects as a different language, so you can only switch to another script
|
|
835
|
+
written in the same language as the one currently being debugged.
|
|
836
|
+
|
|
607
837
|
**Navigation (vim-style by default):**
|
|
608
838
|
|
|
609
839
|
By default the Code View is in Debug mode. Hit `Escape` to switch to Navigate mode
|
|
@@ -661,7 +891,7 @@ results = await asyncio.gather(
|
|
|
661
891
|
fetch(2, 1),
|
|
662
892
|
fetch(3, 3),
|
|
663
893
|
)
|
|
664
|
-
print(results)
|
|
894
|
+
print(results) # next stop lands here, not on each sub-line above
|
|
665
895
|
```
|
|
666
896
|
|
|
667
897
|
lands on `print(results)`, not on each interior sub-line of the `gather` call. Switch to
|
|
@@ -771,6 +1001,7 @@ need to launch through `tdb` up front. Install the hook once at the top of your
|
|
|
771
1001
|
```python
|
|
772
1002
|
import sys
|
|
773
1003
|
import tdb
|
|
1004
|
+
|
|
774
1005
|
sys.excepthook = tdb.exception_hook
|
|
775
1006
|
```
|
|
776
1007
|
|
|
@@ -819,6 +1050,7 @@ continuing--use `tdb.breakpoint()`:
|
|
|
819
1050
|
```python
|
|
820
1051
|
import tdb
|
|
821
1052
|
|
|
1053
|
+
|
|
822
1054
|
def compute(n):
|
|
823
1055
|
total = sum(range(n))
|
|
824
1056
|
tdb.breakpoint() # pause here and drop into tdb
|
|
@@ -961,6 +1193,7 @@ where you want to attach the debugger:
|
|
|
961
1193
|
```python
|
|
962
1194
|
# In the target program:
|
|
963
1195
|
import debugpy
|
|
1196
|
+
|
|
964
1197
|
debugpy.listen(("0.0.0.0", 5678))
|
|
965
1198
|
print("Waiting for tdb to attach on port 5678...")
|
|
966
1199
|
debugpy.wait_for_client() # optional: pause until debugger connects
|
|
@@ -1028,12 +1261,14 @@ tdb --terminal xterm my_tui_app.py
|
|
|
1028
1261
|
```
|
|
1029
1262
|
|
|
1030
1263
|
`--terminal` works for every language `tdb` can *launch* (as opposed to
|
|
1031
|
-
attach to): Python, Perl, Bash, Tcsh, and C/C++
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1264
|
+
attach to): Python, Perl, Bash, Tcsh, Ruby, and C/C++ or native OCaml
|
|
1265
|
+
sessions via `--adapter lldb-dap`. Neither `gdb -i dap` (the default C/C++
|
|
1266
|
+
adapter, and an alternate for native OCaml) nor `ocamlearlybird` (the
|
|
1267
|
+
bytecode OCaml adapter) has any terminal integration -- `tdb` rejects
|
|
1268
|
+
`--terminal` up front for both, with an error pointing at `--adapter
|
|
1269
|
+
lldb-dap` instead. `--terminal` also only applies when `tdb` launches the
|
|
1270
|
+
program itself; it is rejected for remote-attach (`-r`), since there's no
|
|
1271
|
+
program for `tdb` to spawn a terminal around.
|
|
1037
1272
|
|
|
1038
1273
|
The debuggee runs in a separate window of the specified terminal, including
|
|
1039
1274
|
all of its stdin/stdout/stderr -- keyboard input, program output, and
|
|
@@ -1048,9 +1283,17 @@ This feature only works in graphical environments where external terminals are a
|
|
|
1048
1283
|
|
|
1049
1284
|
### Run Mode (`--run`)
|
|
1050
1285
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1286
|
+
`tdb`'s run mode invokes an unmodified program nearly at full speed, without bringing up the TUI.
|
|
1287
|
+
At any point afterwards, hitting `Ctrl-C` in that terminal pauses the program
|
|
1288
|
+
and drops you into the full TUI.
|
|
1289
|
+
From there you can inspect the program's state, navigate the stack, set and continue
|
|
1290
|
+
to breakpoints, and so on. After you finish inspecting, hitting `q` to quit brings up
|
|
1291
|
+
a modal that lets you either detach from the TUI and let the program resume running,
|
|
1292
|
+
or lets you terminate it.
|
|
1293
|
+
|
|
1294
|
+
The primary use cases for run mode are: (1) allowing inspection of a program that
|
|
1295
|
+
appears hung, and (2) finding where a program execution path lands after it
|
|
1296
|
+
receives a problematic input.
|
|
1054
1297
|
|
|
1055
1298
|
```bash
|
|
1056
1299
|
tdb --run my_program.py args...
|
|
@@ -1084,8 +1327,10 @@ nonzero `sys.exit()`, which `debugpy` treats as an uncaught `SystemExit` -- `tdb
|
|
|
1084
1327
|
the TUI at the point of failure instead of exiting silently, so you can inspect the
|
|
1085
1328
|
crash. Exit-code passthrough applies only to a clean exit during the headless phase.
|
|
1086
1329
|
|
|
1087
|
-
Supported languages: Python, Perl, Bash, Tcsh,
|
|
1088
|
-
|
|
1330
|
+
Supported languages: Python, Perl, Bash, Tcsh, Ruby, C/C++ (both `gdb` and
|
|
1331
|
+
`lldb-dap`), and native OCaml (both `gdb` and `lldb-dap`; bytecode/
|
|
1332
|
+
`ocamlearlybird` sessions don't support pause, so `--run` is unavailable
|
|
1333
|
+
for those). `--run` is rejected up front for any other language.
|
|
1089
1334
|
|
|
1090
1335
|
**Limitation:** pausing is cooperative. If the debuggee is blocked inside a single
|
|
1091
1336
|
blocking external call or syscall, the pause can't land until that call returns --
|
|
@@ -1129,7 +1374,9 @@ Both the interactive TUI and the JSON-RPC server run simultaneously.
|
|
|
1129
1374
|
### RPC Protocol
|
|
1130
1375
|
|
|
1131
1376
|
Send POST requests with `{"action": "...", "params": [...]}`. Responses return
|
|
1132
|
-
`{"timestamp": "...", "success": true/false, "value": "..."}`.
|
|
1377
|
+
`{"timestamp": "...", "success": true/false, "value": "..."}`. Actions with a
|
|
1378
|
+
structured result (today only `rust_concurrency`) additionally carry a `data`
|
|
1379
|
+
object holding the full JSON payload; `value` then holds a one-line summary.
|
|
1133
1380
|
|
|
1134
1381
|
```bash
|
|
1135
1382
|
# Check status
|
|
@@ -1187,6 +1434,7 @@ curl -s -X POST http://127.0.0.1:8150/rpc \
|
|
|
1187
1434
|
| `list_tasks` | `[]` | List all asyncio tasks |
|
|
1188
1435
|
| `inspect_task` | `["task_name"]` | Inspect a specific asyncio task |
|
|
1189
1436
|
| `wait_graph` | `[]` | Show wait graph + any deadlock cycles |
|
|
1437
|
+
| `rust_concurrency` | `[]` | Structured Rust thread/wait/deadlock snapshot in `data` (Rust sessions, stopped) |
|
|
1190
1438
|
| `restart` | `[]` | Restart session (preserves breakpoints) |
|
|
1191
1439
|
| `quit` | `[]` | Shut down |
|
|
1192
1440
|
|
|
@@ -1269,7 +1517,7 @@ point), `tdb --mcp` (the main CLI with the `--mcp` switch), and
|
|
|
1269
1517
|
`python -m tdb.mcp` (module form). Pick whichever matches how your MCP
|
|
1270
1518
|
client expects to launch servers.
|
|
1271
1519
|
|
|
1272
|
-
### Tool surface (
|
|
1520
|
+
### Tool surface (17 tools, curated)
|
|
1273
1521
|
|
|
1274
1522
|
| Cluster | Tools |
|
|
1275
1523
|
|---------|-------|
|
|
@@ -1277,7 +1525,7 @@ client expects to launch servers.
|
|
|
1277
1525
|
| Control | `control(action, timeout_s=30)` where `action ∈ {continue, next, step_in, step_out, pause, wait_for_stop}` |
|
|
1278
1526
|
| Inspection | `inspect(expressions)`, `read_source(file_path)`, `stack_trace()`, `status()`, `get_output()` |
|
|
1279
1527
|
| Breakpoints | `set_breakpoint(spec, condition?, hit_condition?)`, `remove_breakpoint(spec)`, `list_breakpoints()` |
|
|
1280
|
-
| Differentiators | `threads(thread_id?)`, `tasks(task_name?)`, `processes(name_or_pid?)`, `wait_graph()` |
|
|
1528
|
+
| Differentiators | `threads(thread_id?)`, `tasks(task_name?)`, `processes(name_or_pid?)`, `wait_graph()`, `rust_concurrency()` |
|
|
1281
1529
|
|
|
1282
1530
|
`control` is intentionally one tool that takes an action enum. The six
|
|
1283
1531
|
underlying RPC actions share a return shape, and agents perform
|
|
@@ -1288,9 +1536,10 @@ single optional argument for the same reason.
|
|
|
1288
1536
|
`debug_launch` accepts optional `lang` and `adapter` parameters mirroring the
|
|
1289
1537
|
CLI's `--lang`/`--adapter`; when omitted, the language is auto-detected from
|
|
1290
1538
|
`program`, so an agent can hand it a compiled binary directly. The
|
|
1291
|
-
|
|
1539
|
+
exception is Rust: compiled native binaries require explicit `lang="rust"`.
|
|
1540
|
+
The `tasks`/`processes`/`wait_graph` tools stay registered for every language but
|
|
1292
1541
|
return a structured "not supported when debugging C/C++"-style error for
|
|
1293
|
-
non-Python debuggees.
|
|
1542
|
+
non-Python debuggees; `rust_concurrency` does the same for non-Rust debuggees.
|
|
1294
1543
|
|
|
1295
1544
|
### Agent flow for a long-running step
|
|
1296
1545
|
|
|
@@ -1408,6 +1657,8 @@ fires as expected.
|
|
|
1408
1657
|
- [textual](https://github.com/Textualize/textual) : TUI framework
|
|
1409
1658
|
- [debugpy](https://github.com/microsoft/debugpy) : Debug Adapter Protocol implementation for Python
|
|
1410
1659
|
- [gdb](https://sourceware.org/gdb/) / [lldb-dap](https://lldb.llvm.org/resources/lldbdap.html) : optional, user-installed DAP adapters for C/C++
|
|
1660
|
+
- [debug gem](https://github.com/ruby/debug) (`rdbg`) : optional, user-installed DAP adapter for Ruby
|
|
1661
|
+
- [ocamlearlybird](https://github.com/hackwaly/ocamlearlybird) : optional, user-installed DAP adapter for OCaml bytecode (native OCaml reuses `gdb`/`lldb-dap`)
|
|
1411
1662
|
- [pygments](https://pygments.org/) : Syntax highlighting
|
|
1412
1663
|
- [FastAPI](https://fastapi.tiangolo.com/) + [uvicorn](https://www.uvicorn.org/) : JSON-RPC server
|
|
1413
1664
|
|