
Binary analysis library built on LLVM for disassembling, lifting, and symbolically executing machine code across x86, ARM, and RISC-V, with CFG recovery and Z3 solving.
A binary analysis library for disassembling, assembling, and analyzing machine code across multiple architectures. Built on LLVM 21.
Features:
Function, or a single flattened IGNIL block (no CFG needed), to LLVM IR, with an optimization pipeline (mem2reg/instcombine/GVN/DCE) on top.pat signature databasesLoadedImage: sections and ELF PT_LOAD segments at their virtual addresses with R/W/X permissions, entry point, image base, symbols with import/export flags, and the architecture auto-detected from the header (no need to name it). loader::disassembleImage goes from a file to a populated Graph in one call. Built on LLVM's llvm::object, so no extra dependencydisassembler CLI — a command-line tool that loads an ELF or PE binary and dumps disassembly, useful for quick inspection and scriptingdragon_c.h) and Python API (cffi) covering most of the feature set above (a few C++-only corners — pattern-matching DSL templates, architecture-specific instruction classification helpers, and similar — are documented as such in docs/cpp_api.md)Tagged releases ship a self-contained SDK archive per platform
(dragon-<version>-{linux-x64,macos-arm64,windows-x64}.{tar.gz,zip}) on the
GitHub Releases page. LLVM is statically linked into the
libraries, so no system LLVM install is required to use them; Z3 is bundled
alongside. Each archive contains:
lib/ libdragon + libdragon_c (shared) and the bundled Z3 runtime
bin/ the `disassembler` CLI (plus the DLLs on Windows)
include/ the C++ headers (dragon/...) and the C-shim header (dragon/dragon_c.h)
share/dragon/python/dragon.py the Python API
Point the Python API at the bundled library with
DRAGON_C_LIB=/path/to/lib/libdragon_c.so (.dylib/.dll as appropriate).
To build from source instead:
mkdir build && cd build
cmake ..
cmake --build .
To run the tests:
ctest --output-on-failure
A handful of x86 semantic round-trip tests are expensive: they JIT-compile
the lifted IR and emulate the raw bytes under Unicorn across a large
cross-product of edge-case inputs (thousands of round-trips each). They are
tagged [.][expensive], which hides them from the default ctest run so it
stays fast. Run them explicitly — typically on a more powerful machine or in
CI — with:
./build/bin/dragon_tests "[expensive]"
On Windows the dependency discovery in CMakeLists.txt needs a few hints,
because it is written for Linux package layouts: Z3 is located through LLVM's
bundled FindZ3.cmake module, and Unicorn is located through pkg-config.
Neither mechanism knows where vcpkg installs things, and LLVM is found via
LLVM_DIR rather than the system path. Supplying three hints fixes all of it.
Prerequisites
C:\llvm-21 (the prebuilt
clang+llvm-*-x86_64-pc-windows-msvc release works)1. Install the libraries with vcpkg (the x64-windows triplet; pkgconf
provides the pkg-config executable Unicorn discovery needs):
vcpkg install z3:x64-windows unicorn:x64-windows pkgconf:x64-windows
2. The three hints CMake needs
| Hint | Purpose | Example value |
|---|---|---|
LLVM_DIR | locate LLVM 21 | C:/llvm-21/lib/cmake/llvm |
CMAKE_PREFIX_PATH | let FindZ3 see the vcpkg tree | C:/vcpkg/installed/x64-windows |
PKG_CONFIG_EXECUTABLE + PKG_CONFIG_PATH | let Unicorn be found via pkg-config | .../tools/pkgconf/pkgconf.exe and .../installed/x64-windows/lib/pkgconfig |
3a. Configure and build (one command)
$env:PKG_CONFIG_PATH = "C:/vcpkg/installed/x64-windows/lib/pkgconfig"
cmake -S . -B build `
-DLLVM_DIR=C:/llvm-21/lib/cmake/llvm `
-DCMAKE_PREFIX_PATH=C:/vcpkg/installed/x64-windows `
-DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe `
-DDRAGON_USE_Z3=ON -DDRAGON_USE_UNICORN=ON
cmake --build build --config Release
A successful configure prints:
-- Found LLVM 21.1.8 at C:/llvm-21/lib/cmake/llvm
-- Found Z3 5.0.0 at C:/vcpkg/installed/x64-windows/lib/libz3.lib
-- Found Unicorn 2.1.4
3b. Or use a preset (recommended)
Save the settings once in a CMakeUserPresets.json next to CMakeLists.txt,
then configure with a single flag. This file holds machine-specific paths, so
keep it out of version control (it is git-ignored).
{
"version": 3,
"configurePresets": [
{
"name": "win-vcpkg",
"generator": "Visual Studio 17 2022",
"architecture": "x64",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"LLVM_DIR": "C:/llvm-21/lib/cmake/llvm",
"CMAKE_PREFIX_PATH": "C:/vcpkg/installed/x64-windows",
"PKG_CONFIG_EXECUTABLE": "C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe",
"DRAGON_USE_Z3": "ON",
"DRAGON_USE_UNICORN": "ON"
},
"environment": {
"PKG_CONFIG_PATH": "C:/vcpkg/installed/x64-windows/lib/pkgconfig"
}
}
],
"buildPresets": [
{ "name": "win-vcpkg", "configurePreset": "win-vcpkg", "configuration": "Release" }
]
}
cmake --preset win-vcpkg
cmake --build build --config Release
Notes
%VCPKG_ROOT% accordingly; if you unpacked LLVM elsewhere, point LLVM_DIR
at that tree's lib/cmake/llvm.-DCMAKE_TOOLCHAIN_FILE=.../vcpkg.cmake) here. It restricts package search
and stops CMake from finding an LLVM that lives outside vcpkg, which is the
usual setup for this project.pkg-config it is simply disabled and
only the tests/semantic/ round-trip tests are skipped. Z3, by contrast, is
required whenever DRAGON_USE_Z3=ON.