CLI tool
lifting-bits/remill avatar
lifting-bits/remill

Remill static binary translation for LLVM-based tools

Library for lifting machine code to LLVM bitcode

1,871 stars189 forksC++Apache-2.0

At a glance

What is it?
Remill is a C++ library that lifts supported machine-code instructions into LLVM bitcode for tools such as McSema. It focuses on instruction semantics, while its documented setup is aimed at building the library rather than providing a complete binary conversion workflow.
Who is it for?
Remill fits developers who need instruction-level LLVM IR semantics inside a larger static binary analysis tool, especially projects modeled on integrations such as McSema. It is a poor fit for users expecting a documented command that accepts a binary and emits a complete LLVM module, or for projects requiring mature AArch32 support.
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 57 days ago.
What is it written in?
Mainly C++, 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

Why Remill targets LLVM-based binary tooling

Remill solves the lower-level problem of translating machine-code instructions into LLVM bitcode. The README says its focus is accurate instruction lifting, while its intended role is to serve as a library inside another tool rather than as a general-purpose application. It names McSema as an example integration, which helps define the expected consumer: software that already needs an LLVM IR representation for analysis, transformation, or downstream processing.

That distinction matters. Producing useful LLVM bitcode from a complete binary requires more than decoding isolated instructions. Code discovery, function boundaries, control flow, data interpretation, and program-level behavior are separate concerns. Remill's documentation directs developers to `docs/LIFE_OF_AN_INSTRUCTION.md` for the instruction-lifting process, `docs/ADD_AN_INSTRUCTION.md` for implementing instruction semantics, and `docs/DESIGN.md` for its architecture. The README does not present Remill as a turnkey binary-to-bitcode converter, so users seeking that kind of command should first examine a downstream integration such as McSema.

The C++ implementation and LLVM dependency also place Remill close to compiler and analysis infrastructure rather than an ordinary utility. Its usefulness depends on how a calling tool maps addresses, registers, memory state, and control flow into the lifted semantics.

Instruction coverage and architectural boundaries

The README lists AArch64, described as 64-bit ARMv8, SPARC32 based on SPARCv8, SPARC64 based on SPARCv9, x86, and amd64. The x86 and amd64 support explicitly includes AVX and AVX512 instructions. AArch32, described as 32-bit ARMv8 or ARMv7, is still under development, so it should not be presented as equivalent to the listed targets.

This creates a clear architecture-selection boundary. A developer targeting AArch64 can select Remill as a candidate, while a developer centered on AArch32 must account for incomplete support before designing a dependency around it. Repository topics include `aarch64`, `armv7`, `armv8`, `thumb2`, `sparcv8`, and `sparcv9`, but the README only confirms that AArch32 support is underway. It does not state the current completion level for every ARM-related topic, so topic labels alone are not proof of production readiness.

Host support is separate from instruction-set support. The README states that Remill supports Linux platforms, has been tested on Ubuntu 22.04, works on macOS, and has experimental Windows support. It also says the Linux version can be built through Docker. A suitable host operating system therefore does not guarantee that every architecture and platform combination is equally mature.

The superbuild behind Remill's LLVM setup

Remill's documented build starts with a dependency superbuild stored in `dependencies/`. That stage builds required dependencies, including LLVM, into the repository's dependency installation prefix. A second CMake invocation configures Remill with `CMAKE_PREFIX_PATH:PATH` pointing at `dependencies/install`, followed by a Ninja build. This arrangement separates dependency acquisition from the main project configuration.

The documented dependency floor includes CMake 3.21 or newer, Ninja 1 or newer, LLVM 15 or newer, Clang 15 or newer, Python 3 or newer, Google Log v0.7.1, Google Test v1.17.0, and Intel XED `v2025.06.08`. Git is listed as a dependency with the latest version. The dependency table also shows `52e94563` on a row labeled Google Flags, although the linked repository is Google Log. For an exact dependency setup, the README points to `docs/DEPENDENCIES.md` as the source for the dependency management system.

This dependency boundary is a concrete adoption cost. A C++ developer may already have LLVM and Clang, but Remill still expects additional build inputs and a two-stage configuration process. The README does not document a package-manager installation for end users, so building from the repository is the documented acquisition path.

Building Remill with managed dependencies

Begin by cloning the repository and changing into its root. These are the exact clone commands documented in the README:

bash
git clone https://github.com/lifting-bits/remill
cd remill

On Linux and macOS, the default path configures the dependency superbuild. Ninja performs that build in the separate `dependencies/build` directory.

bash
cmake -G Ninja -S dependencies -B dependencies/build
cmake --build dependencies/build

After the dependency build completes, configure Remill in Release mode and direct CMake toward `dependencies/install`.

bash
cmake -G Ninja -B build -DCMAKE_PREFIX_PATH:PATH=$(pwd)/dependencies/install -DCMAKE_BUILD_TYPE=Release
cmake --build build

