conflicts

This commit is contained in:
Andrea Fioraldi 2020-09-08 11:19:17 +02:00
commit 10f775be07
34 changed files with 91 additions and 2792 deletions

3
.gitmodules vendored
View File

@ -5,3 +5,6 @@
[submodule "custom_mutators/Grammar-Mutator"]
path = custom_mutators/Grammar-Mutator
url = https://github.com/AFLplusplus/Grammar-Mutator
[submodule "qemu_mode/qemuafl"]
path = qemu_mode/qemuafl
url = https://github.com/AFLplusplus/qemuafl.git

View File

@ -22,10 +22,10 @@ matrix:
- os: linux
dist: trusty
env: NAME="trusty-amd64" MODERN="no" GCC="4.8"
# - os: linux # until travis can fix this!
# dist: xenial
# arch: arm64
# env: NAME="xenial-arm64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0" AFL_NO_X86="1" CPU_TARGET="aarch64"
- os: linux # until travis can fix this!
dist: xenial
arch: arm64
env: NAME="xenial-arm64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0" AFL_NO_X86="1" CPU_TARGET="aarch64"
# - os: osx
# osx_image: xcode11.2
# env: NAME="osx" HOMEBREW_NO_ANALYTICS="1" LINK="http://releases.llvm.org/9.0.0/" NAME="clang+llvm-9.0.0-x86_64-darwin-apple"

View File

@ -29,7 +29,6 @@
#define _AFL_CMPLOG_H
#include "config.h"
#include "forkserver.h"
#define CMP_MAP_W 65536
#define CMP_MAP_H 256
@ -77,7 +76,8 @@ struct cmp_map {
/* Execs the child */
void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv);
struct afl_forkserver;
void cmplog_exec_child(struct afl_forkserver *fsrv, char **argv);
#endif

View File

@ -0,0 +1 @@
eee265a3df

View File

@ -29,13 +29,10 @@
# will be written to ../afl-qemu-trace.
#
VERSION="3.1.1"
QEMU_URL="http://download.qemu-project.org/qemu-${VERSION}.tar.xz"
QEMU_SHA384="28ff22ec4b8c957309460aa55d0b3188e971be1ea7dfebfb2ecc7903cd20cfebc2a7c97eedfcc7595f708357f1623f8b"
QEMUAFL_VERSION="$(cat ./QEMUAFL_VERSION)"
echo "================================================="
echo "AFL binary-only instrumentation QEMU build script"
echo " QemuAFL build script"
echo "================================================="
echo
@ -48,7 +45,7 @@ if [ ! "`uname -s`" = "Linux" ]; then
fi
if [ ! -f "patches/afl-qemu-cpu-inl.h" -o ! -f "../config.h" ]; then
if [ ! -f "../config.h" ]; then
echo "[-] Error: key files not found - wrong working directory?"
exit 1
@ -111,41 +108,38 @@ fi
echo "[+] All checks passed!"
ARCHIVE="`basename -- "$QEMU_URL"`"
CKSUM=`sha384sum -- "$ARCHIVE" 2>/dev/null | cut -d' ' -f1`
if [ ! "$CKSUM" = "$QEMU_SHA384" ]; then
echo "[*] Downloading QEMU ${VERSION} from the web..."
rm -f "$ARCHIVE"
OK=
while [ -z "$OK" ]; do
wget -c -O "$ARCHIVE" -- "$QEMU_URL" && OK=1
done
CKSUM=`sha384sum -- "$ARCHIVE" 2>/dev/null | cut -d' ' -f1`
fi
if [ "$CKSUM" = "$QEMU_SHA384" ]; then
echo "[+] Cryptographic signature on $ARCHIVE checks out."
echo "[*] Making sure qemuafl is checked out"
git status 1>/dev/null 2>/dev/null
if [ $? -eq 0 ]; then
echo "[*] initializing qemuafl submodule"
git submodule init || exit 1
git submodule update 2>/dev/null # ignore errors
else
echo "[-] Error: signature mismatch on $ARCHIVE (perhaps download error?), removing archive ..."
rm -f "$ARCHIVE"
exit 1
echo "[*] cloning qemuafl"
test -d qemuafl || {
CNT=1
while [ '!' -d qemuafl -a "$CNT" -lt 4 ]; do
echo "Trying to clone qemuafl (attempt $CNT/3)"
git clone https://github.com/AFLplusplus/qemuafl
CNT=`expr "$CNT" + 1`
done
}
fi
echo "[*] Uncompressing archive (this will take a while)..."
test -d qemuafl || { echo "[-] Not checked out, please install git or check your internet connection." ; exit 1 ; }
echo "[+] Got qemuafl."
rm -rf "qemu-${VERSION}" || exit 1
tar xf "$ARCHIVE" || exit 1
cd "qemuafl" || exit 1
echo "[*] Checking out $QEMUAFL_VERSION"
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
git checkout "$QEMUAFL_VERSION" || exit 1
echo "[+] Unpacking successful."
echo "[*] Making sure imported headers matches"
cp "../../include/config.h" "./qemuafl/imported/" || exit 1
cp "../../include/cmplog.h" "./qemuafl/imported/" || exit 1
cp "../../include/snapshot-inl.h" "./qemuafl/imported/" || exit 1
cp "../../include/types.h" "./qemuafl/imported/" || exit 1
if [ -n "$HOST" ]; then
echo "[+] Configuring host architecture to $HOST..."
@ -169,34 +163,7 @@ if [ "$ORIG_CPU_TARGET" = "" ]; then
esac
fi
cd qemu-$VERSION || exit 1
echo Building for CPU target $CPU_TARGET
echo "[*] Applying patches..."
patch -p1 <../patches/elfload.diff || exit 1
patch -p1 <../patches/mips-fpu.diff || exit 1
patch -p1 <../patches/bsd-elfload.diff || exit 1
patch -p1 <../patches/cpu-exec.diff || exit 1
patch -p1 <../patches/syscall.diff || exit 1
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/arm-translate-a64.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
patch -p1 <../patches/configure.diff || exit 1
patch -p1 <../patches/tcg-runtime.diff || exit 1
patch -p1 <../patches/tcg-runtime-head.diff || exit 1
patch -p1 <../patches/translator.diff || exit 1
patch -p1 <../patches/__init__.py.diff || exit 1
patch -p1 <../patches/make_strncpy_safe.diff || exit 1
patch -p1 <../patches/mmap_fixes.diff || exit 1
echo "[+] Patching done."
echo "Building for CPU target $CPU_TARGET"
if [ "$STATIC" = "1" ]; then
@ -211,7 +178,7 @@ if [ "$STATIC" = "1" ]; then
--disable-sdl --disable-seccomp --disable-smartcard --disable-snappy --disable-spice --disable-libssh2 \
--disable-libusb --disable-usb-redir --disable-vde --disable-vhost-net --disable-virglrenderer \
--disable-virtfs --disable-vnc --disable-vte --disable-xen --disable-xen-pci-passthrough --disable-xfsctl \
--enable-linux-user --disable-system --disable-blobs --disable-tools --enable-capstone=internal \
--enable-linux-user --disable-system --disable-blobs --disable-tools \
--target-list="${CPU_TARGET}-linux-user" --static --disable-pie --cross-prefix=$CROSS_PREFIX --python="$PYTHONBIN" \
|| exit 1
@ -221,7 +188,7 @@ else
# improvement, much to my surprise. Not sure how universal this is..
./configure --disable-system \
--enable-linux-user --disable-gtk --disable-sdl --disable-vnc --enable-capstone=internal \
--enable-linux-user --disable-gtk --disable-sdl --disable-vnc --disable-werror \
--target-list="${CPU_TARGET}-linux-user" --enable-pie $CROSS_PREFIX --python="$PYTHONBIN" || exit 1
fi
@ -236,7 +203,7 @@ echo "[+] Build process successful!"
echo "[*] Copying binary..."
cp -f "${CPU_TARGET}-linux-user/qemu-${CPU_TARGET}" "../../afl-qemu-trace" || exit 1
cp -f "build/${CPU_TARGET}-linux-user/qemu-${CPU_TARGET}" "../../afl-qemu-trace" || exit 1
cd ..
ls -l ../afl-qemu-trace || exit 1

View File

@ -1,17 +0,0 @@
--- a/scripts/tracetool/__init__.py 2020-03-28 13:42:21.937700726 +0100
+++ b/scripts/tracetool/__init__.py 2020-03-28 13:41:50.991034257 +0100
@@ -447,12 +447,12 @@
import tracetool
format = str(format)
- if len(format) is 0:
+ if len(format) == 0:
raise TracetoolError("format not set")
if not tracetool.format.exists(format):
raise TracetoolError("unknown format: %s" % format)
- if len(backends) is 0:
+ if len(backends) == 0:
raise TracetoolError("no backends specified")
for backend in backends:
if not tracetool.backend.exists(backend):

View File

