Compile whole‐program LLVM bitcode files via rllvm - SVF-tools/SVF GitHub Wiki
rllvm builds a project as usual through compiler wrappers, then extracts one .bc for the whole program, like gllvm and wllvm. It needs no environment variables, and it also captures Rust and mixed C/Rust programs.
1. Install
# on macOS or Linux with Homebrew
brew install h1994st/tap/rllvm
# or build from source via cargo
cargo install rllvm
After this, we have the rllvm commands including rllvm-cc, rllvm-cxx, rllvm-rustc, rllvm-get-bc, rllvm-info and rllvm-init.
2. Choose the LLVM
On first run, rllvm detects LLVM from llvm-config and writes ~/.rllvm/config.toml. To use a specific LLVM, such as the one the bitcode's reader was built with ($LLVM_DIR after SVF's build.sh):
rllvm-init --llvm-prefix $LLVM_DIR
Add --dry-run to print what was detected without writing it. A reader handles bitcode from its own LLVM version and older.
3. Compile and extract bc
Set CC=rllvm-cc and CXX=rllvm-cxx, build as usual, then extract the bitcode from the finished binary:
# Makefile
CC=rllvm-cc make
rllvm-get-bc program # output: program.bc
# CMake
CC=rllvm-cc CXX=rllvm-cxx cmake -S . -B build
cmake --build build
rllvm-get-bc build/program # output: build/program.bc
Extra compiler flags pass through the wrappers, such as the ones the other examples on this wiki use:
export CC="rllvm-cc -O0 -Xclang -disable-O0-optnone -g -fno-discard-value-names"
export CXX="rllvm-cxx -O0 -Xclang -disable-O0-optnone -g -fno-discard-value-names"
make
rllvm-info program.bc prints the target and the function, block and instruction counts.
4. Rust and mixed C/Rust programs
CC=rllvm-cc CXX=rllvm-cxx RUSTC_WRAPPER=rllvm-rustc cargo build
rllvm-get-bc target/debug/program
C and C++ dependencies built by the crate go through CC=rllvm-cc CXX=rllvm-cxx as well, and land in the same module. The Rust standard library is prebuilt and contributes no bitcode. The configured LLVM must be at least as new as the one rustc -vV reports.
5. Examples
SVF
Please check SVF example in rllvm repo to learn more details on how to extract SVF whole-program bitcode, which also has a reproducible script running in Docker
Validated with SVF f3f09503 and LLVM 22.1.8 on Ubuntu.
git clone https://github.com/SVF-tools/SVF
cd SVF
git checkout f3f09503
apt-get install -y libz3-dev zlib1g-dev libzstd-dev libncurses-dev
rllvm-init --llvm-prefix /usr/lib/llvm-22
CC=rllvm-cc CXX=rllvm-cxx cmake -S . -B build \
-G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR=/usr/lib/llvm-22 \
-DBUILD_SHARED_LIBS=OFF -DSVF_WARN_AS_ERROR=OFF
cmake --build build
rllvm-get-bc build/bin/wpa -o wpa.bc
Static libraries put all of SVF into wpa, so one extraction yields the whole tool: 3351 functions.
nghttp2
nghttp2 repo: https://github.com/nghttp2/nghttp2
Please check nghttp2 example in rllvm repo to learn more details, which also covers nghttp3 and ngtcp2
git clone https://github.com/nghttp2/nghttp2
cd nghttp2
git checkout 140157a8
CC=rllvm-cc CXX=rllvm-cxx cmake -S . -B build \
-G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_LIB_ONLY=ON \
-DBUILD_TESTING=OFF -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF
cmake --build build
rllvm-get-bc build/lib/libnghttp2.a -o nghttp2.bc
We get the library's 469 functions at this step.
quiche (Rust + C++), Cloudflare's QUIC library
quiche repo: https://github.com/cloudflare/quiche
Please check quiche example in rllvm repo to learn more details, including how BoringSSL, built by quiche's build script, is captured
git clone --recursive https://github.com/cloudflare/quiche
cd quiche
git checkout 4d23d859
git submodule update --init --recursive
CC=rllvm-cc CXX=rllvm-cxx RUSTC_WRAPPER=rllvm-rustc cargo build --release -p quiche
rllvm-get-bc target/release/libquiche.a -o quiche.bc
One module with the Rust crates and BoringSSL's C and C++: 7376 functions.
Run cargo clean first if quiche was built before without the wrappers: Cargo does not rebuild BoringSSL when only the compilers change.