Skip to content

axon-debug

pipeline coverage

Debugging tools for the Axon programming language β€” GDB and LLDB pretty printers, crash symbolicators, and profiling helpers.

  • GDB Pretty Printers β€” Human-readable display of Axon types (Option, Result, String, Vec, Map) in GDB
  • LLDB Type Formatters β€” Equivalent type summary/synthetic providers for LLDB
  • Crash Symbolicator (axon-sym) β€” Parse crash traces and resolve addresses to source file:line; supports free-form traces, explicit addresses, and structured JSON crash reports
  • C Bindings Generator (axon-bindgen) β€” Generate Axon .axs extern declarations from C header files
  • Performance Benchmarks (tools/bench.py) β€” Micro-benchmarks for addr2line and bindgen with CI thresholds
  • Memory Profiler (tools/memprof.py) β€” Heap allocation tracker + leak detector (issue #34)
  • CPU Profiler (tools/cpu.py) β€” Sampling CPU profiler with hot-spot aggregation (issue #122)
  • Panic Handler (tools/panic_hook.py) β€” Structured panic reporter with category classification (issue #120)
  • DAP Server (tools/dap.py) β€” Minimal Debug Adapter Protocol server for editors like VS Code and Cursor (issue #123)
  • MCP Server (tools/mcp.py) β€” Model Context Protocol server (stdio / JSON-RPC 2.0) exposing 7 debug tools β€” addr2line, crash decode, memprof + CPU summaries, ownership, replay inspect, launch plan β€” to AI agents like Claude Code and Cursor (issue #127)
Axon TypeGDB DisplayLLDB Display
OptionSome(42) / NoneSome(42) / None
ResultOk(val) / Err(e)Ok(val) / Err(e)
String"hello world""hello world"
VecVec(len=3, cap=8) [0]=1 [1]=2 [2]=3Vec(len=3, cap=8)
MapMap(string, len=2, cap=4)Map(string, len=2, cap=4)
Sum / EnumTag::Variant(data)Tag::Variant(data)
Tuple(1, "hello", 3.14)(1, "hello", 3.14)

For full per-platform install instructions (Homebrew, apt, winget, manual, dev), see docs/INSTALL.md.

Terminal window
# macOS / Linux (one-time, auto-detects GDB and/or LLDB):
git clone https://git.catalystgroup.tech/labs/axon/axon-debug.git
cd axon-debug
./install.sh
# Verify:
./install.sh --check # show status
./install.sh --verify # actually load printers in debugger
PlatformCommand
macOSbrew install axon-debug (after tap; see packaging/homebrew/)
Ubuntu/Debiansudo dpkg -i axon-debug_*_all.deb (build with packaging/debian/build-deb.sh)
Windowswinget install catalystgroup.axon-debug (manifest in packaging/winget/)
Any (release)Download tarball from Releases + run ./install.sh
$ gdb ./my_axon_program
(gdb) break main
(gdb) run
(gdb) print my_option
$1 = Some(42)
(gdb) print my_result
$2 = Ok("success")
(gdb) print my_string
$3 = "hello world"
$ lldb ./my_axon_program
(lldb) breakpoint set --name main
(lldb) run
(lldb) frame variable my_option
(axon::Option) my_option = Some(42)
(lldb) frame variable my_result
(axon::Result) my_result = Ok("success")

axon-sym resolves hex addresses in crash traces to source file:line pairs. It works in three modes:

Mode 1 β€” Free-form text / piped trace:

Terminal window
my_program 2>&1 | python3 tools/addr2line.py ./my_program
python3 tools/addr2line.py ./my_program crash.log
python3 tools/addr2line.py ./my_program 0x1234 0x5678

Mode 2 β€” JSON crash report (--crash-file):

When an Axon program crashes, axon_panic_handler() in libaxon_rt.a writes a structured crash.json to ~/.axon/crashes/. The --crash-file mode symbolicates the full stack:

Terminal window
# Use binary_path embedded in the crash report (most common):
python3 tools/addr2line.py --crash-file ~/.axon/crashes/2026-06-20T03-26-21Z.json
# Override binary path if missing from report:
python3 tools/addr2line.py --crash-file crash.json --binary ./my_program
# Machine-readable JSON output (for Sentry pipelines):
python3 tools/addr2line.py --crash-file crash.json --output json > symbolized.json
# Text output with per-frame detail:
python3 tools/addr2line.py --crash-file crash.json --output text

See docs/CRASH_REPORTS.md for the full crash.json schema and storage location documentation.

axon-debug/
β”œβ”€β”€ gdb/
β”‚ β”œβ”€β”€ __init__.py # GDB auto-load package init
β”‚ └── axon_printers.py # GDB pretty printers (Option, Result, String, Vec, Map)
β”œβ”€β”€ lldb/
β”‚ └── axon_formatters.py # LLDB type formatters + synthetic children providers
β”œβ”€β”€ tools/
β”‚ β”œβ”€β”€ addr2line.py # Crash trace symbolicator (free-form + JSON crash reports)
β”‚ β”œβ”€β”€ bindgen.py # C header β†’ Axon .axs extern generator
β”‚ β”œβ”€β”€ aggregate_metrics.py # JUnit + coverage.json β†’ public/metrics.json
β”‚ β”œβ”€β”€ run_tests.sh # Canonical test runner (JUnit + coverage)
β”‚ β”œβ”€β”€ bench.py # Performance micro-benchmarks (addr2line + bindgen)
β”‚ β”œβ”€β”€ dap.py # Debug Adapter Protocol server (stdio/TCP)
β”‚ β”œβ”€β”€ mcp.py # Model Context Protocol server (stdio/JSON-RPC, 7 debug tools)
β”‚ └── remove_blocks.py # Strip axon-debug version blocks from init files
β”œβ”€β”€ tests/
β”‚ β”œβ”€β”€ fixtures/
β”‚ β”‚ β”œβ”€β”€ basic_types.axs # Test fixture (i32, i64, bool)
β”‚ β”‚ └── crash_test.c # C test binary for addr2line end-to-end tests
β”‚ β”œβ”€β”€ conftest.py # Shared pytest fixtures
β”‚ β”œβ”€β”€ test_printers.py # Printer unit tests (no debugger needed)
β”‚ β”œβ”€β”€ test_lldb_formatters.py # LLDB provider interface + parity tests
β”‚ β”œβ”€β”€ test_basic_types.py # GDB integration tests
β”‚ β”œβ”€β”€ test_bindgen.py # bindgen CLI tests
β”‚ β”œβ”€β”€ test_addr2line.py # addr2line unit + end-to-end tests
β”‚ β”œβ”€β”€ test_mcp.py # MCP server tests (handshake, schema, 7 tools)
β”‚ └── test_bench.py # bench.py smoke tests
β”œβ”€β”€ docs/
β”‚ β”œβ”€β”€ INSTALL.md # Full per-platform install guide
β”‚ β”œβ”€β”€ CRASH_REPORTS.md # crash.json schema and storage
β”‚ β”œβ”€β”€ tools.md # tools/ directory reference
β”‚ β”œβ”€β”€ dap.md # Debug Adapter Protocol server guide
β”‚ β”œβ”€β”€ mcp.md # Model Context Protocol server guide
β”‚ β”œβ”€β”€ FORMATTERS.md # GDB/LLDB formatter architecture
β”‚ └── CI.md # CI pipeline and metrics infrastructure
β”œβ”€β”€ public/
β”‚ └── metrics.json # GitLab Pages metrics (deployed by CI)
β”œβ”€β”€ requirements.txt # Python dependencies
β”œβ”€β”€ .gitlab-ci.yml # CI pipeline
β”œβ”€β”€ install.sh # GDB/LLDB installer with idempotency + versioning
β”œβ”€β”€ CONTRIBUTING.md # Contributor guide (start here!)
└── README.md
Terminal window
tools/run_tests.sh # full suite with JUnit + coverage
tools/run_tests.sh --no-cov # skip coverage (faster)
tools/run_tests.sh --keep-results # keep results.xml / coverage files
tools/run_tests.sh tests/test_printers.py # single file
tools/run_tests.sh --help # show all flags
Terminal window
pytest tests/ -v # all tests
pytest tests/test_printers.py -v # unit tests only (no GDB/LLDB required)
pytest tests/test_basic_types.py -v # GDB integration tests

GDB tests auto-skip on macOS (outdated GDB). LLDB tests require an LLVM-based lldb (default on macOS).

Terminal window
python3 tools/bench.py # writes benchmarks.json

Benchmarks measure addr2line (10/100/1000 frames) and bindgen (10/50/100 declarations) wall-clock time.

  • Python 3.8+
  • GDB 10+ (with Python support) and/or LLDB 12+
  • Axon compiler (for building test fixtures)
  • For addr2line end-to-end tests: binutils (addr2line) and a C compiler (cc)
Terminal window
pip install -r requirements.txt
Terminal window
ruff check gdb/ tools/ tests/ lldb/
MRSummary
#127tools/mcp.py β€” Model Context Protocol server exposing 7 debug tools over stdio (see docs/mcp.md, CHANGELOG.md)
#123tools/dap.py β€” minimal Debug Adapter Protocol server (see docs/dap.md)
!12tests/test_bench.py β€” coverage fix for benchmark tests
!11tools/bench.py β€” performance micro-benchmarks for addr2line + bindgen, CI threshold
!10Coverage threshold gate (23%) added to CI
!9Metrics pipeline: run_tests.sh, aggregate_metrics.py, GitLab Pages deployment
!8addr2line.py --crash-file JSON mode, docs/CRASH_REPORTS.md
!7install.sh rewrite: idempotency, versioning, --verify flag

See LICENSE for details.