@ -1,130 +0,0 @@
/*
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-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 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.
*/
#ifndef __AFL_QEMU_COMMON
#define __AFL_QEMU_COMMON
#include "../../config.h"
#include "../../include/cmplog.h"
#define PERSISTENT_DEFAULT_MAX_CNT 1000
#ifdef CPU_NB_REGS
#define AFL_REGS_NUM CPU_NB_REGS
#elif TARGET_ARM
#define AFL_REGS_NUM 16
#elif TARGET_AARCH64
#define AFL_REGS_NUM 32
#else
#define AFL_REGS_NUM 100
#endif
/* NeverZero */
#if (defined(__x86_64__) || defined(__i386__)) && defined(AFL_QEMU_NOT_ZERO)
#define INC_AFL_AREA(loc) \
asm volatile( \
"addb $1, (%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
typedef void (*afl_persistent_hook_fn)(uint64_t *regs, uint64_t guest_base,
uint8_t *input_buf,
uint32_t input_buf_len);
/* Declared in afl-qemu-cpu-inl.h */
extern unsigned char *afl_area_ptr;
extern unsigned int afl_inst_rms;
extern abi_ulong afl_entry_point, afl_start_code, afl_end_code;
extern abi_ulong afl_persistent_addr;
extern abi_ulong afl_persistent_ret_addr;
extern u8 afl_compcov_level;
extern unsigned char afl_fork_child;
extern unsigned char is_persistent;
extern target_long persistent_stack_offset;
extern unsigned char persistent_first_pass;
extern unsigned char persistent_save_gpr;
extern uint64_t persistent_saved_gpr[AFL_REGS_NUM];
extern int persisent_retaddr_offset;
extern u8 * shared_buf;
extern u32 *shared_buf_len;
extern u8 sharedmem_fuzzing;
extern afl_persistent_hook_fn afl_persistent_hook_ptr;
extern __thread abi_ulong afl_prev_loc;
extern struct cmp_map *__afl_cmp_map;
extern __thread u32 __afl_cmp_counter;
void afl_setup(void);
void afl_forkserver(CPUState *cpu);
// void afl_debug_dump_saved_regs(void);
void afl_persistent_loop(void);
void afl_gen_tcg_plain_call(void *func);
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 */
static inline int is_valid_addr(target_ulong addr) {
int flags;
target_ulong page;
page = addr & TARGET_PAGE_MASK;
flags = page_get_flags(page);
if (!(flags & PAGE_VALID) || !(flags & PAGE_READ)) return 0;
return 1;
}
#endif

View File

@ -1,640 +0,0 @@
/*
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-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 QEMU 3.1.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 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 <sys/shm.h>
#include "afl-qemu-common.h"
#ifndef AFL_QEMU_STATIC_BUILD
#include <dlfcn.h>
#endif
/***************************
* VARIOUS AUXILIARY STUFF *
***************************/
/* We use one additional file descriptor to relay "needs translation"
messages between the child and the fork server. */
#define TSL_FD (FORKSRV_FD - 1)
/* This is equivalent to afl-as.h: */
static unsigned char
dummy[MAP_SIZE]; /* costs MAP_SIZE but saves a few instructions */
unsigned char *afl_area_ptr = dummy; /* Exported for afl_gen_trace */
/* Exported variables populated by the code patched into elfload.c: */
abi_ulong afl_entry_point, /* ELF entry point (_start) */
afl_start_code, /* .text start pointer */
afl_end_code; /* .text end pointer */
abi_ulong afl_persistent_addr, afl_persistent_ret_addr;
unsigned int afl_persistent_cnt;
u8 afl_compcov_level;
__thread abi_ulong afl_prev_loc;
struct cmp_map *__afl_cmp_map;
__thread u32 __afl_cmp_counter;
/* Set in the child process in forkserver mode: */
static int forkserver_installed = 0;
static int disable_caching = 0;
unsigned char afl_fork_child;
unsigned int afl_forksrv_pid;
unsigned char is_persistent;
target_long persistent_stack_offset;
unsigned char persistent_first_pass = 1;
unsigned char persistent_save_gpr;
uint64_t persistent_saved_gpr[AFL_REGS_NUM];
int persisent_retaddr_offset;
u8 * shared_buf;
u32 *shared_buf_len;
u8 sharedmem_fuzzing;
afl_persistent_hook_fn afl_persistent_hook_ptr;
/* Instrumentation ratio: */
unsigned int afl_inst_rms = MAP_SIZE; /* Exported for afl_gen_trace */
/* Function declarations. */
static void afl_wait_tsl(CPUState *, int);
static void afl_request_tsl(target_ulong, target_ulong, uint32_t, uint32_t,
TranslationBlock *, int);
/* Data structures passed around by the translate handlers: */
struct afl_tb {
target_ulong pc;
target_ulong cs_base;
uint32_t flags;
uint32_t cf_mask;
};
struct afl_tsl {
struct afl_tb tb;
char is_chain;
};
struct afl_chain {
struct afl_tb last_tb;
uint32_t cf_mask;
int tb_exit;
};
/* Some forward decls: */
static inline TranslationBlock *tb_find(CPUState *, TranslationBlock *, int,
uint32_t);
static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next);
int open_self_maps(void *cpu_env, int fd);
static void afl_map_shm_fuzz(void);
/*************************
* ACTUAL IMPLEMENTATION *
*************************/
/* Set up SHM region and initialize other stuff. */
static void afl_map_shm_fuzz(void) {
char *id_str = getenv(SHM_FUZZ_ENV_VAR);
if (id_str) {
u32 shm_id = atoi(id_str);
u8 *map = (u8 *)shmat(shm_id, NULL, 0);
/* Whooooops. */
if (!map || map == (void *)-1) {
perror("[AFL] ERROR: could not access fuzzing shared memory");
exit(1);
}
shared_buf_len = (u32 *)map;
shared_buf = map + sizeof(u32);
if (getenv("AFL_DEBUG")) {
fprintf(stderr, "[AFL] DEBUG: successfully got fuzzing shared memory\n");
}
} else {
fprintf(stderr,
"[AFL] ERROR: variable for fuzzing shared memory is not set\n");
exit(1);
}
}
void afl_setup(void) {
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;
afl_inst_rms = MAP_SIZE * r / 100;
}
if (id_str) {
shm_id = atoi(id_str);
afl_area_ptr = shmat(shm_id, NULL, 0);
if (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) afl_area_ptr[0] = 1;
}
if (getenv("___AFL_EINS_ZWEI_POLIZEI___")) { // CmpLog forkserver
id_str = getenv(CMPLOG_SHM_ENV_VAR);
if (id_str) {
u32 shm_id = atoi(id_str);
__afl_cmp_map = shmat(shm_id, NULL, 0);
if (__afl_cmp_map == (void *)-1) exit(1);
}
}
if (getenv("AFL_INST_LIBS")) {
afl_start_code = 0;
afl_end_code = (abi_ulong)-1;
}
if (getenv("AFL_CODE_START"))
afl_start_code = strtoll(getenv("AFL_CODE_START"), NULL, 16);
if (getenv("AFL_CODE_END"))
afl_end_code = strtoll(getenv("AFL_CODE_END"), NULL, 16);
/* Maintain for compatibility */
if (getenv("AFL_QEMU_COMPCOV")) { afl_compcov_level = 1; }
if (getenv("AFL_COMPCOV_LEVEL")) {
afl_compcov_level = atoi(getenv("AFL_COMPCOV_LEVEL"));
}
/* pthread_atfork() seems somewhat broken in util/rcu.c, and I'm
not entirely sure what is the cause. This disables that
behaviour, and seems to work alright? */
rcu_disable_atfork();
disable_caching = getenv("AFL_QEMU_DISABLE_CACHE") != NULL;
is_persistent = getenv("AFL_QEMU_PERSISTENT_ADDR") != NULL;
if (is_persistent) {
afl_persistent_addr = strtoll(getenv("AFL_QEMU_PERSISTENT_ADDR"), NULL, 0);
if (getenv("AFL_QEMU_PERSISTENT_RET"))
afl_persistent_ret_addr =
strtoll(getenv("AFL_QEMU_PERSISTENT_RET"), NULL, 0);
/* If AFL_QEMU_PERSISTENT_RET is not specified patch the return addr */
}
if (getenv("AFL_QEMU_PERSISTENT_GPR")) persistent_save_gpr = 1;
if (getenv("AFL_QEMU_PERSISTENT_HOOK")) {
#ifdef AFL_QEMU_STATIC_BUILD
fprintf(stderr,
"[AFL] ERROR: you cannot use AFL_QEMU_PERSISTENT_HOOK when "
"afl-qemu-trace is static\n");
exit(1);
#else
persistent_save_gpr = 1;
void *plib = dlopen(getenv("AFL_QEMU_PERSISTENT_HOOK"), RTLD_NOW);
if (!plib) {
fprintf(stderr, "[AFL] ERROR: invalid AFL_QEMU_PERSISTENT_HOOK=%s\n",
getenv("AFL_QEMU_PERSISTENT_HOOK"));
exit(1);
}
int (*afl_persistent_hook_init_ptr)(void) =
dlsym(plib, "afl_persistent_hook_init");
if (afl_persistent_hook_init_ptr)
sharedmem_fuzzing = afl_persistent_hook_init_ptr();
afl_persistent_hook_ptr = dlsym(plib, "afl_persistent_hook");
if (!afl_persistent_hook_ptr) {
fprintf(stderr,
"[AFL] ERROR: failed to find the function "
"\"afl_persistent_hook\" in %s\n",
getenv("AFL_QEMU_PERSISTENT_HOOK"));
exit(1);
}
#endif
}
if (getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"))
persisent_retaddr_offset =
strtoll(getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"), NULL, 0);
if (getenv("AFL_QEMU_PERSISTENT_CNT"))
afl_persistent_cnt = strtoll(getenv("AFL_QEMU_PERSISTENT_CNT"), NULL, 0);
else
afl_persistent_cnt = PERSISTENT_DEFAULT_MAX_CNT;
}
/* Fork server logic, invoked once we hit _start. */
void afl_forkserver(CPUState *cpu) {
// u32 map_size = 0;
unsigned char tmp[4] = {0};
if (forkserver_installed == 1) return;
forkserver_installed = 1;
if (getenv("AFL_QEMU_DEBUG_MAPS")) open_self_maps(cpu->env_ptr, 0);
// if (!afl_area_ptr) return; // not necessary because of fixed dummy buffer
pid_t child_pid;
int t_fd[2];
u8 child_stopped = 0;
u32 was_killed;
int status = 0;
// with the max ID value
if (MAP_SIZE <= FS_OPT_MAX_MAPSIZE)
status |= (FS_OPT_SET_MAPSIZE(MAP_SIZE) | FS_OPT_MAPSIZE);
if (sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ;
if (status) status |= (FS_OPT_ENABLED);
if (getenv("AFL_DEBUG"))
fprintf(stderr, "Debug: Sending status %08x\n", status);
memcpy(tmp, &status, 4);
/* 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();
int first_run = 1;
if (sharedmem_fuzzing) {
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
if ((was_killed & (0xffffffff & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ))) ==
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ))
afl_map_shm_fuzz();
else {
fprintf(stderr,
"[AFL] ERROR: afl-fuzz is old and does not support"
" shmem input");
exit(1);
}
}
/* All right, let's await orders... */
while (1) {
/* Whoops, parent dead? */
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
/* If we stopped the child in persistent mode, but there was a race
condition and afl-fuzz already issued SIGKILL, write off the old
process. */
if (child_stopped && was_killed) {
child_stopped = 0;
if (waitpid(child_pid, &status, 0) < 0) exit(8);
}
if (!child_stopped) {
/* 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);
} else {
/* Special handling for persistent mode: if the child is alive but
currently stopped, simply restart it with SIGCONT. */
kill(child_pid, SIGCONT);
child_stopped = 0;
}
/* Parent. */
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(5);
/* Collect translation requests until child dies and closes the pipe. */
afl_wait_tsl(cpu, t_fd[0]);
/* Get and relay exit status to parent. */
if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) exit(6);
/* In persistent mode, the child stops itself with SIGSTOP to indicate
a successful run. In this case, we want to wake it up without forking
again. */
if (WIFSTOPPED(status))
child_stopped = 1;
else if (unlikely(first_run && is_persistent)) {
fprintf(stderr, "[AFL] ERROR: no persistent iteration executed\n");
exit(12); // Persistent is wrong
}
first_run = 0;
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7);
}
}
/* A simplified persistent mode handler, used as explained in
* instrumentation/README.llvm.md */
void afl_persistent_loop(void) {
static u32 cycle_cnt;
static struct afl_tsl exit_cmd_tsl = {{-1, 0, 0, 0}, '\0'};
if (!afl_fork_child) return;
if (persistent_first_pass) {
/* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
On subsequent calls, the parent will take care of that, but on the first
iteration, it's our job to erase any trace of whatever happened
before the loop. */
if (is_persistent) {
memset(afl_area_ptr, 0, MAP_SIZE);
afl_area_ptr[0] = 1;
afl_prev_loc = 0;
}
cycle_cnt = afl_persistent_cnt;
persistent_first_pass = 0;
persistent_stack_offset = TARGET_LONG_BITS / 8;
return;
}
if (is_persistent) {
if (--cycle_cnt) {
if (write(TSL_FD, &exit_cmd_tsl, sizeof(struct afl_tsl)) !=
sizeof(struct afl_tsl)) {
/* Exit the persistent loop on pipe error */
afl_area_ptr = dummy;
exit(0);
}
raise(SIGSTOP);
afl_area_ptr[0] = 1;
afl_prev_loc = 0;
} else {
afl_area_ptr = dummy;
exit(0);
}
}
}
/* This code is invoked whenever QEMU decides that it doesn't have a
translation of a particular block and needs to compute it, or when it
decides to chain two TBs together. 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, uint32_t flags,
uint32_t cf_mask, TranslationBlock *last_tb,
int tb_exit) {
if (disable_caching) return;
struct afl_tsl t;
struct afl_chain c;
if (!afl_fork_child) return;
t.tb.pc = pc;
t.tb.cs_base = cb;
t.tb.flags = flags;
t.tb.cf_mask = cf_mask;
t.is_chain = (last_tb != NULL);
if (write(TSL_FD, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl))
return;
if (t.is_chain) {
c.last_tb.pc = last_tb->pc;
c.last_tb.cs_base = last_tb->cs_base;
c.last_tb.flags = last_tb->flags;
c.cf_mask = cf_mask;
c.tb_exit = tb_exit;
if (write(TSL_FD, &c, sizeof(struct afl_chain)) != sizeof(struct afl_chain))
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(CPUState *cpu, int fd) {
struct afl_tsl t;
struct afl_chain c;
TranslationBlock *tb, *last_tb;
while (1) {
u8 invalid_pc = 0;
/* 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;
/* Exit command for persistent */
if (t.tb.pc == (target_ulong)(-1)) return;
tb = tb_htable_lookup(cpu, t.tb.pc, t.tb.cs_base, t.tb.flags, t.tb.cf_mask);
if (!tb) {
/* The child may request to transate a block of memory that is not
mapped in the parent (e.g. jitted code or dlopened code).
This causes a SIGSEV in gen_intermediate_code() and associated
subroutines. We simply avoid caching of such blocks. */
if (is_valid_addr(t.tb.pc)) {
mmap_lock();
tb = tb_gen_code(cpu, t.tb.pc, t.tb.cs_base, t.tb.flags, t.tb.cf_mask);
mmap_unlock();
} else {
invalid_pc = 1;
}
}
if (t.is_chain) {
if (read(fd, &c, sizeof(struct afl_chain)) != sizeof(struct afl_chain))
break;
if (!invalid_pc) {
last_tb = tb_htable_lookup(cpu, c.last_tb.pc, c.last_tb.cs_base,
c.last_tb.flags, c.cf_mask);
#define TB_JMP_RESET_OFFSET_INVALID 0xffff
if (last_tb && (last_tb->jmp_reset_offset[c.tb_exit] !=
TB_JMP_RESET_OFFSET_INVALID)) {
tb_add_jump(last_tb, c.tb_exit, tb);
}
}
}
}
close(fd);
}

