CLI tool
encounter/objdiff avatar
encounter/objdiff

objdiff: object file diffing for decompilation projects

A local diffing tool for decompilation projects

605 stars92 forksRustApache-2.0

At a glance

What is it?
objdiff compares relocatable object files rather than source text, rebuilding your base object on every source change and showing where the assembly still differs from the target, across a dozen console architectures.
Who is it for?
Adopt objdiff if you are matching decompiled code against a target binary and want a per-function, per-instruction view of what still differs, with the build system doing the recompiles. Do not reach for it to diff source files, and expect to supply an objdiff.json that lists every object, since without that mapping the tool has nothing to compare.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

It diffs object files, not source text

objdiff is described as a local diffing tool for decompilation projects, and it is inspired by decomp.me and asm-differ. The subject of the comparison is the point. objdiff compares two relocatable object files, the .o files, so the unit of difference is what the compiler actually emitted rather than what a person typed. That catches the failures that text diffing cannot, a missing volatile, a different struct layout, an inline function that vanished, a compiler flag that changed codegen. The feature list spells out the scope. It can compare entire object files including functions and data, it has built-in C++ symbol demangling for GCC, MSVC, CodeWarrior and the Itanium scheme, it offers search and filter over objects with quick switching, and clicking a value highlights the related registers in the view. Detailed progress reporting is what powers decomp.dev.

objdiff.json is the map between your two builds

Everything starts with a configuration file named objdiff.json in the project root, which you write by hand or generate from your build script. It lists all objects in the project with their target path, the expected result, and their base path, the object built from your current source code. A small version looks like this:

json
{
  "$schema": "https://raw.githubusercontent.com/encounter/objdiff/main/config.schema.json",
  "custom_make": "ninja",
  "custom_args": [
    "-d",
    "keeprsp"
  ],
  "build_target": false,
  "build_base": true
}

Each entry in the units list is one object:

json
  "units": [
    {
      "name": "main/MetroTRK/mslsupp",
      "target_path": "build/asm/MetroTRK/mslsupp.o",
      "base_path": "build/src/MetroTRK/mslsupp.o",
      "metadata": {}
    }
  ]

The base path can be omitted when there is no source object yet, which is how a project starts on a new function. The name is what appears in the sidebar and defaults to the object's path. Two metadata fields carry meaning for a matching project: metadata.auto_generated hides an object from the sidebar while still counting it in progress reports, and metadata.complete marks an object as complete when true or incomplete when false. The file also supports watch_patterns and ignore_patterns, glob patterns that decide which source changes trigger a rebuild.

Your build system does the compiling

The usage sequence is short and it delegates the hard part. You create the configuration, load the project in objdiff, select an object from the sidebar, and objdiff then executes the build system to compile the base object from the current source code, compares the two objects, displays the differences, and watches for source file changes to rebuild when it detects them. The build command is configurable rather than hardcoded, with custom_make defaulting to make and custom_args added before the object path, so a ninja based project works the same way. Two switches control which side gets built: build_base, defaulting to true, builds the base objects before diffing, and build_target, defaulting to false, builds the target objects when those are not produced by default or can change with project configuration. That last one is the setting a project needs when the expected object is not simply a checked-in file but depends on how the project is configured. The documentation is clear that build_target requires proper build system configuration to work.

A dozen architectures, from GBA to PowerPC

The supported platform list is what makes this a decompilation tool rather than a general binary differ. ARM covers GBA, DS and 3DS, ARM64 covers Switch, MIPS covers N64, PS1, PS2 and PSP, PowerPC covers GameCube, Wii, PS3 and Xbox 360, SuperH covers Saturn and Dreamcast, and x86 with x86_64 covers the PC. The repository topics mirror that list with entries for gamecube, metrowerks, mips, nintendo-64, powerpc and wii, which also tells you what kinds of projects use it. Two details in the configuration hint at the origin of many of these projects. The custom_args example passes keeprsp, a Metrowerks codewarrior compiler option, and the sample unit name is main/MetroTRK/mslsupp, a path from the Metrowerks Nintendo DS toolchain. Demangling support for GCC, MSVC, CodeWarrior and Itanium covers the compiler families those projects actually use.

A GUI, a CLI, a WebAssembly build and a VS Code extension

