Skip to content

Commit

Permalink
Merge branch 'qemu_7_2' into qemu_8_1
Browse files Browse the repository at this point in the history
This is a port of SymQEMU to version 8.1 of QEMU. This port is itself
based on the port to QEMU 7.2 performed by Aurélien Hernandez.

Here is a description of the non trivial adaptations that had to be
performed :

accel/tcg/tcg-runtime-sym.h

In the previous SymQEMU version, the declaration of the helper functions for sym_load_guest_i32,
sym_load_guest_i64, sym_store_guest_i32, sym_store_guest_i64 use the
macro dh_alias_tl for describing the type of the load / store address.
This macro is expanded to i_32 or i_64 depending on the guest
architecture.

However, in QEMU 8.1, dh_alias_tl is not avaialable in all compilation
units that include tcg-runtime-sym.h. This is due to the fact that this
macro is only available in the compilation units that include
target/<arch>/cpu-param.h, and dependance on this header has been
reduced in QEMU 8.1

As a solution, I replaced dh_alias_tl with i64. This obviously does not
cause any problem for 64 bits guests. Even with 32 bits guests, this
should be ok as, even in the original SymQEMU, the load / store addresses are
always converted to 64 bit pointers before being passed to the symbolic
backend.

include/exec/helper-gen-common.h, helper-proto-common.h,
accel/tcg/tcg-runtime-sym.c

The way helper functions should be included for their macros to be
expanded has changed. In QEMU 8.1, the helper expansions are done with
the help of include/exec/helper-proto.h.inc, include/exec/helper/gen.h.inc, include/exec/helper-info.c.inc.

I have adapted it for tcg-runtime-sym by imitating the way it is done
for tcg-runtime.

tcg/tcg.c:tcg_temp_new_internal

QEMU 8.1 allows to create 128 bits TCGTemps. On a 64 bits host, a 128
bits temp will actually be stored in two consecutive 64 bits TCGTemps
that are created by tcg_temp_new_internal.

This conflicts with the design of SymQEMU, that consists of storing
symbolic version of a TCGTemp right after the concrete one. For now, I
have edited the function such that it triggers an error if an attempt to
create a 128 bits TCGTemp is made.

tcg/tcg.c:tcg_context_init

In previous SymQEMU version, a macro expansion in tcg_context_init
computes the distance between ArchCPU.env and ArchCPU.env_exprs.

In QEMU 8.1, ArchCPU is not included in tcg.c. As a solution, the macro
expansion is now placed in tcg-all.c:tcg_init_machine and the result
offset is passed as argument to tcg_context_init.

tcg/tcg.h: tcgv_i32_expr_num, tcgv_i64_expr_num

Changed the return type of those two functions from TCGv to TCGv_i64,
as the TCGv macro is not available for all compilation units that
include tcg.h.

TCGv expands to TCGv_i64 or TCGv_i32 depending on the guest
architecture. However, the return value of tcgv_i32_expr_num and tcgv_i64_expr_num are only
used in instrumentation code that expects 64 bits TCGArgs, even when
the guest is 32 bits. Thus, TCGv_i64 makes more sense here than TGCv.

include/tcg/tcg-op.h, include/tcg/tcg-op-common.h

In QEMU 8.1, most of the content of tcg-op.h has been moved into the new file
tcg-op-common.h

include/tcg/tcg-op.h: tcg_gen_qemu_ld_i32, tcg_gen_qemu_st_i32,
tcg_gen_qemu_ld_i64, tcg_gen_qemu_st_i64

In QEMU 8.1, the logic of those functions has been delegated to
internal functions in tcg/tcg-op-ldst.c. Additionally, those internal
functions now receive the load / store address temp as a TCGTemp instead
of a TCGv_i64. The instrumentation code had to be adapted accordingly.
  • Loading branch information
damienmaier committed Nov 19, 2023
2 parents 78385bc + 5bdb1bd commit 23e570b
Show file tree
Hide file tree
Showing 27 changed files with 1,986 additions and 57 deletions.
102 changes: 102 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# SymQEMU

This is SymQEMU, a binary-only symbolic executor based on QEMU and SymCC. It
currently extends QEMU 7.2 and works with the most recent version of SymCC.
(See README.orig for QEMU's original README file.)

## 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:

``` 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
```

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.

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:

``` shell

$ ../configure \
--audio-drv-list= \
--disable-sdl \
--disable-gtk \
--disable-vte \
--disable-opengl \
--disable-virglrenderer \
--disable-werror \
--target-list=x86_64-linux-user \
--symcc-source=</path/to/symcc>/sources \
--symcc-build=</path/to/symcc>/build

$ make
```

This will build a relatively stripped-down emulator targeting 64-bit x86
binaries. We also have experimental support for AARCH64. Working with 32-bit
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.

## Running SymQEMU

If you built SymQEMU as described above, the binary will be in
`x86_64-linux-user/symqemu-x86_64`. For a quick test, try the following:

``` shell
$ mkdir /tmp/output
$ echo test | x86_64-linux-user/symqemu-x86_64 /bin/cat -t -
This is SymCC running with the QSYM backend
Reading program input until EOF (use Ctrl+D in a terminal)...
[STAT] SMT: { "solving_time": 0, "total_time": 93207 }
[STAT] SMT: { "solving_time": 480 }
[INFO] New testcase: /tmp/output/000000
...
```
This runs your system's `/bin/cat` with options that make it inspect each
character on standard input to check whether or not it's in the non-printable
range. In `/tmp/output`, the default location for test cases generated by
SymQEMU, you'll find versions of the input (i.e., "test") containing
non-printable characters in various positions.
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
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.)
## 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}` (which delegates any
actual symbolic computation to SymCC's symbolic backend), and we have modified
most code-generating functions in `tcg/tcg-op.c` 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`.
## License
SymQEMU extends the QEMU emulator, and our contributions to previously existing
files adopt those files' respective licenses; the files that we have added are
made available under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or (at your
option) any later version.
File renamed without changes.
1 change: 1 addition & 0 deletions accel/tcg/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ tcg_ss.add(files(
'tb-maint.c',
'tcg-runtime-gvec.c',
'tcg-runtime.c',
'tcg-runtime-sym.c',
'translate-all.c',
'translator.c',
))
Expand Down
2 changes: 1 addition & 1 deletion accel/tcg/tcg-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ static int tcg_init_machine(MachineState *ms)

page_init();
tb_htable_init();
tcg_init(s->tb_size * MiB, s->splitwx_enabled, max_cpus);
tcg_init(s->tb_size * MiB, s->splitwx_enabled, max_cpus, offsetof(ArchCPU, env_exprs) - offsetof(ArchCPU, env));

#if defined(CONFIG_SOFTMMU)
/*
Expand Down

0 comments on commit 23e570b

Please sign in to comment.