View File

@ -1,310 +0,0 @@
/*
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-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 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 "afl-qemu-common.h"
#include "tcg.h"
#include "tcg-op.h"
#if TCG_TARGET_REG_BITS == 64
#define _DEFAULT_MO MO_64
#else
#define _DEFAULT_MO MO_32
#endif
static void afl_gen_compcov(target_ulong cur_loc, TCGv arg1, TCGv arg2,
TCGMemOp ot, int is_imm) {
if (cur_loc > afl_end_code || cur_loc < afl_start_code) return;
if (__afl_cmp_map) {
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= CMP_MAP_W - 1;
TCGv cur_loc_v = tcg_const_tl(cur_loc);
switch (ot & MO_SIZE) {
case MO_64:
gen_helper_afl_cmplog_64(cur_loc_v, arg1, arg2);
break;
case MO_32:
gen_helper_afl_cmplog_32(cur_loc_v, arg1, arg2);
break;
case MO_16:
gen_helper_afl_cmplog_16(cur_loc_v, arg1, arg2);
break;
case MO_8:
gen_helper_afl_cmplog_8(cur_loc_v, arg1, arg2);
break;
default:
break;
}
tcg_temp_free(cur_loc_v);
} else if (afl_compcov_level) {
if (!is_imm && afl_compcov_level < 2) return;
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 7;
TCGv cur_loc_v = tcg_const_tl(cur_loc);
if (cur_loc >= afl_inst_rms) return;
switch (ot & MO_SIZE) {
case MO_64:
gen_helper_afl_compcov_64(cur_loc_v, arg1, arg2);
break;
case MO_32:
gen_helper_afl_compcov_32(cur_loc_v, arg1, arg2);
break;
case MO_16:
gen_helper_afl_compcov_16(cur_loc_v, arg1, arg2);
break;
default:
break;
}
tcg_temp_free(cur_loc_v);
}
}
/* Routines for debug */
/*
static void log_x86_saved_gpr(void) {
static const char reg_names[CPU_NB_REGS][4] = {
#ifdef TARGET_X86_64
[R_EAX] = "rax",
[R_EBX] = "rbx",
[R_ECX] = "rcx",
[R_EDX] = "rdx",
[R_ESI] = "rsi",
[R_EDI] = "rdi",
[R_EBP] = "rbp",
[R_ESP] = "rsp",
[8] = "r8",
[9] = "r9",
[10] = "r10",
[11] = "r11",
[12] = "r12",
[13] = "r13",
[14] = "r14",
[15] = "r15",
#else
[R_EAX] = "eax",
[R_EBX] = "ebx",
[R_ECX] = "ecx",
[R_EDX] = "edx",
[R_ESI] = "esi",
[R_EDI] = "edi",
[R_EBP] = "ebp",
[R_ESP] = "esp",
#endif
};
int i;
for (i = 0; i < CPU_NB_REGS; ++i) {
fprintf(stderr, "%s = %lx\n", reg_names[i], persistent_saved_gpr[i]);
}
}
static void log_x86_sp_content(void) {
fprintf(stderr, ">> SP = %lx -> %lx\n", persistent_saved_gpr[R_ESP],
*(unsigned long*)persistent_saved_gpr[R_ESP]);
}*/
static void callback_to_persistent_hook(void) {
afl_persistent_hook_ptr(persistent_saved_gpr, guest_base, shared_buf,
*shared_buf_len);
}
static void gpr_saving(TCGv *cpu_regs, int regs_num) {
int i;
TCGv_ptr gpr_sv;
TCGv_ptr first_pass_ptr = tcg_const_ptr(&persistent_first_pass);
TCGv first_pass = tcg_temp_local_new();
TCGv one = tcg_const_tl(1);
tcg_gen_ld8u_tl(first_pass, first_pass_ptr, 0);
TCGLabel *lbl_restore_gpr = gen_new_label();
tcg_gen_brcond_tl(TCG_COND_NE, first_pass, one, lbl_restore_gpr);
// save GPR registers
for (i = 0; i < regs_num; ++i) {
gpr_sv = tcg_const_ptr(&persistent_saved_gpr[i]);
tcg_gen_st_tl(cpu_regs[i], gpr_sv, 0);
tcg_temp_free_ptr(gpr_sv);
}
gen_set_label(lbl_restore_gpr);
afl_gen_tcg_plain_call(&afl_persistent_loop);
if (afl_persistent_hook_ptr)
afl_gen_tcg_plain_call(callback_to_persistent_hook);
// restore GPR registers
for (i = 0; i < regs_num; ++i) {
gpr_sv = tcg_const_ptr(&persistent_saved_gpr[i]);
tcg_gen_ld_tl(cpu_regs[i], gpr_sv, 0);
tcg_temp_free_ptr(gpr_sv);
}
tcg_temp_free_ptr(first_pass_ptr);
tcg_temp_free(first_pass);
tcg_temp_free(one);
}
static void restore_state_for_persistent(TCGv *cpu_regs, int regs_num, int sp) {
if (persistent_save_gpr) {
gpr_saving(cpu_regs, regs_num);
} else if (afl_persistent_ret_addr == 0) {
TCGv_ptr stack_off_ptr = tcg_const_ptr(&persistent_stack_offset);
TCGv stack_off = tcg_temp_new();
tcg_gen_ld_tl(stack_off, stack_off_ptr, 0);
tcg_gen_sub_tl(cpu_regs[sp], cpu_regs[sp], stack_off);
tcg_temp_free(stack_off);
}
}
#define AFL_QEMU_TARGET_I386_SNIPPET \
if (is_persistent) { \
\
if (s->pc == afl_persistent_addr) { \
\
restore_state_for_persistent(cpu_regs, AFL_REGS_NUM, R_ESP); \
/*afl_gen_tcg_plain_call(log_x86_saved_gpr); \
afl_gen_tcg_plain_call(log_x86_sp_content);*/ \
\
if (afl_persistent_ret_addr == 0) { \
\
TCGv paddr = tcg_const_tl(afl_persistent_addr); \
tcg_gen_qemu_st_tl(paddr, cpu_regs[R_ESP], persisent_retaddr_offset, \
_DEFAULT_MO); \
tcg_temp_free(paddr); \
\
} \
\
if (!persistent_save_gpr) afl_gen_tcg_plain_call(&afl_persistent_loop); \
/*afl_gen_tcg_plain_call(log_x86_sp_content);*/ \
\
} else if (afl_persistent_ret_addr && s->pc == afl_persistent_ret_addr) { \
\
gen_jmp_im(s, afl_persistent_addr); \
gen_eob(s); \
\
} \
\
}
// SP = 13, LINK = 14
#define AFL_QEMU_TARGET_ARM_SNIPPET \
if (is_persistent) { \
\
if (dc->pc == afl_persistent_addr) { \
\
if (persistent_save_gpr) gpr_saving(cpu_R, AFL_REGS_NUM); \
\
if (afl_persistent_ret_addr == 0) { \
\
tcg_gen_movi_tl(cpu_R[14], afl_persistent_addr); \
\
} \
\
if (!persistent_save_gpr) afl_gen_tcg_plain_call(&afl_persistent_loop); \
\
} else if (afl_persistent_ret_addr && dc->pc == afl_persistent_ret_addr) { \
\
gen_bx_im(dc, afl_persistent_addr); \
\
} \
\
}
// SP = 31, LINK = 30
#define AFL_QEMU_TARGET_ARM64_SNIPPET \
if (is_persistent) { \
\
if (s->pc == afl_persistent_addr) { \
\
if (persistent_save_gpr) gpr_saving(cpu_X, AFL_REGS_NUM); \
\
if (afl_persistent_ret_addr == 0) { \
\
tcg_gen_movi_tl(cpu_X[30], afl_persistent_addr); \
\
} \
\
if (!persistent_save_gpr) afl_gen_tcg_plain_call(&afl_persistent_loop); \
\
} else if (afl_persistent_ret_addr && s->pc == afl_persistent_ret_addr) { \
\
gen_goto_tb(s, 0, afl_persistent_addr); \
\
} \
\
}

