mirror of
https://github.com/lifting-bits/mcsema
synced 2026-06-08 15:31:09 +00:00
267 lines
7.8 KiB
Bash
Executable File
267 lines
7.8 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Build and install KLEE.
|
|
#
|
|
set -euo pipefail
|
|
|
|
LLVM_VER=10
|
|
CXX_COMMON_VER=0.1.4
|
|
KLEE_UCLIBC_VER=1.2
|
|
KLEE_VER=2.2
|
|
|
|
OCWD="$(pwd -P)"
|
|
SCRIPT_DIR="$(dirname $(realpath ${BASH_SOURCE[0]}))"
|
|
BUILD_DIR="$(dirname "$SCRIPT_DIR")/build"
|
|
INSTALL_DIR="$(dirname "$SCRIPT_DIR")/installed"
|
|
|
|
export MAKEFLAGS="-j$(nproc)"
|
|
|
|
msg() {
|
|
echo -e "[+] ${1-}" >&2
|
|
}
|
|
|
|
die() {
|
|
echo -e "[!] ${1-}" >&2
|
|
exit 1
|
|
}
|
|
|
|
get_distro() {
|
|
if test -f /etc/os-release; then # freedesktop.org and systemd
|
|
. /etc/os-release
|
|
echo $NAME | cut -f 1 -d ' ' | tr '[:upper:]' '[:lower:]'
|
|
elif type lsb_release >/dev/null 2>&1; then # linuxbase.org
|
|
lsb_release -si | tr '[:upper:]' '[:lower:]'
|
|
elif test -f /etc/lsb-release; then
|
|
. /etc/lsb-release
|
|
echo "$DISTRIB_ID" | tr '[:upper:]' '[:lower:]'
|
|
elif test -f /etc/arch-release; then
|
|
echo "arch"
|
|
elif test -f /etc/debian_version; then
|
|
# Older Debian, Ubuntu
|
|
echo "debian"
|
|
elif test -f /etc/SuSe-release; then
|
|
# Older SuSE
|
|
echo "opensuse"
|
|
elif test -f /etc/fedora-release; then
|
|
# Older Fedora
|
|
echo "fedora"
|
|
elif test -f /etc/redhat-release; then
|
|
# Older Red Hat, CentOS
|
|
echo "centos"
|
|
elif type uname >/dev/null 2>&1; then
|
|
# Fall back to uname
|
|
echo "$(uname -s)"
|
|
else
|
|
die "Unable to determine the distribution"
|
|
fi
|
|
}
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
[!] Usage: $(basename "${BASH_SOURCE[0]}") [-h] [-v] [--llvm LLVM_version]
|
|
|
|
Build and install KLEE.
|
|
|
|
Available options:
|
|
|
|
-h, --help Print this help and exit
|
|
-v, --verbose Print script debug info
|
|
--llvm Specify LLVM version (9 or 10, default: 10)
|
|
EOF
|
|
}
|
|
|
|
parse_params() {
|
|
while :; do
|
|
case "${1-}" in
|
|
-h | --help) usage; exit ;;
|
|
-v | --verbose) set -x ;;
|
|
--llvm)
|
|
LLVM_VER="${2-}"
|
|
if [ "$LLVM_VER" != "9" -a "$LLVM_VER" != "10" ]; then
|
|
die "Invalid LLVM version: $LLVM_VER\n$(usage)"
|
|
fi
|
|
shift
|
|
;;
|
|
--libcxx) LIBCXX=1 ;; # enable KLEE_LIBCXX
|
|
-?*) die "Unknown option: $1\n$(usage)" ;;
|
|
*) break ;;
|
|
esac
|
|
shift
|
|
done
|
|
}
|
|
|
|
install_cxx_common() {
|
|
pushd "$BUILD_DIR" >/dev/null
|
|
URL="https://github.com/lifting-bits/cxx-common/releases/download/v${CXX_COMMON_VER}/vcpkg_ubuntu-20.04_llvm-${LLVM_VER}_amd64.tar.xz"
|
|
FILE="$(basename "$URL")"
|
|
if [ ! -f "$FILE" ]; then
|
|
msg "Downloading cxx-common..."
|
|
curl -LO "$URL"
|
|
fi
|
|
msg "Extracting cxx-common..."
|
|
tar xf $FILE
|
|
mv vcpkg_ubuntu-20.04_llvm-${LLVM_VER}_amd64 "$INSTALL_DIR/cxx-common"
|
|
popd >/dev/null
|
|
}
|
|
|
|
install_klee_uclibc() {
|
|
vcpkg_prefix="$INSTALL_DIR/cxx-common/installed/x64-linux-rel"
|
|
export PATH="$vcpkg_prefix/bin:${PATH}"
|
|
export CC="$vcpkg_prefix/bin/clang"
|
|
export CXX="$vcpkg_prefix/bin/clang++"
|
|
|
|
pushd "$BUILD_DIR" >/dev/null
|
|
URL="https://github.com/klee/klee-uclibc/archive/klee_uclibc_v${KLEE_UCLIBC_VER}.tar.gz"
|
|
FILE="$(basename "$URL")"
|
|
if [ ! -f "$FILE" ]; then
|
|
msg "Downloading klee-uclibc..."
|
|
curl -LO "$URL"
|
|
fi
|
|
msg "Extracting klee-uclibc..."
|
|
tar xf $FILE
|
|
|
|
srcdir="$BUILD_DIR/klee-uclibc-klee_uclibc_v${KLEE_UCLIBC_VER}"
|
|
pkgdir="$INSTALL_DIR/klee-uclibc"
|
|
pushd "$srcdir" >/dev/null
|
|
msg "Building klee-uclibc..."
|
|
"$srcdir"/configure --make-llvm-lib --with-cc="$CC"
|
|
sed -i "$srcdir"/.config \
|
|
-e "s|DEVEL_PREFIX=\"[^\"]*\"|DEVEL_PREFIX=\"$pkgdir/usr\"|" \
|
|
-e "s|RUNTIME_PREFIX=\"[^\"]*\"|RUNTIME_PREFIX=\"$pkgdir/usr\"|"
|
|
make
|
|
msg "Installing klee-uclibc..."
|
|
make install
|
|
popd >/dev/null
|
|
popd >/dev/null
|
|
}
|
|
|
|
install_klee() {
|
|
vcpkg_prefix="$INSTALL_DIR/cxx-common/installed/x64-linux-rel"
|
|
export PATH="$vcpkg_prefix/bin:${PATH}"
|
|
export CC="$vcpkg_prefix/bin/clang"
|
|
export CXX="$vcpkg_prefix/bin/clang++"
|
|
|
|
pushd "$BUILD_DIR" >/dev/null
|
|
URL="https://github.com/klee/klee/archive/v${KLEE_VER}.tar.gz"
|
|
FILE="$(basename "$URL")"
|
|
if [ ! -f "$FILE" ]; then
|
|
msg "Downloading klee..."
|
|
curl -LO "$URL"
|
|
fi
|
|
msg "Extracting klee..."
|
|
tar xf $FILE
|
|
URL="https://github.com/google/googletest/archive/release-1.10.0.tar.gz"
|
|
FILE="$(basename "$URL")"
|
|
if [ ! -f "$FILE" ]; then
|
|
msg "Downloading googletest..."
|
|
curl -LO "$URL"
|
|
fi
|
|
msg "Extracting googletest..."
|
|
tar xf $FILE
|
|
msg "Copying KLEE patches..."
|
|
cp "$SCRIPT_DIR/00-ret-void.patch" "$BUILD_DIR"
|
|
cp "$SCRIPT_DIR/01-skip-Z3_get_error_msg-check.patch" "$BUILD_DIR"
|
|
|
|
srcdir="$BUILD_DIR/klee-${KLEE_VER}"
|
|
gtestdir="$BUILD_DIR/googletest-release-1.10.0/googletest"
|
|
pkgdir="$INSTALL_DIR/klee"
|
|
pushd "$srcdir" >/dev/null
|
|
msg "Patching klee..."
|
|
patch -Np1 -i "$BUILD_DIR/00-ret-void.patch"
|
|
patch -Np1 -i "$BUILD_DIR/01-skip-Z3_get_error_msg-check.patch"
|
|
mkdir -p "$srcdir/build"
|
|
pushd "$srcdir/build" >/dev/null
|
|
msg "Building klee..."
|
|
cmake \
|
|
-DCMAKE_C_COMPILER="$CC" \
|
|
-DCMAKE_CXX_COMPILER="$CXX" \
|
|
-DENABLE_TCMALLOC=ON \
|
|
-DENABLE_POSIX_RUNTIME=ON \
|
|
-DENABLE_KLEE_UCLIBC=ON \
|
|
-DKLEE_UCLIBC_PATH="$INSTALL_DIR/klee-uclibc/usr" \
|
|
-DENABLE_SOLVER_Z3=ON \
|
|
-DENABLE_SOLVER_STP=OFF \
|
|
-DENABLE_SOLVER_METASMT=OFF \
|
|
-DZ3_INCLUDE_DIRS="$vcpkg_prefix/include" \
|
|
-DZ3_LIBRARIES="$vcpkg_prefix/lib/libz3.a" \
|
|
-DCMAKE_INSTALL_PREFIX="$INSTALL_DIR/klee/usr" \
|
|
-DCMAKE_INSTALL_LIBDIR="$INSTALL_DIR/klee/usr/lib" \
|
|
-DCMAKE_BUILD_TYPE=Release \
|
|
-DGTEST_SRC_DIR="$gtestdir" \
|
|
-DENABLE_UNIT_TESTS=ON \
|
|
-DENABLE_SYSTEM_TESTS=ON \
|
|
-DCMAKE_VERBOSE_MAKEFILE=True \
|
|
"$srcdir"
|
|
make
|
|
msg "Testing klee..."
|
|
make systemtests
|
|
msg "Installing klee..."
|
|
make install
|
|
popd >/dev/null
|
|
popd >/dev/null
|
|
popd >/dev/null
|
|
}
|
|
|
|
main() {
|
|
parse_params $@
|
|
|
|
if [ -e "$INSTALL_DIR" ]; then
|
|
while true; do
|
|
echo -n "'$INSTALL_DIR' exists. Remove it? [Y/n] "
|
|
read remove
|
|
remove="$(echo "$remove" | tr '[:upper:]' '[:lower:]')"
|
|
[ -z "${remove##y*}" ] && \
|
|
{ rm -rf "$INSTALL_DIR"; break; }
|
|
[ -z "${remove##n*}" ] && \
|
|
die "'$INSTALL_DIR' exists"
|
|
done
|
|
fi
|
|
mkdir -p "$BUILD_DIR" "$INSTALL_DIR"
|
|
|
|
DISTRO="$(get_distro)"
|
|
msg "LLVM version: $LLVM_VER"
|
|
msg "cxx-common version: $CXX_COMMON_VER"
|
|
msg "KLEE-uclibc version: $KLEE_UCLIBC_VER"
|
|
msg "KLEE version: $KLEE_VER"
|
|
msg "Build location: $BUILD_DIR"
|
|
msg "Install location: $INSTALL_DIR"
|
|
msg "Detected distribution: $DISTRO"
|
|
|
|
if [ "$DISTRO" = "arch" ]; then
|
|
makedepends=(base-devel curl git cmake wget)
|
|
depends=(libcap sqlite gperftools zlib python python-tabulate
|
|
lib32-glibc lib32-gcc-libs)
|
|
msg "Installing dependencies..."
|
|
sudo pacman -Syq --needed --noconfirm --asdeps ${makedepends[@]} ${depends[@]}
|
|
|
|
elif [ "$DISTRO" = "ubuntu" ]; then
|
|
depends=(build-essential liblzma-dev libssl-dev curl libtinfo-dev
|
|
ccache libncurses5-dev libncursesw5-dev libarchive-tools)
|
|
depends+=(python3 wget) # klee-uclibc
|
|
depends+=(libcap-dev libsqlite3-dev libgoogle-perftools-dev zlib1g-dev
|
|
python3 python3-pip python3-tabulate gcc-multilib g++-multilib
|
|
git cmake) # klee-git
|
|
msg "Installing dependencies..."
|
|
sudo apt update -y -qq
|
|
sudo apt install -y -qq ${depends[@]}
|
|
pip3 install "lit==0.${LLVM_VER}.0"
|
|
if ! command -v python >/dev/null 2>&1; then
|
|
sudo ln -s "$(which python3)" /usr/bin/python
|
|
fi
|
|
|
|
else
|
|
die "Unsupported distribution: $DISTRO"
|
|
fi
|
|
|
|
install_cxx_common
|
|
install_klee_uclibc
|
|
install_klee
|
|
|
|
msg "DONE"
|
|
}
|
|
|
|
|
|
main $@
|
|
|
|
# vim: set ts=4 sw=4 et:
|