Installation¶
xollvm ships three ways from one source tree, with no edits to any LLVM file:
| Target | Mechanism | Platforms |
|---|---|---|
| clang/opt toolchain (obfuscator built in) | LLVM static extension (LLVM_EXTERNAL_PROJECTS + LINK_INTO_TOOLS) |
Linux · Windows · macOS |
loadable plugin Obfuscator.so |
standalone build against installed LLVM (-fpass-plugin) |
Linux · macOS |
Windows & loadable plugins
Loadable pass plugins need the host LLVM built with -DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON,
which prebuilt toolchains don't ship. On Windows, use the static extension — the pass is
compiled straight into clang/opt.
Prebuilt releases¶
If you just want binaries, skip building — grab a release:
| File | What | OS |
|---|---|---|
xollvm-linux-Release.tar.zst |
clang/opt with the obfuscator built in |
Linux x86_64 |
xollvm-windows-Release.7z |
clang/opt with the obfuscator built in |
Windows x64 |
Obfuscator-linux-x64.so |
loadable -fpass-plugin |
Linux x86_64 |
Backends included: X86 · AArch64 · ARM · RISCV.
Prerequisites¶
Common to every build:
- CMake ≥ 3.20
- Ninja (recommended generator)
- Python 3 (generates the AES stub bitcode header)
- A C++17 compiler
- git
Mode-specific:
| Build | Also needs |
|---|---|
| Static extension | A checkout of stock LLVM (release/22.x or release/23.x) and an external clang on PATH (see below) |
| Loadable plugin | An installed LLVM 22 or 23 with CMake config + dev headers (llvm-22-dev / llvm-23-dev) and clang-22 / clang-23 |
LLVM 22 and 23
xollvm builds against both LLVM 22 and 23 from the same sources — the version is detected at
compile time (LLVM_VERSION_MAJOR), no flags to flip. Every command below that pins release/22.x
works identically with release/23.x. Changes are validated against both before release.
Why an external clang? (static extension only)
The AES runtime stub is compiled to LLVM bitcode by clang. When the obfuscator is linked
into the tools (LINK_INTO_TOOLS), it cannot use the in-tree clang being built — that
would form a dependency cycle (clang → LLVMExtensions → Obfuscator → aes → clang). So the
build uses a separate, already-installed clang found on PATH. Any reasonably recent
clang works; the LLVM 22/23 you build reads its (older) bitcode.
- Linux:
sudo apt-get install -y clang - Windows:
choco install llvm(givesC:\Program Files\LLVM\bin\clang.exe) - macOS: the Xcode/Homebrew
clangonPATH
Static extension (toolchain)¶
Builds clang, opt, etc. with the obfuscator compiled in. The three obfuscator flags are the
whole integration:
LLVM_EXTERNAL_PROJECTS=Obfuscator— register xollvm as an external LLVM projectLLVM_EXTERNAL_OBFUSCATOR_SOURCE_DIR=<xollvm dir>— where itsCMakeLists.txtlivesLLVM_OBFUSCATOR_LINK_INTO_TOOLS=ON— statically link it intoclang/opt
git clone --depth 1 --branch release/22.x https://github.com/llvm/llvm-project # or release/23.x
git clone https://github.com/und3ath/xollvm
sudo apt-get install -y ninja-build cmake python3 clang # external clang for the aes stub
cmake -S llvm-project/llvm -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_PROJECTS="llvm;clang" \
-DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_EH=ON \
-DLLVM_TARGETS_TO_BUILD="X86;AArch64;ARM;RISCV" \
-DLLVM_INCLUDE_TESTS=OFF -DLLVM_BUILD_TESTS=OFF \
-DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_BUILD_BENCHMARKS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF \
-DCLANG_INCLUDE_TESTS=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF \
-DLLVM_ENABLE_ASSERTIONS=OFF \
-DLLVM_DISTRIBUTION_COMPONENTS="clang;clang-resource-headers;opt" \
-DLLVM_EXTERNAL_PROJECTS=Obfuscator \
-DLLVM_EXTERNAL_OBFUSCATOR_SOURCE_DIR="$PWD/xollvm" \
-DLLVM_OBFUSCATOR_LINK_INTO_TOOLS=ON \
-DCMAKE_INSTALL_PREFIX="$PWD/install"
# install-distribution builds ONLY the shipped components (clang, opt + libs),
# not the ~40 other standalone llvm-* tools — a big time saving.
cmake --build build --target install-distribution
From an x64 Native Tools developer prompt (after choco install llvm ninja):
git clone --depth 1 --branch release/22.x https://github.com/llvm/llvm-project REM or release/23.x
git clone https://github.com/und3ath/xollvm
cmake -S llvm-project\llvm -B build -G Ninja ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL ^
-DLLVM_ENABLE_PROJECTS="llvm;clang" ^
-DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_EH=ON ^
-DLLVM_TARGETS_TO_BUILD="X86;AArch64;ARM;RISCV" ^
-DLLVM_INCLUDE_TESTS=OFF -DLLVM_BUILD_TESTS=OFF ^
-DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_BUILD_BENCHMARKS=OFF ^
-DLLVM_INCLUDE_EXAMPLES=OFF ^
-DCLANG_INCLUDE_TESTS=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_ENABLE_ARCMT=OFF ^
-DLLVM_ENABLE_ASSERTIONS=OFF ^
-DLLVM_PARALLEL_LINK_JOBS=1 ^
-DLLVM_DISTRIBUTION_COMPONENTS="clang;clang-resource-headers;opt" ^
-DLLVM_EXTERNAL_PROJECTS=Obfuscator ^
-DLLVM_EXTERNAL_OBFUSCATOR_SOURCE_DIR=%CD%\xollvm ^
-DLLVM_OBFUSCATOR_LINK_INTO_TOOLS=ON ^
-DCMAKE_INSTALL_PREFIX=%CD%\install
cmake --build build --target install-distribution
LLVM_PARALLEL_LINK_JOBS=1 keeps peak RAM sane during the big links.
Tip
Trim LLVM_TARGETS_TO_BUILD to just what you need (e.g. X86) for a much faster build. Want
the full toolchain (llvm-*, lld, …)? Drop LLVM_DISTRIBUTION_COMPONENTS and build
--target install instead — slower and much larger.
Loadable plugin¶
Builds only the pass, against an installed LLVM 22 or 23. No LLVM source build — fast.
(The example below uses 22; substitute 23 throughout for an LLVM 23 install.)
# Ubuntu 24.04 lacks clang-22/llvm-22 in default repos; add apt.llvm.org:
wget -qO llvm.sh https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 22
sudo apt-get install -y ninja-build clang-22 llvm-22 llvm-22-dev
git clone https://github.com/und3ath/xollvm
cmake -S xollvm -B build -G Ninja \
-DLLVM_DIR=/usr/lib/llvm-22/lib/cmake/llvm \
-DCMAKE_C_COMPILER=clang-22 -DCMAKE_CXX_COMPILER=clang++-22 \
-DCMAKE_BUILD_TYPE=Release
ninja -C build Obfuscator # -> build/Obfuscator.so
On distros that already ship LLVM 22 (e.g. Ubuntu 26.04) the llvm.sh step is unnecessary — just
apt-get install llvm-22-dev clang-22.
Verify the build¶
cat > ann.c <<'EOF'
#define OBF(spec) __attribute__((annotate("obf: " spec)))
OBF("mba, bcf, split")
int secret(int x){ int a=x*3+7; for(int i=0;i<x;i++) a+=(i^a); return a; }
EOF
clang -O0 -emit-llvm -S ann.c -o ann.ll
@secret should grow substantially; an unannotated function is left untouched.
Troubleshooting¶
| Symptom | Cause / fix |
|---|---|
Unable to locate package clang-22 / llvm-22-dev |
Ubuntu 24.04 default repos lack LLVM 22. Add apt.llvm.org: sudo ./llvm.sh 22. |
fatal error: aes_stub_bc.inc: No such file |
AES stub header not generated before compile. Build with the current CMakeLists.txt; reconfigure from clean. |
aes stub: external clang not found |
No clang on PATH for the stub. Install one — the in-tree clang can't be used under LINK_INTO_TOOLS. |
| dependency-cycle error at configure | The aes stub picked the in-tree clang. Ensure an external clang is found first, or that LLVM_OBFUSCATOR_LINK_INTO_TOOLS=ON is set. |
-load-pass-plugin aborts on Windows |
Loadable plugins aren't supported on Windows. Use the static extension. |
Option '…' registered more than once |
A second copy of LLVM's global state. Don't static-link LLVM into the .so. |