# How Ghidra's Version Tracking and Program Diff Work: A Deep Dive into Binary Comparison

> Discover how Ghidra's version tracking and program diff identify binary differences. Learn about its address set conversion, memory-block comparison, and cross-version correlation for functions and data.

- Repository: [National Security Agency/ghidra](https://github.com/NationalSecurityAgency/ghidra)
- Tags: deep-dive
- Published: 2026-03-04

---

**Ghidra compares binary programs by converting them into address sets and running them through a memory-block comparator that identifies byte-level, code-unit, and symbolic differences, while Version Tracking adds a persistent correlation layer that matches functions and data structures across program versions.**

Ghidra's reverse engineering platform provides two powerful capabilities for analyzing binary evolution: **Program Diff** for immediate comparison and **Version Tracking (VT)** for long-term correlation management. Both systems rely on a shared architecture that treats program differences as **address sets** computed by the `ProgramDiff` engine in [`Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiff.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiff.java). Understanding how these subsystems traverse memory blocks, apply filters, and persist matches reveals how the NSA's open-source framework enables analysts to track code changes across firmware versions and malware variants.

## Core Diff Engine Architecture

The diff engine is built around three primary components that transform two binaries into comparable address ranges. The **`ProgramDiff`** class orchestrates the process, utilizing **`ProgramMemoryComparator`** to validate address-space compatibility and **`ProgramDiffFilter`** to determine which difference types to calculate.

Key implementation files include:

- **[`ProgramDiff.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/ProgramDiff.java)**: Located at [`Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiff.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiff.java), this class builds address sets for each difference type including bytes, code units, comments, references, symbols, and functions.
- **[`ProgramDiffFilter.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/ProgramDiffFilter.java)**: A bitmask interface at [`Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffFilter.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/Base/src/main/java/ghidra/program/util/ProgramDiffFilter.java) that specifies which primary diff types to compute (e.g., `BYTE_DIFFS`, `CODE_UNIT_DIFFS`).
- **[`ProgramDiffPlugin.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/ProgramDiffPlugin.java)**: The UI layer at [`Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/plugin/core/diff/ProgramDiffPlugin.java) implements the **`DiffService`** interface, allowing other plugins to launch diff sessions programmatically.

The **`ProgramMemoryComparator`** validates that both programs share compatible memory maps, determining "in-common" versus "only-in-one" address ranges while handling uninitialized versus initialized memory states.

## How ProgramDiff Computes Differences

The diff computation follows a four-phase pipeline that operates transaction-free, ensuring the source binaries remain read-only throughout the comparison.

1. **Compatibility Check**: `ProgramDiff` instantiates a `ProgramMemoryComparator` to verify address-space alignment. If memory maps diverge, the engine restricts comparison to symbolic differences only.

2. **Address Set Creation**: For each enabled diff type in the filter, `ProgramDiff.createAddressSet` invokes specialized routines like `getByteDifferences`, `getCodeUnitDifferences`, and `getReferenceDifferences`. These methods traverse the address ranges returned by `getAddressesInCommon()`, populating an `AddressSet` with discrepancy start addresses.

3. **Filtering and Post-Processing**: The `computeDiffsToReturn` method applies user-defined constraints—ignore sets, restrict ranges, and check addresses—to refine the results.

4. **Result Delivery**: The final `AddressSetView` returns to the UI, which highlights differing addresses and enables navigation between source and destination locations.

The engine processes memory in small chunks of `BYTE_DIFF_GRAB_SIZE = 1024` bytes to maintain UI responsiveness and support cancellation via `TaskMonitor`.

## Version Tracking Infrastructure

Version Tracking extends Program Diff with a **match-making** and **markup persistence** layer. While Program Diff identifies raw differences, VT correlates them into meaningful entities like functions and data structures, storing analyst decisions in a `VTSessionDB` database.

Core VT components include:

- **[`VTPlugin.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/VTPlugin.java)**: The entry point at [`Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTPlugin.java) that registers actions (Create, Open, Add, Save, Auto-VT) and instantiates UI providers.
- **[`VTControllerImpl.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/VTControllerImpl.java)**: The model-side controller at [`Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTControllerImpl.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTControllerImpl.java) implementing the `VTController` service interface, managing the active session and forwarding events.
- **[`VTSessionDB.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/VTSessionDB.java)**: A database-backed session implementation at [`Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/db/VTSessionDB.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/db/VTSessionDB.java) that persists matches (`VTMatch`), markup items (`VTMarkupItem`), status flags, and tags.
- **[`AddressCorrelatorManager.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/AddressCorrelatorManager.java)**: Executes correlation algorithms (function similarity, data-type similarity, instruction similarity) that propose matches for the match table.

The UI providers—including `VTMatchTableProvider`, `VTMarkupItemsTableProvider`, and `VTFunctionAssociationProvider`—render the correlation results and enable acceptance, rejection, and markup application.

## VT Session Lifecycle and Persistence

A Version Tracking session progresses through six distinct stages, integrating closely with Ghidra's transaction system for undo/redo support.

**Session Creation**: Users launch the *Create New Session* wizard (`CreateVersionTrackingSessionAction`), which instantiates `VTNewSessionWizardModel` to capture source and destination programs. `VTControllerImpl` constructs a `VTSessionDB` instance, registering it as a `DomainObjectListener` on both programs to invalidate caches automatically when changes occur.

**Correlation Execution**: `AddressCorrelatorManager` runs function, data, and instruction correlators, generating `VTMatch` objects that populate the match table with proposed correspondences.

**User Interaction**: Analysts accept, reject, or apply markup from matches. Applying markup creates `VTMarkupItem` objects—such as function renames or operand changes—that are persisted within the session.

**Synchronization**: When saving, `VTControllerImpl.checkForSave` creates a `SaveTask` to synchronize the destination program with the session database, ensuring consistency between the `.vt` domain file and underlying binaries.

**Undo/Redo Integration**: Each bulk operation starts a transaction via `session.startTransaction(taskTitle)`, enabling standard Ghidra undo/redo across VT sessions.

Background tasks like `ApplyMatchTask` and `AutoVersionTrackingTask` execute expensive operations without blocking the UI, utilizing the `VTTask` hierarchy.

## Automating Diff and VT via Service APIs

Both subsystems expose service interfaces that scripts and plugins can invoke to programmatically launch comparisons.

Launching a classic Program Diff:

```java
import ghidra.app.services.DiffService;
import ghidra.framework.model.DomainFile;

DiffService diffService = tool.getService(DiffService.class);
if (diffService != null && diffService.launchDiff(otherFile)) {
    println("Diff launched successfully.");
}

```

The `DiffService` interface is defined at [`Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/services/DiffService.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/ProgramDiff/src/main/java/ghidra/app/services/DiffService.java).

Managing Version Tracking sessions:

```java
import ghidra.feature.vt.api.main.VTController;
import ghidra.framework.model.DomainFile;

VTController vtController = tool.getService(VTController.class);

// Open existing session
if (vtController.openVersionTrackingSession(vtFile)) {
    println("VT session opened.");
}

// Create new session programmatically
vtController.openVersionTrackingSession(srcFile);
vtController.openVersionTrackingSession(dstFile);
vtController.runVTTask(new AutoVersionTrackingTask(vtController));

```

The `VTController` implementation resides in [`VTControllerImpl.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/VTControllerImpl.java) at [`Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTControllerImpl.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/plugin/VTControllerImpl.java).

## Summary

- **ProgramDiff** provides a read-only, address-set-based comparison engine that computes byte, code-unit, and symbolic differences through `ProgramMemoryComparator` and `ProgramDiffFilter`.
- **Version Tracking** layers correlation algorithms and persistence on top of Program Diff, storing matches and markup decisions in `VTSessionDB` via the `VTControllerImpl` architecture.
- Both systems utilize chunked memory processing (`BYTE_DIFF_GRAB_SIZE = 1024`) and background tasks to maintain UI responsiveness during large binary comparisons.
- Service interfaces (`DiffService` and `VTController`) enable automation of diff launches and VT session management from Ghidra scripts and plugins.
- The UI components (`ProgramDiffPlugin`, `VTMatchTableProvider`, `VTMarkupItemsTableProvider`) render results through a filter-driven diff engine that supports transaction-based undo/redo.

## Frequently Asked Questions

### What is the difference between Program Diff and Version Tracking in Ghidra?

Program Diff is a transient, read-only comparison that highlights immediate differences between two binaries using address sets and memory-block comparators. Version Tracking is a persistent workflow that uses correlation algorithms to match functions and data structures across versions, storing analyst decisions (accept/reject matches, applied markup) in a database-backed `VTSessionDB` that survives across Ghidra sessions.

### How does Ghidra's diff engine handle large binaries without freezing the UI?

The `ProgramDiff` class processes memory in configurable chunks (`BYTE_DIFF_GRAB_SIZE = 1024` bytes) and accepts a `TaskMonitor` parameter for cancellation support. All difference computation runs transaction-free in the background, with heavy operations delegated to `VTTask` subclasses like `AutoVersionTrackingTask`, ensuring the interface remains responsive during comparisons.

### Can Version Tracking sessions be automated through Ghidra scripts?

Yes. Both Program Diff and Version Tracking expose service interfaces—`DiffService` and `VTController` respectively—that scripts can obtain via `tool.getService()`. Developers can programmatically launch diffs, create VT sessions, run auto-correlators via `AutoVersionTrackingTask`, and apply markup without manual UI interaction, as implemented in `VTControllerImpl`.

### Where does Ghidra store Version Tracking match and markup data?

VT persists matches (`VTMatch` objects), markup items (`VTMarkupItem`), and session metadata in a `.vt` domain file managed by `VTSessionDB` at [`Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/db/VTSessionDB.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/db/VTSessionDB.java). This database registers as a `DomainObjectListener` on both source and destination programs, automatically invalidating caches when underlying program data changes.