Ghidra Backend

Ghidra provides a user-space concrete emulator based on its Pcode language models.

Pcode models a huge number of ISAs, offering far greater language support than the other concrete emulators. It’s also very focused on user-space features, making it a little more abstract and in some ways more forgiving than QEMU-based emulators.

The downside is that the Pcode language models vary wildly in their fidelity, and exercising an unsupported or partially-supported feature will simply produce incorrect behavior, rather than reporting an error.

Note

Using GhidraEmulator requires an operation Ghidra installation, and requires that the environment variable GHIDRA_INSTALL_DIR contain the path to that install directory.

See the installation docs for more information about setting up Ghidra for use with smallworld.

Note

Using GhidraEmulator requires launching a Java Virtual Machine in the background of your python process.

This is done once the first time you call the GhidraEmulator constructor, and may take about ten seconds to complete.

Execution Control

GhidraEmulator supports run() and step() normally.

It does not support step_block(); the underlying emulator operates strictly on instructions. Invoking step_block() will raise an exception.

Note

GhidraEmulator.step() may execute more than one instruction.

This only happens on instructions with delay slots; the emulator must execute the instruction and its delay slot as a single step.

Exit Points and Bounds

GhidraEmulator supports exit points and bounds normally. It will treat execution of unmapped memory as an out-of-bounds execution.

Accessing Registers

GhidraEmulator supports normal register access.

Setting labels on registers has no effect on GhidraEmulator, and the labels are not preserved after execution starts.

Mapping Memory

GhidraEmulator enforces its memory map. Accesses to unmapped memory will produce an exception, reporting either an unmapped “read”, “write”, or “fetch” (for an unmapped program counter.)

The memory map works on a byte resolution.

Accessing Memory

GhidraEmulator supports normal memory accesses.

Setting labels on memory has no effect on GhidraEmulator, and labels are not preserved once execution begins.

Warning

TODO: How well-supported are ISA features that change memory layout, like x86 segmentation?

Event Handlers

GhidraEmulator supports the following event types:

  • Instruction Hooks

  • Function Models

  • Memory Accesses

Caution

GhidraEmulator hooks behave oddly around delay slot instructions.

Instruction hooks will not fire if attached to an instruction in a delay slot.

Memory accesses that occur in a delay slot will report the program counter for the parent instruction, although all other machine state will be correct.

Interacting with Ghidra

Note

Understanding this section is not necessary to write a normal harness.

The features described here are completely abstracted behind the GhidraEmulator interface, and are only useful if you want to leverage Unicorn for analysis.

This section describes how to access the relevant objects, and any caveats regarding their access. Using them for analysis is an exercise left to other tutorials.

It’s possible to access the Ghidra emulator instance directly via the property GhidraEmulator._emu.