# Adding a debugger

This module walks you through an example of how to add a debugger agent to Ghidra.
It has no exercises and is certainly not the only way to implement an agent, but hopefully contains some useful pointers and highlights some pit-falls that you might encounter.
The example traces the implementation of an actual agent &mdash; the agent for *Meta*'s **drgn** debugger, which provides a scriptable, albeit read-only, interface to the running Linux kernel, as well as user-mode and core-dump targets.

## Debugger documentation

- Recommended reading: **drgn** (<https://github.com/osandov/drgn>)
- Also: **drgn (docs)** (<https://drgn.readthedocs.io/en/latest>)

## Anatomy of a Ghidra debugger agent

To support debugging on various platforms, the Ghidra debugger has *agents*, i.e. clients capable of receiving information from a native debugger and passing it to the Ghidra GUI.
They include the **dbgeng** agent that supports Windows debuggers, the **gdb** agent for gdb on a variery of platforms, the **lldb** agent for macOS and Linux, and the **jpda** agent for Java.
All but the last are written in Python 3, and all communicate with the GUI via a protobuf-based protocol described in [Debugger-rmi-trace](../../../Ghidra/Debug/Debugger-rmi-trace/src/main/proto/trace-rmi.proto).

At the highest level, each agent has four elements (ok, a somewhat arbitrary division, but...):

* [`debugger-launchers`](../../../Ghidra/Debug/Debugger-agent-drgn/data/debugger-launchers) &ndash; A set of launchers, often a mixture of `.bat`,`.sh`, and sometime `.py` scripts
* [`schema.xml`](../../../Ghidra/Debug/Debugger-agent-drgn/src/main/py/src/ghidradrgn/schema.xml) &ndash; An object-model schema. (While expressed in XML, this is not an "XML schema".)
* [`src/ghidradrgn`](../../../Ghidra/Debug/Debugger-agent-drgn/src/main/py/src/ghidradrgn) &ndash; Python files for architecture, commands, hooks, methods, and common utility functions
* [`build.gradle`](../../../Ghidra/Debug/Debugger-agent-drgn/build.gradle) &ndash; Build logic

Large portions of each are identical or similar across agents, so, as a general strategy, copying an existing agent and renaming all agent-specific variables, methods, etc. is not the worst plan of action. Typically, this leads to large chunks of detritus that need to be edited out late in the development process.

## drgn as an Example

### The first launcher &mdash; `local-drgn.sh`

The initial objective is to create a shell that sets up the environment variables for parameters we'll need and invokes the target. 
For this project, I originally started duplicating the **lldb** agent and then switched to the **dbgeng** agent. 
Why? The hardest part of writing an agent is getting the initial launch pattern correct.
**drgn** is itself written in Python.
While gdb and lldb support Python as scripting languages, their cores are not Python-based.
For these debuggers, the launcher runs the native debugger and instructs it to load our plugin, which is the agent. 
The dbgeng agent inverts this pattern, i.e. the agent is a Python application that uses the **Pybag** package to access the native *kd* interface over COM.
**drgn** follows this pattern.

That said, a quick look at the launchers in the **dbgeng** project (under [`debugger-launchers`](../../../Ghidra/Debug/Debugger-agent-dbgeng/data/debugger-launchers)) shows `.bat` files, each of which calls a `.py` file in [`data/support`](../../../Ghidra/Debug/Debugger-agent-dbgeng/data/support). 
As **drgn** is a Linux-only debugger, we need to convert the `.bat` examples to `.sh`. 
Luckily, the conversion is pretty simple: most line annotations use `#` in place of `::` and environment variables are referenced using `$VAR` in place of `%VAR%`.

The syntax of the `.sh` is typical of any *\*nix* shell. 
In addition to the shell script, a launcher include a metadata header to populate its menu and options dialog.
Annotations include:

* A `#!` line for the shell invocation
* The Ghidra license
* A `#@title` line for the launcher name
* A `#@desc`-annotated HTML description, as displayed in the launch dialog
* `#@menu-group` for organizing launchers 
* `#@icon` for an icon
* `#@help` the help file and anchor
* Some number of `#@arg` variables, usually only one to name the executable image
* `#@args` specifies the remainder of the arguments, passed to a user-mode target if applicable
* Some number of `#@env` variables referenced by the Python code
 
While the **drgn** launcher does not use `@arg` or `@args`, there are plentiful examples
in the [**gdb** project](../../../Ghidra/Debug/Debugger-agent-gdb/data/debugger-launchers).
The `#@env` lines are composed of the variable name (usually in caps), its type, default value, a label for the dialog if the user need to be queried, and a description.
The syntax looks like:

* `#@env` *Name* `:` *Type* [ `!` ] `=` *DefaultValue* *Label* *Description*

where `!`, if present, indicates the option is required.

For **drgn**, invoking the `drgn` command directly saves us a lot of the work involved in getting the environment correct.
We pass it our Python launcher `local-drgn.py` instead of allowing it to call `run_interactive`, which does not return.
Instead, we created an instance of `prog` based on the parameters, complete the Ghidra-specific initialization, and call `run_interactive(prog)` ourselves.

The Python script needs to do the setup work for Ghidra and for **drgn**.
A good start is to try to implement a script that calls the methods for `connect`, `create`, and `start`, with `create` doing as little as possible initially.
This should allow you to work the kinks out of `arch.py` and `util.py`.

For this particular target, there are some interesting wrinkles surrounding the use of `sudo` (required for most targets) which complicate where wheels are installed (i.e. it is pretty easy to accidentally mix user-local and system `site-packages`).
Additionally, the `-E` parameter is required to ensure that the environment variable we defined get passed to the root environment. 
In the cases where we use `sudo`, the first message printed in the interactive shell will be the request for the user's password.

### The schema

The schema, specified in `schema.xml`, provides a basic structure for Ghidra's **Model** View and allows Ghidra to identify and locate various interfaces that are used to populate the GUI.
For example, the *Memory* interface identifies the container for items with the interface *MemoryRegion*, which provide information used to fill the **Memory** View.
Among the important interfaces are *Process*, *Thread*, *Frame*, *Register*, *MemoryRegion*, *Module*, and *Section*.
These interfaces are "built into" Ghidra so that it can identify which objects provide specific information and commands.

For the purposes of getting started, it's easiest to clone the **dbgeng** schema and modify it as needed.
Again, this will require substantial cleanup later on, but, as schema erro