The tool ships in more than one shape, and the differences are practical rather than cosmetic. The GUI has prebuilt binaries for Windows x86_64, Linux x86_64, macOS arm64 and macOS x86_64, and on Linux and macOS you need to run chmod +x objdiff-* to make the binary executable. The CLI binaries are on the releases page separately, which matters for scripting a match check into continuous integration. The workspace also contains an objdiff-wasm crate, exposed through a WebAssembly API, alongside a separate web interface project and a Visual Studio Code extension marked as work in progress. The detailed progress reporting is what powers decomp.dev, so the same object analysis feeds a hosted matching service. The repository is a Cargo workspace with four members, objdiff-cli, objdiff-core, objdiff-gui and objdiff-wasm, where objdiff-wasm is deliberately excluded from the default members so a plain cargo build does not spend time on it.

Building from source needs Rust 1.88 and the 2024 edition

The build instructions start with installing Rust through rustup, then cloning and running:

shell
git clone https://github.com/encounter/objdiff.git
cd objdiff
cargo run --release

or installing both binaries straight from the repository:

shell
cargo install --locked --git https://github.com/encounter/objdiff.git objdiff-gui objdiff-cli

which puts objdiff and objdiff-cli in your cargo bin directory. The workspace metadata sets version 3.8.3, the Rust 2024 edition, a rust-version floor of 1.88, and a dual licence of MIT OR Apache-2.0, with LICENSE-APACHE and LICENSE-MIT files at the top level. The release profile uses fat link time optimisation, strips debuginfo and sets codegen-units to 1, while a separate release-min profile inherits from it and lowers the optimisation level for a small binary. Contributors are pointed at pre-commit, with a nightly toolchain needed for cargo fmt and clippy, cargo-deny for dependency checks through the deny.toml in the root, and the uv tool installer as one route to pre-commit.

Configuration is generated, not hand-maintained

One piece of advice in the documentation is worth repeating because it saves the most time. If a project already has a generator script, for example configure.py, it is highly recommended to generate the objdiff configuration file as well, and then add objdiff.json to .gitignore so the file is not committed. That is right for a decompilation project, where the list of objects changes every time a function is added or renamed, and where a stale configuration silently compares the wrong files. The configuration also allows complete flexibility in project structure, since the build directories can have any layout as long as the paths are specified correctly. The schema itself lives at config.schema.json in the repository root, and the documentation points to it for every available option rather than trying to list them, with the summary in the guide covering the build, watch and unit settings. The release history is regular, with v3.8.3 on 2026-10-19, v3.8.2 on 2026-09-29 and v3.8.1 on 2026-08-29, and the last push was on the same day as the newest tag.

Editorial conclusion

Adopt objdiff if you are matching decompiled code against a target binary and want a per-function, per-instruction view of what still differs, with the build system doing the recompiles. Do not reach for it to diff source files, and expect to supply an objdiff.json that lists every object, since without that mapping the tool has nothing to compare.

Frequently asked questions

What does objdiff compare?

It compares two relocatable object files, the .o files, rather than source text. The target path is the expected object and the base path is the object built from your current source code, and the difference is reported at function and data level.

How do I configure objdiff for my project?

Create an objdiff.json file in the project root that lists every object with its target_path and base_path, and optionally set custom_make and custom_args for your build system. The schema for all options is published at config.schema.json in the repository.

Which platforms does objdiff support?

ARM for GBA, DS and 3DS, ARM64 for Switch, MIPS for N64, PS1, PS2 and PSP, PowerPC for GameCube, Wii, PS3 and Xbox 360, SuperH for Saturn and Dreamcast, and x86 and x86_64 for the PC.

How do I build objdiff from source?

Install Rust through rustup, clone the repository, then run cargo run --release, or install both binaries with cargo install --locked --git https://github.com/encounter/objdiff.git objdiff-gui objdiff-cli. The binaries are then installed to the cargo bin directory as objdiff and objdiff-cli.

What licence is objdiff released under?

The workspace metadata declares MIT OR Apache-2.0, and the repository ships LICENSE-APACHE and LICENSE-MIT files. The workspace version is 3.8.3 and the Rust edition is 2024 with a rust-version floor of 1.88.

Official sources

  1. encounter/objdiff on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/encounter-objdiff.svg)](https://hysenlabs.com/projects/encounter-objdiff)

Was this useful?