View File

@ -1,223 +0,0 @@
/*
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-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 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 {
float32 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);
}
}
}
}
}
}
}
}

View File

@ -1,46 +0,0 @@
/*
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-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 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.
*/
void afl_gen_tcg_plain_call(void *func);
void afl_gen_tcg_plain_call(void *func) {
TCGOp *op = tcg_emit_op(INDEX_op_call);
TCGOP_CALLO(op) = 0;
op->args[0] = (uintptr_t)func;
op->args[1] = 0;
TCGOP_CALLI(op) = 0;
}

View File

@ -1,250 +0,0 @@
/*
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-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 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 "afl-qemu-common.h"
#include "tcg.h"
void HELPER(afl_entry_routine)(CPUArchState *env) {
afl_forkserver(ENV_GET_CPU(env));
}
void HELPER(afl_compcov_16)(target_ulong cur_loc, target_ulong arg1,
target_ulong arg2) {
register uintptr_t idx = cur_loc;
if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(idx); }
}
void HELPER(afl_compcov_32)(target_ulong cur_loc, target_ulong arg1,
target_ulong arg2) {
register uintptr_t idx = cur_loc;
if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) {
INC_AFL_AREA(idx + 2);
if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) {
INC_AFL_AREA(idx + 1);
if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(idx); }
}
}
}
void HELPER(afl_compcov_64)(target_ulong cur_loc, target_ulong arg1,
target_ulong arg2) {
register uintptr_t idx = cur_loc;
if ((arg1 & 0xff00000000000000) == (arg2 & 0xff00000000000000)) {
INC_AFL_AREA(idx + 6);
if ((arg1 & 0xff000000000000) == (arg2 & 0xff000000000000)) {
INC_AFL_AREA(idx + 5);
if ((arg1 & 0xff0000000000) == (arg2 & 0xff0000000000)) {
INC_AFL_AREA(idx + 4);
if ((arg1 & 0xff00000000) == (arg2 & 0xff00000000)) {
INC_AFL_AREA(idx + 3);
if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) {
INC_AFL_AREA(idx + 2);
if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) {
INC_AFL_AREA(idx + 1);
if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(idx); }
}
}
}
}
}
}
}
void HELPER(afl_cmplog_8)(target_ulong cur_loc, target_ulong arg1,
target_ulong arg2) {
register uintptr_t k = (uintptr_t)cur_loc;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
// if (!__afl_cmp_map->headers[k].cnt)
// __afl_cmp_map->headers[k].cnt = __afl_cmp_counter++;
__afl_cmp_map->headers[k].shape = 0;
hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = arg1;
__afl_cmp_map->log[k][hits].v1 = arg2;
}
void HELPER(afl_cmplog_16)(target_ulong cur_loc, target_ulong arg1,
target_ulong arg2) {
register uintptr_t k = (uintptr_t)cur_loc;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
// if (!__afl_cmp_map->headers[k].cnt)
// __afl_cmp_map->headers[k].cnt = __afl_cmp_counter++;
__afl_cmp_map->headers[k].shape = 1;
hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = arg1;
__afl_cmp_map->log[k][hits].v1 = arg2;
}
void HELPER(afl_cmplog_32)(target_ulong cur_loc, target_ulong arg1,
target_ulong arg2) {
register uintptr_t k = (uintptr_t)cur_loc;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 3;
hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = arg1;
__afl_cmp_map->log[k][hits].v1 = arg2;
}
void HELPER(afl_cmplog_64)(target_ulong cur_loc, target_ulong arg1,
target_ulong arg2) {
register uintptr_t k = (uintptr_t)cur_loc;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 7;
hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = arg1;
__afl_cmp_map->log[k][hits].v1 = arg2;
}
#include <sys/mman.h>
static int area_is_mapped(void *ptr, size_t len) {
char *p = ptr;
char *page = (char *)((uintptr_t)p & ~(sysconf(_SC_PAGE_SIZE) - 1));
int r = msync(page, (p - page) + len, MS_ASYNC);
if (r < 0) return errno != ENOMEM;
return 1;
}
void HELPER(afl_cmplog_rtn)(CPUArchState *env) {
#if defined(TARGET_X86_64)
void *ptr1 = g2h(env->regs[R_EDI]);
void *ptr2 = g2h(env->regs[R_ESI]);
#elif defined(TARGET_I386)
target_ulong *stack = g2h(env->regs[R_ESP]);
if (!area_is_mapped(stack, sizeof(target_ulong) * 2)) return;
// when this hook is executed, the retaddr is not on stack yet
void * ptr1 = g2h(stack[0]);
void * ptr2 = g2h(stack[1]);
#else
// stupid code to make it compile
void *ptr1 = NULL;
void *ptr2 = NULL;
return;
#endif
if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return;
#if defined(TARGET_X86_64) || defined(TARGET_I386)
uintptr_t k = (uintptr_t)env->eip;
#else
uintptr_t k = 0;
#endif
k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 31;
hits &= CMP_MAP_RTN_H - 1;
__builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0,
ptr1, 32);
__builtin_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1,
ptr2, 32);
}

View File

@ -1,75 +0,0 @@
/*
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-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 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 "afl-qemu-common.h"
#include "tcg-op.h"
void HELPER(afl_maybe_log)(target_ulong cur_loc) {
register uintptr_t afl_idx = cur_loc ^ afl_prev_loc;
INC_AFL_AREA(afl_idx);
afl_prev_loc = cur_loc >> 1;
}
/* Generates TCG code for AFL's tracing instrumentation. */
static void afl_gen_trace(target_ulong cur_loc) {
/* Optimize for cur_loc > afl_end_code, which is the most likely case on
Linux systems. */
if (cur_loc > afl_end_code ||
cur_loc < afl_start_code /*|| !afl_area_ptr*/) // not needed because of
// static dummy buffer
return;
/* Looks like QEMU always maps to fixed locations, so ASLR 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 >= afl_inst_rms) return;
TCGv cur_loc_v = tcg_const_tl(cur_loc);
gen_helper_afl_maybe_log(cur_loc_v);
tcg_temp_free(cur_loc_v);
}

View File

@ -1,64 +0,0 @@
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index fd36425..992bf17 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -39,6 +39,8 @@
#include "translate-a64.h"
#include "qemu/atomic128.h"
+#include "../patches/afl-qemu-cpu-translate-inl.h"
+
static TCGv_i64 cpu_X[32];
static TCGv_i64 cpu_pc;
@@ -3365,6 +3367,12 @@ static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
return;
}
+ if (rd == 31 && sub_op) { // cmp xX, imm
+ TCGv_i64 tcg_imm = tcg_const_i64(imm);
+ afl_gen_compcov(s->pc, tcg_rn, tcg_imm, is_64bit ? MO_64 : MO_32, 1);
+ tcg_temp_free_i64(tcg_imm);
+ }
+
tcg_result = tcg_temp_new_i64();
if (!setflags) {
if (sub_op) {
@@ -3972,6 +3980,9 @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
tcg_rm = read_cpu_reg(s, rm, sf);
ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
+
+ if (rd == 31 && sub_op) // cmp xX, xY
+ afl_gen_compcov(s->pc, tcg_rn, tcg_rm, sf ? MO_64 : MO_32, 0);
tcg_result = tcg_temp_new_i64();
@@ -4037,6 +4048,9 @@ static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
+ if (rd == 31 && sub_op) // cmp xX, xY
+ afl_gen_compcov(s->pc, tcg_rn, tcg_rm, sf ? MO_64 : MO_32, 0);
+
tcg_result = tcg_temp_new_i64();
if (!setflags) {
@@ -4246,6 +4260,8 @@ static void disas_cc(DisasContext *s, uint32_t insn)
tcg_y = cpu_reg(s, y);
}
tcg_rn = cpu_reg(s, rn);
+
+ afl_gen_compcov(s->pc, tcg_rn, tcg_y, sf ? MO_64 : MO_32, is_imm);
/* Set the flags for the new comparison. */
tcg_tmp = tcg_temp_new_i64();
@@ -13317,6 +13333,8 @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
static void disas_a64_insn(CPUARMState *env, DisasContext *s)
{
uint32_t insn;
+
+ AFL_QEMU_TARGET_ARM64_SNIPPET
insn = arm_ldl_code(env, s->pc, s->sctlr_b);
s->insn = insn;

View File

@ -1,152 +0,0 @@
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 7c4675f..e3d999a 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -59,6 +59,8 @@
#define IS_USER(s) (s->user)
#endif
+#include "../patches/afl-qemu-cpu-translate-inl.h"
+
/* We reuse the same 64-bit temporaries for efficiency. */
static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
static TCGv_i32 cpu_R[16];
@@ -9541,6 +9543,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
} else {
if (set_cc) {
gen_sub_CC(tmp, tmp, tmp2);
+ afl_gen_compcov(s->pc, tmp, tmp2, MO_32, insn & (1 << 25));
} else {
tcg_gen_sub_i32(tmp, tmp, tmp2);
}
@@ -9550,6 +9553,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
case 0x03:
if (set_cc) {
gen_sub_CC(tmp, tmp2, tmp);
+ afl_gen_compcov(s->pc, tmp, tmp2, MO_32, insn & (1 << 25));
} else {
tcg_gen_sub_i32(tmp, tmp2, tmp);
}
@@ -9604,6 +9608,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
case 0x0a:
if (set_cc) {
gen_sub_CC(tmp, tmp, tmp2);
+ afl_gen_compcov(s->pc, tmp, tmp2, MO_32, insn & (1 << 25));
}
tcg_temp_free_i32(tmp);
break;
@@ -10565,7 +10570,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)
{
int logic_cc;
@@ -10611,15 +10616,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(t0, t0, t1);
- else
+ afl_gen_compcov(s->pc, t0, t1, MO_32, has_imm);
+ } else
tcg_gen_sub_i32(t0, t0, t1);
break;
case 14: /* rsb */
- if (conds)
+ if (conds) {
gen_sub_CC(t0, t1, t0);
- else
+ afl_gen_compcov(s->pc, t0, t1, MO_32, has_imm);
+ } else
tcg_gen_sub_i32(t0, t1, t0);
break;
default: /* 5, 6, 7, 9, 12, 15. */
@@ -11085,7 +11092,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
conds = (insn & (1 << 20)) != 0;
logic_cc = (conds && thumb2_logic_op(op));
gen_arm_shift_im(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(tmp2);
if (rd == 13 &&
@@ -11955,7 +11962,7 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
}
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(tmp2);
rd = (insn >> 8) & 0xf;
@@ -12206,8 +12213,10 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
if (insn & (1 << 9)) {
if (s->condexec_mask)
tcg_gen_sub_i32(tmp, tmp, tmp2);
- else
+ else {
gen_sub_CC(tmp, tmp, tmp2);
+ afl_gen_compcov(s->pc, tmp, tmp2, MO_32, insn & (1 << 10));
+ }
} else {
if (s->condexec_mask)
tcg_gen_add_i32(tmp, tmp, tmp2);
@@ -12247,6 +12256,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
switch (op) {
case 1: /* cmp */
gen_sub_CC(tmp, tmp, tmp2);
+ afl_gen_compcov(s->pc, tmp, tmp2, MO_32, 1);
tcg_temp_free_i32(tmp);
tcg_temp_free_i32(tmp2);
break;
@@ -12261,8 +12271,10 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
case 3: /* sub */
if (s->condexec_mask)
tcg_gen_sub_i32(tmp, tmp, tmp2);
- else
+ else {
gen_sub_CC(tmp, tmp, tmp2);
+ afl_gen_compcov(s->pc, tmp, tmp2, MO_32, 1);
+ }
tcg_temp_free_i32(tmp2);
store_reg(s, rd, tmp);
break;
@@ -12308,6 +12320,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
tmp = load_reg(s, rd);
tmp2 = load_reg(s, rm);
gen_sub_CC(tmp, tmp, tmp2);
+ afl_gen_compcov(s->pc, tmp, tmp2, MO_32, 0);
tcg_temp_free_i32(tmp2);
tcg_temp_free_i32(tmp);
break;
@@ -12466,6 +12479,7 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
break;
case 0xa: /* cmp */
gen_sub_CC(tmp, tmp, tmp2);
+ afl_gen_compcov(s->pc, tmp, tmp2, MO_32, 0);
rd = 16;
break;
case 0xb: /* cmn */
@@ -13233,6 +13247,8 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
return;
}
+ AFL_QEMU_TARGET_ARM_SNIPPET
+
insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
dc->insn = insn;
dc->pc += 4;
@@ -13301,6 +13317,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
return;
}
+ AFL_QEMU_TARGET_ARM_SNIPPET
+
insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);
is_16bit = thumb_insn_is_16bit(dc, insn);
dc->pc += 2;

View File

@ -1,83 +0,0 @@
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 7cccf3eb..195875af 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -15,6 +15,8 @@
#undef ELF_ARCH
#endif
+extern abi_ulong afl_entry_point, afl_start_code, afl_end_code;
+
/* from personality.h */
/*
@@ -737,9 +739,13 @@ static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
end_addr = HOST_PAGE_ALIGN(elf_bss);
if (end_addr1 < end_addr) {
- mmap((void *)g2h(end_addr1), end_addr - end_addr1,
+ void *p = mmap((void *)g2h(end_addr1), end_addr - end_addr1,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (p == MAP_FAILED) {
+ perror("padzero: cannot mmap");
+ exit(-1);
+ }
}
}
@@ -979,9 +985,13 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
/* Map the last of the bss segment */
if (last_bss > elf_bss) {
- target_mmap(elf_bss, last_bss-elf_bss,
+ void *p = target_mmap(elf_bss, last_bss-elf_bss,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (p == MAP_FAILED) {
+ perror("load_elf_interp: cannot mmap");
+ exit(-1);
+ }
}
free(elf_phdata);
@@ -1522,6 +1532,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
info->start_data = start_data;
info->end_data = end_data;
info->start_stack = bprm->p;
+ if (!afl_start_code) afl_start_code = vaddr;
+ if (!afl_end_code) afl_end_code = vaddr_ef;
/* Calling set_brk effectively mmaps the pages that we need for the bss and break
sections */
@@ -1544,11 +1556,29 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
and some applications "depend" upon this behavior.
Since we do not have the power to recompile these, we
emulate the SVr4 behavior. Sigh. */
- target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+ void *p = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, -1, 0);
+ if (p == MAP_FAILED) {
+ perror("load_elf_binary: cannot mmap");
+ exit(-1);
+ }
}
info->entry = elf_entry;
+ if (!afl_entry_point) {
+ char *ptr;
+ if ((ptr = getenv("AFL_ENTRYPOINT")) != NULL) {
+ afl_entry_point = strtoul(ptr, NULL, 16);
+ } else {
+ afl_entry_point = info->entry;
+ }
+#ifdef TARGET_ARM
+ /* The least significant bit indicates Thumb mode. */
+ afl_entry_point = afl_entry_point & ~(target_ulong)1;
+#endif
+ }
+ if (getenv("AFL_DEBUG") != NULL)
+ fprintf(stderr, "AFL forkserver entrypoint: %p\n", (void*)afl_entry_point);
return 0;
}

