mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-11 01:31:37 +00:00
conflicts
This commit is contained in:
commit
10f775be07
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
1
qemu_mode/QEMUAFL_VERSION
Normal file
1
qemu_mode/QEMUAFL_VERSION
Normal file
@ -0,0 +1 @@
|
||||
eee265a3df
|
@ -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
|
||||
|
@ -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):
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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;
|
@ -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;
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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,
|
@ -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];
|
@ -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];
|
||||
}
|
@ -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;
|
@ -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) {
|
@ -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,
|
||||
|
@ -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. */
|
||||
|
@ -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"
|
@ -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:
|
@ -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)
|
@ -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"
|
@ -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(). */
|
@ -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;
|
||||
|
@ -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
1
qemu_mode/qemuafl
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit eee265a3df4b3c1acaca2873d1b28f0bd8837da4
|
47
qemu_mode/update_ref.sh
Executable file
47
qemu_mode/update_ref.sh
Executable 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."
|
Loading…
x
Reference in New Issue
Block a user