removed unused diffs

This commit is contained in:
Dominik Maier 2020-02-10 00:19:12 +01:00
parent f772d49faf
commit e19e06aba7
7 changed files with 0 additions and 991 deletions

View File

@ -1,48 +0,0 @@
/*
american fuzzy lop++ - unicorn instrumentation
----------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski
Adapted for afl-unicorn by Dominik Maier <mail@dmnk.co>
CompareCoverage and NeverZero counters by Andrea Fioraldi
<andreafioraldi@gmail.com>
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 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 Unicorn 1.0.1. 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 libunicorn 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 "../../config.h"
/* NeverZero */
#if (defined(__x86_64__) || defined(__i386__)) && defined(AFL_QEMU_NOT_ZERO)
#define INC_AFL_AREA(loc) \
asm volatile( \
"incb (%0, %1, 1)\n" \
"adcb $0, (%0, %1, 1)\n" \
: /* no out */ \
: "r"(afl_area_ptr), "r"(loc) \
: "memory", "eax")
#else
#define INC_AFL_AREA(loc) afl_area_ptr[loc]++
#endif

View File

@ -1,293 +0,0 @@
/*
american fuzzy lop++ - unicorn instrumentation
----------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski
Adapted for afl-unicorn by Dominik Maier <mail@dmnk.co>
CompareCoverage and NeverZero counters by Andrea Fioraldi
<andreafioraldi@gmail.com>
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 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 Unicorn 1.0.1. 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 libunicorn 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 <sys/shm.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "afl-unicorn-common.h"
/***************************
* VARIOUS AUXILIARY STUFF *
***************************/
/* A snippet patched into tb_find_slow to inform the parent process that
we have hit a new block that hasn't been translated yet, and to tell
it to translate within its own context, too (this avoids translation
overhead in the next forked-off copy). */
#define AFL_UNICORN_CPU_SNIPPET1 \
do { \
\
afl_request_tsl(pc, cs_base, flags); \
\
} while (0)
/* This snippet kicks in when the instruction pointer is positioned at
_start and does the usual forkserver stuff, not very different from
regular instrumentation injected via afl-as.h. */
#define AFL_UNICORN_CPU_SNIPPET2 \
do { \
\
if (unlikely(afl_first_instr == 0)) { \
\
afl_setup(env->uc); \
afl_forkserver(env); \
afl_first_instr = 1; \
\
} \
afl_maybe_log(env->uc, tb->pc); \
\
} while (0)
/* We use one additional file descriptor to relay "needs translation"
messages between the child and the fork server. */
#define TSL_FD (FORKSRV_FD - 1)
/* Set in the child process in forkserver mode: */
static unsigned char afl_fork_child;
static unsigned int afl_forksrv_pid;
/* Function declarations. */
static void afl_setup(struct uc_struct* uc);
static void afl_forkserver(CPUArchState*);
static inline void afl_maybe_log(struct uc_struct* uc, unsigned long);
static void afl_wait_tsl(CPUArchState*, int);
static void afl_request_tsl(target_ulong, target_ulong, uint64_t);
static TranslationBlock* tb_find_slow(CPUArchState*, target_ulong, target_ulong,
uint64_t);
/* Data structure passed around by the translate handlers: */
struct afl_tsl {
target_ulong pc;
target_ulong cs_base;
uint64_t flags;
};
/*************************
* ACTUAL IMPLEMENTATION *
*************************/
/* Set up SHM region and initialize other stuff. */
static void afl_setup(struct uc_struct* uc) {
char *id_str = getenv(SHM_ENV_VAR), *inst_r = getenv("AFL_INST_RATIO");
int shm_id;
if (inst_r) {
unsigned int r;
r = atoi(inst_r);
if (r > 100) r = 100;
if (!r) r = 1;
uc->afl_inst_rms = MAP_SIZE * r / 100;
} else {
uc->afl_inst_rms = MAP_SIZE;
}
if (id_str) {
shm_id = atoi(id_str);
uc->afl_area_ptr = shmat(shm_id, NULL, 0);
if (uc->afl_area_ptr == (void*)-1) exit(1);
/* With AFL_INST_RATIO set to a low value, we want to touch the bitmap
so that the parent doesn't give up on us. */
if (inst_r) uc->afl_area_ptr[0] = 1;
}
/* Maintain for compatibility */
if (getenv("AFL_QEMU_COMPCOV")) { uc->afl_compcov_level = 1; }
if (getenv("AFL_COMPCOV_LEVEL")) {
uc->afl_compcov_level = atoi(getenv("AFL_COMPCOV_LEVEL"));
}
}
/* Fork server logic, invoked once we hit first emulated instruction. */
static void afl_forkserver(CPUArchState* env) {
static unsigned char tmp[4];
if (!env->uc->afl_area_ptr) return;
/* Tell the parent that we're alive. If the parent doesn't want
to talk, assume that we're not running in forkserver mode. */
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
afl_forksrv_pid = getpid();
/* All right, let's await orders... */
while (1) {
pid_t child_pid;
int status, t_fd[2];
/* Whoops, parent dead? */
if (read(FORKSRV_FD, tmp, 4) != 4) exit(2);
/* Establish a channel with child to grab translation commands. We'll
read from t_fd[0], child will write to TSL_FD. */
if (pipe(t_fd) || dup2(t_fd[1], TSL_FD) < 0) exit(3);
close(t_fd[1]);
child_pid = fork();
if (child_pid < 0) exit(4);
if (!child_pid) {
/* Child process. Close descriptors and run free. */
afl_fork_child = 1;
close(FORKSRV_FD);
close(FORKSRV_FD + 1);
close(t_fd[0]);
return;
}
/* Parent. */
close(TSL_FD);
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(5);
/* Collect translation requests until child dies and closes the pipe. */
afl_wait_tsl(env, t_fd[0]);
/* Get and relay exit status to parent. */
if (waitpid(child_pid, &status, 0) < 0) exit(6);
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7);
}
}
/* The equivalent of the tuple logging routine from afl-as.h. */
static inline void afl_maybe_log(struct uc_struct* uc, unsigned long cur_loc) {
static __thread unsigned long prev_loc;
u8* afl_area_ptr = uc->afl_area_ptr;
if (!afl_area_ptr) return;
/* Looks like QEMU always maps to fixed locations, so ASAN is not a
concern. Phew. But instruction addresses may be aligned. Let's mangle
the value to get something quasi-uniform. */
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 1;
/* Implement probabilistic instrumentation by looking at scrambled block
address. This keeps the instrumented locations stable across runs. */
if (cur_loc >= uc->afl_inst_rms) return;
register uintptr_t afl_idx = cur_loc ^ prev_loc;
INC_AFL_AREA(afl_idx);
prev_loc = cur_loc >> 1;
}
/* This code is invoked whenever QEMU decides that it doesn't have a
translation of a particular block and needs to compute it. When this happens,
we tell the parent to mirror the operation, so that the next fork() has a
cached copy. */
static void afl_request_tsl(target_ulong pc, target_ulong cb, uint64_t flags) {
struct afl_tsl t;
if (!afl_fork_child) return;
t.pc = pc;
t.cs_base = cb;
t.flags = flags;
if (write(TSL_FD, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl))
return;
}
/* This is the other side of the same channel. Since timeouts are handled by
afl-fuzz simply killing the child, we can just wait until the pipe breaks. */
static void afl_wait_tsl(CPUArchState* env, int fd) {
struct afl_tsl t;
while (1) {
/* Broken pipe means it's time to return to the fork server routine. */
if (read(fd, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) break;
tb_find_slow(env, t.pc, t.cs_base, t.flags);
}
close(fd);
}

View File

@ -1,57 +0,0 @@
/*
american fuzzy lop++ - unicorn instrumentation
----------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski
Adapted for afl-unicorn by Dominik Maier <mail@dmnk.co>
CompareCoverage and NeverZero counters by Andrea Fioraldi
<andreafioraldi@gmail.com>
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 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 Unicorn 1.0.1. 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 libunicorn 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 "../../config.h"
static void afl_gen_compcov(TCGContext *s, uint64_t cur_loc, TCGv_i64 arg1,
TCGv_i64 arg2, TCGMemOp ot, int is_imm) {
if (!s->uc->afl_compcov_level || !s->uc->afl_area_ptr) return;
if (!is_imm && s->uc->afl_compcov_level < 2) return;
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 7;
if (cur_loc >= s->uc->afl_inst_rms) return;
switch (ot) {
case MO_64: gen_afl_compcov_log_64(s, cur_loc, arg1, arg2); break;
case MO_32: gen_afl_compcov_log_32(s, cur_loc, arg1, arg2); break;
case MO_16: gen_afl_compcov_log_16(s, cur_loc, arg1, arg2); break;
default: return;
}
}

View File

@ -1,59 +0,0 @@
/*
american fuzzy lop++ - unicorn instrumentation
----------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski
Adapted for afl-unicorn by Dominik Maier <mail@dmnk.co>
CompareCoverage and NeverZero counters by Andrea Fioraldi
<andreafioraldi@gmail.com>
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 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 Unicorn 1.0.1. 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 libunicorn 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.
*/
static inline void gen_afl_compcov_log_16(TCGContext *tcg_ctx, uint64_t cur_loc,
TCGv_i64 arg1, TCGv_i64 arg2) {
TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc);
TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc);
gen_helper_afl_compcov_log_16(tcg_ctx, tuc, tcur_loc, arg1, arg2);
}
static inline void gen_afl_compcov_log_32(TCGContext *tcg_ctx, uint64_t cur_loc,
TCGv_i64 arg1, TCGv_i64 arg2) {
TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc);
TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc);
gen_helper_afl_compcov_log_32(tcg_ctx, tuc, tcur_loc, arg1, arg2);
}
static inline void gen_afl_compcov_log_64(TCGContext *tcg_ctx, uint64_t cur_loc,
TCGv_i64 arg1, TCGv_i64 arg2) {
TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc);
TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc);
gen_helper_afl_compcov_log_64(tcg_ctx, tuc, tcur_loc, arg1, arg2);
}

