Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SymCC Runtime Integration #55

Merged
merged 19 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
build
.git
27 changes: 14 additions & 13 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
on:
workflow_dispatch:
push:
pull_request:

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: git submodule update --init --recursive symcc
- run: docker build -t symcc symcc
- run: docker build -t symqemu .
on:
workflow_dispatch:
push:
pull_request:
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: git submodule update --init --recursive subprojects/symcc-rt
# build and test with default LLVM version 15
- run: docker build -t symqemu .
# LLVM version 14
- run: docker build --build-arg LLVM_VERSION=14 -t symqemu .
7 changes: 4 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
[submodule "tests/lcitool/libvirt-ci"]
path = tests/lcitool/libvirt-ci
url = https://gitlab.com/libvirt/libvirt-ci.git
[submodule "symcc"]
path = symcc
url = https://github.com/eurecom-s3/symcc.git
[submodule "subprojects/symcc-rt"]
path = subprojects/symcc-rt
url = https://github.com/eurecom-s3/symcc-rt.git
branch = main
55 changes: 33 additions & 22 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,47 +1,58 @@
# prepare machine
FROM ubuntu:22.04 as builder

RUN apt update
RUN apt install -y \
RUN apt update && apt install -y \
ninja-build \
libglib2.0-dev \
llvm \
git \
python3 \
python3-pip

#
FROM builder as symqemu
python3-pip \
cmake \
wget \
lsb-release \
software-properties-common \
gnupg \
z3 \
libz3-dev \
libz3-dev \
libzstd-dev

RUN pip install --user meson

# This is passed along to symcc and qsym backend
arg LLVM_VERSION=15

# installing/building with the right LLVM version, currently:
# - no plan to support < 11
# - 12 to 15 are in official packages,
# - 16 and 17 provided by llvm.org
# - TODO 18 should be fixed
RUN if [ $LLVM_VERSION -le 11 ]; then echo "LLVM <= 11 not supported" ; false ;fi
RUN if [ $LLVM_VERSION -ge 18 ]; then echo "LLVM >= 18 currently not supported" ; false ;fi
RUN if [ $LLVM_VERSION -eq 12 ] || [ $LLVM_VERSION -eq 13 ] || [ $LLVM_VERSION -eq 14 ] || [ $LLVM_VERSION -eq 15 ]; then \
apt install -y llvm-${LLVM_VERSION} clang-${LLVM_VERSION} ; \
else mkdir /llvm && cd /llvm && wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh ${LLVM_VERSION}; \
fi

COPY . /symqemu_source
WORKDIR /symqemu_source

# Meson gives an error if symcc is in a subdirectory of symqemu
RUN mv /symqemu_source/symcc /symcc

# The only symcc artifact needed by symqemu is libSymRuntime.so
# Instead of compiling symcc in this image, we rely on the existing symcc docker image and
# we just copy libSymRuntime.so at the location where symqemu expects it
COPY --from=symcc /symcc_build/SymRuntime-prefix/src/SymRuntime-build/libSymRuntime.so /symcc/build/SymRuntime-prefix/src/SymRuntime-build/libSymRuntime.so

RUN ./configure \
RUN mkdir build && cd build && ../configure \
--audio-drv-list= \
--disable-sdl \
--disable-gtk \
--disable-vte \
--disable-opengl \
--disable-virglrenderer \
--disable-werror \
--target-list=x86_64-linux-user,riscv64-linux-user \
--target-list=x86_64-linux-user,riscv64-linux-user \
--enable-debug \
--symcc-source=/symcc \
--symcc-build=/symcc/build \
--enable-debug-tcg \
--enable-werror
--symcc-rt-llvm-version="$LLVM_VERSION"

RUN make -j
RUN cd build && make -j

RUN make check
RUN cd build && make check

WORKDIR /symqemu_source/tests/symqemu
RUN python3 -m unittest test.py
85 changes: 37 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,25 @@

