Zxdb client library

This is a library for writing debugger frontends. The client library provides a way to connect to a remote Fuchsia system's running debug agent. It maintains the objects that represent running processes, threads, and stack frames, and provides a way to query and control these things.

Main objects

From largest to smallest.

Session

This is the main global object. It represents the connection to the remote system and provides functions to Connect and Disconnect.

The basic debugger initialization is to make a Session object and run the message loop (in src/developer/debug/shared).

The IPC layer is represented by the RemoteAPI which the Session maintains. The RemoteAPI is often mocked for testing.

System

This is the client representation of the remote system. Its main job is to maintain the list of Target objects. It also maintains breakpoints and filters. There is a 1:1 correspondence between Session and System (they could be the same object but we split them between “connection-related” and “OS-state-related” to keep things smaller).

Target

A target is a holder for a process. The process itself may or may not be running. Requests to start or kill a process are on the target and there is always at least one in the System. The target also maintains state that needs to survive across process launches like command line arguments.

When running, the Target will have a Process object.

Process

A running process on the remote system. It holds the running threads and provides an API to read and write memory. There are also functions to do process-wide suspend and resume.

In the console frontend, a “process” noun actually represents a target in the client library. The console frontend process may or may not be running or attached, while a client Process object always represents a running process.

Thread

A running thread in a process. It provides a nonempty Stack when paused, and the main stepping logic is here (see “Thread Control” below).

Stack

The backtrace of a Thread when the thread is paused. At its simplest it's a list of stack frames, but there is a lot of extra complexity around handling of inline stack frames.

In our system when a thread stops at an exception only the top two stack frames are sent from the debug_agent running on the remote system. This makes things faster since many exceptions are internally handled to implement stepping and unwinding the whole stack can take time. If you need the whole stack you will need to asynchronously SyncFrames.

Frame

One stack frame. Some stack frames are real and some represent inline function calls without any real information on the stack. Usually when you want to get a variable or evaluate an expression you do it in the context of a stack frame. You do this by getting the frame's EvalContext.

Other objects

Breakpoint

Breakpoints are global and are maintained by the System. You can have process- and thread-specific ones but those states are a property of the breakpoint. The breakpoint objects themselves are still global.

Job

Job is used to watch for process launches in Zircon.

Filter

A filter is a way to watch for processes on jobs and automatically attach when the name matches.

Thread control

Stepping is implemented by ThreadController objects. To do a certain kind of step operation on a thread, you instantiate the type of ThreadController that implements the operation you want and call Thread::ContinueWith to run that controller. The thread controller will watch for exceptions and resume as necessary to implement its operation.

The main ones are:

  • FinishThreadController
  • StepOverThreadController
  • StepThreadController (implements various kinds of “step into”)
  • UntilThreadController

Thread controllers are nested so that you can do a “step over”, hit an exception, complete some other steppings, and have the thread still stop when the original “step over” has completed.

Expressions

Expression and variable evaluation is provided by the expr library. To run this you give it an EvalContext in which to do it's job. This context is most commonly provided by a Frame which provides access to the local variables and all process state.