The repository's `build/` directory becomes the final Remill build directory. The README stops at compilation and does not provide a standalone executable command that accepts a binary and produces a complete LLVM module. Its first-use examples concern dependency installation and Doxygen generation. A binary analysis workflow therefore requires linking the library into downstream C++ code or using a documented downstream tool.

Reusing an external LLVM installation

Developers who already manage LLVM can use the documented `USE_EXTERNAL_LLVM` option instead of building the default LLVM dependency. On Linux, enable the option during the dependency stage, build that stage, and then configure Remill with its dependency prefix.

bash
cmake -G Ninja -S dependencies -B dependencies/build -DUSE_EXTERNAL_LLVM=ON
cmake --build dependencies/build

The main configuration then follows the documented Release build pattern.

bash
cmake -G Ninja -B build "-DCMAKE_PREFIX_PATH:PATH=$(pwd)/dependencies/install" -DCMAKE_BUILD_TYPE=Release
cmake --build build

For macOS, the README specifies Homebrew LLVM 17 and obtains its prefix with `brew --prefix llvm@17`. That prefix is passed to the dependency superbuild through `CMAKE_PREFIX_PATH:PATH`.

bash
brew install llvm@17
LLVM_PREFIX=$(brew --prefix llvm@17)
cmake -G Ninja -S dependencies -B dependencies/build -DUSE_EXTERNAL_LLVM=ON "-DCMAKE_PREFIX_PATH:PATH=$LLVM_PREFIX"
cmake --build dependencies/build

This option controls dependency sourcing rather than compatibility. LLVM 15 is the documented minimum, while the macOS example specifically uses LLVM 17.

Docker and experimental Windows build paths

The repository includes a `Dockerfile` for building against LLVM versions obtained from `apt.llvm.org`. Its defaults are `LLVM_VERSION=22` and `UBUNTU_VERSION=24.04`. The visible build stages install build tools, configure Git for version detection, obtain the LLVM prefix through `llvm-config-${LLVM_VERSION}`, and build dependencies with `USE_EXTERNAL_LLVM=ON`. The Dockerfile available for this article is truncated, so its complete command sequence and final image behavior cannot be established from that file.

Windows support is described as experimental. The README requires `clang-cl` and a Visual Studio developer prompt. Its dependency configuration sets both compilers to `clang-cl`.

bash
cmake -G Ninja -S dependencies -B dependencies/build -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
cmake --build dependencies/build

Afterward, the README configures Remill with the same compilers, `%CD%/dependencies/install` as its dependency prefix, and `Release` as the build type.

bash
cmake -G Ninja -B build -DCMAKE_PREFIX_PATH:PATH=%CD%/dependencies/install -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=Release
cmake --build build

Because Windows support is experimental, the build commands establish compilation prerequisites rather than a promise of identical behavior across all Remill dependencies and downstream tools.

Semantics, maintenance, and Apache-2.0 obligations

Remill's central technical commitment is instruction-level accuracy. Its design documentation and repository layout point toward a library with exposed APIs in `include/`, implementations in `lib/`, generated artifacts in `generated/`, and testing code under `tests/` and `test_runner_lib/`. The README does not publish a test command, coverage percentage, or supported instruction count, so those details should not be inferred from the repository layout.

The repository is not archived, and its last push was on 2026-08-27. The latest listed release is `v6.0.1`, published on 2026-04-21, following `v6.0.0` from 2025-11-06. These dates show recent repository activity, but an upgrading project still needs to check LLVM compatibility and run its own integration tests. The documented Intel XED revision and minimum tool versions are concrete version boundaries to compare during that work.

Remill uses the Apache-2.0 license, and the repository includes a `LICENSE` file. That file is the source for reviewing permissions, conditions, redistribution requirements, and notices. Its terms should be checked alongside the licenses of the LLVM, Clang, Google, and XED dependencies used in a particular build.

Editorial conclusion

Remill fits developers who need instruction-level LLVM IR semantics inside a larger static binary analysis tool, especially projects modeled on integrations such as McSema. It is a poor fit for users expecting a documented command that accepts a binary and emits a complete LLVM module, or for projects requiring mature AArch32 support. Check the required architecture, LLVM version, and semantics tests first, then confirm that a downstream tool can consume the generated IR correctly.

Frequently asked questions

Which machine-code architectures does Remill support?

The README lists AArch64, SPARC32, SPARC64, x86, and amd64, with AVX and AVX512 included for x86 and amd64. It describes AArch32 support as underway.

What are Remill's minimum LLVM and CMake requirements?

Remill requires LLVM 15 or newer and CMake 3.21 or newer. Ninja 1 or newer and Python 3 or newer are also listed dependencies.

Does Remill provide a documented command for converting a binary into LLVM bitcode?

No. The README documents building the library and positions Remill as a component for tools such as McSema rather than as a standalone binary conversion command.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. lifting-bits/remill on GitHub
  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/lifting-bits-remill.svg)](https://hysenlabs.com/projects/lifting-bits-remill)

Was this useful?