MESA infers program reachability by (1) extracting feasible control‑flow paths from LLVM IR and (2) minimizing an augmented weak‑distance objective over those paths. This page shows how to build and run MESA using Docker (recommended) and how to run it natively for development.
Download MESA
Download code from here.
Download sources from here.
The Docker workflow builds a ready‑to‑use environment with LLVM 14, glog, and Python dependencies.
Build the image (from the repository root):
./mydocker.sh build . # uses the Dockerfile in the repo (clang/LLVM 14)
Start a container with the repo mounted:
./mydocker.sh run . # drops you in /mnt inside the container
Inside the container you can now run the quickstart below.
Install prerequisites (Debian/Ubuntu example):
sudo apt-get update
sudo apt-get install -y clang-14 llvm-14 llvm-14-tools opt \
python3 python3-venv python3-dev python3-pip \
libgoogle-glog-dev libgtest-dev cmake graphviz jq
pip3 install numpy==2.0.1 scipy==1.13.1
# Build and install GoogleTest static libs (system packages sometimes omit them)
cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv lib/libgtest*.a /usr/local/lib
These are quickstart instructions using an example benchmark and the provided build scripts.
Provide a benchmark config (example under test_data/):
# choose one config, e.g., test_data/21_*/config.json
CONFIG=test_data/21_foo/config.json
Build the analysis artifact euler.so for this config:
make clean_euler # ensure a fresh build
make configfile="$CONFIG" euler.so
Generate path specifications:
make PATHS.txt
# Creates PATHS.txt based on LLVM passes (label_basic_blocks, find_paths)
Run the minimization driver:
python3 src/min.py
What you get
euler.so — the analysis shared library implementing the augmented objective and instrumentation hooks.PATHS.txt — the set of boolean branch decisions for each discovered path.REACHABLE if any path minimizes to 0).Intermediate IR artifacts helpful for debugging:
foo.ll (IR from the input C), label.ll (labeled blocks), foo_embed.ll (with __pen_* calls), foo_x.o, etc.Use the provided helper to iterate over many config.json files:
./run_newton.sh
The script times three phases for each config: (1) build euler.so, (2) compute PATHS.txt, and (3) run src/min.py. It prints per‑step and total CPU time.
If you want to exercise the call_to_block → label_basic_blocks → find_paths pipeline directly on a sample .ll file:
./quick_run.sh
This runs the three passes and ensures the outputs are created in test_data/challenge11/.
MESA reads parameters from config.json to control path search and entry/target selection. Typical keys include:
entry_func_name — entry function of the analysis (e.g., foo).target_func_name — reachability target (e.g., __logic_error_marker).max_number_paths, max_path_depth, max_call_stack_size — BFS bounds for path search.foo, foox, foo_inc — input sources for the benchmark (see the Makefile rules foo.c, foo_x.c, and foo.ll).euler_lib_flags — extra linker flags when producing euler.so.You can switch benchmarks by passing configfile=<path> to make, which copies it to ./config.json and records the source path.
src/ and compile to loadable .so files: label_basic_blocks.so, find_paths.so, get_types.so, embed.so, call_to_block.so.make euler.so links src/pen.o, foo_embed.ll, and foo_x.o into the runtime library used by min.py.make PATHS.txt runs opt with the analysis passes to materialize the boolean path file consumed by the minimizer.src/min.py uses ctypes to load euler.so and Scipy’s basinhopping to minimize the objective over each path.By default it expects ./euler.so and ./PATHS.txt. You can point to alternates:
python3 src/min.py --euler ./euler.so --paths ./PATHS.txt --dimension 1
“cannot open shared object file” when loading euler.so
.so matches your CPU architecture: file ./euler.so should say x86-64 if you’re on x86‑64.If you previously built for a different arch, clean and rebuild:
make clean_euler && make clean
make configfile="$CONFIG" euler.so
Linker says Relocations in generic ELF (EM: 183) or file in wrong format
ldd ./euler.so shows missing deps
Install the required libs (inside Docker they’re preinstalled):
sudo apt-get install -y libstdc++6 libgoogle-glog0v5 libgflags2.2
If you use custom prefixes, update the runtime path:
export LD_LIBRARY_PATH=/usr/local/lib:/usr/lib:$LD_LIBRARY_PATH
sudo ldconfig
Pass pipeline didn’t create PATHS.txt
Re‑run labeling and find‑paths on a fresh IR:
rm -f foo.ll foo_embed.ll label.ll PATHS.txt
make PATHS.txt
Check config.json for entry_func_name / target_func_name correctness.
Verbose C++ logging
min.py initializes glog at WARNING level. For deeper debugging, change the level or call init_glog differently in src/min.py.euler.so, and PATHS.txt; helpers clean_euler, test, etc.build and run helpers for Docker..ll.test_data/*/config.json.euler() per path.# Prereqs
sudo apt-get update && sudo apt-get install -y \
clang-14 llvm-14 llvm-14-tools opt libgoogle-glog-dev libgtest-dev cmake \
python3 python3-dev python3-pip graphviz jq && \
pip3 install numpy==2.0.1 scipy==1.13.1 && \
(cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv lib/libgtest*.a /usr/local/lib)
# Build and run a benchmark
make clean_euler && make clean
make configfile=test_data/21_foo/config.json euler.so
make PATHS.txt
python3 src/min.py
Last updated: 2025‑10‑13.