View File

@ -1,33 +0,0 @@
--- a/configure 2019-08-02 18:04:50.000000000 +0200
+++ b/configure 2020-02-28 06:31:30.424895061 +0100
@@ -1479,6 +1479,8 @@
;;
--enable-capstone=system) capstone="system"
;;
+ --enable-capstone=internal) capstone="internal"
+ ;;
--with-git=*) git="$optarg"
;;
--enable-git-update) git_update=yes
@@ -4604,6 +4606,21 @@
fi
##########################################
+cat > $TMPC << EOF
+#include <dlfcn.h>
+#include <stdlib.h>
+int main(int argc, char **argv) { return dlopen("libc.so", RTLD_NOW) != NULL; }
+EOF
+if compile_prog "" "" ; then
+ :
+elif compile_prog "" "-ldl" ; then
+ LIBS="-ldl $LIBS"
+ libs_qga="-ldl $libs_qga"
+else
+ error_exit "libdl check failed"
+fi
+
+##########################################
# spice probe
if test "$spice" != "no" ; then
cat > $TMPC << EOF

View File

@ -1,38 +0,0 @@
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 870027d4..0bc87dfc 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -36,6 +36,8 @@
#include "sysemu/cpus.h"
#include "sysemu/replay.h"
+#include "../patches/afl-qemu-cpu-inl.h"
+
/* -icount align implementation. */
typedef struct SyncClocks {
@@ -397,11 +399,13 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
TranslationBlock *tb;
target_ulong cs_base, pc;
uint32_t flags;
+ bool was_translated = false, was_chained = false;
tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask);
if (tb == NULL) {
mmap_lock();
tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask);
+ was_translated = true;
mmap_unlock();
/* We add the TB in the virtual pc hash table for the fast lookup */
atomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb);
@@ -418,6 +422,10 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
/* See if we can patch the calling TB. */
if (last_tb) {
tb_add_jump(last_tb, tb_exit, tb);
+ was_chained = true;
+ }
+ if (was_translated || was_chained) {
+ afl_request_tsl(pc, cs_base, flags, cf_mask, was_chained ? last_tb : NULL, tb_exit);
}
return tb;
}

