qemuafl now supports persistent mode for *mipsel* targets. This patch
changes the `SYS` variable tests and runs the persistent qemu_mode
tests for *mipsel* as well.
This also adds an optional environment variable called `CPU_TARGET_CC`
that you can pass to the `./test-qemu-mode.sh` test script.
This allows you to specify a cross-compiler for the target platform. The
test script then it uses to compile `test-instr.c` and `test-compcov.c`.
Example usage:
```
CPU_TARGET_CC=mipsel-linux-gnu-cc CPU_TARGET=mipsel ./test-qemu-mode.sh
```
The output should look something like this:
```
[*] Using environment variable CPU_TARGET=mipsel for SYS
[*] starting AFL++ test framework ...
[*] Testing: qemu_mode
[*] Using mipsel-linux-gnu-cc as compiler for target
[*] running afl-fuzz for qemu_mode, this will take approx 10 seconds
[+] afl-fuzz is working correctly with qemu_mode
[*] running afl-fuzz for qemu_mode AFL_ENTRYPOINT, this will take approx 6 seconds
[+] afl-fuzz is working correctly with qemu_mode AFL_ENTRYPOINT
[-] not an intel or arm platform, cannot test qemu_mode compcov
[-] not an intel or arm platform, cannot test qemu_mode cmplog
[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds
[+] afl-fuzz is working correctly with persistent qemu_mode
[+] persistent qemu_mode was noticeable faster than standard qemu_mode
[*] running afl-fuzz for persistent qemu_mode with AFL_QEMU_PERSISTENT_EXITS, this will take approx 10 seconds
[+] afl-fuzz is working correctly with persistent qemu_mode and AFL_QEMU_PERSISTENT_EXITS
[+] persistent qemu_mode with AFL_QEMU_PERSISTENT_EXITS was noticeable faster than standard qemu_mode
[-] we cannot test qemu_mode unsigaction library (32 bit) because it is not present
[+] qemu_mode unsigaction library (64 bit) ignores signals
[*] 1 test cases completed.
[-] not all test cases were executed
[+] all tests were successful :-)
```
Add a test case to `test/test-qemu-mode.sh` and make sure that
AFL_QEMU_PERSISTENT_EXITS loops correctly.
This works only on platforms for which `afl-qemu-trace` detects exit
signals and resets the program counter.
This commit updates `test-instr.c` to optionally call `exit(n)` instead of
returning n to the operating system. This option can be activated using
the `EXIT_AT_END` flag. This way, we can test the
QEMU persistent exit mode without having to add a new test file.
You can compile and run `test-instr.c` with the exit mode like so:
```bash
gcc -o exit -DEXIT_AT_END test-instr.c
AFL_QEMU_DEBUG_MAPS= \
AFL_DEBUG= \
AFL_QEMU_PERSISTENT_ADDR=$(readelf -a exit | grep 'main$' | awk '{ printf "0x%s", $2 }') \
AFL_QEMU_PERSISTENT_GPR=1 \
AFL_QEMU_PERSISTENT_EXITS=1 \
./afl-qemu-trace exit
```
Press enter repeatedly and you will see an output like this:
```
...
Debug: Sending status 0xc201ffff
test-instr:
Neither one or zero? How quaint!
test-instr:
Neither one or zero? How quaint!
test-instr:
Neither one or zero? How quaint!
test-instr:
Neither one or zero? How quaint!
test-instr:
Neither one or zero? How quaint!
```
To make sure that persistent exits are detected correctly on x86_64, I've made
the following changes to qemuafl:
```
linux-user/i386/cpu_loop.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c
index 4509f46b95..46bdbaf94a 100644
--- a/linux-user/i386/cpu_loop.c
+++ b/linux-user/i386/cpu_loop.c
@@ -235,7 +235,7 @@ void cpu_loop(CPUX86State *env)
#ifndef TARGET_ABI32
case EXCP_SYSCALL:
/* linux syscall from syscall instruction */
- if (afl_fork_child && persistent_exits &&
+ if (persistent_exits &&
env->regs[R_EAX] == TARGET_NR_exit_group) {
env->eip = afl_persistent_addr;
continue;
```