View File

@ -1,176 +0,0 @@
/*
american fuzzy lop++ - unicorn instrumentation
----------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski
Adapted for afl-unicorn by Dominik Maier <mail@dmnk.co>
CompareCoverage and NeverZero counters by Andrea Fioraldi
<andreafioraldi@gmail.com>
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 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 Unicorn 1.0.1. 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 libunicorn 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 "uc_priv.h"
#include "afl-unicorn-common.h"
void HELPER(afl_compcov_log_16)(void* uc_ptr, uint64_t cur_loc, uint64_t arg1,
uint64_t arg2) {
u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr;
if ((arg1 & 0xff) == (arg2 & 0xff)) { INC_AFL_AREA(cur_loc); }
}
void HELPER(afl_compcov_log_32)(void* uc_ptr, uint64_t cur_loc, uint64_t arg1,
uint64_t arg2) {
u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr;
if ((arg1 & 0xff) == (arg2 & 0xff)) {
INC_AFL_AREA(cur_loc);
if ((arg1 & 0xffff) == (arg2 & 0xffff)) {
INC_AFL_AREA(cur_loc + 1);
if ((arg1 & 0xffffff) == (arg2 & 0xffffff)) { INC_AFL_AREA(cur_loc + 2); }
}
}
}
void HELPER(afl_compcov_log_64)(void* uc_ptr, uint64_t cur_loc, uint64_t arg1,
uint64_t arg2) {
u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr;
if ((arg1 & 0xff) == (arg2 & 0xff)) {
INC_AFL_AREA(cur_loc);
if ((arg1 & 0xffff) == (arg2 & 0xffff)) {
INC_AFL_AREA(cur_loc + 1);
if ((arg1 & 0xffffff) == (arg2 & 0xffffff)) {
INC_AFL_AREA(cur_loc + 2);
if ((arg1 & 0xffffffff) == (arg2 & 0xffffffff)) {
INC_AFL_AREA(cur_loc + 3);
if ((arg1 & 0xffffffffff) == (arg2 & 0xffffffffff)) {
INC_AFL_AREA(cur_loc + 4);
if ((arg1 & 0xffffffffffff) == (arg2 & 0xffffffffffff)) {
INC_AFL_AREA(cur_loc + 5);
if ((arg1 & 0xffffffffffffff) == (arg2 & 0xffffffffffffff)) {
INC_AFL_AREA(cur_loc + 6);
}
}
}
}
}
}
}
}
/* // Little endian CompCov
void HELPER(afl_compcov_log_16)(void* uc_ptr, uint64_t cur_loc, uint64_t arg1,
uint64_t arg2) {
u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr;
if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); }
}
void HELPER(afl_compcov_log_32)(void* uc_ptr, uint64_t cur_loc, uint64_t arg1,
uint64_t arg2) {
u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr;
if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) {
INC_AFL_AREA(cur_loc + 2);
if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) {
INC_AFL_AREA(cur_loc + 1);
if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); }
}
}
}
void HELPER(afl_compcov_log_64)(void* uc_ptr, uint64_t cur_loc, uint64_t arg1,
uint64_t arg2) {
u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr;
if ((arg1 & 0xff00000000000000) == (arg2 & 0xff00000000000000)) {
INC_AFL_AREA(cur_loc + 6);
if ((arg1 & 0xff000000000000) == (arg2 & 0xff000000000000)) {
INC_AFL_AREA(cur_loc + 5);
if ((arg1 & 0xff0000000000) == (arg2 & 0xff0000000000)) {
INC_AFL_AREA(cur_loc + 4);
if ((arg1 & 0xff00000000) == (arg2 & 0xff00000000)) {
INC_AFL_AREA(cur_loc + 3);
if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) {
INC_AFL_AREA(cur_loc + 2);
if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) {
INC_AFL_AREA(cur_loc + 1);
if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); }
}
}
}
}
}
}
}
*/

