blob: 813985df193a2b95872e4281a899d0e1aea8a396 [file] [log] [blame] [view]
# Debugging a process, component, or crash dump
## Attaching to a process by name filters
Running a process on Fuchsia is more complicated than in other systems because there are different
loader environments (see "A note about launcher environments" below).
The only want to reliably debug all types of processes is to create a filter on the process name via
"attach" and start it the normal way you would start that process. The process name is usually the
name of the build target that generates it. To check what this is, use "ps" (either in the debugger
or from a system shell) with it running.
> Note: only the first 32 bytes of the name are included in the Zircon process description.
> Sometimes the number of path components can cause the name to be truncated. If the filter isn't
> working, check the actual name in "ps". We hope to have a better way to match this in the future.
This example sets a pending breakpoint on `main` to stop at the beginning of execution, and waits
for a process called "my\_app" to start:
```
[zxdb] attach my_app
Waiting for process matching "my_app"
[zxdb] break main
Breakpoint 1 (Software) on Global, Enabled, stop=All, @ main
Pending: No matches for location, it will be pending library loads.
```
Then run the process the way you would in normal use (directly on the command line, via `fx test`,
via the shell's `run fuchsia-pkg://...`, or another way. The debugger should then immediately break
on `main` (it may take some time to load symbols so you may see a delay before showing the source
code):
```
Attached Process 1 [Running] koid=51590 my_app.cmx
🛑 on bp 1 main(…) • main.cc:222
220 }
221
▶ 222 int main(int argc, const char* argv[]) {
223 foo::CommandLineOptions options;
224 cmdline::Status status = ParseCommandLine(argc, argv, &options);
```
You can then do basic commands that are similar to GDB:
```
next
step
print argv[1]
continue
quit
```
#### A note about launcher environments
The following loader environments all have different capabilities (in order
from least capable to most capable):
* The debugger's `run <file name>` command (base system process stuff).
* The system console or `fx shell` (adds some libraries).
* The base component environment via the shell's `run` and the debugger's
`run -c <package url>` (adds component capabilities).
* The test environment via `fx test`.
* The user environment when launched from a "story" (adds high-level
services like scenic).
This panoply of environments is why the debugger can't have a simple "run"
command that always works.
## Launching simple command-line processes
Minimal console apps including some unit tests can be launched directly from within the debugger
which avoids the above "attach" dance:
```
[zxdb] break main
Breakpoint 1 (Software) on Global, Enabled, stop=All, @ $main
Pending: No matches for location, it will be pending library loads.
[zxdb] run /bin/cowsay
```
If you get a shared library load error or errors about files or services not being found, it means
the app can't be run from within the debugger's launcher environment. This is true even for things
that may seem relatively simple.
## Directly launching components
Components that can be executed with the console command `run fuchsia-pkg://...` can be loaded in
the debugger with the following command, substituting your component's URL:
```
[zxdb] run -c fuchsia-pkg://fuchsia.com/your\_app#meta/your\_app.cmx
```
Not all components can be launched this way since most higher-level services won't be accessible: if
you can't do `run ...` from the system console, it won't work from the debugger either. Note also
that `fx test` is a different environment. According to your test's dependencies, it may or may not
work from the debugger's `run` command.
## Attaching to an existing process
You can attach to most running processes given the process koid (the [kernel object
ID](/docs/concepts/kernel/concepts.md) that, when applied to a process, is equivalent to a process
ID on other systems). You can get the koid by running `ps` on the target Fuchsia system or use
zxdb's built-in `ps` command:
```
[zxdb] ps
j: 1030 root
j: 1079 zircon-drivers
p: 1926 driver_host:sys
...
```
In this listing, "j:" indicates a [job](/docs/concepts/kernel/concepts.md) (a container for
processes) and "p:" indicates a process. The number following the type prefix is the object's koid.
Then to attach:
```
[zxdb] attach 3517
Process 1 Running koid=1249 pwrbtn-monitor
```
When youre done, you can choose to `detach` (keep running) or `kill` (terminate) the process.
## Attaching to processes in specific jobs
By default the debugger will attampt to attach to the root job so process launch filters will apply
globally. Normally this will appear as "job 1" in the debugger:
```
[zxdb] job
# State Koid Name
1 Attached 1027 root
```
You can also apply filters for processes launched in a specific job. First attach to the job using
the `attach-job` command, specifying the job's koid:
```
[zxdb] attach-job 30053
Job 2 state=Attached koid=30053 name=""
```
The debugger will now be attached to two jobs, with the new job being the current one:
```
[zxdb] job
# State Koid Name
1 Attached 1027 root
▶ 2 Attached 30053
```
Now you can make a filter (see above) that applies to the process names only to this job by
prefixing the attach command with the job object number (not koid) created above:
```
[zxdb] job 2 attach my_app
Waiting for process matching "my_app".
Type "filter" to see the current filters.
```
You can also attach to all current and future processes in a job using the `*` wildcard as the
filter name:
```
[zxdb] attach-job 30053
Job 2 state=Attached koid=30053 name=""
[zxdb] job 2 attach *
Attached Process 1 state=Running koid=28071 name=sysmem_connector.cmx
```
> **Warning:** Be careful only to use the wildcard `attach *` command with an explicit,
> narrowly-scoped job. Making a global filter or applying it to a job with too many children can
> attach to too many processes that may include drivers necessary for the system to function.
## Debugging drivers
It's not currently possible to set up the debugger early enough in system startup to debug most
driver initialization. And since zxdb itself uses the network and filesystem, no drivers associated
with network communication can be debuged, and neither can many drivers associated with storage or
other critical system functions.
Driver debugging support is tracked in issue
[5456](https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=5456).
You can debug running drivers by attaching like any other process (see Attaching to an existing
process”). You can delay initialization to allow time to attach by adding a busyloop at the
beginning of your code:
```
volatile bool stop = false;
while (!stop) {}
```
To break out of the loop after attaching, either set the variable to true:
```
[zxdb] print stop = true
true
[zxdb] continue
```
Or jump to the line after the loop:
```
[zxdb] jump <line #>
[zxdb] continue
```
## Debugging crash dumps
Zxdb supports loading a minidump generated by a crash report. Use the "opendump" verb and supply the
local file name of the dump. The debugger must not be attached to another dump or a running system
(use "disconnect" first if so).
```
[zxdb] opendump upload_file_minidump-e71256ba30163a0.dmp
Opening dump file
Dump loaded successfully.
```
Now the thread, stack, and memory commands can be used to inspect the state of the program. Use
`disconnect` to close the dump.
For in-tree users, the `fx debug` command can take the path to a core file as an argument.
```
fx debug -c upload_file_minidump-e71256ba30163a0.dmp
```
#### Downloading symbols
To tell zxdb to look for debug symbols for your core dump in a GCS URL and download those symbols
automatically, run the following command, substituting the location of your symbols:
```
zxdb --symbol-server gs://my-bucket-name/namespace
```
In-tree users automatically have the option set, with the server pointed to a bucket containing
symbols for all release builds.
The first time you use the symbol server, you will have to authenticate using the `auth` command.
The authentication flow will require you to complete part of the authentication in your browser.
```
[zxdb] auth
To authenticate, please supply an authentication token. You can retrieve a token from:
https://accounts.google.com/o/oauth2/v2/< very long URL omitted >
Once you've retrieved a token, run 'auth <token>'
[zxdb] auth 4/hAF-pASODIFUASDIFUASODIUFSADF329827349872V6
Successfully authenticated with gs://fuchsia-artifacts-release/debug
```
### Debugging multiple processes
You can debug many arbitrary processes at the same time. Attaching or running when a process is
already running in the debugger will just create a new one in parallel.
Recall from the Interaction model section you can list the current processes with:
```
[zxdb] process
# State Koid Name
▶ 1 Running 1249 pwrbtn-monitor
2 Not running 7235 pwrbtn-monitor
```
Select one of those as the default by providing its index (not koid):
```
[zxdb] process 2
```
Or apply commands to a specific process (even if its not the default) with:
```
[zxdb] process 2 pause
```