aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Fioraldi <andreafioraldi@gmail.com>2019-10-25 20:04:16 +0200
committerAndrea Fioraldi <andreafioraldi@gmail.com>2019-10-25 20:04:16 +0200
commit4ec4e5b394dfa4e40a26574e3053a9bd7eaa8d37 (patch)
tree4ae76859d96fb31b3635a12f8632771cdaa9664f
parente7871b2c7675e0f6df4fbe1a8f53a23ed5d2024f (diff)
downloadafl++-4ec4e5b394dfa4e40a26574e3053a9bd7eaa8d37.tar.gz
floating point compcov
-rwxr-xr-xqemu_mode/build_qemu_support.sh3
-rw-r--r--qemu_mode/patches/afl-qemu-common.h12
-rw-r--r--qemu_mode/patches/afl-qemu-floats.h217
-rw-r--r--qemu_mode/patches/i386-fpu_helper.diff54
-rw-r--r--qemu_mode/patches/i386-ops_sse.diff61
-rw-r--r--qemu_mode/patches/softfloat.diff10
6 files changed, 357 insertions, 0 deletions
diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh
index f18cbdf3..6b9f91f9 100755
--- a/qemu_mode/build_qemu_support.sh
+++ b/qemu_mode/build_qemu_support.sh
@@ -150,6 +150,9 @@ patch -p1 <../patches/translate-all.diff || exit 1
patch -p1 <../patches/tcg.diff || exit 1
patch -p1 <../patches/i386-translate.diff || exit 1
patch -p1 <../patches/arm-translate.diff || exit 1
+patch -p1 <../patches/i386-ops_sse.diff || exit 1
+patch -p1 <../patches/i386-fpu_helper.diff || exit 1
+patch -p1 <../patches/softfloat.diff || exit 1
echo "[+] Patching done."
diff --git a/qemu_mode/patches/afl-qemu-common.h b/qemu_mode/patches/afl-qemu-common.h
index 409a7eab..d4024353 100644
--- a/qemu_mode/patches/afl-qemu-common.h
+++ b/qemu_mode/patches/afl-qemu-common.h
@@ -31,6 +31,9 @@
*/
+#ifndef __AFL_QEMU_COMMON
+#define __AFL_QEMU_COMMON
+
#include "../../config.h"
#ifndef CPU_NB_REGS
@@ -81,6 +84,12 @@ void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc,
void tcg_gen_afl_maybe_log_call(target_ulong cur_loc);
+void afl_float_compcov_log_32(target_ulong cur_loc, float32 arg1, float32 arg2,
+ void *status);
+void afl_float_compcov_log_64(target_ulong cur_loc, float64 arg1, float64 arg2,
+ void *status);
+void afl_float_compcov_log_80(target_ulong cur_loc, floatx80 arg1,
+ floatx80 arg2);
/* Check if an address is valid in the current mapping */
@@ -99,3 +108,6 @@ static inline int is_valid_addr(target_ulong addr) {
return 1;
}
+
+#endif
+
diff --git a/qemu_mode/patches/afl-qemu-floats.h b/qemu_mode/patches/afl-qemu-floats.h
new file mode 100644
index 00000000..765deb74
--- /dev/null
+++ b/qemu_mode/patches/afl-qemu-floats.h
@@ -0,0 +1,217 @@
+/*
+ american fuzzy lop++ - high-performance binary-only instrumentation
+ -------------------------------------------------------------------
+
+ Originally written by Andrew Griffiths <agriffiths@google.com> and
+ Michal Zalewski
+
+ TCG instrumentation and block chaining support by Andrea Biondo
+ <andrea.biondo965@gmail.com>
+
+ QEMU 3.1.1 port, TCG thread-safety, CompareCoverage and NeverZero
+ counters by Andrea Fioraldi <andreafioraldi@gmail.com>
+
+ Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
+ Copyright 2019 AFLplusplus Project. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ This code is a shim patched into the separately-distributed source
+ code of QEMU 3.1.0. It leverages the built-in QEMU tracing functionality
+ to implement AFL-style instrumentation and to take care of the remaining
+ parts of the AFL fork server logic.
+
+ The resulting QEMU binary is essentially a standalone instrumentation
+ tool; for an example of how to leverage it for other purposes, you can
+ have a look at afl-showmap.c.
+
+ */
+
+#include "tcg.h"
+#include "afl-qemu-common.h"
+
+union afl_float32 {
+ float64 f;
+ struct {
+ u64 sign : 1;
+ u64 exp : 7;
+ u64 frac : 24;
+ };
+};
+
+
+union afl_float64 {
+ float64 f;
+ struct {
+ u64 sign : 1;
+ u64 exp : 11;
+ u64 frac : 52;
+ };
+};
+
+
+// TODO 16 and 128 bits floats
+// TODO figure out why float*_unpack_canonical does not work
+
+void afl_float_compcov_log_32(target_ulong cur_loc, float32 arg1, float32 arg2,
+ void* status) {
+
+ cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
+ cur_loc &= MAP_SIZE - 7;
+
+ if (cur_loc >= afl_inst_rms) return;
+
+ //float_status* s = (float_status*)status;
+ //FloatParts a = float32_unpack_canonical(arg1, s);
+ //FloatParts b = float32_unpack_canonical(arg2, s);
+ union afl_float32 a = { .f = arg1 };
+ union afl_float32 b = { .f = arg2 };
+
+ // if (is_nan(a.cls) || is_nan(b.cls)) return;
+
+ register uintptr_t idx = cur_loc;
+
+ if (a.sign != b.sign) return;
+ INC_AFL_AREA(idx);
+ if (a.exp != b.exp) return;
+ INC_AFL_AREA(idx + 1);
+
+ if ((a.frac & 0xff0000) == (b.frac & 0xff0000)) {
+
+ INC_AFL_AREA(idx + 2);
+ if ((a.frac & 0xff00) == (b.frac & 0xff00)) { INC_AFL_AREA(idx + 3); }
+
+ }
+
+}
+
+void afl_float_compcov_log_64(target_ulong cur_loc, float64 arg1, float64 arg2,
+ void* status) {
+
+ cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
+ cur_loc &= MAP_SIZE - 7;
+
+ if (cur_loc >= afl_inst_rms) return;
+
+ //float_status* s = (float_status*)status;
+ //FloatParts a = float64_unpack_canonical(arg1, s);
+ //FloatParts b = float64_unpack_canonical(arg2, s);
+ union afl_float64 a = { .f = arg1 };
+ union afl_float64 b = { .f = arg2 };
+
+ // if (is_nan(a.cls) || is_nan(b.cls)) return;
+
+ register uintptr_t idx = cur_loc;
+
+ if (a.sign == b.sign) INC_AFL_AREA(idx);
+ if ((a.exp & 0xff00) == (b.exp & 0xff00)) {
+
+ INC_AFL_AREA(idx + 1);
+ if ((a.exp & 0xff) == (b.exp & 0xff)) INC_AFL_AREA(idx + 2);
+
+ }
+
+ if ((a.frac & 0xff000000000000) == (b.frac & 0xff000000000000)) {
+
+ INC_AFL_AREA(idx + 3);
+ if ((a.frac & 0xff0000000000) == (b.frac & 0xff0000000000)) {
+
+ INC_AFL_AREA(idx + 4);
+ if ((a.frac & 0xff00000000) == (b.frac & 0xff00000000)) {
+
+ INC_AFL_AREA(idx + 5);
+ if ((a.frac & 0xff000000) == (b.frac & 0xff000000)) {
+
+ INC_AFL_AREA(idx + 6);
+ if ((a.frac & 0xff0000) == (b.frac & 0xff0000)) {
+
+ INC_AFL_AREA(idx + 7);
+ if ((a.frac & 0xff00) == (b.frac & 0xff00)) INC_AFL_AREA(idx + 8);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+}
+
+void afl_float_compcov_log_80(target_ulong cur_loc, floatx80 arg1,
+ floatx80 arg2) {
+
+ cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
+ cur_loc &= MAP_SIZE - 7;
+
+ if (cur_loc >= afl_inst_rms) return;
+
+ if (floatx80_invalid_encoding(arg1) || floatx80_invalid_encoding(arg2))
+ return;
+
+ flag a_sign = extractFloatx80Sign(arg1);
+ flag b_sign = extractFloatx80Sign(arg2);
+
+ /*if (((extractFloatx80Exp(arg1) == 0x7fff) &&
+ (extractFloatx80Frac(arg1) << 1)) ||
+ ((extractFloatx80Exp(arg2) == 0x7fff) &&
+ (extractFloatx80Frac(arg2) << 1)))
+ return;*/
+
+ register uintptr_t idx = cur_loc;
+
+ if (a_sign == b_sign) INC_AFL_AREA(idx);
+
+ if ((arg1.high & 0x7f00) == (arg2.high & 0x7f00)) {
+
+ INC_AFL_AREA(idx + 1);
+ if ((arg1.high & 0xff) == (arg2.high & 0xff)) INC_AFL_AREA(idx + 2);
+
+ }
+
+ if ((arg1.low & 0xff00000000000000) == (arg2.low & 0xff00000000000000)) {
+
+ INC_AFL_AREA(idx + 3);
+ if ((arg1.low & 0xff000000000000) == (arg2.low & 0xff000000000000)) {
+
+ INC_AFL_AREA(idx + 4);
+ if ((arg1.low & 0xff0000000000) == (arg2.low & 0xff0000000000)) {
+
+ INC_AFL_AREA(idx + 5);
+ if ((arg1.low & 0xff00000000) == (arg2.low & 0xff00000000)) {
+
+ INC_AFL_AREA(idx + 6);
+ if ((arg1.low & 0xff000000) == (arg2.low & 0xff000000)) {
+
+ INC_AFL_AREA(idx + 7);
+ if ((arg1.low & 0xff0000) == (arg2.low & 0xff0000)) {
+
+ INC_AFL_AREA(idx + 8);
+ if ((arg1.low & 0xff00) == (arg2.low & 0xff00)) {
+
+ INC_AFL_AREA(idx + 9);
+ //if ((arg1.low & 0xff) == (arg2.low & 0xff))
+ // INC_AFL_AREA(idx + 10);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+}
+
diff --git a/qemu_mode/patches/i386-fpu_helper.diff b/qemu_mode/patches/i386-fpu_helper.diff
new file mode 100644
index 00000000..3bd09d9c
--- /dev/null
+++ b/qemu_mode/patches/i386-fpu_helper.diff
@@ -0,0 +1,54 @@
+diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c
+index ea5a0c48..89901315 100644
+--- a/target/i386/fpu_helper.c
++++ b/target/i386/fpu_helper.c
+@@ -384,10 +384,16 @@ void helper_fxchg_ST0_STN(CPUX86State *env, int st_index)
+
+ static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
+
++#include "../patches/afl-qemu-common.h"
++
+ void helper_fcom_ST0_FT0(CPUX86State *env)
+ {
+ int ret;
+
++ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
++ env->eip >= afl_start_code)
++ afl_float_compcov_log_80(env->eip, ST0, FT0);
++
+ ret = floatx80_compare(ST0, FT0, &env->fp_status);
+ env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
+ }
+@@ -396,6 +402,10 @@ void helper_fucom_ST0_FT0(CPUX86State *env)
+ {
+ int ret;
+
++ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
++ env->eip >= afl_start_code)
++ afl_float_compcov_log_80(env->eip, ST0, FT0);
++
+ ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
+ env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
+ }
+@@ -407,6 +417,10 @@ void helper_fcomi_ST0_FT0(CPUX86State *env)
+ int eflags;
+ int ret;
+
++ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
++ env->eip >= afl_start_code)
++ afl_float_compcov_log_80(env->eip, ST0, FT0);
++
+ ret = floatx80_compare(ST0, FT0, &env->fp_status);
+ eflags = cpu_cc_compute_all(env, CC_OP);
+ eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
+@@ -418,6 +432,10 @@ void helper_fucomi_ST0_FT0(CPUX86State *env)
+ int eflags;
+ int ret;
+
++ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
++ env->eip >= afl_start_code)
++ afl_float_compcov_log_80(env->eip, ST0, FT0);
++
+ ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
+ eflags = cpu_cc_compute_all(env, CC_OP);
+ eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
diff --git a/qemu_mode/patches/i386-ops_sse.diff b/qemu_mode/patches/i386-ops_sse.diff
new file mode 100644
index 00000000..d2779ea8
--- /dev/null
+++ b/qemu_mode/patches/i386-ops_sse.diff
@@ -0,0 +1,61 @@
+diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
+index ed059897..a5296caa 100644
+--- a/target/i386/ops_sse.h
++++ b/target/i386/ops_sse.h
+@@ -997,6 +997,8 @@ SSE_HELPER_CMP(cmpord, FPU_CMPORD)
+
+ static const int comis_eflags[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
+
++#include "../patches/afl-qemu-common.h"
++
+ void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s)
+ {
+ int ret;
+@@ -1004,6 +1006,11 @@ void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s)
+
+ s0 = d->ZMM_S(0);
+ s1 = s->ZMM_S(0);
++
++ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
++ env->eip >= afl_start_code)
++ afl_float_compcov_log_32(env->eip, s0, s1, &env->sse_status);
++
+ ret = float32_compare_quiet(s0, s1, &env->sse_status);
+ CC_SRC = comis_eflags[ret + 1];
+ }
+@@ -1015,6 +1022,11 @@ void helper_comiss(CPUX86State *env, Reg *d, Reg *s)
+
+ s0 = d->ZMM_S(0);
+ s1 = s->ZMM_S(0);
++
++ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
++ env->eip >= afl_start_code)
++ afl_float_compcov_log_32(env->eip, s0, s1, &env->sse_status);
++
+ ret = float32_compare(s0, s1, &env->sse_status);
+ CC_SRC = comis_eflags[ret + 1];
+ }
+@@ -1026,6 +1038,11 @@ void helper_ucomisd(CPUX86State *env, Reg *d, Reg *s)
+
+ d0 = d->ZMM_D(0);
+ d1 = s->ZMM_D(0);
++
++ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
++ env->eip >= afl_start_code)
++ afl_float_compcov_log_64(env->eip, d0, d1, &env->sse_status);
++
+ ret = float64_compare_quiet(d0, d1, &env->sse_status);
+ CC_SRC = comis_eflags[ret + 1];
+ }
+@@ -1037,6 +1054,11 @@ void helper_comisd(CPUX86State *env, Reg *d, Reg *s)
+
+ d0 = d->ZMM_D(0);
+ d1 = s->ZMM_D(0);
++
++ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
++ env->eip >= afl_start_code)
++ afl_float_compcov_log_64(env->eip, d0, d1, &env->sse_status);
++
+ ret = float64_compare(d0, d1, &env->sse_status);
+ CC_SRC = comis_eflags[ret + 1];
+ }
diff --git a/qemu_mode/patches/softfloat.diff b/qemu_mode/patches/softfloat.diff
new file mode 100644
index 00000000..86ffb97f
--- /dev/null
+++ b/qemu_mode/patches/softfloat.diff
@@ -0,0 +1,10 @@
+diff --git a/fpu/softfloat.c b/fpu/softfloat.c
+index e1eef954..2f8d0d62 100644
+--- a/fpu/softfloat.c
++++ b/fpu/softfloat.c
+@@ -7205,3 +7205,5 @@ float128 float128_scalbn(float128 a, int n, float_status *status)
+ , status);
+
+ }
++
++#include "../../patches/afl-qemu-floats.h"