View File

@ -1,70 +0,0 @@
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5bccd2e2..fd7460b3 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -20,6 +20,8 @@
#define ELF_OSABI ELFOSABI_SYSV
+extern abi_ulong afl_entry_point, afl_start_code, afl_end_code;
+
/* from personality.h */
/*
@@ -2301,6 +2303,21 @@ static void load_elf_image(const char *image_name, int image_fd,
info->brk = 0;
info->elf_flags = ehdr->e_flags;
+ if (!afl_entry_point) {
+ char *ptr;
+ if ((ptr = getenv("AFL_ENTRYPOINT")) != NULL) {
+ afl_entry_point = strtoul(ptr, NULL, 16);
+ } else {
+ afl_entry_point = info->entry;
+ }
+#ifdef TARGET_ARM
+ /* The least significant bit indicates Thumb mode. */
+ afl_entry_point = afl_entry_point & ~(target_ulong)1;
+#endif
+ }
+ if (getenv("AFL_DEBUG") != NULL)
+ fprintf(stderr, "AFL forkserver entrypoint: %p\n", (void*)afl_entry_point);
+
for (i = 0; i < ehdr->e_phnum; i++) {
struct elf_phdr *eppnt = phdr + i;
if (eppnt->p_type == PT_LOAD) {
@@ -2335,9 +2352,11 @@ static void load_elf_image(const char *image_name, int image_fd,
if (elf_prot & PROT_EXEC) {
if (vaddr < info->start_code) {
info->start_code = vaddr;
+ if (!afl_start_code) afl_start_code = vaddr;
}
if (vaddr_ef > info->end_code) {
info->end_code = vaddr_ef;
+ if (!afl_end_code) afl_end_code = vaddr_ef;
}
}
if (elf_prot & PROT_WRITE) {
@@ -2662,6 +2681,22 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
change some of these later */
bprm->p = setup_arg_pages(bprm, info);
+ // On PowerPC64 the entry point is the _function descriptor_
+ // of the entry function. For AFL to properly initialize,
+ // afl_entry_point needs to be set to the actual first instruction
+ // as opposed executed by the target program. This as opposed to
+ // where the function's descriptor sits in memory.
+ // copied from PPC init_thread
+#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+ if (get_ppc64_abi(infop) < 2) {
+ uint64_t val;
+ get_user_u64(val, infop->entry + 8);
+ _regs->gpr[2] = val + infop->load_bias;
+ get_user_u64(val, infop->entry);
+ infop->entry = val + infop->load_bias;
+ }
+#endif
+
scratch = g_new0(char, TARGET_PAGE_SIZE);
if (STACK_GROWS_DOWN) {
bprm->p = copy_elf_strings(1, &bprm->filename, scratch,

View File

@ -1,54 +0,0 @@
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];

View File

@ -1,61 +0,0 @@
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];
}

View File

@ -1,62 +0,0 @@
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 0dd5fbe4..0d405fb6 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -32,6 +32,8 @@
#include "trace-tcg.h"
#include "exec/log.h"
+#include "../patches/afl-qemu-cpu-translate-inl.h"
+
#define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 0x04
@@ -1343,9 +1345,11 @@ static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
s1->mem_index, ot | MO_LE);
tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
+ afl_gen_compcov(s1->pc, s1->cc_srcT, s1->T1, ot, d == OR_EAX);
} else {
tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
+ afl_gen_compcov(s1->pc, s1->T0, s1->T1, ot, d == OR_EAX);
gen_op_st_rm_T0_A0(s1, ot, d);
}
gen_op_update2_cc(s1);
@@ -1389,6 +1393,7 @@ static void gen_op(DisasContext *s1, int op, TCGMemOp ot, int d)
tcg_gen_mov_tl(cpu_cc_src, s1->T1);
tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
+ afl_gen_compcov(s1->pc, s1->T0, s1->T1, ot, d == OR_EAX);
set_cc_op(s1, CC_OP_SUBB + ot);
break;
}
@@ -4508,6 +4513,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
rex_w = -1;
rex_r = 0;
+ AFL_QEMU_TARGET_I386_SNIPPET
+
next_byte:
b = x86_ldub_code(env, s);
/* Collect prefixes. */
@@ -5056,6 +5063,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
tcg_gen_ext16u_tl(s->T0, s->T0);
}
next_eip = s->pc - s->cs_base;
+ if (__afl_cmp_map && next_eip >= afl_start_code &&
+ next_eip < afl_end_code)
+ gen_helper_afl_cmplog_rtn(cpu_env);
tcg_gen_movi_tl(s->T1, next_eip);
gen_push_v(s, s->T1);
gen_op_jmp_v(s->T0);
@@ -6544,6 +6554,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
tval = (int16_t)insn_get(env, s, MO_16);
}
next_eip = s->pc - s->cs_base;
+ if (__afl_cmp_map && next_eip >= afl_start_code &&
+ next_eip < afl_end_code)
+ gen_helper_afl_cmplog_rtn(cpu_env);
tval += next_eip;
if (dflag == MO_16) {
tval &= 0xffff;

View File

@ -1,31 +0,0 @@
--- a/util/qemu-sockets.c 2020-03-28 13:55:09.511029429 +0100
+++ b/util/qemu-sockets.c 2020-03-28 14:01:12.147693937 +0100
@@ -877,7 +877,7 @@
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
- strncpy(un.sun_path, path, sizeof(un.sun_path));
+ strncpy(un.sun_path, path, sizeof(un.sun_path) - 1);
if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
error_setg_errno(errp, errno, "Failed to bind socket to %s", path);
@@ -922,7 +922,7 @@
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
- strncpy(un.sun_path, saddr->path, sizeof(un.sun_path));
+ strncpy(un.sun_path, saddr->path, sizeof(un.sun_path) - 1);
/* connect to peer */
do {
--- a/block/sheepdog.c 2020-03-28 14:01:57.164360270 +0100
+++ b/block/sheepdog.c 2020-03-28 14:02:52.781026597 +0100
@@ -1236,7 +1236,7 @@
* don't want the send_req to read uninitialized data.
*/
strncpy(buf, filename, SD_MAX_VDI_LEN);
- strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN);
+ strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN - 1);
memset(&hdr, 0, sizeof(hdr));
if (lock) {

View File

@ -1,15 +0,0 @@
--- a/linux-user/elfload.c 2020-07-13 20:10:37.776374566 -0700
+++ b/linux-user/elfload.c 2020-07-13 20:11:51.794957015 -0700
@@ -2667,6 +2667,11 @@
char *elf_interpreter = NULL;
char *scratch;
+ memset(&interp_info, 0, sizeof(interp_info));
+#ifdef TARGET_MIPS
+ interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
+#endif
+
info->start_mmap = (abi_ulong)ELF_START_MMAP;
load_elf_image(bprm->filename, bprm->fd, info,

View File

@ -1,165 +0,0 @@
diff --git a/exec.c b/exec.c
index df5571e..d484098 100644
--- a/exec.c
+++ b/exec.c
@@ -2457,7 +2457,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length)
area = mmap(vaddr, length, PROT_READ | PROT_WRITE,
flags, -1, 0);
}
- if (area != vaddr) {
+ if (area == MAP_FAILED || area != vaddr) {
error_report("Could not remap addr: "
RAM_ADDR_FMT "@" RAM_ADDR_FMT "",
length, addr);
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 41e0983..0a8b8e5 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -612,9 +612,13 @@ static void mmap_reserve(abi_ulong start, abi_ulong size)
real_end -= qemu_host_page_size;
}
if (real_start != real_end) {
- mmap(g2h(real_start), real_end - real_start, PROT_NONE,
+ void *p = mmap(g2h(real_start), real_end - real_start, PROT_NONE,
MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE,
-1, 0);
+ if (p == MAP_FAILED) {
+ perror("mmap_reserve: cannot mmap");
+ exit(-1);
+ }
}
}
diff --git a/roms/SLOF/tools/sloffs.c b/roms/SLOF/tools/sloffs.c
index 9a1eace..10366f0 100644
--- a/roms/SLOF/tools/sloffs.c
+++ b/roms/SLOF/tools/sloffs.c
@@ -308,6 +308,10 @@ sloffs_append(const int file, const char *name, const char *dest)
fstat(fd, &stat);
append = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (append == MAP_FAILED) {
+ perror("sloffs_append: cannot mmap for read");
+ exit(1);
+ }
header = sloffs_header(file);
if (!header)
@@ -331,6 +335,10 @@ sloffs_append(const int file, const char *name, const char *dest)
write(out, "", 1);
write_start = mmap(NULL, new_len, PROT_READ | PROT_WRITE,
MAP_SHARED, out, 0);
+ if (write_start == MAP_FAILED) {
+ perror("sloffs_append: cannot mmap for read/write");
+ exit(1);
+ }
memset(write_start, 0, new_len);
memset(&new_file, 0, sizeof(struct sloffs));
diff --git a/roms/skiboot/core/test/run-trace.c b/roms/skiboot/core/test/run-trace.c
index 9801688..236b51d 100644
--- a/roms/skiboot/core/test/run-trace.c
+++ b/roms/skiboot/core/test/run-trace.c
@@ -178,6 +178,10 @@ static void test_parallel(void)
i = (CPUS*len + getpagesize()-1)&~(getpagesize()-1);
p = mmap(NULL, i, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_SHARED, -1, 0);
+ if (p == MAP_FAILED) {
+ perror("test_parallel: cannot mmap");
+ exit(-1);
+ }
for (i = 0; i < CPUS; i++) {
fake_cpus[i].trace = p + i * len;
diff --git a/roms/skiboot/external/ffspart/ffspart.c b/roms/skiboot/external/ffspart/ffspart.c
index 7703477..efbbd5b 100644
--- a/roms/skiboot/external/ffspart/ffspart.c
+++ b/roms/skiboot/external/ffspart/ffspart.c
@@ -379,7 +379,7 @@ int main(int argc, char *argv[])
}
data_ptr = mmap(NULL, pactual, PROT_READ, MAP_SHARED, data_fd, 0);
- if (!data_ptr) {
+ if (data_ptr == MAP_FAILED) {
fprintf(stderr, "Couldn't mmap data file for partition '%s': %s\n",
name, strerror(errno));
rc = -1;
diff --git a/roms/skiboot/extract-gcov.c b/roms/skiboot/extract-gcov.c
index 3d31d1b..ebc03e6 100644
--- a/roms/skiboot/extract-gcov.c
+++ b/roms/skiboot/extract-gcov.c
@@ -229,7 +229,11 @@ int main(int argc, char *argv[])
}
addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- assert(addr != NULL);
+ assert(addr != MAP_FAILED);
+ if (addr == MAP_FAILED) {
+ perror("main: cannot mmap");
+ exit(-1);
+ }
skiboot_dump_size = sb.st_size;
printf("Skiboot memory dump %p - %p\n",
diff --git a/roms/skiboot/libstb/create-container.c b/roms/skiboot/libstb/create-container.c
index 5cf80a0..64699ad 100644
--- a/roms/skiboot/libstb/create-container.c
+++ b/roms/skiboot/libstb/create-container.c
@@ -96,7 +96,11 @@ void getSigRaw(ecc_signature_t *sigraw, char *inFile)
assert(r==0);
infile = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
- assert(infile);
+ assert(infile != MAP_FAILED);
+ if (infile == MAP_FAILED) {
+ perror("getSigRaw: cannot mmap");
+ exit(-1);
+ }
signature = d2i_ECDSA_SIG(NULL, (const unsigned char **) &infile, 7 + 2*EC_COORDBYTES);
@@ -356,7 +360,11 @@ int main(int argc, char* argv[])
r = fstat(fdin, &s);
assert(r==0);
infile = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
- assert(infile);
+ assert(infile != MAP_FAILED);
+ if (infile == MAP_FAILED) {
+ perror("main: cannot mmap");
+ exit(-1);
+ }
fdout = open(params.imagefn, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
assert(fdout > 0);
diff --git a/tests/tcg/multiarch/test-mmap.c b/tests/tcg/multiarch/test-mmap.c
index 11d0e77..14f5919 100644
--- a/tests/tcg/multiarch/test-mmap.c
+++ b/tests/tcg/multiarch/test-mmap.c
@@ -203,6 +203,7 @@ void check_aligned_anonymous_fixed_mmaps(void)
p1 = mmap(addr, pagesize, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-1, 0);
+ fail_unless (p1 != MAP_FAILED);
/* Make sure we get pages aligned with the pagesize.
The target expects this. */
p = (uintptr_t) p1;
@@ -234,6 +235,7 @@ void check_aligned_anonymous_fixed_mmaps_collide_with_host(void)
p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-1, 0);
+ fail_unless (p1 != MAP_FAILED);
/* Make sure we get pages aligned with the pagesize.
The target expects this. */
p = (uintptr_t) p1;
@@ -401,6 +403,10 @@ void check_file_fixed_mmaps(void)
p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ,
MAP_PRIVATE | MAP_FIXED,
test_fd, pagesize * 3);
+ fail_unless (p1 != MAP_FAILED);
+ fail_unless (p2 != MAP_FAILED);
+ fail_unless (p3 != MAP_FAILED);
+ fail_unless (p4 != MAP_FAILED);
/* Make sure we get pages aligned with the pagesize.
The target expects this. */

View File

@ -1,10 +0,0 @@
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"

View File

@ -1,102 +0,0 @@
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b13a170e..3f5cc902 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -111,6 +111,9 @@
#include "qemu.h"
#include "fd-trans.h"
+#include <linux/sockios.h>
+
+extern unsigned int afl_forksrv_pid;
#ifndef CLONE_IO
#define CLONE_IO 0x80000000 /* Clone io context */
@@ -250,7 +253,8 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
#endif
#ifdef __NR_gettid
-_syscall0(int, gettid)
+#define __NR_sys_gettid __NR_gettid
+_syscall0(int, sys_gettid)
#else
/* This is a replacement for the host gettid() and must return a host
errno. */
@@ -5384,7 +5388,7 @@ static void *clone_func(void *arg)
cpu = ENV_GET_CPU(env);
thread_cpu = cpu;
ts = (TaskState *)cpu->opaque;
- info->tid = gettid();
+ info->tid = sys_gettid();
task_settid(ts);
if (info->child_tidptr)
put_user_u32(info->tid, info->child_tidptr);
@@ -5529,9 +5533,9 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
mapping. We can't repeat the spinlock hack used above because
the child process gets its own copy of the lock. */
if (flags & CLONE_CHILD_SETTID)
- put_user_u32(gettid(), child_tidptr);
+ put_user_u32(sys_gettid(), child_tidptr);
if (flags & CLONE_PARENT_SETTID)
- put_user_u32(gettid(), parent_tidptr);
+ put_user_u32(sys_gettid(), parent_tidptr);
ts = (TaskState *)cpu->opaque;
if (flags & CLONE_SETTLS)
cpu_set_tls (env, newtls);
@@ -6554,7 +6558,8 @@ static int open_self_cmdline(void *cpu_env, int fd)
return 0;
}
-static int open_self_maps(void *cpu_env, int fd)
+int open_self_maps(void *cpu_env, int fd);
+int open_self_maps(void *cpu_env, int fd)
{
CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
TaskState *ts = cpu->opaque;
@@ -7324,10 +7329,12 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR_stime /* not on alpha */
case TARGET_NR_stime:
{
- time_t host_time;
- if (get_user_sal(host_time, arg1))
+ struct timespec ts;
+ ts.tv_nsec = 0;
+ if (get_user_sal(ts.tv_sec, arg1)) {
return -TARGET_EFAULT;
- return get_errno(stime(&host_time));
+ }
+ return get_errno(clock_settime(CLOCK_REALTIME, &ts));
}
#endif
#ifdef TARGET_NR_alarm /* not on alpha */
@@ -10529,7 +10536,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
return TARGET_PAGE_SIZE;
#endif
case TARGET_NR_gettid:
- return get_errno(gettid());
+ return get_errno(sys_gettid());
#ifdef TARGET_NR_readahead
case TARGET_NR_readahead:
#if TARGET_ABI_BITS == 32
@@ -10813,8 +10820,19 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
case TARGET_NR_tgkill:
- return get_errno(safe_tgkill((int)arg1, (int)arg2,
- target_to_host_signal(arg3)));
+ {
+ int pid = (int)arg1,
+ tgid = (int)arg2,
+ sig = (int)arg3;
+
+ /* Not entirely sure if the below is correct for all architectures. */
+
+ if(afl_forksrv_pid && afl_forksrv_pid == pid && sig == SIGABRT)
+ pid = tgid = getpid();
+
+ ret = get_errno(safe_tgkill(pid, tgid, target_to_host_signal(sig)));
+
+ }
#ifdef TARGET_NR_set_robust_list
case TARGET_NR_set_robust_list:

View File

@ -1,19 +0,0 @@
diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h
index 1bd39d13..81ef3973 100644
--- a/accel/tcg/tcg-runtime.h
+++ b/accel/tcg/tcg-runtime.h
@@ -260,3 +260,14 @@ DEF_HELPER_FLAGS_4(gvec_leu8, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_leu16, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_leu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_leu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
+
+DEF_HELPER_FLAGS_1(afl_entry_routine, TCG_CALL_NO_RWG, void, env)
+DEF_HELPER_FLAGS_1(afl_maybe_log, TCG_CALL_NO_RWG, void, tl)
+DEF_HELPER_FLAGS_3(afl_compcov_16, TCG_CALL_NO_RWG, void, tl, tl, tl)
+DEF_HELPER_FLAGS_3(afl_compcov_32, TCG_CALL_NO_RWG, void, tl, tl, tl)
+DEF_HELPER_FLAGS_3(afl_compcov_64, TCG_CALL_NO_RWG, void, tl, tl, tl)
+DEF_HELPER_FLAGS_3(afl_cmplog_8, TCG_CALL_NO_RWG, void, tl, tl, tl)
+DEF_HELPER_FLAGS_3(afl_cmplog_16, TCG_CALL_NO_RWG, void, tl, tl, tl)
+DEF_HELPER_FLAGS_3(afl_cmplog_32, TCG_CALL_NO_RWG, void, tl, tl, tl)
+DEF_HELPER_FLAGS_3(afl_cmplog_64, TCG_CALL_NO_RWG, void, tl, tl, tl)
+DEF_HELPER_FLAGS_1(afl_cmplog_rtn, TCG_CALL_NO_RWG, void, env)

View File

@ -1,10 +0,0 @@
diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c
index d0d44844..009ef15a 100644
--- a/accel/tcg/tcg-runtime.c
+++ b/accel/tcg/tcg-runtime.c
@@ -167,3 +167,5 @@ void HELPER(exit_atomic)(CPUArchState *env)
{
cpu_loop_exit_atomic(ENV_GET_CPU(env), GETPC());
}
+
+#include "../../../patches/afl-qemu-tcg-runtime-inl.h"

View File

@ -1,14 +0,0 @@
diff --git a/tcg/tcg.c b/tcg/tcg.c
index e85133ef..54b9b390 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1612,6 +1612,9 @@ bool tcg_op_supported(TCGOpcode op)
}
}
+
+#include "../../patches/afl-qemu-tcg-inl.h"
+
/* Note: we convert the 64 bit args to 32 bit and do some alignment
and endian swap. Maybe it would be better to do the alignment
and endian swap in tcg_reg_alloc_call(). */

View File

@ -1,21 +0,0 @@
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 639f0b27..21a45494 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -59,6 +59,8 @@
#include "exec/log.h"
#include "sysemu/cpus.h"
+#include "../patches/afl-qemu-translate-inl.h"
+
/* #define DEBUG_TB_INVALIDATE */
/* #define DEBUG_TB_FLUSH */
/* make various TB consistency checks */
@@ -1721,6 +1723,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
tcg_func_start(tcg_ctx);
tcg_ctx->cpu = ENV_GET_CPU(env);
+ afl_gen_trace(pc);
gen_intermediate_code(cpu, tb);
tcg_ctx->cpu = NULL;

View File

@ -1,25 +0,0 @@
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index afd0a49e..773ea712 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -18,6 +18,8 @@
#include "exec/log.h"
#include "exec/translator.h"
+#include "../../../patches/afl-qemu-common.h"
+
/* Pairs with tcg_clear_temp_count.
To be called by #TranslatorOps.{translate_insn,tb_stop} if
(1) the target is sufficiently clean to support reporting,
@@ -92,6 +94,11 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
break;
}
}
+
+ if (db->pc_next == afl_entry_point) {
+ afl_setup();
+ gen_helper_afl_entry_routine(cpu_env);
+ }
/* Disassemble one instruction. The translate_insn hook should
update db->pc_next and db->is_jmp to indicate what should be

1
qemu_mode/qemuafl Submodule

@ -0,0 +1 @@
Subproject commit eee265a3df4b3c1acaca2873d1b28f0bd8837da4

47
qemu_mode/update_ref.sh Executable file
View File

@ -0,0 +1,47 @@
#/bin/sh
##################################################
# AFL++ internal tool to update qemuafl ref.
# Usage: ./update_ref.sh <new commit hash>
# If no commit hash was provided, it'll take HEAD.
##################################################
UC_VERSION_FILE='./QEMUAFL_VERSION'
NEW_VERSION="$1"
if [ "$NEW_VERSION" = "-h" ]; then
echo "Internal script to update bound qemuafl version."
echo
echo "Usage: ./update_ref.sh <new commit hash>"
echo "If no commit hash is provided, will use HEAD."
echo "-h to show this help screen."
exit 1
fi
git submodule init && git submodule update || exit 1
cd ./qemuafl || exit 1
git fetch origin master 1>/dev/null || exit 1
git stash 1>/dev/null 2>/dev/null
git stash drop 1>/dev/null 2>/dev/null
git checkout master
git pull origin master 1>/dev/null || exit 1
if [ -z "$NEW_VERSION" ]; then
# No version provided, take HEAD.
NEW_VERSION=$(git rev-parse --short HEAD)
fi
if [ -z "$NEW_VERSION" ]; then
echo "Error getting version."
exit 1
fi
git checkout "$NEW_VERSION" || exit 1
cd ..
rm "$UC_VERSION_FILE"
echo "$NEW_VERSION" > "$UC_VERSION_FILE"
echo "Done. New qemuafl version is $NEW_VERSION."