blob: 0086c045cf26fd034b960149889a14530fe636ee [file] [log] [blame] [view]
# 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 Conrol" 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.
### JobContext / Job
This is like the Target/Process split. The JobContexts is the holder for a job
that may or may not be attached, and the Job represents an attached job on the
remote system.
In Zircon you use attach to jobs to watch for process launches. It is like a
breakpoint for jobs.
### 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 ares nested so that you can to a "step over", hit an
exception and do some other stepping, and the thread sill still stop when the
original "step over" complets.
## 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.