Skip to content

Commit 23e570b

Browse files
committed
Merge branch 'qemu_7_2' into qemu_8_1
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.
2 parents 78385bc + 5bdb1bd commit 23e570b

27 files changed

+1986
-57
lines changed

README.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# SymQEMU
2+
3+
This is SymQEMU, a binary-only symbolic executor based on QEMU and SymCC. It
4+
currently extends QEMU 7.2 and works with the most recent version of SymCC.
5+
(See README.orig for QEMU's original README file.)
6+
7+
## How to build
8+
9+
SymQEMU requires [SymCC](https://github.com/eurecom-s3/symcc), so please
10+
download and build SymCC first. For best results, configure it with the QSYM
11+
backend as explained in the README. For the impatient, here's a quick summary of
12+
the required steps that may or may not work on your system:
13+
14+
``` shell
15+
$ git clone https://github.com/eurecom-s3/symcc.git
16+
$ cd symcc
17+
$ git submodule update --init
18+
$ mkdir build
19+
$ cd build
20+
$ cmake -G Ninja -DQSYM_BACKEND=ON ..
21+
$ ninja
22+
```
23+
24+
Next, make sure that QEMU's build dependencies are installed. Most package
25+
managers provide a command to get them, e.g., `apt build-dep qemu` on Debian and
26+
Ubuntu, or `dnf builddep qemu` on Fedora and CentOS.
27+
28+
We've extended QEMU's configuration script to accept pointers to SymCC's source
29+
and binaries. The following invocation is known to work on Debian 10, Arch and
30+
Fedora 33:
31+
32+
``` shell
33+
34+
$ ../configure \
35+
--audio-drv-list= \
36+
--disable-sdl \
37+
--disable-gtk \
38+
--disable-vte \
39+
--disable-opengl \
40+
--disable-virglrenderer \
41+
--disable-werror \
42+
--target-list=x86_64-linux-user \
43+
--symcc-source=</path/to/symcc>/sources \
44+
--symcc-build=</path/to/symcc>/build
45+
46+
$ make
47+
```
48+
49+
This will build a relatively stripped-down emulator targeting 64-bit x86
50+
binaries. We also have experimental support for AARCH64. Working with 32-bit
51+
target architectures is possible in principle but will require a bit of work
52+
because the current implementation assumes that we can pass around host pointers
53+
in guest registers.
54+
55+
## Running SymQEMU
56+
57+
If you built SymQEMU as described above, the binary will be in
58+
`x86_64-linux-user/symqemu-x86_64`. For a quick test, try the following:
59+
60+
``` shell
61+
$ mkdir /tmp/output
62+
$ echo test | x86_64-linux-user/symqemu-x86_64 /bin/cat -t -
63+
This is SymCC running with the QSYM backend
64+
Reading program input until EOF (use Ctrl+D in a terminal)...
65+
[STAT] SMT: { "solving_time": 0, "total_time": 93207 }
66+
[STAT] SMT: { "solving_time": 480 }
67+
[INFO] New testcase: /tmp/output/000000
68+
...
69+
```
70+
71+
This runs your system's `/bin/cat` with options that make it inspect each
72+
character on standard input to check whether or not it's in the non-printable
73+
range. In `/tmp/output`, the default location for test cases generated by
74+
SymQEMU, you'll find versions of the input (i.e., "test") containing
75+
non-printable characters in various positions.
76+
77+
This is a very basic use of symbolic execution. See SymCC's documentation for
78+
more advanced scenarios. Since SymQEMU is based on it, it understands all the
79+
same
80+
[settings](https://github.com/eurecom-s3/symcc/blob/master/docs/Configuration.txt),
81+
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
82+
prefix the target command with `x86_64-linux-user/symqemu-x86_64`. (Note that
83+
you'll have to run AFL in QEMU mode by adding `-Q` to its command line; the
84+
fuzzing helper will automatically pick up the setting and use QEMU mode too.)
85+
86+
## Documentation
87+
88+
The [paper](http://www.s3.eurecom.fr/tools/symbolic_execution/symqemu.html)
89+
contains details on how SymQEMU works. A large part of the implementation is the
90+
run-time support in `accel/tcg/tcg-runtime-sym.{c,h}` (which delegates any
91+
actual symbolic computation to SymCC's symbolic backend), and we have modified
92+
most code-generating functions in `tcg/tcg-op.c` to emit calls to the runtime.
93+
For development, configure with `--enable-debug` for run-time assertions; there
94+
are tests for the symbolic run-time support in `tests/check-sym-runtime.c`.
95+
96+
## License
97+
98+
SymQEMU extends the QEMU emulator, and our contributions to previously existing
99+
files adopt those files' respective licenses; the files that we have added are
100+
made available under the terms of the GNU General Public License as published by
101+
the Free Software Foundation, either version 2 of the License, or (at your
102+
option) any later version.

README.rst renamed to README.orig

File renamed without changes.

accel/tcg/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ tcg_ss.add(files(
66
'tb-maint.c',
77
'tcg-runtime-gvec.c',
88
'tcg-runtime.c',
9+
'tcg-runtime-sym.c',
910
'translate-all.c',
1011
'translator.c',
1112
))

accel/tcg/tcg-all.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static int tcg_init_machine(MachineState *ms)
114114

115115
page_init();
116116
tb_htable_init();
117-
tcg_init(s->tb_size * MiB, s->splitwx_enabled, max_cpus);
117+
tcg_init(s->tb_size * MiB, s->splitwx_enabled, max_cpus, offsetof(ArchCPU, env_exprs) - offsetof(ArchCPU, env));
118118

119119
#if defined(CONFIG_SOFTMMU)
120120
/*

0 commit comments

Comments
 (0)