about summary refs log tree commit diff
path: root/qemu_mode/patches/afl-qemu-floats.h
diff options
context:
space:
mode:
Diffstat (limited to 'qemu_mode/patches/afl-qemu-floats.h')
-rw-r--r--qemu_mode/patches/afl-qemu-floats.h217
1 files changed, 217 insertions, 0 deletions
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);
+
+              }
+
+            }
+
+          }
+
+        }
+
+      }
+
+    }
+
+  }
+
+}
+