| # `src/developer/debug` Development Guide for AI Agents |
| |
| Follow these cross-cutting rules and progressive-disclosure gates when you |
| write, refactor, or review code under `//src/developer/debug`. |
| |
| ## Subsystem Map & Mandatory `README.md` Pre-Edit Gate |
| |
| Each subsystem maintains a local `README.md` contract with `## Interface`, `## |
| Invariants`, `## Side Effects`, and `## Verification` sections. |
| |
| **Mandatory Pre-Edit & Code Review Gate**: Before you edit or review (`/review`) |
| any file in a subdirectory, read `## Invariants` and `## Verification` in its |
| `README.md`. |
| |
| Each subsystem maps to a local contract, build target, test suite, and |
| architectural layer: |
| |
| - **`debug_agent/`** ([README.md](./debug_agent/README.md), |
| [posix](./debug_agent/posix/README.md)): Target-side Fuchsia and Linux stub |
| (`DebugAgent`, `DebuggedJob`, `DebuggedProcess`, `DebuggedThread`, |
| `LimboProvider`). Build `//src/developer/debug/debug_agent` and run `fx test |
| debug_agent_unit_tests`. |
| - **`ipc/`** ([README.md](./ipc/README.md)): Versioned binary wire protocol |
| (`debug_ipc`) between `zxdb` and `debug_agent`. Build |
| `//src/developer/debug/ipc` and run `fx test zxdb_tests`. |
| - **`shared/`** ([README.md](./shared/README.md), |
| [logging](./shared/logging/README.md)): Cross-platform `MessageLoop`, |
| `StreamBuffer`, `BufferedStream`, `Arch`, `RegisterID`, `Status`, and |
| `Result`. Build `//src/developer/debug/shared` and run `fx test zxdb_tests`. |
| - **`zxdb/common/`** ([README.md](./zxdb/common/README.md)): **Layer 1 |
| (Lowest)** base utilities (`Err`, `ErrOr`, `AddressRanges`). Must not depend |
| on other `zxdb` layers. Build `//src/developer/debug/zxdb/common` and run `fx |
| test zxdb_tests`. |
| - **`zxdb/symbols/`** ([README.md](./zxdb/symbols/README.md)): **Layer 2** DWARF |
| and ELF symbol indexing (`Index`, `DwarfDieRef`, `LazySymbol`) and |
| `DwarfExprEval`. Build `//src/developer/debug/zxdb/symbols` and run `fx test |
| zxdb_tests`. |
| - **`zxdb/expr/`** ([README.md](./zxdb/expr/README.md)): **Layer 3** C++ and |
| Rust parser, AST (`ExprNode`), bytecode VM (`VmExec`), and `PrettyType`. Build |
| `//src/developer/debug/zxdb/expr` and run `fx test zxdb_tests`. |
| - **`zxdb/format/`** ([README.md](./zxdb/format/README.md)): **Layer 4** styled |
| output buffers (`OutputBuffer`, `AsyncOutputBuffer`) and value or identifier |
| formatting. Build `//src/developer/debug/zxdb/format` and run `fx test |
| zxdb_tests`. |
| - **`zxdb/client/`** ([README.md](./zxdb/client/README.md)): **Layer 4** |
| UI-agnostic session model (`Session`, `Target`, `Process`, `Thread`, `Stack`, |
| `ThreadController`). Build `//src/developer/debug/zxdb/client` and run `fx |
| test zxdb_tests`. |
| - **`zxdb/console/`** ([README.md](./zxdb/console/README.md), |
| [commands](./zxdb/console/commands/README.md)): **Layer 5 (UI)** interactive |
| CLI frontend, noun and verb parser, and `ConsoleContext`. Build |
| `//src/developer/debug/zxdb/console` and run `fx test zxdb_tests`. |
| - **`zxdb/debug_adapter/`** ([README.md](./zxdb/debug_adapter/README.md), |
| [handlers](./zxdb/debug_adapter/handlers/README.md)): **Layer 6 (UI)** |
| `cppdap` Debug Adapter Protocol (DAP) server sharing `client::Session`. Build |
| `//src/developer/debug/zxdb/debug_adapter` and run `fx test zxdb_tests`. |
| - **`ffx_zxdb/`** ([README.md](./ffx_zxdb/README.md), |
| [src](./ffx_zxdb/src/README.md), [ffx/AGENTS.md](../ffx/AGENTS.md)): Host Rust |
| integration for `ffx debug`. Read |
| [//src/developer/ffx/AGENTS.md](../ffx/AGENTS.md) for `FDomain` and `fho` |
| rules, and build `//src/developer/debug/ffx_zxdb`. |
| - **`e2e_tests/`** ([README.md](./e2e_tests/README.md)): Host-driven `.script` |
| E2E tests and `dap_integration_tests`. Run `fx test --e2e zxdb_e2e_tests`. |
| |
| Enforce this upward dependency rule across `zxdb/`: |
| |
| - **Strict Upward Layering in `zxdb/`**: Dependencies inside `zxdb/` must point |
| upward (`common` <- `symbols` <- `expr` <- `{format, client}` <- `console` <- |
| `debug_adapter`). |
| |
| ## Cross-Cutting Idioms |
| |
| Apply these C++ and subsystem idioms across all files in |
| `//src/developer/debug`: |
| |
| - **Async Object Lifetimes**: Never capture raw pointers (`Target*`, `Process*`, |
| `Thread*`, `Frame*`, `Breakpoint*`, `FormatNode*`) across asynchronous |
| callbacks. Capture `fxl::WeakPtr<T>` (or `fxl::RefPtr<T>` for ref-counted |
| `Symbol`, `EvalContext`, `CommandContext`, `AsyncOutputBuffer`) and check |
| validity before dereferencing. |
| - **Lazy Stack & Multi-Thread State**: Never assume all stack frames exist when |
| a thread stops (`debug_agent` sends only the top 1 to 2 frames). Call |
| `Stack::SyncFrames` asynchronously for full backtraces, and check |
| `process->AllThreadsStopped()` before inspecting process-wide state. |
| - **Error Returns vs. Invariant Assertions**: Never use `bool` with |
| out-parameter pointers for fallible parsing or validation. Return |
| `zxdb::ErrOr<T>` (in `zxdb`) or `debug::Status` / `debug::Result<T, E>` (in |
| `shared`, `ipc`, `debug_agent`). Reserve `FX_CHECK` and `FX_DCHECK` for |
| internal programmer invariants. |
| - **Sentinel Values (`0`)**: Never use `0` as an invalid sentinel for DWARF unit |
| offsets or type signatures. `0` is valid in DWARF, so use |
| `std::optional<uint64_t>`. For Zircon KOIDs (`zx_koid_t`), `0` |
| (`ZX_KOID_INVALID`) is invalid, so reject `0` when parsing external or DAP |
| IDs. |
| - **Callbacks & Symbol RTTI**: Never use `std::function` or C++ `dynamic_cast` |
| (the build disables compiler RTTI). Use `fit::function`, `fit::callback`, or |
| `fit::deferred_callback`, and call `symbol->As<T>()` to downcast `Symbol` |
| objects. |
| - **Internal Linkage & TODOs**: Place file-local `.cc` helpers in an anonymous |
| `namespace`. Format bug links as `https://fxbug.dev/<id>`, and state the |
| condition required to delete each `TODO`. |
| - **Agent Skill Encapsulation**: Never expose internal `ffx debug` or `zxdb` |
| Unix socket paths in `skills/` documentation. Direct agents through supported |
| CLI commands instead. |
| |
| ## Downstream Couplings, Documentation, & Reviewer Gates |
| |
| Follow these build, documentation, comment, and testing gates before completing |
| any work: |
| |
| - **Dual Bazel/GN Build Files (`# BAZEL2GN SENTINEL`)**: Never hand-edit |
| `BUILD.gn` files below a `# BAZEL2GN SENTINEL` marker. Edit the matching |
| `BUILD.bazel` file and run `fx bazel2gn`. |
| - **Documentation Freshness & Prose Style**: |
| - Update matching documentation (`//docs/development/debugger/`, local |
| `README.md` contracts, and CLI help text in `verbs.h` / `verb_*.cc`) |
| whenever you edit user-facing surfaces or internal architecture. Create new |
| documentation if none exists. |
| - Keep standalone documentation distinct from code comments. Standalone docs |
| explain the problem, architecture, and high-level approach. Inline code |
| comments explain non-obvious implementation mechanics. |
| - Write all non-coding prose in Simplified Technical English (`asd-ste100`) |
| and follow Google Technical Writing guidelines (`technical-writing`). |
| - **Code Comment Style**: |
| - Never use numbered lists (`// 1.`, `// Step 1:`) in source code comments. |
| Decompose multi-phase logic into named helper functions and let symbol names |
| show execution order. |
| - Prefer longer explanatory block comments with references for complex |
| sequences over short comments scattered through the sequence. |
| - **Co-locate Unit Tests in Patch Stacks**: Include unit tests in the same CL |
| that introduces a new class, data structure, or handler. Never defer unit |
| tests to a later commit in a patch stack. |
| - **Mandatory Boundary, Control-Flow, & Multi-Thread Coverage**: |
| - Test zero and invalid boundaries explicitly (CU offset `0`, invalid DWARF |
| signatures, `koid == 0`). Test multi-threaded states with 2 or more threads |
| (such as `zxdb.AsyncBacktrace` and pause synchronization). |
| - In `ThreadController` subclasses and `DebuggedThread` exception paths, test |
| early-exit paths (bottom frames, PLT trampolines, unrelated breakpoints). |
| Use `fit::defer` or `fit::deferred_callback` to restore state on early |
| returns. |
| - Never land commented-out test assertions. |
| - **Editing & Verification Workflow Skill**: Read |
| [`editing-zxdb`](./.agents/skills/editing_zxdb/SKILL.md) to build targets, run |
| unit and E2E tests, reload `/core/debugger`, and test with `fx debug cli`. |