blob: 2f110d277249e0a3d92ab75afa19543de8417188 [file] [view] [edit]
<!--* freshness: { reviewed: '2026-10-12' } *-->
# Debug IPC (`ipc`)
This directory contains the shared wire protocol (`debug_ipc`) between
`debug_agent` ([../debug_agent](../debug_agent/README.md)) and `zxdb`
([../zxdb](../zxdb/README.md)). External programs should not depend on this
directory directly. Debugger clients should use the client library in
[../zxdb/client](../zxdb/client/README.md) instead.
`debug_ipc` uses a self-contained binary format so `debug_agent` can talk to a
host machine without high-level runtime dependencies while debugging low-level
system state.
## Protocol Format
`MessageWriter` and `MessageReader` encode wire primitives with these rules:
- Structs use fixed-size fields in little-endian byte order so little-endian
hosts and targets can copy them directly with `memcpy`.
- Vectors encode a 32-bit element count followed by each serialized element.
- Strings encode a 32-bit byte length followed by raw 8-bit characters without a
null terminator.
## Interface
Public headers expose these protocol constants, records, and helpers:
- `debug_ipc::kCurrentProtocolVersion`, `debug_ipc::kMinimumProtocolVersion`,
`debug_ipc::kTimestampDefault`: Protocol version bounds and default timestamp
constants (`protocol.h`).
- `debug_ipc::MsgHeader`, `debug_ipc::IsDebugIpcMessageType`,
`debug_ipc::IsDebugIpcNotificationType`: Wire message header
(`MsgHeader::Type`) and C++20 concepts for request/reply and notification
types (`protocol.h`).
- Request and Reply messages (`protocol.h`): `HelloRequest`, `StatusRequest`,
`KillRequest`, `AttachRequest`, `DetachRequest`, `PauseRequest`,
`ResumeRequest`, `ProcessTreeRequest`, `ThreadsRequest`, `ReadMemoryRequest`,
and their matching `*Reply` structs. Also defines
`AddOrChangeBreakpointRequest`, `RemoveBreakpointRequest`, `SysInfoRequest`,
`ThreadStatusRequest`, `AddressSpaceRequest`, `ModulesRequest`,
`UpdateFilterRequest`, `WriteMemoryRequest`, and `LoadInfoHandleTableRequest`.
Also defines `UpdateGlobalSettingsRequest`, `SaveMinidumpRequest`,
`ReadRegistersRequest`, `WriteRegistersRequest`, `RunBinaryRequest`,
`RunComponentRequest`, and `RunTestRequest`.
- Notification messages (`protocol.h`): `NotifyProcessStarting`,
`NotifyProcessExiting`, `NotifyThreadStarting`, `NotifyThreadExiting`,
`NotifyException`, `NotifyModules`, `NotifyIO`, `NotifyLog`,
`NotifyComponentDiscovered`, `NotifyComponentStarting`,
`NotifyComponentExiting`, `NotifyTestExited`, `NotifyFilterCreated`.
- Protocol records (`records.h`): `ExceptionType`, `ExceptionStrategy`,
`ProcessThreadId`, `ExceptionRecord`, `ComponentInfo`, `TaskType`,
`ProcessTreeRecord`, `StackFrame`, `ThreadRecord`, `AddressRegion`,
`ProcessRecord`, `MemoryBlock`, `ProcessBreakpointSettings`, and `Stop`. Also
defines `BreakpointType`, `BreakpointSettings`, `BreakpointStats`, `Module`,
`AttachConfig`, `InfoHandleVmo`, `InfoHandle`, `FilterConfig`, `Filter`
(`Filter::Identifier`, `Filter::Originator`), `MatchedTask`, and
`FilterMatch`.
- Serialization (`message_reader.h`, `message_writer.h`):
`debug_ipc::MessageReader`, `debug_ipc::MessageWriter`,
`debug_ipc::Serialize`, `debug_ipc::Deserialize`.
- Filter utilities (`filter_utils.h`): `debug_ipc::FilterMatches`,
`debug_ipc::ResolveFilterType`, `debug_ipc::GetFilterForId`,
`debug_ipc::GenerateFilterIdValue`,
`debug_ipc::GetAttachConfigsForFilterMatches`.
- Exception decoding (`decode_exception.h`): `debug_ipc::X64DebugRegs`,
`debug_ipc::DecodeX64Exception`, `debug_ipc::DecodeArm64Exception`,
`debug_ipc::DecodeRiscv64Exception`.
- Breakpoint automation (`automation_instruction.h`):
`debug_ipc::AutomationOperandKind`, `debug_ipc::AutomationOperand`,
`debug_ipc::AutomationConditionKind`, `debug_ipc::AutomationCondition`,
`debug_ipc::AutomationInstructionKind`, `debug_ipc::AutomationInstruction`.
- Unwinder conversions (`unwinder_support.h`): `debug_ipc::ConvertRegisters`,
`debug_ipc::ConvertFrames`, `debug_ipc::ConvertTrust`.
## Invariants
Callers and protocol definitions must preserve these invariants:
- `protocol.h` and `records.h` pack all wire structs to 8-byte alignment via
`#pragma pack(push, 8)`.
- The ABI compatibility window spans `[kMinimumProtocolVersion,
kCurrentProtocolVersion]`. Version-gated fields serialize conditionally (`if
(ver >= ...)`), and messages with `kSupportedSinceVersion` return an empty
byte vector on older versions.
- The first 4 bytes of every serialized message store the total byte size
(including `MsgHeader`), which `MessageWriter::MessageComplete()` writes on
completion.
- `HelloReply` starts with a fixed 64-bit signature (`0x7a7864624950433e`, ASCII
`"zxdbIPC>"`). Readers deserialize `HelloReply` at version `0` first to read
the version, and then deserialize again at the negotiated version.
- Notification messages always set `transaction_id` to `0` in `MsgHeader` and
satisfy `IsDebugIpcNotificationType` by providing a `timestamp` field.
- `Filter::Identifier` stores `Filter::Originator` in bits 24 to 31 and a
client-assigned 24-bit ID in bits 0 to 23. Both `kInvalidFilterId` and
`kDebugAgentInternalBreakpointId` equal `static_cast<uint32_t>(-1)`.
- When multiple filters match one task in `GetAttachConfigsForFilterMatches`,
the highest `AttachConfig::Priority` (`kStrong > kWeak > kMinimal`) wins.
- In `BreakpointSettings::locations`, if any `ProcessBreakpointSettings` entry
specifies a non-zero thread KOID, it must be the only entry.
## Side Effects
These functions produce the following state and callback side effects:
- `ResolveFilterType` truncates its `pattern` string argument in place to 31
characters (Zircon's process name limit) for `kProcessName` and
`kProcessNameSubstr`.
- `GenerateFilterIdValue` advances a function-local static random number engine
(`std::independent_bits_engine`) to generate 24-bit IDs and asserts that the
upper 8 bits are zero.
- `MessageWriter::MessageComplete()` writes the buffer size into the first 4
bytes and moves the internal buffer out, leaving the writer empty.
- `MessageReader::SerializeBytes` advances the read offset or sets the sticky
`has_error_` flag when fewer bytes remain than requested.
- `DecodeX64Exception` and `DecodeArm64Exception` call `fetch_debug_regs` or
`fetch_esr` callbacks on demand to disambiguate hardware breakpoints,
watchpoints, and single-step traps.
## Verification
Run these commands to build and test `ipc`:
- Build: `fx build //src/developer/debug/ipc`
- Test: `fx test zxdb_tests`