View File

@ -1,251 +0,0 @@
diff --git a/include/uc_priv.h b/include/uc_priv.h
index 22f494e..1aa7b3a 100644
--- a/include/uc_priv.h
+++ b/include/uc_priv.h
@@ -245,6 +245,12 @@ struct uc_struct {
uint32_t target_page_align;
uint64_t next_pc; // save next PC for some special cases
bool hook_insert; // insert new hook at begin of the hook list (append by default)
+
+#ifdef UNICORN_AFL
+ unsigned char *afl_area_ptr;
+ int afl_compcov_level;
+ unsigned int afl_inst_rms;
+#endif
};
// Metadata stub for the variable-size cpu context used with uc_context_*()
diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c
index 4995eda..06c7e63 100644
--- a/qemu/target-arm/translate.c
+++ b/qemu/target-arm/translate.c
@@ -63,6 +63,12 @@ static TCGv_i64 cpu_exclusive_test;
static TCGv_i32 cpu_exclusive_info;
#endif
+#if defined(UNICORN_AFL)
+#include "../../afl-unicorn-cpu-translate-inl.h"
+#else
+#define afl_gen_compcov(a,b,c,d,e,f) do {} while (0)
+#endif
+
static const char *regnames[] =
{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -8214,6 +8220,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
} else {
if (set_cc) {
gen_sub_CC(s, tmp, tmp, tmp2);
+ afl_gen_compcov(tcg_ctx, s->pc, tmp, tmp2, MO_32, insn & (1 << 25));
} else {
tcg_gen_sub_i32(tcg_ctx, tmp, tmp, tmp2);
}
@@ -8223,6 +8230,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
case 0x03:
if (set_cc) {
gen_sub_CC(s, tmp, tmp2, tmp);
+ afl_gen_compcov(tcg_ctx, s->pc, tmp, tmp2, MO_32, insn & (1 << 25));
} else {
tcg_gen_sub_i32(tcg_ctx, tmp, tmp2, tmp);
}
@@ -8277,6 +8285,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq
case 0x0a:
if (set_cc) {
gen_sub_CC(s, tmp, tmp, tmp2);
+ afl_gen_compcov(tcg_ctx, s->pc, tmp, tmp2, MO_32, insn & (1 << 25));
}
tcg_temp_free_i32(tcg_ctx, tmp);
break;
@@ -9148,7 +9157,7 @@ thumb2_logic_op(int op)
static int
gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
- TCGv_i32 t0, TCGv_i32 t1)
+ TCGv_i32 t0, TCGv_i32 t1, int has_imm)
{
TCGContext *tcg_ctx = s->uc->tcg_ctx;
int logic_cc;
@@ -9195,15 +9204,17 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
}
break;
case 13: /* sub */
- if (conds)
+ if (conds) {
gen_sub_CC(s, t0, t0, t1);
- else
+ afl_gen_compcov(tcg_ctx, s->pc, t0, t1, MO_32, has_imm);
+ } else
tcg_gen_sub_i32(tcg_ctx, t0, t0, t1);
break;
case 14: /* rsb */
- if (conds)
+ if (conds) {
gen_sub_CC(s, t0, t1, t0);
- else
+ afl_gen_compcov(tcg_ctx, s->pc, t0, t1, MO_32, has_imm);
+ } else
tcg_gen_sub_i32(tcg_ctx, t0, t1, t0);
break;
default: /* 5, 6, 7, 9, 12, 15. */
@@ -9572,7 +9583,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
conds = (insn & (1 << 20)) != 0;
logic_cc = (conds && thumb2_logic_op(op));
gen_arm_shift_im(s, tmp2, shiftop, shift, logic_cc);
- if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
+ if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2, insn & (1 << 10)))
goto illegal_op;
tcg_temp_free_i32(tcg_ctx, tmp2);
if (rd != 15) {
@@ -10215,7 +10226,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
}
op = (insn >> 21) & 0xf;
if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
- shifter_out, tmp, tmp2))
+ shifter_out, tmp, tmp2, insn & (1 << 10)))
goto illegal_op;
tcg_temp_free_i32(tcg_ctx, tmp2);
rd = (insn >> 8) & 0xf;
@@ -10471,8 +10482,10 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
if (insn & (1 << 9)) {
if (s->condexec_mask)
tcg_gen_sub_i32(tcg_ctx, tmp, tmp, tmp2);
- else
+ else {
gen_sub_CC(s, tmp, tmp, tmp2);
+ afl_gen_compcov(tcg_ctx, s->pc, tmp, tmp2, MO_32, insn & (1 << 10));
+ }
} else {
if (s->condexec_mask)
tcg_gen_add_i32(tcg_ctx, tmp, tmp, tmp2);
@@ -10509,6 +10522,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
switch (op) {
case 1: /* cmp */
gen_sub_CC(s, tmp, tmp, tmp2);
+ afl_gen_compcov(tcg_ctx, s->pc, tmp, tmp2, MO_32, 1);
tcg_temp_free_i32(tcg_ctx, tmp);
tcg_temp_free_i32(tcg_ctx, tmp2);
break;
@@ -10523,8 +10537,10 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
case 3: /* sub */
if (s->condexec_mask)
tcg_gen_sub_i32(tcg_ctx, tmp, tmp, tmp2);
- else
+ else {
gen_sub_CC(s, tmp, tmp, tmp2);
+ afl_gen_compcov(tcg_ctx, s->pc, tmp, tmp2, MO_32, 1);
+ }
tcg_temp_free_i32(tcg_ctx, tmp2);
store_reg(s, rd, tmp);
break;
@@ -10562,6 +10578,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
tmp = load_reg(s, rd);
tmp2 = load_reg(s, rm);
gen_sub_CC(s, tmp, tmp, tmp2);
+ afl_gen_compcov(tcg_ctx, s->pc, tmp, tmp2, MO_32, 0);
tcg_temp_free_i32(tcg_ctx, tmp2);
tcg_temp_free_i32(tcg_ctx, tmp);
break;
@@ -10680,6 +10697,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq
break;
case 0xa: /* cmp */
gen_sub_CC(s, tmp, tmp, tmp2);
+ afl_gen_compcov(tcg_ctx, s->pc, tmp, tmp2, MO_32, 0);
rd = 16;
break;
case 0xb: /* cmn */
diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c
index 36fae09..196d346 100644
--- a/qemu/target-i386/translate.c
+++ b/qemu/target-i386/translate.c
@@ -33,6 +33,12 @@
#include "uc_priv.h"
+#if defined(UNICORN_AFL)
+#include "../../afl-unicorn-cpu-translate-inl.h"
+#else
+#define afl_gen_compcov(a,b,c,d,e,f) do {} while (0)
+#endif
+
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 0x04
@@ -1555,6 +1561,7 @@ static void gen_op(DisasContext *s, int op, TCGMemOp ot, int d)
case OP_SUBL:
tcg_gen_mov_tl(tcg_ctx, cpu_cc_srcT, *cpu_T[0]);
tcg_gen_sub_tl(tcg_ctx, *cpu_T[0], *cpu_T[0], *cpu_T[1]);
+ afl_gen_compcov(tcg_ctx, s->pc, *cpu_T[0], *cpu_T[1], ot, d == OR_EAX);
gen_op_st_rm_T0_A0(s, ot, d);
gen_op_update2_cc(tcg_ctx);
set_cc_op(s, CC_OP_SUBB + ot);
@@ -1582,6 +1589,7 @@ static void gen_op(DisasContext *s, int op, TCGMemOp ot, int d)
tcg_gen_mov_tl(tcg_ctx, cpu_cc_src, *cpu_T[1]);
tcg_gen_mov_tl(tcg_ctx, cpu_cc_srcT, *cpu_T[0]);
tcg_gen_sub_tl(tcg_ctx, cpu_cc_dst, *cpu_T[0], *cpu_T[1]);
+ afl_gen_compcov(tcg_ctx, s->pc, *cpu_T[0], *cpu_T[1], ot, d == OR_EAX);
set_cc_op(s, CC_OP_SUBB + ot);
break;
}
diff --git a/qemu/tcg-runtime.c b/qemu/tcg-runtime.c
index 21b022a..14d7891 100644
--- a/qemu/tcg-runtime.c
+++ b/qemu/tcg-runtime.c
@@ -31,9 +31,14 @@
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2));
+#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
+ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), dh_ctype(t4));
#include "tcg-runtime.h"
+#ifdef UNICORN_AFL
+#include "../afl-unicorn-tcg-runtime-inl.h"
+#endif
/* 32-bit helpers */
diff --git a/qemu/tcg/tcg-op.h b/qemu/tcg/tcg-op.h
index 38b7dd9..c5a9af9 100644
--- a/qemu/tcg/tcg-op.h
+++ b/qemu/tcg/tcg-op.h
@@ -27,6 +27,10 @@
int gen_new_label(TCGContext *);
+#ifdef UNICORN_AFL
+#include "../../afl-unicorn-tcg-op-inl.h"
+#endif
+
static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, int32_t type, void *uc, uint64_t pc)
{
TCGv_i32 tsize = tcg_const_i32(tcg_ctx, size);
diff --git a/qemu/tcg/tcg-runtime.h b/qemu/tcg/tcg-runtime.h
index 23a0c37..90b993c 100644
--- a/qemu/tcg/tcg-runtime.h
+++ b/qemu/tcg/tcg-runtime.h
@@ -14,3 +14,9 @@ DEF_HELPER_FLAGS_2(sar_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
DEF_HELPER_FLAGS_2(mulsh_i64, TCG_CALL_NO_RWG_SE, s64, s64, s64)
DEF_HELPER_FLAGS_2(muluh_i64, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+
+#ifdef UNICORN_AFL
+DEF_HELPER_FLAGS_4(afl_compcov_log_16, 0, void, ptr, i64, i64, i64)
+DEF_HELPER_FLAGS_4(afl_compcov_log_32, 0, void, ptr, i64, i64, i64)
+DEF_HELPER_FLAGS_4(afl_compcov_log_64, 0, void, ptr, i64, i64, i64)
+#endif
diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h
index 8dcbb3e..11e18b4 100644
--- a/qemu/unicorn_common.h
+++ b/qemu/unicorn_common.h
@@ -84,6 +84,10 @@ static inline void uc_common_init(struct uc_struct* uc)
if (!uc->release)
uc->release = release_common;
+
+#ifdef UNICORN_AFL
+ uc->afl_area_ptr = 0;
+#endif
}
#endif

View File

@ -1,107 +0,0 @@
diff --git a/Makefile b/Makefile
index 7d73782..fb3ccfd 100644
--- a/Makefile
+++ b/Makefile
@@ -88,6 +88,10 @@ AR = llvm-ar
LDFLAGS := -fsanitize=address ${LDFLAGS}
endif
+ifeq ($(UNICORN_AFL),yes)
+UNICORN_CFLAGS += -DUNICORN_AFL
+endif
+
ifeq ($(CROSS),)
CC ?= cc
AR ?= ar
diff --git a/config.mk b/config.mk
index c3621fb..c7b4f7e 100644
--- a/config.mk
+++ b/config.mk
@@ -8,7 +8,7 @@
# Compile with debug info when you want to debug code.
# Change this to 'no' for release edition.
-UNICORN_DEBUG ?= yes
+UNICORN_DEBUG ?= no
################################################################################
# Specify which archs you want to compile in. By default, we build all archs.
@@ -28,3 +28,9 @@ UNICORN_STATIC ?= yes
# a shared library.
UNICORN_SHARED ?= yes
+
+
+################################################################################
+# Changing 'UNICORN_AFLL = yes' to 'UNICORN_AFL = no' disables AFL instrumentation
+
+UNICORN_AFL ?= yes
diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c
index 7755adf..8114b70 100644
--- a/qemu/cpu-exec.c
+++ b/qemu/cpu-exec.c
@@ -24,6 +24,11 @@
#include "uc_priv.h"
+#if defined(UNICORN_AFL)
+#include "../afl-unicorn-cpu-inl.h"
+static int afl_first_instr = 0;
+#endif
+
static tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr);
static TranslationBlock *tb_find_slow(CPUArchState *env, target_ulong pc,
target_ulong cs_base, uint64_t flags);
@@ -231,6 +236,10 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq
next_tb & TB_EXIT_MASK, tb);
}
+#if defined(UNICORN_AFL)
+ AFL_UNICORN_CPU_SNIPPET2;
+#endif
+
/* cpu_interrupt might be called while translating the
TB, but before it is linked into a potentially
infinite loop and becomes env->current_tb. Avoid
@@ -369,6 +378,11 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, target_ulong pc,
not_found:
/* if no translated code available, then translate it now */
tb = tb_gen_code(cpu, pc, cs_base, (int)flags, 0); // qq
+
+#if defined(UNICORN_AFL)
+ /* There seems to be no chaining in unicorn ever? :( */
+ AFL_UNICORN_CPU_SNIPPET1;
+#endif
found:
/* Move the last found TB to the head of the list */
diff --git a/qemu/translate-all.c b/qemu/translate-all.c
index 1a96c34..7ef4878 100644
--- a/qemu/translate-all.c
+++ b/qemu/translate-all.c
@@ -403,11 +403,25 @@ static PageDesc *page_find_alloc(struct uc_struct *uc, tb_page_addr_t index, int
#if defined(CONFIG_USER_ONLY)
/* We can't use g_malloc because it may recurse into a locked mutex. */
+#if defined(UNICORN_AFL)
+ /* This was added by unicorn-afl to bail out semi-gracefully if out of memory. */
+# define ALLOC(P, SIZE) \
+ do { \
+ void* _tmp = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
+ if (_tmp == (void*)-1) { \
+ qemu_log(">>> Out of memory for stack, bailing out. <<<\n"); \
+ exit(1); \
+ } \
+ (P) = _tmp; \
+ } while (0)
+#else /* !UNICORN_AFL */
# define ALLOC(P, SIZE) \
do { \
P = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
} while (0)
+#endif /* UNICORN_AFL */
#else
# define ALLOC(P, SIZE) \
do { P = g_malloc0(SIZE); } while (0)