This is SymQEMU, a binary-only symbolic executor based on QEMU and SymCC. It
currently extends QEMU 8.1 and works with the most recent version of SymCC.
(See README.orig for QEMU's original README file.)
A separate branch is available for the [old version of SymQEMU based on QEMU 4.1.1](https://github.com/eurecom-s3/symqemu/tree/4.1.1) we don't expect much
(See README.orig for QEMU's original README file.) A separate branch is
available for the [old version of SymQEMU based on QEMU
4.1.1](https://github.com/eurecom-s3/symqemu/tree/4.1.1) we don't expect much
changes to happen there, but PR may be accepted.

## How to build

SymQEMU requires [SymCC](https://github.com/eurecom-s3/symcc), so please
download and build SymCC first. For best results, configure it with the QSYM
backend as explained in the README. For the impatient, here's a quick summary of
the required steps that may or may not work on your system:
First of all, make sure the
[symcc-rt](https://github.com/eurecom-s3/symcc-rt.git) submodule is initialized:

``` shell
$ git clone https://github.com/eurecom-s3/symcc.git
$ cd symcc
$ git submodule update --init
$ mkdir build
$ cd build
$ cmake -G Ninja -DQSYM_BACKEND=ON ..
$ ninja
$ git submodule update --init --recursive subprojects/symcc-rt
```

Next, make sure that QEMU's build dependencies are installed. Most package
managers provide a command to get them, e.g., `apt build-dep qemu` on Debian and
Ubuntu, or `dnf builddep qemu` on Fedora and CentOS.
Make sure that QEMU's build dependencies are installed. Most package managers
provide a command to get them, e.g., `apt build-dep qemu` on Debian and Ubuntu,
or `dnf builddep qemu` on Fedora and CentOS.

We've extended QEMU's configuration script to accept pointers to SymCC's source
and binaries. The following invocation is known to work on Debian 10, Arch and
Fedora 33:
The following invocation is known to work on Ubuntu 22.04 and Arch:

``` shell
$ mkdir build
Expand All @@ -42,9 +33,7 @@ $ ../configure \
--disable-opengl \
--disable-virglrenderer \
--disable-werror \
--target-list=x86_64-linux-user \
--symcc-source=../symcc \
--symcc-build=../symcc/build
--target-list=x86_64-linux-user
$ make -j
```

Expand All @@ -54,6 +43,15 @@ target architectures is possible in principle but will require a bit of work
because the current implementation assumes that we can pass around host pointers
in guest registers.

## SymQEMU compilation options

Several compilation options are available:
- `enable-symcc-shared`: Compile SymQEMU with the shared library of `SymCC
Runtime` instead of a static library.
- `symcc-backend`: Choose a specific backend from `SymCC Runtime`. Please have a
look at [symcc-rt](https://github.com/eurecom-s3/symcc-rt.git) to get an
exhaustive list of available backends.

## Running SymQEMU

If you built SymQEMU as described above, the binary will be in
Expand Down Expand Up @@ -84,23 +82,14 @@ This is a very basic use of symbolic execution. See SymCC's documentation for
more advanced scenarios. Since SymQEMU is based on it, it understands all the
same
[settings](https://github.com/eurecom-s3/symcc/blob/master/docs/Configuration.txt),
and you can even run SymQEMU with `symcc_fuzzing_helper` for [hybrid fuzzing](https://github.com/eurecom-s3/symcc/blob/master/docs/Fuzzing.txt): just
and you can even run SymQEMU with `symcc_fuzzing_helper` for [hybrid
fuzzing](https://github.com/eurecom-s3/symcc/blob/master/docs/Fuzzing.txt): just
prefix the target command with `x86_64-linux-user/symqemu-x86_64`. (Note that
you'll have to run AFL in QEMU mode by adding `-Q` to its command line; the
fuzzing helper will automatically pick up the setting and use QEMU mode too.)

## Build with Docker
First, make sure to have an up-to-date Docker image of SymCC. If you
don't have one, either in the submodule, run:

``` shell
git submodule update --init --recursive symcc
cd symcc
docker build -t symcc .
cd ..
```

Then build the SymQEMU image with (this will also run the tests):
Build the SymQEMU image with (this will also run the tests):
```shell
docker build -t symqemu .
```
Expand Down Expand Up @@ -146,23 +135,23 @@ Also, refer to [QEMU's own tests suite documentation](https://www.qemu.org/docs/

## Documentation

The [paper](http://www.s3.eurecom.fr/tools/symbolic_execution/symqemu.html) contains
details on how SymQEMU works. A large part of the implementation is the run-time support
in `accel/tcg/tcg-runtime-sym.{c,h}` and `accel/tcg/tcg-runtime-sym-vec.{c,h}` (which
delegates any actual symbolic computation to SymCC's symbolic backend), and we have
modified most code-generating functions in `tcg/tcg-op.c`, `tcg/tcg-op-vec.c` and
The [paper](http://www.s3.eurecom.fr/tools/symbolic_execution/symqemu.html)
contains details on how SymQEMU works. A large part of the implementation is the
run-time support in `accel/tcg/tcg-runtime-sym.{c,h}` and
`accel/tcg/tcg-runtime-sym-vec.{c,h}` (which delegates any actual symbolic
computation to SymCC's symbolic backend), and we have modified most
code-generating functions in `tcg/tcg-op.c`, `tcg/tcg-op-vec.c` and
`include/tcg/tcg-op-common.h` to emit calls to the runtime.

For development, configure with `--enable-debug` for run-time assertions; there are tests
for the symbolic run-time support in `tests/check-sym-runtime.c`.
For development, configure with `--enable-debug` for run-time assertions; there
are tests for the symbolic run-time support in `tests/check-sym-runtime.c`.

More information about the port to QEMU 8 and internals of (Sym)QEMU
can be found in the QEMU 8 merge commit message
[23e570bf42](https://github.com/eurecom-s3/symqemu/commit/23e570bf42531bcac66a54283eafd4c9c233891a) which
gives some information about the adaptations performed. There are also
some detailed explanations about potential problems in section 5.1 of
Damien Maier's [bachelor
thesis](https://dmaier.ch/bachelor-thesis.pdf).
More information about the port to QEMU 8 and internals of (Sym)QEMU can be
found in the QEMU 8 merge commit message
[23e570bf42](https://github.com/eurecom-s3/symqemu/commit/23e570bf42531bcac66a54283eafd4c9c233891a)
which gives some information about the adaptations performed. There are also
some detailed explanations about potential problems in section 5.1 of Damien
Maier's [bachelor thesis](https://dmaier.ch/bachelor-thesis.pdf).

## License

Expand Down
21 changes: 0 additions & 21 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,6 @@ default_cflags='-O2 -g'
git_submodules_action="update"
docs="auto"
EXESUF=""
symcc_source=""
symcc_build=""
system="yes"
linux_user=""
bsd_user=""
Expand Down Expand Up @@ -696,10 +694,6 @@ for opt do
;;
--static) static="yes"
;;
--symcc-source=*) symcc_source="$optarg"
;;
--symcc-build=*) symcc_build="$optarg"
;;
--host=*|--build=*|\
--disable-dependency-tracking|\
--sbindir=*|--sharedstatedir=*|\
Expand Down Expand Up @@ -880,8 +874,6 @@ Advanced options (experts only):
start the emulator (only use if you are including
desired devices in configs/devices/)
--with-devices-ARCH=NAME override default configs/devices
--symcc-source=PATH PATH to SymCC source code
--symcc-build=PATH PATH to the build directory of SymCC with Qsym backend
--enable-debug enable common debug build options
--cpu=CPU Build for host CPU [$cpu]
--disable-containers don't use containers for cross-building
Expand Down Expand Up @@ -1678,19 +1670,6 @@ if test "$targetos" = windows; then
echo "CONFIG_WIN32=y" >> contrib/plugins/$config_host_mak
fi

echo "# SymQEMU config" >> $config_host_mak
if test -e "$symcc_source/runtime/RuntimeCommon.h"; then
echo "SYMCC_INC=$symcc_source/runtime" >> $config_host_mak
else
error_exit "SymCC (source)" "Point --symcc-source to the SymCC source code"
fi
if test -e "$symcc_build/SymRuntime-prefix/src/SymRuntime-build/libSymRuntime.so"; then
echo "SYMCC_BUILD=$symcc_build/SymRuntime-prefix/src/SymRuntime-build" >> $config_host_mak
echo "SYMCC_LIBS=$symcc_build/SymRuntime-prefix/src/SymRuntime-build/libSymRuntime.so" >> $config_host_mak
else
error_exit "SymCC (runtime)" "Point --symcc-build to the SymCC build directory"
fi

# tests/tcg configuration
(config_host_mak=tests/tcg/config-host.mak
mkdir -p tests/tcg
Expand Down
Loading