diff --git a/CMakeLists.txt b/CMakeLists.txt index 69af3b8e..1eca217e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,8 +35,6 @@ else() include_directories( ${CMAKE_BINARY_DIR} ) - # Try to build AFL support on all other platform. - set(UNICORN_HAS_AFL TRUE) endif() include_directories( @@ -328,10 +326,6 @@ else() OUTPUT_FILE ${CMAKE_BINARY_DIR}/riscv64-softmmu/config-target.h ) endif() - if (UNICORN_HAS_AFL) - # Make it globally - set (UNICORN_CFLAGS ${UNICORN_CFLAGS} -DUNICORN_HAS_AFL) - endif() add_compile_options( ${UNICORN_CFLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/tcg/${UNICORN_TARGET_ARCH} diff --git a/bindings/Makefile b/bindings/Makefile index 44423401..296b44f3 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -24,8 +24,8 @@ build: $(MAKE) -C go gen_const $(MAKE) -C java gen_const $(MAKE) -C ruby gen_const - python3 const_generator.py dotnet - python3 const_generator.py pascal + python const_generator.py dotnet + python const_generator.py pascal install: build $(MAKE) -C python install diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 03cc19a4..0b91cac1 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -28,7 +28,6 @@ module Common = let UC_MODE_LITTLE_ENDIAN = 0 let UC_MODE_BIG_ENDIAN = 1073741824 - let UC_MODE_AFL = 536870912 let UC_MODE_ARM = 0 let UC_MODE_THUMB = 16 @@ -76,10 +75,6 @@ module Common = let UC_ERR_HOOK_EXIST = 19 let UC_ERR_RESOURCE = 20 let UC_ERR_EXCEPTION = 21 - let UC_ERR_AFL_RET_ERROR = 22 - let UC_ERR_AFL_RET_NO_AFL = 23 - let UC_ERR_AFL_RET_CALLED_TWICE = 24 - let UC_ERR_AFL_RET_FINISHED = 25 let UC_MEM_READ = 16 let UC_MEM_WRITE = 17 let UC_MEM_FETCH = 18 diff --git a/bindings/go/Makefile b/bindings/go/Makefile index f8b0d5f1..fe898ae1 100644 --- a/bindings/go/Makefile +++ b/bindings/go/Makefile @@ -6,7 +6,7 @@ all: gen_const cd unicorn && go build gen_const: - cd .. && python3 const_generator.py go + cd .. && python const_generator.py go test: all cd unicorn && LD_LIBRARY_PATH=../../../ DYLD_LIBRARY_PATH=../../../ go test diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index a45e1452..6196fde5 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -23,7 +23,6 @@ const ( MODE_LITTLE_ENDIAN = 0 MODE_BIG_ENDIAN = 1073741824 - MODE_AFL = 536870912 MODE_ARM = 0 MODE_THUMB = 16 @@ -71,10 +70,6 @@ const ( ERR_HOOK_EXIST = 19 ERR_RESOURCE = 20 ERR_EXCEPTION = 21 - ERR_AFL_RET_ERROR = 22 - ERR_AFL_RET_NO_AFL = 23 - ERR_AFL_RET_CALLED_TWICE = 24 - ERR_AFL_RET_FINISHED = 25 MEM_READ = 16 MEM_WRITE = 17 MEM_FETCH = 18 diff --git a/bindings/java/Makefile b/bindings/java/Makefile index 313db888..73d20725 100644 --- a/bindings/java/Makefile +++ b/bindings/java/Makefile @@ -19,7 +19,7 @@ uninstall: $(MAKE) -f Makefile.build uninstall gen_const: - cd .. && python3 const_generator.py java + cd .. && python const_generator.py java clean: rm -f unicorn/*.class diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index ce6744be..f4396003 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -25,7 +25,6 @@ public interface UnicornConst { public static final int UC_MODE_LITTLE_ENDIAN = 0; public static final int UC_MODE_BIG_ENDIAN = 1073741824; - public static final int UC_MODE_AFL = 536870912; public static final int UC_MODE_ARM = 0; public static final int UC_MODE_THUMB = 16; @@ -73,10 +72,6 @@ public interface UnicornConst { public static final int UC_ERR_HOOK_EXIST = 19; public static final int UC_ERR_RESOURCE = 20; public static final int UC_ERR_EXCEPTION = 21; - public static final int UC_ERR_AFL_RET_ERROR = 22; - public static final int UC_ERR_AFL_RET_NO_AFL = 23; - public static final int UC_ERR_AFL_RET_CALLED_TWICE = 24; - public static final int UC_ERR_AFL_RET_FINISHED = 25; public static final int UC_MEM_READ = 16; public static final int UC_MEM_WRITE = 17; public static final int UC_MEM_FETCH = 18; diff --git a/bindings/pascal/unicorn/UnicornConst.pas b/bindings/pascal/unicorn/UnicornConst.pas index 3f202cb9..29303b89 100644 --- a/bindings/pascal/unicorn/UnicornConst.pas +++ b/bindings/pascal/unicorn/UnicornConst.pas @@ -26,7 +26,6 @@ const UC_API_MAJOR = 2; UC_MODE_LITTLE_ENDIAN = 0; UC_MODE_BIG_ENDIAN = 1073741824; - UC_MODE_AFL = 536870912; UC_MODE_ARM = 0; UC_MODE_THUMB = 16; @@ -74,10 +73,6 @@ const UC_API_MAJOR = 2; UC_ERR_HOOK_EXIST = 19; UC_ERR_RESOURCE = 20; UC_ERR_EXCEPTION = 21; - UC_ERR_AFL_RET_ERROR = 22; - UC_ERR_AFL_RET_NO_AFL = 23; - UC_ERR_AFL_RET_CALLED_TWICE = 24; - UC_ERR_AFL_RET_FINISHED = 25; UC_MEM_READ = 16; UC_MEM_WRITE = 17; UC_MEM_FETCH = 18; diff --git a/bindings/python/Makefile b/bindings/python/Makefile index 363d646f..ea831fd9 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -3,16 +3,16 @@ .PHONY: gen_const install install3 clean sdist sdist3 bdist bdist3 sdist_win bdist_win gen_const: - cd .. && python3 const_generator.py python + cd .. && python const_generator.py python install: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll if test -n "${DESTDIR}"; then \ - python3 setup.py install --root="${DESTDIR}"; \ + python setup.py install --root="${DESTDIR}"; \ else \ - python3 setup.py install; \ + python setup.py install; \ fi install3: @@ -30,7 +30,7 @@ sdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python3 setup.py sdist register upload + python setup.py sdist register upload # build & upload PyPi package with source code of the core sdist3: @@ -44,7 +44,7 @@ bdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python3 setup.py bdist_wheel register upload + python setup.py bdist_wheel register upload # build & upload PyPi package with precompiled core bdist3: @@ -57,7 +57,7 @@ bdist3: # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand sdist_win: rm -rf src/ dist/ - python3 setup.py sdist register upload + python setup.py sdist register upload # build & upload PyPi package with prebuilt core # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index dbbc4d35..58c6ee06 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -9,7 +9,7 @@ import os.path import sys import weakref import functools -import gc + from . import x86_const, arm64_const, unicorn_const as uc if not hasattr(sys.modules[__name__], "__file__"): @@ -120,15 +120,6 @@ class _uc_mem_region(ctypes.Structure): ("perms", ctypes.c_uint32), ] -#typedef bool (*uc_afl_cb_place_input_t)(uc_engine *uc, char *input, -# size_t input_len, uint32_t persistent_round, void *data); -AFL_PLACE_INPUT_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.POINTER(ctypes.c_char), - ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p) - -#typedef bool (*uc_afl_cb_validate_crash_t)(uc_engine *uc, uc_err unicorn_result, char *input, -# int input_len, int persistent_round, void *data); -AFL_VALIDATE_CRASH_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ucerr, ctypes.POINTER(ctypes.c_char), - ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p) _setup_prototype(_uc, "uc_version", ctypes.c_uint, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)) _setup_prototype(_uc, "uc_arch_supported", ctypes.c_bool, ctypes.c_int) @@ -160,7 +151,6 @@ _setup_prototype(_uc, "uc_context_free", ucerr, uc_context) _setup_prototype(_uc, "uc_mem_regions", ucerr, uc_engine, ctypes.POINTER(ctypes.POINTER(_uc_mem_region)), ctypes.POINTER(ctypes.c_uint32)) # https://bugs.python.org/issue42880 _setup_prototype(_uc, "uc_hook_add", ucerr, uc_engine, ctypes.POINTER(uc_hook_h), ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64) -_setup_prototype(_uc, "uc_afl_fuzz", ucerr, uc_engine, ctypes.c_char_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint64), ctypes.c_size_t, ctypes.c_void_p, ctypes.c_bool, ctypes.c_uint32, ctypes.c_void_p) UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p) UC_HOOK_INSN_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.c_void_p) @@ -421,8 +411,6 @@ class Uc(object): self._callback_count = 0 self._cleanup.register(self) - self.afl_called_before = False # type: bool - @staticmethod def release_handle(uch): if uch: @@ -444,127 +432,6 @@ class Uc(object): status = _uc.uc_emu_stop(self._uch) if status != uc.UC_ERR_OK: raise UcError(status) - - def afl_fuzz( - self, # type: Uc - input_file, # type: str - place_input_callback, # type: Callable[[Uc, bytes, int, Any], Optional[bool]] - exits, # type: List[int] - validate_crash_callback=None, # type: Optional[Callable[[Uc, UcError, bytes, int, Any], Optional[bool]]] - always_validate=False, # type: bool - persistent_iters=1, # type: int - data=None, # type: Any - ): - # type: (...) -> bool - """ - The main fuzzer. - Starts the forkserver, then beginns a persistent loop. - Reads input, calls the place_input callback, emulates, repeats. - If unicorn errors out, will call the validate_crash_callback, if set. - Will only return in the parent after the whole fuzz thing has been finished and afl died. - The child processes never return from here. - - :param input_file: filename/path to the (AFL) inputfile. Usually supplied on the commandline. - :param place_input_callback: Callback function that will be called before each test runs. - This function needs to write the input from afl to the correct position on the unicorn object. - This function is mandatory. - It's purpose is to place the input at the right place in unicorn. - - @uc: (Uc) Unicorn instance - @input: (bytes) The current input we're working on. Place this somewhere in unicorn's memory now. - @persistent_round: (int) which round we are currently crashing in, if using persistent mode. - @data: (Any) Data pointer passed to uc_afl_fuzz(...). - - @return: (bool) - If you return is True (or None) all is well. Fuzzing starts. - If you return False, the input is rejected; we will continue with the next input. - :param exits: address list of exits where fuzzing should stop - :param persistent_iters: - The amount of loop iterations in persistent mode before restarting with a new forked child. - If your target cannot be fuzzed using persistent mode (global state changes a lot), - set persistent_iters = 1 for the normal fork-server experience. - Else, the default is usually around 1000. - If your target is super stable (and unicorn is, too - not sure about that one), - you may pass persistent_iter = 0 for that an infinite fuzz loop. - :param validate_crash_callback: Optional callback (if not needed, pass NULL), that determines - if a non-OK uc_err is an actual error. If false is returned, the test-case will not crash. - Callback function called after a non-UC_ERR_OK returncode was returned by Unicorn. - This function is not mandatory. - @uc: Unicorn instance - @unicorn_result: The error state returned by the current testcase - @input: The current input we're working with. - @persistent_round: which round we are currently crashing in, if using persistent mode. - @data: Data pointer passed to uc_afl_fuzz(...). - - @Return: - If you return false, the crash is considered invalid and not reported to AFL. - -> Next loop iteration begins. - If return is true, the crash is reported // the program crashes. - -> The child will die and the forkserver will spawn a new child. - :param always_validate: If false, validate_crash_callback will only be called for crashes. - :param data: Your very own data pointer. This will passed into every callback. - - :return: - True, if we fuzzed. - False, if AFL was not available but we ran once. - raises UcAflException if nothing worked. - """ - if self.afl_called_before: - raise UcError(uc.UC_ERR_AFL_RET_CALLED_TWICE) - self.afl_called_before = True - self._pre_afl() - exit_count = len(exits) - - def place_input_wrapper(c_uc, input, input_len, persistent_round, c_data): - # print("Calling back home. :)", c_uc, input, input_len, persistent_round, c_data) - ret = place_input_callback( - self, - ctypes.cast(input, ctypes.POINTER(ctypes.c_char * input_len)).contents, - persistent_round, - data - ) - if ret is False: - return False - return True - - def validate_crash_wrapper(c_uc, uc_err, input, input_len, persistent_round, c_data): - # print("Calling after crash!", c_uc, input, input_len, persistent_round, c_data) - # assert type(uc_err) == int - ret = validate_crash_callback( - self, - UcError(uc_err), - ctypes.cast(input, ctypes.POINTER(ctypes.c_char * input_len)).contents, - persistent_round, - data - ) - if ret is False or (ret is None and uc_err == uc.UC_ERR_OK): - return False - return True - - # This only returns in the parent, child processes all die or loop or other things. - status = _uc.uc_afl_fuzz( - self._uch, - input_file.encode('utf-8'), - AFL_PLACE_INPUT_CB(place_input_wrapper), - (ctypes.c_uint64 * exit_count)(*exits), - exit_count, # bad languages, like c, need more params. - AFL_VALIDATE_CRASH_CB(validate_crash_wrapper) if validate_crash_callback else None, - always_validate, - persistent_iters, - None # no need to pass the user data through C as the callback keeps it as closure. - ) - if status != uc.UC_ERR_OK: - # Something went wrong. - raise UcError(status) - - def _pre_afl(self): - # type: (Uc) -> None - """ - Internal func making sure exits are set and flushing buffers/gc - :param exits: exits - """ - sys.stdout.flush() # otherwise children will inherit the unflushed buffer - gc.collect() # Collect all unneeded memory, No need to clone it on fork. # return the value of a register def reg_read(self, reg_id, opt=None): diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 1b9ac693..a517572a 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -21,7 +21,6 @@ UC_ARCH_MAX = 9 UC_MODE_LITTLE_ENDIAN = 0 UC_MODE_BIG_ENDIAN = 1073741824 -UC_MODE_AFL = 536870912 UC_MODE_ARM = 0 UC_MODE_THUMB = 16 @@ -69,10 +68,6 @@ UC_ERR_FETCH_UNALIGNED = 18 UC_ERR_HOOK_EXIST = 19 UC_ERR_RESOURCE = 20 UC_ERR_EXCEPTION = 21 -UC_ERR_AFL_RET_ERROR = 22 -UC_ERR_AFL_RET_NO_AFL = 23 -UC_ERR_AFL_RET_CALLED_TWICE = 24 -UC_ERR_AFL_RET_FINISHED = 25 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 diff --git a/bindings/ruby/Makefile b/bindings/ruby/Makefile index aa92fa53..9d52de94 100644 --- a/bindings/ruby/Makefile +++ b/bindings/ruby/Makefile @@ -8,4 +8,4 @@ install: gen_const cd unicorn_gem && gem install --local pkg/unicorn-engine-1.0.1.gem gen_const: - cd .. && python3 const_generator.py ruby + cd .. && python const_generator.py ruby diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb index 698b71c0..a09f3e82 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb @@ -23,7 +23,6 @@ module UnicornEngine UC_MODE_LITTLE_ENDIAN = 0 UC_MODE_BIG_ENDIAN = 1073741824 - UC_MODE_AFL = 536870912 UC_MODE_ARM = 0 UC_MODE_THUMB = 16 @@ -71,10 +70,6 @@ module UnicornEngine UC_ERR_HOOK_EXIST = 19 UC_ERR_RESOURCE = 20 UC_ERR_EXCEPTION = 21 - UC_ERR_AFL_RET_ERROR = 22 - UC_ERR_AFL_RET_NO_AFL = 23 - UC_ERR_AFL_RET_CALLED_TWICE = 24 - UC_ERR_AFL_RET_FINISHED = 25 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 diff --git a/include/afl/afl-common.h b/include/afl/afl-common.h deleted file mode 100644 index eb342255..00000000 --- a/include/afl/afl-common.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -#include "config.h" -#include "types.h" - -/* 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 - diff --git a/include/afl/afl-cpu-inl.h b/include/afl/afl-cpu-inl.h deleted file mode 100644 index fcb44b8e..00000000 --- a/include/afl/afl-cpu-inl.h +++ /dev/null @@ -1,527 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -#include -#include -#include -#include -#include "config.h" -#include "types.h" -#include "afl-common.h" - -/* We use one additional file descriptor to relay "needs translation" - or "child done" messages between the child and the fork server. */ - -#define FF16 (0xFFFFFFFFFFFFFFFF) - -/* Copied from aflpp/types.h to talk to forkserver */ -#define FS_OPT_ENABLED 0x80000001 -#define FS_OPT_SHDMEM_FUZZ 0x01000000 - -/** - * The correct fds for reading and writing pipes - */ - -#define _R(pipe) ((pipe)[0]) -#define _W(pipe) ((pipe)[1]) - -/* Function declarations. */ - -static void afl_setup(struct uc_struct*); -static inline uc_afl_ret afl_forkserver(CPUState*); -static int afl_find_wifsignaled_id(void); - -static enum afl_child_ret afl_handle_child_requests(CPUState*); -static void afl_request_tsl(CPUState *cpu, target_ulong, target_ulong, uint64_t, uint32_t); -static uc_afl_ret afl_request_next(struct uc_struct* uc, bool found_crash); - -// static TranslationBlock* tb_find_slow(CPUArchState*, target_ulong, target_ulong, uint64_t); - -/* Data structure passed around by the translate handlers: */ - -struct afl_tsl { - - target_ulong pc; - target_ulong cs_base; - uint64_t flags; - uint32_t cf_mask; -#if defined(TARGET_MIPS) - target_ulong hflags; - target_ulong btarget; -#endif - -}; - -/* Current state, as forwarded from forkserver child to parent */ - -enum afl_child_ret { - - // Persistent - AFL_CHILD_NEXT, - // Crash discovered but still alive in persistent mode - AFL_CHILD_FOUND_CRASH, - // Read again, one afl_tsl struct. - AFL_CHILD_TSL_REQUEST, - // Child no longer there. Read status code. - AFL_CHILD_EXITED, - -}; - -static int wifsignaled; - -/************************* - * ACTUAL IMPLEMENTATION * - *************************/ - -/* Set up SHM region and initialize other stuff. */ - -static void afl_setup(struct uc_struct* uc) { - - char *id_str = getenv(SHM_ENV_VAR); - char *inst_r = getenv("AFL_INST_RATIO"); - - // A value we can use to tell AFL our persistent mode found a crash - wifsignaled = afl_find_wifsignaled_id(); - - int shm_id; - - if (inst_r) { - - unsigned int r; - - r = atoi(inst_r); - - if (r > 100) r = 100; - if (!r) r = 1; - - uc->afl_inst_rms = MAP_SIZE * r / 100; - - } else { - - uc->afl_inst_rms = MAP_SIZE; - - } - - if (id_str) { - - shm_id = atoi(id_str); - uc->afl_area_ptr = shmat(shm_id, NULL, 0); - uc->afl_prev_loc = 0; - uc->afl_area_ptr[0] = 1; - - if (uc->afl_area_ptr == (void*)-1) exit(1); - - } - - /* Maintain for compatibility */ - if (getenv("AFL_QEMU_COMPCOV")) { uc->afl_compcov_level = 1; } - if (getenv("AFL_COMPCOV_LEVEL")) { - - uc->afl_compcov_level = atoi(getenv("AFL_COMPCOV_LEVEL")); - - } -#if defined(AFL_DEBUG) - if (uc->afl_compcov_level) { - printf("[d] USING AFL_COMPCOV_LEVEL %d\n", uc->afl_compcov_level); - } -#endif - -} - -// Some dirty hack to come up with a valid statuscode that AFL will just accept. - -static int afl_find_wifsignaled_id(void) { - - int ret = 0; // A faux status code that AFL will accept as signaled/crashed. 1 on linux. - while (!(WIFSIGNALED(ret))) ret++; - -#if defined(AFL_DEBUG) - printf("[d] wifsignaled is %d (WIFSIGNALED(x)=%d)\n", ret, WIFSIGNALED(ret)); -#endif - - return ret; - -} - -/* Fork server logic, invoked by calling uc_afl_forkserver_start. - Roughly follows https://github.com/vanhauser-thc/AFLplusplus/blob/c83e8e1e6255374b085292ba8673efdca7388d76/llvm_mode/afl-llvm-rt.o.c#L130 - */ - -static inline uc_afl_ret afl_forkserver(CPUState* cpu) { - - unsigned char tmp[4] = {0}; - pid_t child_pid; - enum afl_child_ret child_ret = AFL_CHILD_EXITED; - bool first_round = true; - u32 status = 0; - - if (!cpu->uc->afl_area_ptr) return UC_AFL_RET_NO_AFL; - - if (cpu->uc->afl_testcase_ptr) { - /* Parent supports testcases via shared map - and the user wants to use it. Tell AFL. */ - status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); - } - - /* Phone home and tell the parent that we're OK. If parent isn't there, - assume we're not running in forkserver mode and just execute program. */ - - if (write(FORKSRV_FD + 1, &status, 4) != 4) return UC_AFL_RET_NO_AFL; - - /* afl tells us in an extra message if it accepted this option or not */ - if (cpu->uc->afl_testcase_ptr && getenv(SHM_FUZZ_ENV_VAR)) { - if (read(FORKSRV_FD, &status, 4) != 4) { - fprintf(stderr, "[!] AFL parent exited before forkserver was up\n"); - return UC_AFL_RET_ERROR; - } - if (status != (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) { - fprintf(stderr, "[!] Unexpected response from AFL++ on forkserver setup\n"); - return UC_AFL_RET_ERROR; - } - } else { -#if defined(AFL_DEBUG) - printf("[d] AFL++ sharedmap fuzzing not supported/SHM_FUZZ_ENV_VAR not set\n"); -#endif - } - - void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL); - -#if defined(AFL_DEBUG) - printf("[d] Entering forkserver loop\n"); -#endif - - while (1) { - - uint32_t was_killed; - int status; - - /* Wait for parent by reading from the pipe. Abort if read fails. */ - - if (read(FORKSRV_FD, &was_killed, 4) != 4) return UC_AFL_RET_FINISHED; - - /* 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_ret != AFL_CHILD_EXITED) && was_killed) { - -#if defined(AFL_DEBUG) - printf("[d] Child was killed by AFL in the meantime.\n"); -#endif - - child_ret = AFL_CHILD_EXITED; - if (waitpid(child_pid, &status, 0) < 0) { - perror("[!] Error waiting for child!"); - return UC_AFL_RET_ERROR; - } - - } - - if (child_ret == AFL_CHILD_EXITED) { - - /* Child dead. Establish new a channel with child to grab translation commands. - We'll read from _R(afl_child_pipe), child will write to _W(afl_child_pipe). */ - - /* close the read fd of previous round. */ - - if (_R(cpu->uc->afl_child_pipe)) { - close(_R(cpu->uc->afl_child_pipe)); - close(_W(cpu->uc->afl_parent_pipe)); - } - - if (pipe(cpu->uc->afl_child_pipe)) { - perror("[!] Error creating pipe to child"); - return UC_AFL_RET_ERROR; - } - if (pipe(cpu->uc->afl_parent_pipe)) { - perror("[!] Error creating pipe to parent"); - close(_R(cpu->uc->afl_child_pipe)); - close(_W(cpu->uc->afl_child_pipe)); - return UC_AFL_RET_ERROR; - } - - /* Create a clone of our process. */ - - child_pid = fork(); - if (child_pid < 0) { - perror("[!] Could not fork! "); - return UC_AFL_RET_ERROR; - } - - /* In child process: close fds, resume execution. */ - - if (!child_pid) { // New child - - signal(SIGCHLD, old_sigchld_handler); - // FORKSRV_FD is for communication with AFL, we don't need it in the child. - close(FORKSRV_FD); - close(FORKSRV_FD + 1); - close(_R(cpu->uc->afl_child_pipe)); - close(_W(cpu->uc->afl_parent_pipe)); - cpu->uc->afl_child_request_next = afl_request_next; - - memset(cpu->uc->afl_area_ptr, 0, MAP_SIZE); - MEM_BARRIER(); // Make very sure everything has been written to the map at this point - - if (!first_round) { - - // For persistent mode: Clear the map manually after forks. - memset(cpu->uc->afl_area_ptr, 0, MAP_SIZE); - - } else { - // For persistent mode: Clear the map manually after forks. - //memset(env->uc->afl_area_ptr, 0, MAP_SIZE); - - first_round = false; - } - - cpu->uc->afl_prev_loc = 0; - // Tell AFL we're alive - cpu->uc->afl_area_ptr[0] = 1; - - return UC_AFL_RET_CHILD; - - } else { // parent for new child - - /* If we don't close this in parent, we don't get notified on afl_child_pipe once child is gone. */ - - close(_W(cpu->uc->afl_child_pipe)); - close(_R(cpu->uc->afl_parent_pipe)); - - } - - } else { // parent, in persistent mode - - /* Special handling for persistent mode: if the child is alive but - currently stopped, simply restart it with a write to afl_parent_pipe. - In case we fuzz using shared map, use this method to forward the size - of the current testcase to the child without cost. */ - - if (write(_W(cpu->uc->afl_parent_pipe), tmp, 4) != 4) { - - fprintf(stderr,"[!] Child died when we tried to resume it\n"); - return UC_AFL_RET_ERROR; - - } - - } - - /* In parent process: write PID to AFL. */ - - if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { - return UC_AFL_RET_FINISHED; - } - - /* Collect translation requests until child finishes a run or dies */ - - child_ret = afl_handle_child_requests(cpu); - - if (child_ret == AFL_CHILD_NEXT) { - - /* Child asks for next in persistent mode */ - - status = 0; - - } else if (child_ret == AFL_CHILD_FOUND_CRASH) { - - /* WIFSIGNALED(wifsignaled) == 1 -> tells AFL the child crashed (even though it's still alive for persistent mode) */ - - status = wifsignaled; - - } else if (child_ret == AFL_CHILD_EXITED) { - - /* If child exited, get and relay exit status to parent through waitpid. */ - - if (waitpid(child_pid, &status, 0) < 0) { - - // Zombie Child could not be collected. Scary! - perror("[!] The child's exit code could not be determined. "); - return UC_AFL_RET_ERROR; - - } - - } - - /* Relay wait status to AFL pipe, then loop back. */ - - if (write(FORKSRV_FD + 1, &status, 4) != 4) return UC_AFL_RET_FINISHED; - - } - -} - -/* This code is invoked whenever Unicorn decides that it doesn't have a - translation of a particular block and needs to compute it. When this happens, - we tell the parent to mirror the operation, so that the next fork() has a - cached copy. */ - -static inline void afl_request_tsl(CPUState *cpu, target_ulong pc, target_ulong cb, uint64_t flags, uint32_t cf_mask) { - - /* Dual use: if this func is not set, we're not a child process */ - - struct uc_struct* uc = cpu->uc; - if (uc->afl_child_request_next == NULL) return; - enum afl_child_ret tsl_req = AFL_CHILD_TSL_REQUEST; -#if defined(TARGET_MIPS) - CPUArchState* env = cpu->env_ptr; -#endif - - struct afl_tsl t = { - .pc = pc, - .cs_base = cb, - .flags = flags, - .cf_mask = cf_mask, -#if defined(TARGET_MIPS) - .hflags = env->hflags, - .btarget = env->btarget, -#endif - }; - -#if defined(AFL_DEBUG) - printf("Requesting tsl, pc=0x%llx, cb=0x%llx, flags=0x%llx\n", (unsigned long long) pc, (unsigned long long) cb, (unsigned long long) flags); -#endif - - // We write tsl requests in two steps but that's fine since cache requests are not very common over the time of fuzzing. - - if ((write(_W(uc->afl_child_pipe), &tsl_req, sizeof(enum afl_child_ret)) != sizeof(enum afl_child_ret)) - || write(_W(uc->afl_child_pipe), &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) { - - fprintf(stderr, "Error writing to child pipe. Parent dead?\n"); - - } - -} - -/* This code is invoked whenever the child decides that it is done with one fuzz-case. */ - -static uc_afl_ret afl_request_next(struct uc_struct* uc, bool crash_found) { - - enum afl_child_ret msg = crash_found? AFL_CHILD_FOUND_CRASH : AFL_CHILD_NEXT; - char tmp[4]; - -#if defined(AFL_DEBUG) - printf("[d] request next. crash found: %s\n", crash_found ? "true": "false"); -#endif - - MEM_BARRIER(); // Make very sure everything has been written to the map at this point - - if (write(_W(uc->afl_child_pipe), &msg, sizeof(msg)) != sizeof(msg)) { - - fprintf(stderr, "[!] Error writing to parent pipe. Parent dead?\n"); - return UC_AFL_RET_ERROR; - - } - - // Once the parent has written something, the next persistent loop starts. - // The parent itself will wait for AFL to signal the new testcases is available. - // This blocks until the next testcase is ready. - if (read(_R(uc->afl_parent_pipe), tmp, 4) != 4) { - - fprintf(stderr, "[!] Error reading from parent pipe. Parent dead?\n"); - return UC_AFL_RET_ERROR; - - } - - /* For shared map fuzzing, the forkserver parent forwards the size of the current testcase. */ - memset(uc->afl_area_ptr, 0, MAP_SIZE); - MEM_BARRIER(); // Also make sure nothing read before this point. - - // Start with a clean slate. - uc->afl_prev_loc = 0; - uc->afl_area_ptr[0] = 1; - - return UC_AFL_RET_CHILD; - -} - - -/* This is the reading side of afl_child_pipe. It will handle persistent mode and (tsl) cache requests. - Since timeouts are handled by afl-fuzz simply killing the child, we can just wait until the pipe breaks. - For persistent mode, we will also receive child responses over this chanel. - For persistent mode, if child is still alive, this will return if the child crashed or not */ - -static enum afl_child_ret afl_handle_child_requests(CPUState* cpu) { - - enum afl_child_ret child_msg; - struct afl_tsl t; -#if defined(TARGET_MIPS) - CPUArchState* env = cpu->env_ptr; -#endif - - while (1) { - - /* Broken pipe means it's time to return to the fork server routine. */ - - if (read(_R(cpu->uc->afl_child_pipe), &child_msg, sizeof(enum afl_child_ret)) != sizeof(enum afl_child_ret)) return AFL_CHILD_EXITED; // child is dead. - - if (child_msg == AFL_CHILD_NEXT || child_msg == AFL_CHILD_FOUND_CRASH) { - - // Forward if child found a crash or not, for persistent mode. - return child_msg; - - } else if (child_msg == AFL_CHILD_TSL_REQUEST) { - - // TODO: Add option to disable cache for self-modifying code? // Ignore code that has not been loaded? - - // Child will send a tsl request next, that we have to cache. - if (read(_R(cpu->uc->afl_child_pipe), &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) return AFL_CHILD_EXITED; // child is dead. - - // Prepare hflags for delay slot -#if defined(TARGET_MIPS) - struct afl_tsl tmp; - tmp.hflags = env->hflags; - tmp.btarget = env->btarget; - env->hflags = t.hflags; - env->btarget = t.btarget; -#endif - - // Cache. - //tb_find_slow(env, t.pc, t.cs_base, t.flags); - - // TODO: Caching! tb = tb_find(cpu, last_tb, tb_exit, t.cflags); - - // Restore hflags -#if defined(TARGET_MIPS) - env->hflags = tmp.hflags; - env->btarget = tmp.btarget; -#endif - - } else { - - fprintf(stderr, "[!] Unexpected response by child! %d. Please report this as bug for unicornafl.\n" - " Expected one of {AFL_CHILD_NEXT: %d, AFL_CHILD_FOUND_CRASH: %d, AFL_CHILD_TSL_REQUEST: %d}.\n", - child_msg, AFL_CHILD_NEXT, AFL_CHILD_FOUND_CRASH, AFL_CHILD_TSL_REQUEST); - - } - - } - -} diff --git a/include/afl/afl-cpu-translate-inl.h b/include/afl/afl-cpu-translate-inl.h deleted file mode 100644 index 7692ff3c..00000000 --- a/include/afl/afl-cpu-translate-inl.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -#include "config.h" -#include "types.h" - -/* These are executed on code generation. Execution is in afl-unicorn-tcg-runtime-inl.h */ -/* Roughly afl_gen_maybe_log -> gen_afl_maybe_log -> emit HELPER(afl_maybe_log) -> call afl_maybe_log */ - -static void afl_gen_maybe_log(TCGContext *s, uint64_t cur_loc) { - - if (!s->uc->afl_area_ptr) return; - - /* "Hash" */ - - cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); - cur_loc &= MAP_SIZE - 7; - - /* Implement probabilistic instrumentation by looking at scrambled block - address. This keeps the instrumented locations stable across runs. */ - - if (cur_loc >= s->uc->afl_inst_rms) return; - - gen_afl_maybe_log(s, cur_loc); - -} - -// Currently only arm32 and x86. We undefine it for others to silence unused func compiler warnings. -#if defined(ARCH_HAS_COMPCOV) -static void afl_gen_compcov(TCGContext *s, uint64_t cur_loc, TCGv arg1, - TCGv arg2, TCGMemOp ot, int is_imm) { - - if (!s->uc->afl_compcov_level || !s->uc->afl_area_ptr) return; - - if (!is_imm && s->uc->afl_compcov_level < 2) return; - - cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); - cur_loc &= MAP_SIZE - 7; - - if (cur_loc >= s->uc->afl_inst_rms) return; - - switch (ot) { - - case MO_64: gen_afl_compcov_log_64(s, cur_loc, (TCGv_i64)arg1, (TCGv_i64)arg2); break; - case MO_32: gen_afl_compcov_log_32(s, cur_loc, (TCGv_i32)arg1, (TCGv_i32)arg2); break; - case MO_16: gen_afl_compcov_log_16(s, cur_loc, (TCGv_i32)arg1, (TCGv_i32)arg2); break; - default: return; - - } - -} -#endif \ No newline at end of file diff --git a/include/afl/afl-tcg-op-inl.h b/include/afl/afl-tcg-op-inl.h deleted file mode 100644 index 5770066c..00000000 --- a/include/afl/afl-tcg-op-inl.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -static inline void gen_afl_maybe_log(TCGContext *tcg_ctx, uint64_t cur_loc) { - - TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); - TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); - gen_helper_afl_maybe_log(tcg_ctx, tuc, tcur_loc); - -} - -static inline void gen_afl_compcov_log_16(TCGContext *tcg_ctx, uint64_t cur_loc, - TCGv_i32 arg1, TCGv_i32 arg2) { -#if defined(AFL_DEBUG) - printf("[d] Emitting 16 bit COMPCOV instrumentation for loc 0x%lx\n", cur_loc); -#endif - - TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); - TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); - gen_helper_afl_compcov_log_16(tcg_ctx, tuc, tcur_loc, arg1, arg2); - -} - -static inline void gen_afl_compcov_log_32(TCGContext *tcg_ctx, uint64_t cur_loc, - TCGv_i32 arg1, TCGv_i32 arg2) { -#if defined(AFL_DEBUG) - printf("[d] Emitting 32 bit COMPCOV instrumentation for loc 0x%lux\n", cur_loc); -#endif - - TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); - TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); - gen_helper_afl_compcov_log_32(tcg_ctx, tuc, tcur_loc, arg1, arg2); - -} - -static inline void gen_afl_compcov_log_64(TCGContext *tcg_ctx, uint64_t cur_loc, - TCGv_i64 arg1, TCGv_i64 arg2) { -#if defined(AFL_DEBUG) - printf("[d] Emitting 64 bit COMPCOV instrumentation for loc 0x%lux\n", cur_loc); -#endif - - TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); - TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); - gen_helper_afl_compcov_log_64(tcg_ctx, tuc, tcur_loc, arg1, arg2); - -} - diff --git a/include/afl/afl-tcg-runtime-inl.h b/include/afl/afl-tcg-runtime-inl.h deleted file mode 100644 index 237c55b5..00000000 --- a/include/afl/afl-tcg-runtime-inl.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -#include "uc_priv.h" -#include "afl-common.h" - -/* This is the main instrumentation function, patched in at translate. - cur_loc has already been shifted in afl-unicorn-translate-inl.h at this point. - Also this helper will only be emitted if running instrumented. */ - -void HELPER(afl_maybe_log)(void* uc_ptr, uint64_t cur_loc) { - - struct uc_struct* uc = (struct uc_struct*) uc_ptr; - u8* afl_area_ptr = uc->afl_area_ptr; // Don't remove, it's used by INC_AFL_AREA implicitly; - - register uintptr_t afl_idx = cur_loc ^ uc->afl_prev_loc; - - INC_AFL_AREA(afl_idx); - -#if defined(AFL_DEBUG) - printf("[d] At loc 0x%llx: prev: 0x%llx, afl_idx: %lu, map[afl_idx]: %d\n", (unsigned long long) cur_loc, (unsigned long long) uc->afl_prev_loc, (unsigned long) afl_idx, afl_area_ptr[afl_idx]); -#endif - - uc->afl_prev_loc = cur_loc >> 1; - -} - -void HELPER(afl_compcov_log_16)(void* uc_ptr, uint64_t cur_loc, uint32_t arg1, - uint32_t arg2) { - - u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr; - - if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); } - -} - -void HELPER(afl_compcov_log_32)(void* uc_ptr, uint64_t cur_loc, uint32_t arg1, - uint32_t arg2) { - - u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr; - - if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) { - - INC_AFL_AREA(cur_loc + 2); - if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) { - - INC_AFL_AREA(cur_loc + 1); - if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); } - - } - - } - -} - -void HELPER(afl_compcov_log_64)(void* uc_ptr, uint64_t cur_loc, uint64_t arg1, - uint64_t arg2) { - - u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr; - - if ((arg1 & 0xff00000000000000) == (arg2 & 0xff00000000000000)) { - - INC_AFL_AREA(cur_loc + 6); - if ((arg1 & 0xff000000000000) == (arg2 & 0xff000000000000)) { - - INC_AFL_AREA(cur_loc + 5); - if ((arg1 & 0xff0000000000) == (arg2 & 0xff0000000000)) { - - INC_AFL_AREA(cur_loc + 4); - if ((arg1 & 0xff00000000) == (arg2 & 0xff00000000)) { - - INC_AFL_AREA(cur_loc + 3); - if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) { - - INC_AFL_AREA(cur_loc + 2); - if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) { - - INC_AFL_AREA(cur_loc + 1); - if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); } - - } - - } - - } - - } - - } - - } - -} - diff --git a/include/afl/config.h b/include/afl/config.h deleted file mode 100644 index 4630da0c..00000000 --- a/include/afl/config.h +++ /dev/null @@ -1,510 +0,0 @@ -/* - american fuzzy lop++ - vaguely configurable bits - ------------------------------------------------ - - Originally written by Michal Zalewski - - Now maintained by Marc Heuse , - Heiko Eißfeldt , - Andrea Fioraldi , - Dominik Maier - - Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2021 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 - - */ - -#ifndef _HAVE_CONFIG_H -#define _HAVE_CONFIG_H - -/* Version string: */ - -// c = release, a = volatile github dev, e = experimental branch -#define VERSION "++3.15a" - -/****************************************************** - * * - * Settings that may be of interest to power users: * - * * - ******************************************************/ - -/* Default shared memory map size. Most targets just need a coverage map - between 20-250kb. Plus there is an auto-detection feature in afl-fuzz. - However if a target has problematic constructors and init arrays then - this can fail. Hence afl-fuzz deploys a larger default map. The largest - map seen so far is the xlsx fuzzer for libreoffice which is 5MB. - At runtime this value can be overriden via AFL_MAP_SIZE. - Default: 8MB (defined in bytes) */ -#define DEFAULT_SHMEM_SIZE (8 * 1024 * 1024) - -/* Default file permission umode when creating files (default: 0600) */ -#define DEFAULT_PERMISSION 0600 - -/* CMPLOG/REDQUEEN TUNING - * - * Here you can modify tuning and solving options for CMPLOG. - * Note that these are run-time options for afl-fuzz, no target - * recompilation required. - * - */ - -/* if TRANSFORM is enabled with '-l T', this additionally enables base64 - encoding/decoding */ -// #define CMPLOG_SOLVE_TRANSFORM_BASE64 - -/* If a redqueen pass finds more than one solution, try to combine them? */ -#define CMPLOG_COMBINE - -/* Minimum % of the corpus to perform cmplog on. Default: 10% */ -#define CMPLOG_CORPUS_PERCENT 5U - -/* Number of potential positions from which we decide if cmplog becomes - useless, default 8096 */ -#define CMPLOG_POSITIONS_MAX (12 * 1024) - -/* Maximum allowed fails per CMP value. Default: 128 */ -#define CMPLOG_FAIL_MAX 96 - -/* -------------------------------------*/ -/* Now non-cmplog configuration options */ -/* -------------------------------------*/ - -/* If a persistent target keeps state and found crashes are not reproducable - then enable this option and set the AFL_PERSISTENT_RECORD env variable - to a number. These number of testcases prior and including the crash case - will be kept and written to the crash/ directory as RECORD:... files. - Note that every crash will be written, not only unique ones! */ - -//#define AFL_PERSISTENT_RECORD - -/* console output colors: There are three ways to configure its behavior - * 1. default: colored outputs fixed on: defined USE_COLOR && defined - * ALWAYS_COLORED The env var. AFL_NO_COLOR will have no effect - * 2. defined USE_COLOR && !defined ALWAYS_COLORED - * -> depending on env var AFL_NO_COLOR=1 colors can be switched off - * at run-time. Default is to use colors. - * 3. colored outputs fixed off: !defined USE_COLOR - * The env var. AFL_NO_COLOR will have no effect - */ - -/* Comment out to disable terminal colors (note that this makes afl-analyze - a lot less nice): */ - -#define USE_COLOR - -#ifdef USE_COLOR - /* Comment in to always enable terminal colors */ - /* Comment out to enable runtime controlled terminal colors via AFL_NO_COLOR - */ - #define ALWAYS_COLORED 1 -#endif - -/* StatsD config - Config can be adjusted via AFL_STATSD_HOST and AFL_STATSD_PORT environment - variable. -*/ -#define STATSD_UPDATE_SEC 1 -#define STATSD_DEFAULT_PORT 8125 -#define STATSD_DEFAULT_HOST "127.0.0.1" - -/* If you want to have the original afl internal memory corruption checks. - Disabled by default for speed. it is better to use "make ASAN_BUILD=1". */ - -// #define _WANT_ORIGINAL_AFL_ALLOC - -/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ - -#ifndef ANDROID_DISABLE_FANCY // Fancy boxes are ugly from adb - #define FANCY_BOXES -#endif - -/* Default timeout for fuzzed code (milliseconds). This is the upper bound, - also used for detecting hangs; the actual value is auto-scaled: */ - -#define EXEC_TIMEOUT 1000U - -/* Timeout rounding factor when auto-scaling (milliseconds): */ - -#define EXEC_TM_ROUND 20U - -/* 64bit arch MACRO */ -#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__)) - #define WORD_SIZE_64 1 -#endif - -/* Default memory limit for child process (MB) 0 = disabled : */ - -#define MEM_LIMIT 0U - -/* Default memory limit when running in QEMU mode (MB) 0 = disabled : */ - -#define MEM_LIMIT_QEMU 0U - -/* Default memory limit when running in Unicorn mode (MB) 0 = disabled : */ - -#define MEM_LIMIT_UNICORN 0U - -/* Number of calibration cycles per every new test case (and for test - cases that show variable behavior): */ - -#define CAL_CYCLES 8U -#define CAL_CYCLES_LONG 20U - -/* Number of subsequent timeouts before abandoning an input file: */ - -#define TMOUT_LIMIT 250U - -/* Maximum number of unique hangs or crashes to record: */ - -#define KEEP_UNIQUE_HANG 500U -#define KEEP_UNIQUE_CRASH 10000U - -/* Baseline number of random tweaks during a single 'havoc' stage: */ - -#define HAVOC_CYCLES 256U -#define HAVOC_CYCLES_INIT 1024U - -/* Maximum multiplier for the above (should be a power of two, beware - of 32-bit int overflows): */ - -#define HAVOC_MAX_MULT 64U -#define HAVOC_MAX_MULT_MOPT 64U - -/* Absolute minimum number of havoc cycles (after all adjustments): */ - -#define HAVOC_MIN 12U - -/* Power Schedule Divisor */ -#define POWER_BETA 1U -#define MAX_FACTOR (POWER_BETA * 32) - -/* Maximum stacking for havoc-stage tweaks. The actual value is calculated - like this: - - n = random between 1 and HAVOC_STACK_POW2 - stacking = 2^n - - In other words, the default (n = 4) produces 2, 4, 8, 16 - stacked tweaks: */ - -#define HAVOC_STACK_POW2 4U - -/* Caps on block sizes for cloning and deletion operations. Each of these - ranges has a 33% probability of getting picked, except for the first - two cycles where smaller blocks are favored: */ - -#define HAVOC_BLK_SMALL 32U -#define HAVOC_BLK_MEDIUM 128U -#define HAVOC_BLK_LARGE 1500U - -/* Extra-large blocks, selected very rarely (<5% of the time): */ - -#define HAVOC_BLK_XL 32768U - -/* Probabilities of skipping non-favored entries in the queue, expressed as - percentages: */ - -#define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */ -#define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */ -#define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */ - -/* Splicing cycle count: */ - -#define SPLICE_CYCLES 15 - -/* Nominal per-splice havoc cycle length: */ - -#define SPLICE_HAVOC 32 - -/* Maximum offset for integer addition / subtraction stages: */ - -#define ARITH_MAX 35 - -/* Limits for the test case trimmer. The absolute minimum chunk size; and - the starting and ending divisors for chopping up the input file: */ - -#define TRIM_MIN_BYTES 4 -#define TRIM_START_STEPS 16 -#define TRIM_END_STEPS 1024 - -/* Maximum size of input file, in bytes (keep under 100MB, default 1MB): - (note that if this value is changed, several areas in afl-cc.c, afl-fuzz.c - and afl-fuzz-state.c have to be changed as well! */ - -#define MAX_FILE (1 * 1024 * 1024L) - -/* The same, for the test case minimizer: */ - -#define TMIN_MAX_FILE (10 * 1024 * 1024L) - -/* Block normalization steps for afl-tmin: */ - -#define TMIN_SET_MIN_SIZE 4 -#define TMIN_SET_STEPS 128 - -/* Maximum dictionary token size (-x), in bytes: */ - -#define MAX_DICT_FILE 128 - -/* Length limits for auto-detected dictionary tokens: */ - -#define MIN_AUTO_EXTRA 3 -#define MAX_AUTO_EXTRA 32 - -/* Maximum number of user-specified dictionary tokens to use in deterministic - steps; past this point, the "extras/user" step will be still carried out, - but with proportionally lower odds: */ - -#define MAX_DET_EXTRAS 256 - -/* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing - (first value), and to keep in memory as candidates. The latter should be much - higher than the former. */ - -#define USE_AUTO_EXTRAS 128 -#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 64) - -/* Scaling factor for the effector map used to skip some of the more - expensive deterministic steps. The actual divisor is set to - 2^EFF_MAP_SCALE2 bytes: */ - -#define EFF_MAP_SCALE2 3 - -/* Minimum input file length at which the effector logic kicks in: */ - -#define EFF_MIN_LEN 128 - -/* Maximum effector density past which everything is just fuzzed - unconditionally (%): */ - -#define EFF_MAX_PERC 90 - -/* UI refresh frequency (Hz): */ - -#define UI_TARGET_HZ 5 - -/* Fuzzer stats file and plot update intervals (sec): */ - -#define STATS_UPDATE_SEC 60 -#define PLOT_UPDATE_SEC 5 - -/* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ - -#define AVG_SMOOTHING 16 - -/* Sync interval (every n havoc cycles): */ - -#define SYNC_INTERVAL 8 - -/* Sync time (minimum time between syncing in ms, time is halfed for -M main - nodes) - default is 30 minutes: */ - -#define SYNC_TIME (30 * 60 * 1000) - -/* Output directory reuse grace period (minutes): */ - -#define OUTPUT_GRACE 25 - -/* Uncomment to use simple file names (id_NNNNNN): */ - -// #define SIMPLE_FILES - -/* List of interesting values to use in fuzzing. */ - -#define INTERESTING_8 \ - -128, /* Overflow signed 8-bit when decremented */ \ - -1, /* */ \ - 0, /* */ \ - 1, /* */ \ - 16, /* One-off with common buffer size */ \ - 32, /* One-off with common buffer size */ \ - 64, /* One-off with common buffer size */ \ - 100, /* One-off with common buffer size */ \ - 127 /* Overflow signed 8-bit when incremented */ - -#define INTERESTING_8_LEN 9 - -#define INTERESTING_16 \ - -32768, /* Overflow signed 16-bit when decremented */ \ - -129, /* Overflow signed 8-bit */ \ - 128, /* Overflow signed 8-bit */ \ - 255, /* Overflow unsig 8-bit when incremented */ \ - 256, /* Overflow unsig 8-bit */ \ - 512, /* One-off with common buffer size */ \ - 1000, /* One-off with common buffer size */ \ - 1024, /* One-off with common buffer size */ \ - 4096, /* One-off with common buffer size */ \ - 32767 /* Overflow signed 16-bit when incremented */ - -#define INTERESTING_16_LEN 10 - -#define INTERESTING_32 \ - -2147483648LL, /* Overflow signed 32-bit when decremented */ \ - -100663046, /* Large negative number (endian-agnostic) */ \ - -32769, /* Overflow signed 16-bit */ \ - 32768, /* Overflow signed 16-bit */ \ - 65535, /* Overflow unsig 16-bit when incremented */ \ - 65536, /* Overflow unsig 16 bit */ \ - 100663045, /* Large positive number (endian-agnostic) */ \ - 2147483647 /* Overflow signed 32-bit when incremented */ - -#define INTERESTING_32_LEN 8 - -/*********************************************************** - * * - * Really exotic stuff you probably don't want to touch: * - * * - ***********************************************************/ - -/* Call count interval between reseeding the libc PRNG from /dev/urandom: */ - -#define RESEED_RNG 100000 - -/* The default maximum testcase cache size in MB, 0 = disable. - A value between 50 and 250 is a good default value. Note that the - number of entries will be auto assigned if not specified via the - AFL_TESTCACHE_ENTRIES env variable */ - -#define TESTCASE_CACHE_SIZE 50 - -/* Maximum line length passed from GCC to 'as' and used for parsing - configuration files: */ - -#define MAX_LINE 8192 - -/* Environment variable used to pass SHM ID to the called program. */ - -#define SHM_ENV_VAR "__AFL_SHM_ID" - -/* Environment variable used to pass SHM FUZZ ID to the called program. */ - -#define SHM_FUZZ_ENV_VAR "__AFL_SHM_FUZZ_ID" - -/* Other less interesting, internal-only variables. */ - -#define CLANG_ENV_VAR "__AFL_CLANG_MODE" -#define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK" -#define PERSIST_ENV_VAR "__AFL_PERSISTENT" -#define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" - -/* In-code signatures for deferred and persistent mode. */ - -#define PERSIST_SIG "##SIG_AFL_PERSISTENT##" -#define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##" - -/* Distinctive bitmap signature used to indicate failed execution: */ - -#define EXEC_FAIL_SIG 0xfee1dead - -/* Distinctive exit code used to indicate MSAN trip condition: */ - -#define MSAN_ERROR 86 - -/* Distinctive exit code used to indicate LSAN trip condition: */ - -#define LSAN_ERROR 23 - -/* Designated file descriptors for forkserver commands (the application will - use FORKSRV_FD and FORKSRV_FD + 1): */ - -#define FORKSRV_FD 198 - -/* Fork server init timeout multiplier: we'll wait the user-selected - timeout plus this much for the fork server to spin up. */ - -#define FORK_WAIT_MULT 10 - -/* Calibration timeout adjustments, to be a bit more generous when resuming - fuzzing sessions or trying to calibrate already-added internal finds. - The first value is a percentage, the other is in milliseconds: */ - -#define CAL_TMOUT_PERC 125 -#define CAL_TMOUT_ADD 50 - -/* Number of chances to calibrate a case before giving up: */ - -#define CAL_CHANCES 3 - -/* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than - 2; you probably want to keep it under 18 or so for performance reasons - (adjusting AFL_INST_RATIO when compiling is probably a better way to solve - problems with complex programs). You need to recompile the target binary - after changing this - otherwise, SEGVs may ensue. */ - -#define MAP_SIZE_POW2 16 -#define MAP_SIZE (1U << MAP_SIZE_POW2) - -/* Maximum allocator request size (keep well under INT_MAX): */ - -#define MAX_ALLOC 0x40000000 - -/* A made-up hashing seed: */ - -#define HASH_CONST 0xa5b35705 - -/* Constants for afl-gotcpu to control busy loop timing: */ - -#define CTEST_TARGET_MS 5000 -#define CTEST_CORE_TRG_MS 1000 -#define CTEST_BUSY_CYCLES (10 * 1000 * 1000) - -/* Enable NeverZero counters in QEMU mode */ - -#define AFL_QEMU_NOT_ZERO - -/* AFL RedQueen */ - -#define CMPLOG_SHM_ENV_VAR "__AFL_CMPLOG_SHM_ID" - -/* CPU Affinity lockfile env var */ - -#define CPU_AFFINITY_ENV_VAR "__AFL_LOCKFILE" - -/* Uncomment this to use inferior block-coverage-based instrumentation. Note - that you need to recompile the target binary for this to have any effect: */ - -// #define COVERAGE_ONLY - -/* Uncomment this to ignore hit counts and output just one bit per tuple. - As with the previous setting, you will need to recompile the target - binary: */ - -// #define SKIP_COUNTS - -/* Uncomment this to use instrumentation data to record newly discovered paths, - but do not use them as seeds for fuzzing. This is useful for conveniently - measuring coverage that could be attained by a "dumb" fuzzing algorithm: */ - -// #define IGNORE_FINDS - -/* Text mutations */ - -/* Minimum length of a queue input to be evaluated for "is_ascii"? */ - -#define AFL_TXT_MIN_LEN 12 - -/* What is the minimum percentage of ascii characters present to be classifed - as "is_ascii"? */ - -#define AFL_TXT_MIN_PERCENT 94 - -/* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ - -#define AFL_TXT_BIAS 6 - -/* Maximum length of a string to tamper with */ - -#define AFL_TXT_STRING_MAX_LEN 1024 - -/* Maximum mutations on a string */ - -#define AFL_TXT_STRING_MAX_MUTATIONS 6 - -#endif /* ! _HAVE_CONFIG_H */ - diff --git a/include/afl/types.h b/include/afl/types.h deleted file mode 100644 index 7b94fb83..00000000 --- a/include/afl/types.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - american fuzzy lop++ - type definitions and minor macros - -------------------------------------------------------- - - Originally written by Michal Zalewski - - Now maintained by Marc Heuse , - Heiko Eißfeldt , - Andrea Fioraldi , - Dominik Maier - - Copyright 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 - - */ - -#ifndef _HAVE_TYPES_H -#define _HAVE_TYPES_H - -#include -#include -#include "config.h" - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -#ifdef WORD_SIZE_64 -typedef unsigned __int128 uint128_t; -typedef uint128_t u128; -#endif - -/* Extended forkserver option values */ - -/* Reporting errors */ -#define FS_OPT_ERROR 0xf800008f -#define FS_OPT_GET_ERROR(x) ((x & 0x00ffff00) >> 8) -#define FS_OPT_SET_ERROR(x) ((x & 0x0000ffff) << 8) -#define FS_ERROR_MAP_SIZE 1 -#define FS_ERROR_MAP_ADDR 2 -#define FS_ERROR_SHM_OPEN 4 -#define FS_ERROR_SHMAT 8 -#define FS_ERROR_MMAP 16 - -/* Reporting options */ -#define FS_OPT_ENABLED 0x80000001 -#define FS_OPT_MAPSIZE 0x40000000 -#define FS_OPT_SNAPSHOT 0x20000000 -#define FS_OPT_AUTODICT 0x10000000 -#define FS_OPT_SHDMEM_FUZZ 0x01000000 -#define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000 -// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22 -#define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1) -#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) -#define FS_OPT_SET_MAPSIZE(x) \ - (x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1)) - -typedef unsigned long long u64; - -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; -#ifdef WORD_SIZE_64 -typedef __int128 int128_t; -typedef int128_t s128; -#endif - -#ifndef MIN - #define MIN(a, b) \ - ({ \ - \ - __typeof__(a) _a = (a); \ - __typeof__(b) _b = (b); \ - _a < _b ? _a : _b; \ - \ - }) - - #define MAX(a, b) \ - ({ \ - \ - __typeof__(a) _a = (a); \ - __typeof__(b) _b = (b); \ - _a > _b ? _a : _b; \ - \ - }) - -#endif /* !MIN */ - -#define SWAP16(_x) \ - ({ \ - \ - u16 _ret = (_x); \ - (u16)((_ret << 8) | (_ret >> 8)); \ - \ - }) - -#define SWAP32(_x) \ - ({ \ - \ - u32 _ret = (_x); \ - (u32)((_ret << 24) | (_ret >> 24) | ((_ret << 8) & 0x00FF0000) | \ - ((_ret >> 8) & 0x0000FF00)); \ - \ - }) - -#define SWAP64(_x) \ - ({ \ - \ - u64 _ret = (_x); \ - _ret = \ - (_ret & 0x00000000FFFFFFFF) << 32 | (_ret & 0xFFFFFFFF00000000) >> 32; \ - _ret = \ - (_ret & 0x0000FFFF0000FFFF) << 16 | (_ret & 0xFFFF0000FFFF0000) >> 16; \ - _ret = \ - (_ret & 0x00FF00FF00FF00FF) << 8 | (_ret & 0xFF00FF00FF00FF00) >> 8; \ - _ret; \ - \ - }) - -// It is impossible to define 128 bit constants, so ... -#ifdef WORD_SIZE_64 - #define SWAPN(_x, _l) \ - ({ \ - \ - u128 _res = (_x), _ret; \ - char *d = (char *)&_ret, *s = (char *)&_res; \ - int i; \ - for (i = 0; i < 16; i++) \ - d[15 - i] = s[i]; \ - u32 sr = 128U - ((_l) << 3U); \ - (_ret >>= sr); \ - (u128) _ret; \ - \ - }) -#endif - -#define SWAPNN(_x, _y, _l) \ - ({ \ - \ - char *d = (char *)(_x), *s = (char *)(_y); \ - u32 i, l = (_l)-1; \ - for (i = 0; i <= l; i++) \ - d[l - i] = s[i]; \ - \ - }) - -#ifdef AFL_LLVM_PASS - #if defined(__linux__) || !defined(__ANDROID__) - #define AFL_SR(s) (srandom(s)) - #define AFL_R(x) (random() % (x)) - #else - #define AFL_SR(s) ((void)s) - #define AFL_R(x) (arc4random_uniform(x)) - #endif -#else - #if defined(__linux__) || !defined(__ANDROID__) - #define SR(s) (srandom(s)) - #define R(x) (random() % (x)) - #else - #define SR(s) ((void)s) - #define R(x) (arc4random_uniform(x)) - #endif -#endif /* ^AFL_LLVM_PASS */ - -#define STRINGIFY_INTERNAL(x) #x -#define STRINGIFY(x) STRINGIFY_INTERNAL(x) - -#define MEM_BARRIER() __asm__ volatile("" ::: "memory") - -#if __GNUC__ < 6 - #ifndef likely - #define likely(_x) (_x) - #endif - #ifndef unlikely - #define unlikely(_x) (_x) - #endif -#else - #ifndef likely - #define likely(_x) __builtin_expect(!!(_x), 1) - #endif - #ifndef unlikely - #define unlikely(_x) __builtin_expect(!!(_x), 0) - #endif -#endif - -#endif /* ! _HAVE_TYPES_H */ - diff --git a/include/uc_priv.h b/include/uc_priv.h index a148c10e..8c564396 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -15,31 +15,14 @@ // These are masks of supported modes for each cpu/arch. // They should be updated when changes are made to the uc_mode enum typedef. -#ifdef UNICORN_HAS_AFL -#define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \ - |UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN|UC_MODE_AFL) -#define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_PPC_MASK (UC_MODE_PPC32|UC_MODE_PPC64|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN|UC_MODE_AFL) -#else #define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \ |UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|UC_MODE_BIG_ENDIAN) -#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN) #define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN) +#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN) #define UC_MODE_PPC_MASK (UC_MODE_PPC32|UC_MODE_PPC64|UC_MODE_BIG_ENDIAN) #define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN) #define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN) #define UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN) -#endif - -#ifndef NDEBUG -#define UCLOG(...) fprintf(stderr, __VA_ARGS__) -#else -#define UCLOG(...) -#endif #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) @@ -112,20 +95,6 @@ typedef void (*uc_softfloat_initialize)(void); // tcg flush softmmu tlb typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc); -typedef enum uc_afl_ret { - UC_AFL_RET_ERROR = 0, // Something went horribly wrong in the parent - UC_AFL_RET_CHILD, // Fork worked. we are a child - UC_AFL_RET_NO_AFL, // No AFL, no need to fork. - UC_AFL_RET_CALLED_TWICE, // AFL has already been started before. - UC_AFL_RET_FINISHED, // We forked before but now AFL is gone (parent) -} uc_afl_ret; - -// we use this as shortcut deep inside uc_afl for the arch specific uc_afl_next(uc, bool) -typedef uc_afl_ret(*uc_afl_ret_uc_bool_t)(struct uc_struct*, bool); - -// afl_forkserver_start -typedef int (*uc_afl_forkserver_t)(struct uc_struct*); - struct hook { int type; // UC_HOOK_* int insn; // instruction for HOOK_INSN @@ -313,23 +282,6 @@ struct uc_struct { bool first_tb; // is this the first Translation-Block ever generated since uc_emu_start()? struct list saved_contexts; // The contexts saved by this uc_struct. bool no_exit_request; // Disable check_exit_request temporarily. A workaround to treat the IT block as a whole block. - -#ifdef UNICORN_HAS_AFL - bool afl; - uc_afl_forkserver_t afl_forkserver_start; // function to start afl forkserver - uc_afl_ret_uc_bool_t afl_child_request_next; // function from child to ask for new testcase (if in child) - int afl_child_pipe[2]; // pipe used to send information from child process to forkserver - int afl_parent_pipe[2]; // pipe used to send information from parent to child in forkserver - uint8_t *afl_area_ptr; // map, shared with afl, to report coverage feedback etc. during runs - uint64_t afl_prev_loc; // previous location - int afl_compcov_level; // how much compcove we want - unsigned int afl_inst_rms; - size_t exit_count; // number of exits set in afl_fuzz or afl_forkserver - uint64_t *exits; // pointer to the actual exits - char *afl_testcase_ptr; // map, shared with afl, to get testcases delivered from for each run - uint32_t *afl_testcase_size_p; // size of the current testcase, if using shared map fuzzing with afl. - void *afl_data_ptr; // Pointer for various (bindings-related) uses. -#endif }; // Metadata stub for the variable-size cpu context used with uc_context_*() diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 042318e8..d7780e56 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -105,7 +105,6 @@ typedef enum uc_arch { typedef enum uc_mode { UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode - UC_MODE_AFL = 1 << 29, // arm / arm64 UC_MODE_ARM = 0, // ARM mode @@ -172,10 +171,6 @@ typedef enum uc_err { UC_ERR_HOOK_EXIST, // hook for this event already existed UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() UC_ERR_EXCEPTION, // Unhandled CPU exception - UC_ERR_AFL_RET_ERROR, // Something went horribly wrong in the parent - UC_ERR_AFL_RET_NO_AFL, // No AFL, no need to fork. - UC_ERR_AFL_RET_CALLED_TWICE, // AFL has already been started before. - UC_ERR_AFL_RET_FINISHED, // We forked before but now AFL is gone (parent) } uc_err; @@ -573,82 +568,6 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size); UNICORN_EXPORT uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count); -/* Callback function called for each input from AFL. - This function is mandatory. - It's purpose is to place the input at the right place in unicorn. - @uc: Unicorn instance - @input: The current input we're working on. Place this somewhere in unicorn's memory now. - @input_len: length of the input - @persistent_round: which round we are currently crashing in, if using persistent mode. - @data: Data pointer passed to uc_afl_fuzz(...). - @return: - If you return is true, all is well. Fuzzing starts. - If you return false, the input is rejected; we will continue with the next input. -*/ -typedef bool (*uc_afl_cb_place_input_t)(uc_engine *uc, char *input, size_t input_len, uint32_t persistent_round, void *data); - -/* Callback function called after a non-UC_ERR_OK returncode was returned by Unicorn. - This function is not mandatory (pass NULL). - @uc: Unicorn instance - @unicorn_result: The error state returned by the current testcase - @input: The current input we're workin with. - @input_len: length of the input - @persistent_round: which round we are currently crashing in, if using persistent mode. - @data: Data pointer passed to uc_afl_fuzz(...). -@Return: - If you return false, the crash is considered invalid and not reported to AFL. - If return is true, the crash is reported. - -> The child will die and the forkserver will spawn a new child. -*/ -typedef bool (*uc_afl_cb_validate_crash_t)(uc_engine *uc, uc_err unicorn_result, char *input, int input_len, int persistent_round, void *data); - -/* - The main fuzzer. - Starts uc_afl_forkserver(), then beginns a persistent loop. - Reads input, calls the place_input callback, emulates, uc_afl_next(...), repeats. - If unicorn errors out, will call the validate_crash_callback, if set. - Will only retrun in the parent after the whole fuzz thing has been finished and afl died. - The child processes never return from here. - - Note: This API is not supported on Windows. - - @uc: handle returned by uc_open() - @input_file: filename/path to the (AFL) inputfile. Usualy suplied on the commandline. - @place_input_callback: Callback function that will be called before each test runs. - This function needs to write the input from afl to the correct position on the unicorn object. - @exits: address list of exits where fuzzing should stop (len == exit_count) - @exit_count: number of exits where fuzzing should stop - @validate_crash_callback: Optional callback (if not needed, pass NULL), that determines - if a non-OK uc_err is an actual error. If false is returned, the test-case will not crash. - @always_validate: If false, validate_crash_callback will only be called for crashes. - @persistent_iters: - The amount of loop iterations in persistent mode before restarteing with a new forked child. - If your target cannot be fuzzed using persistent mode (global state changes a lot), - set persistent_iters = 1 for the normal fork-server experience. - Else, the default is usually around 1000. - If your target is super stable (and unicorn is, too - not sure about that one), - you may pass persistent_iter = 0 for that an infinite fuzz loop. - @data: Your very own data pointer. This will passed into every callback. - @return uc_afl_ret: - >UC_AFL_RET_ERROR = 0, // Something went horribly wrong in the parent - >UC_AFL_RET_CHILD, // Can never happen, the child will loop happily or exit. - >UC_AFL_RET_NO_AFL, // No AFL, we ran the testacse once and are done. - >UC_AFL_RET_FINISHED, // We forked before but now AFL is gone (parent) - >> We're retuning after having fuzzed. We may now pack our bags and exit. -*/ -UNICORN_EXPORT -uc_err uc_afl_fuzz( - uc_engine *uc, - char* input_file, - uc_afl_cb_place_input_t place_input_callback, - uint64_t *exits, - size_t exit_count, - uc_afl_cb_validate_crash_t validate_crash_callback, - bool always_validate, - uint32_t persistent_iters, - void *data -); - /* Stop emulation (which was started by uc_emu_start() API. This is typically called from callback functions registered via tracing APIs. diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 21397dcd..75d71514 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64 #endif -#define afl_forkserver_start afl_forkserver_start_aarch64 -#define helper_afl_maybe_log helper_afl_maybe_log_aarch64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_aarch64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_aarch64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_aarch64 #define use_idiv_instructions use_idiv_instructions_aarch64 #define arm_arch arm_arch_aarch64 #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 55536832..ee750153 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64eb #endif -#define afl_forkserver_start afl_forkserver_start_aarch64eb -#define helper_afl_maybe_log helper_afl_maybe_log_aarch64eb -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_aarch64eb -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_aarch64eb -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_aarch64eb #define use_idiv_instructions use_idiv_instructions_aarch64eb #define arm_arch arm_arch_aarch64eb #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64eb diff --git a/qemu/accel/tcg/cpu-exec.c b/qemu/accel/tcg/cpu-exec.c index ea5b8045..79bcdd13 100644 --- a/qemu/accel/tcg/cpu-exec.c +++ b/qemu/accel/tcg/cpu-exec.c @@ -29,10 +29,6 @@ #include "sysemu/cpus.h" #include "uc_priv.h" -#ifdef UNICORN_HAS_AFL -#include "afl/afl-cpu-inl.h" -#endif - /* -icount align implementation. */ typedef struct SyncClocks { @@ -258,11 +254,6 @@ static inline TranslationBlock *tb_find(CPUState *cpu, /* We add the TB in the virtual pc hash table for the fast lookup */ cpu->tb_jmp_cache[tb_jmp_cache_hash_func(cpu->uc, pc)] = tb; } - -#if defined(UNICORN_HAS_AFL) - afl_request_tsl(cpu, pc, cs_base, flags, cf_mask); -#endif - /* We don't take care of direct jumps when address mapping changes in * system emulation. So it's not safe to make a direct jump to a TB * spanning two pages because the mapping for the second page can change. @@ -588,31 +579,3 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu) return ret; } - -#ifdef UNICORN_HAS_AFL -int afl_forkserver_start(struct uc_struct *uc) -{ - // Not sure if we need all of this setup foo. - CPUState *cpu = uc->cpu; - if (!cpu->created) { - cpu->created = true; - cpu->halted = 0; - qemu_init_vcpu(cpu); - - } - cpu_resume(cpu); - - if (uc->count_hook != 0) { - uc_hook_del(uc, uc->count_hook); - uc->count_hook = 0; - } - - uc->quit_request = false; - uc->cpu = cpu; - smp_mb(); - - // Would love to not have the extra step in cpus.c, but it doesn't work otherwise(?) - afl_setup(uc); - return afl_forkserver(cpu); -} -#endif \ No newline at end of file diff --git a/qemu/accel/tcg/tcg-runtime.c b/qemu/accel/tcg/tcg-runtime.c index 67829b91..1e8283ea 100644 --- a/qemu/accel/tcg/tcg-runtime.c +++ b/qemu/accel/tcg/tcg-runtime.c @@ -32,10 +32,6 @@ #include -#ifdef UNICORN_HAS_AFL -#include "afl/afl-tcg-runtime-inl.h" -#endif - /* 32-bit helpers */ int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2) diff --git a/qemu/accel/tcg/tcg-runtime.h b/qemu/accel/tcg/tcg-runtime.h index 813c1c07..ab7369e8 100644 --- a/qemu/accel/tcg/tcg-runtime.h +++ b/qemu/accel/tcg/tcg-runtime.h @@ -259,10 +259,3 @@ 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_5(gvec_bitsel, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) - -#if defined(UNICORN_HAS_AFL) -DEF_HELPER_FLAGS_2(afl_maybe_log, 0, void, ptr, i64) -DEF_HELPER_FLAGS_4(afl_compcov_log_16, 0, void, ptr, i64, i32, i32) -DEF_HELPER_FLAGS_4(afl_compcov_log_32, 0, void, ptr, i64, i32, i32) -DEF_HELPER_FLAGS_4(afl_compcov_log_64, 0, void, ptr, i64, i64, i64) -#endif \ No newline at end of file diff --git a/qemu/accel/tcg/translator.c b/qemu/accel/tcg/translator.c index 8afbc1fd..0fca28a9 100644 --- a/qemu/accel/tcg/translator.c +++ b/qemu/accel/tcg/translator.c @@ -17,11 +17,6 @@ #include -#if defined(UNICORN_HAS_AFL) -#undef ARCH_HAS_COMPCOV -#include "afl/afl-cpu-translate-inl.h" -#endif - /* 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, @@ -61,29 +56,6 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, /* Reset the temp count so that we can identify leaks */ tcg_clear_temp_count(); -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = cpu->uc->exits; - size_t exit_count = cpu->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (tb->pc == exits[i]) { - // This should catch that instruction is at the end - // and generate appropriate halting code. - gen_tb_start(tcg_ctx, db->tb); - ops->tb_start(db, cpu); - db->num_insns++; - ops->insn_start(db, cpu); - ops->translate_insn(db, cpu); - goto _end_loop; - } - } - } - } -#endif - /* Unicorn: early check to see if the address of this block is * the "run until" address. */ if (tb->pc == cpu->uc->addr_end) { @@ -109,10 +81,6 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, // tcg_dump_ops(tcg_ctx, false, "translator loop"); -#ifdef UNICORN_HAS_AFL - afl_gen_maybe_log(tcg_ctx, tb->pc); -#endif - /* Start translating. */ gen_tb_start(tcg_ctx, db->tb); // tcg_dump_ops(tcg_ctx, false, "tb start"); diff --git a/qemu/arm.h b/qemu/arm.h index ef9fa72d..d3cc372d 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _arm #endif -#define afl_forkserver_start afl_forkserver_start_arm -#define helper_afl_maybe_log helper_afl_maybe_log_arm -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_arm -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_arm -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_arm #define use_idiv_instructions use_idiv_instructions_arm #define arm_arch arm_arch_arm #define tb_target_set_jmp_target tb_target_set_jmp_target_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 7ecccaaa..0a51a80d 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _armeb #endif -#define afl_forkserver_start afl_forkserver_start_armeb -#define helper_afl_maybe_log helper_afl_maybe_log_armeb -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_armeb -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_armeb -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_armeb #define use_idiv_instructions use_idiv_instructions_armeb #define arm_arch arm_arch_armeb #define tb_target_set_jmp_target tb_target_set_jmp_target_armeb diff --git a/qemu/include/tcg/tcg-op.h b/qemu/include/tcg/tcg-op.h index 915fe79f..73d1b93f 100644 --- a/qemu/include/tcg/tcg-op.h +++ b/qemu/include/tcg/tcg-op.h @@ -29,10 +29,6 @@ #include "exec/helper-proto.h" #include "exec/helper-gen.h" -#ifdef UNICORN_HAS_AFL -#include "afl/afl-tcg-op-inl.h" -#endif - static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, int32_t type, void *uc, uint64_t pc) { TCGv_i32 tsize = tcg_const_i32(tcg_ctx, size); diff --git a/qemu/m68k.h b/qemu/m68k.h index 77fb249c..cb3d430b 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _m68k #endif -#define afl_forkserver_start afl_forkserver_start_m68k -#define helper_afl_maybe_log helper_afl_maybe_log_m68k -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_m68k -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_m68k -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_m68k #define use_idiv_instructions use_idiv_instructions_m68k #define arm_arch arm_arch_m68k #define tb_target_set_jmp_target tb_target_set_jmp_target_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 9eef9f63..a2b78379 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips #endif -#define afl_forkserver_start afl_forkserver_start_mips -#define helper_afl_maybe_log helper_afl_maybe_log_mips -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mips -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mips -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mips #define use_idiv_instructions use_idiv_instructions_mips #define arm_arch arm_arch_mips #define tb_target_set_jmp_target tb_target_set_jmp_target_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 9dde191e..9faef36b 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64 #endif -#define afl_forkserver_start afl_forkserver_start_mips64 -#define helper_afl_maybe_log helper_afl_maybe_log_mips64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mips64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mips64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mips64 #define use_idiv_instructions use_idiv_instructions_mips64 #define arm_arch arm_arch_mips64 #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 4634c429..6f748b36 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64el #endif -#define afl_forkserver_start afl_forkserver_start_mips64el -#define helper_afl_maybe_log helper_afl_maybe_log_mips64el -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mips64el -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mips64el -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mips64el #define use_idiv_instructions use_idiv_instructions_mips64el #define arm_arch arm_arch_mips64el #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 1e6ce28b..a4831183 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mipsel #endif -#define afl_forkserver_start afl_forkserver_start_mipsel -#define helper_afl_maybe_log helper_afl_maybe_log_mipsel -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mipsel -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mipsel -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mipsel #define use_idiv_instructions use_idiv_instructions_mipsel #define arm_arch arm_arch_mipsel #define tb_target_set_jmp_target tb_target_set_jmp_target_mipsel diff --git a/qemu/ppc.h b/qemu/ppc.h index e787604c..8cb9ea3e 100644 --- a/qemu/ppc.h +++ b/qemu/ppc.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc #endif -#define afl_forkserver_start afl_forkserver_start_ppc -#define helper_afl_maybe_log helper_afl_maybe_log_ppc -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_ppc -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_ppc -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_ppc #define use_idiv_instructions use_idiv_instructions_ppc #define arm_arch arm_arch_ppc #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc diff --git a/qemu/ppc64.h b/qemu/ppc64.h index ada125c0..1d055072 100644 --- a/qemu/ppc64.h +++ b/qemu/ppc64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc64 #endif -#define afl_forkserver_start afl_forkserver_start_ppc64 -#define helper_afl_maybe_log helper_afl_maybe_log_ppc64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_ppc64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_ppc64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_ppc64 #define use_idiv_instructions use_idiv_instructions_ppc64 #define arm_arch arm_arch_ppc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc64 diff --git a/qemu/riscv32.h b/qemu/riscv32.h index f91bcf0b..df9eed70 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv32 #endif -#define afl_forkserver_start afl_forkserver_start_riscv32 -#define helper_afl_maybe_log helper_afl_maybe_log_riscv32 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_riscv32 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_riscv32 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_riscv32 #define use_idiv_instructions use_idiv_instructions_riscv32 #define arm_arch arm_arch_riscv32 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index c59c5148..c41e7178 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv64 #endif -#define afl_forkserver_start afl_forkserver_start_riscv64 -#define helper_afl_maybe_log helper_afl_maybe_log_riscv64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_riscv64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_riscv64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_riscv64 #define use_idiv_instructions use_idiv_instructions_riscv64 #define arm_arch arm_arch_riscv64 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv64 diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index 464e7b94..f983f634 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -194,23 +194,6 @@ void resume_all_vcpus(struct uc_struct* uc) tb_flush_jmp_cache(cpu, uc->addr_end); } -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - TranslationBlock *tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(uc, exits[i])]; - if (tb) { - qht_remove(&uc->tcg_ctx->tb_ctx.htable, tb, tb->hash); - tb_flush_jmp_cache(cpu, uc->exits[i]); - } - } - } - } -#endif cpu->created = false; } diff --git a/qemu/sparc.h b/qemu/sparc.h index daa2dcb6..741e7565 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc #endif -#define afl_forkserver_start afl_forkserver_start_sparc -#define helper_afl_maybe_log helper_afl_maybe_log_sparc -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_sparc -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_sparc -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_sparc #define use_idiv_instructions use_idiv_instructions_sparc #define arm_arch arm_arch_sparc #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index a2e1ec32..5262a11b 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc64 #endif -#define afl_forkserver_start afl_forkserver_start_sparc64 -#define helper_afl_maybe_log helper_afl_maybe_log_sparc64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_sparc64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_sparc64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_sparc64 #define use_idiv_instructions use_idiv_instructions_sparc64 #define arm_arch arm_arch_sparc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc64 diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index ef8ad7aa..a9eb1ca0 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -37,11 +37,6 @@ #include "qemu/atomic128.h" #include "kvm-consts.h" -#if defined(UNICORN_HAS_AFL) -#undef ARCH_HAS_COMPCOV -#include "afl/afl-cpu-translate-inl.h" -#endif - static const char *regnames[] = { "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", @@ -14641,23 +14636,6 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) DisasContext *dc = container_of(dcbase, DisasContext, base); CPUARMState *env = cpu->env_ptr; -#ifdef UNICORN_HAS_AFL - if (dc->uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = dc->uc->exits; - size_t exit_count = dc->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (dcbase->pc_next == exits[i]) { - dcbase->is_jmp = DISAS_WFI; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (dcbase->pc_next == dc->uc->addr_end) { // imitate WFI instruction to halt emulation diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 1c4827d7..742a55fd 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -11420,23 +11420,6 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) return; } -#ifdef UNICORN_HAS_AFL - if (dc->uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = dc->uc->exits; - size_t exit_count = dc->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (dcbase->pc_next == exits[i]) { - dcbase->is_jmp = DISAS_WFI; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (dcbase->pc_next == dc->uc->addr_end) { // imitate WFI instruction to halt emulation diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index fce8d914..cf148c4b 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -4764,27 +4764,6 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) s->uc = env->uc; -#ifdef UNICORN_HAS_AFL - if (s->uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = s->uc->exits; - size_t exit_count = s->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (s->pc == exits[i]) { - // imitate the HLT instruction - gen_update_cc_op(s); - gen_jmp_im(s, pc_start - s->cs_base); - gen_helper_hlt(tcg_ctx, tcg_ctx->cpu_env, tcg_const_i32(tcg_ctx, s->pc - pc_start)); - s->base.is_jmp = DISAS_NORETURN; - return s->pc; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { // imitate the HLT instruction diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index 0dc9af2b..323eff44 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -6325,23 +6325,6 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) CPUM68KState *env = cpu->env_ptr; uint16_t insn; -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (dc->pc == exits[i]) { - gen_exception(dc, dc->pc, EXCP_HLT); - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (dc->pc == uc->addr_end) { gen_exception(dc, dc->pc, EXCP_HLT); diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index 4660a2b3..97e680a3 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -30931,24 +30931,6 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) is_slot = ctx->hflags & MIPS_HFLAG_BMASK; -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (ctx->base.pc_next == exits[i]) {// raise a special interrupt to quit - gen_helper_wait(tcg_ctx, tcg_ctx->cpu_env); - ctx->base.is_jmp = DISAS_NORETURN; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == uc->addr_end) { // raise a special interrupt to quit diff --git a/qemu/target/ppc/translate.c b/qemu/target/ppc/translate.c index 2e06bbb7..8cfebab2 100644 --- a/qemu/target/ppc/translate.c +++ b/qemu/target/ppc/translate.c @@ -7625,23 +7625,6 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n", ctx->base.pc_next, ctx->mem_idx, (int)msr_ir); -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (ctx->base.pc_next == exits[i]) { - gen_wait(ctx); - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == uc->addr_end) { gen_wait(ctx); diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index a1ef4139..9898093d 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -849,24 +849,6 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) TCGOp *tcg_op, *prev_op = NULL; bool insn_hook = false; -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = ctx->uc->exits; - size_t exit_count = ctx->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (ctx->base.pc_next == exits[i]) { - // Unicorn: We have to exit current execution here. - dcbase->is_jmp = DISAS_UC_EXIT; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == ctx->uc->addr_end) { // Unicorn: We have to exit current execution here. diff --git a/qemu/target/sparc/translate.c b/qemu/target/sparc/translate.c index 6c45978c..c6f3d9cd 100644 --- a/qemu/target/sparc/translate.c +++ b/qemu/target/sparc/translate.c @@ -5950,26 +5950,6 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) CPUSPARCState *env = cs->env_ptr; unsigned int insn; -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (dc->pc == exits[i]) { -#ifndef TARGET_SPARC64 - gen_helper_power_down(tcg_ctx, tcg_ctx->cpu_env); -#endif - dcbase->is_jmp = DISAS_NORETURN; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (dc->pc == uc->addr_end) { #ifndef TARGET_SPARC64 diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index 6e4f3d49..5fd5ff0f 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -1655,7 +1655,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) def = &s->tcg_op_defs[c]; if (c == INDEX_op_insn_start) { nb_oargs = 0; - UCLOG(" ----"); + printf(" ----"); for (i = 0; i < TARGET_INSN_START_WORDS; ++i) { target_ulong a; @@ -1664,7 +1664,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) #else a = op->args[i]; #endif - UCLOG(" " TARGET_FMT_lx, a); + printf(" " TARGET_FMT_lx, a); } } else if (c == INDEX_op_call) { /* variable number of arguments */ @@ -1673,11 +1673,11 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) nb_cargs = def->nb_cargs; /* function name, flags, out args */ - UCLOG(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name, + printf(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name, tcg_find_helper(s, op->args[nb_oargs + nb_iargs]), op->args[nb_oargs + nb_iargs + 1], nb_oargs); for (i = 0; i < nb_oargs; i++) { - UCLOG(",%s", tcg_get_arg_str(s, buf, sizeof(buf), + printf(",%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[i])); } for (i = 0; i < nb_iargs; i++) { @@ -1686,33 +1686,33 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) if (arg != TCG_CALL_DUMMY_ARG) { t = tcg_get_arg_str(s, buf, sizeof(buf), arg); } - UCLOG(",%s", t); + printf(",%s", t); } } else { - UCLOG(" %s ", def->name); + printf(" %s ", def->name); nb_oargs = def->nb_oargs; nb_iargs = def->nb_iargs; nb_cargs = def->nb_cargs; if (def->flags & TCG_OPF_VECTOR) { - UCLOG("v%d,e%d,", 64 << TCGOP_VECL(op), + printf("v%d,e%d,", 64 << TCGOP_VECL(op), 8 << TCGOP_VECE(op)); } k = 0; for (i = 0; i < nb_oargs; i++) { if (k != 0) { - UCLOG(","); + printf(","); } - UCLOG("%s", tcg_get_arg_str(s, buf, sizeof(buf), + printf("%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[k++])); } for (i = 0; i < nb_iargs; i++) { if (k != 0) { - UCLOG(","); + printf(","); } - UCLOG("%s", tcg_get_arg_str(s, buf, sizeof(buf), + printf("%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[k++])); } switch (c) { @@ -1728,9 +1728,9 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) case INDEX_op_cmpsel_vec: if (op->args[k] < ARRAY_SIZE(cond_name) && cond_name[op->args[k]]) { - UCLOG(",%s", cond_name[op->args[k++]]); + printf(",%s", cond_name[op->args[k++]]); } else { - UCLOG(",$0x%" TCG_PRIlx, op->args[k++]); + printf(",$0x%" TCG_PRIlx, op->args[k++]); } i = 1; break; @@ -1744,12 +1744,12 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) unsigned ix = get_mmuidx(oi); if (op & ~(MO_AMASK | MO_BSWAP | MO_SSIZE)) { - UCLOG(",$0x%x,%u", op, ix); + printf(",$0x%x,%u", op, ix); } else { const char *s_al, *s_op; s_al = alignment_name[(op & MO_AMASK) >> MO_ASHIFT]; s_op = ldst_name[op & (MO_BSWAP | MO_SSIZE)]; - UCLOG(",%s%s,%u", s_al, s_op, ix); + printf(",%s%s,%u", s_al, s_op, ix); } i = 1; } @@ -1764,7 +1764,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) case INDEX_op_brcond_i32: case INDEX_op_brcond_i64: case INDEX_op_brcond2_i32: - UCLOG("%s$L%d", k ? "," : "", + printf("%s$L%d", k ? "," : "", arg_label(op->args[k])->id); i++, k++; break; @@ -1772,12 +1772,12 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) break; } for (; i < nb_cargs; i++, k++) { - UCLOG("%s$0x%" TCG_PRIlx, k ? "," : "", op->args[k]); + printf("%s$0x%" TCG_PRIlx, k ? "," : "", op->args[k]); } if(c == INDEX_op_mov_i64){ struct TCGTemp* tp = arg_temp(op->args[1]); if (tp && tp->val_type == TEMP_VAL_MEM){ - UCLOG(" mem_base=%p ", tp->mem_base); + printf(" mem_base=%p ", tp->mem_base); } } } @@ -1786,19 +1786,19 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) unsigned life = op->life; if (life & (SYNC_ARG * 3)) { - UCLOG(" sync:"); + printf(" sync:"); for (i = 0; i < 2; ++i) { if (life & (SYNC_ARG << i)) { - UCLOG(" %d", i); + printf(" %d", i); } } } life /= DEAD_ARG; if (life) { - UCLOG(" dead:"); + printf(" dead:"); for (i = 0; life; ++i, life >>= 1) { if (life & 1) { - UCLOG(" %d", i); + printf(" %d", i); } } } @@ -1809,28 +1809,28 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) TCGRegSet set = op->output_pref[i]; if (i == 0) { - UCLOG(" pref="); + printf(" pref="); } else { - UCLOG(","); + printf(","); } if (set == 0) { - UCLOG("none"); + printf("none"); } else if (set == MAKE_64BIT_MASK(0, TCG_TARGET_NB_REGS)) { - UCLOG("all"); + printf("all"); #ifdef CONFIG_DEBUG_TCG } else if (tcg_regset_single(set)) { TCGReg reg = tcg_regset_first(set); printf("%s", tcg_target_reg_names[reg]); #endif } else if (TCG_TARGET_NB_REGS <= 32) { - UCLOG("%#x", (uint32_t)set); + printf("%#x", (uint32_t)set); } else { - UCLOG("%#" PRIx64, (uint64_t)set); + printf("%#" PRIx64, (uint64_t)set); } } } - UCLOG("\n"); + printf("\n"); } #if 0 @@ -1863,16 +1863,16 @@ void tcg_dump_ops(TCGContext *s, bool have_prefs, const char *headline) int insn_idx = 0; int op_idx = 0; - UCLOG("\n*** %s\n", headline); + printf("\n*** %s\n", headline); // tcg_dump_tbs(s, tcg_dump_tb, NULL); QTAILQ_FOREACH(op, &s->ops, link) { if (op->opc == INDEX_op_insn_start) { - UCLOG("\n insn_idx=%d", insn_idx); + printf("\n insn_idx=%d", insn_idx); insn_idx++; op_idx = 0; } else { - UCLOG(" %d: ", op_idx); + printf(" %d: ", op_idx); } op_idx++; tcg_dump_op(s, have_prefs, op); diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 02b10ea8..84bbb9f1 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -11,7 +11,6 @@ void vm_start(struct uc_struct*); void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size); -int afl_forkserver_start(struct uc_struct*); // return true on success, false on failure static inline bool cpu_physical_mem_read(AddressSpace *as, hwaddr addr, @@ -107,9 +106,7 @@ static inline void uc_common_init(struct uc_struct* uc) uc->softfloat_initialize = softfloat_init; uc->tcg_flush_tlb = tcg_flush_softmmu_tlb; uc->memory_map_io = memory_map_io; -#ifdef UNICORN_HAS_AFL - uc->afl_forkserver_start = afl_forkserver_start; -#endif + if (!uc->release) uc->release = release_common; } diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 233e03c3..a1896af7 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _x86_64 #endif -#define afl_forkserver_start afl_forkserver_start_x86_64 -#define helper_afl_maybe_log helper_afl_maybe_log_x86_64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_x86_64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_x86_64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_x86_64 #define use_idiv_instructions use_idiv_instructions_x86_64 #define arm_arch arm_arch_x86_64 #define tb_target_set_jmp_target tb_target_set_jmp_target_x86_64 diff --git a/symbols.sh b/symbols.sh index 0f8541b2..19997fb4 100755 --- a/symbols.sh +++ b/symbols.sh @@ -4,11 +4,6 @@ CMD_PATH=$(realpath $0) SOURCE_DIR=$(dirname ${CMD_PATH}) COMMON_SYMBOLS=" -afl_forkserver_start \ -helper_afl_maybe_log \ -helper_afl_compcov_log_16 \ -helper_afl_compcov_log_32 \ -helper_afl_compcov_log_64 \ use_idiv_instructions \ arm_arch \ tb_target_set_jmp_target \ diff --git a/uc.c b/uc.c index a4f438b8..3e24674c 100644 --- a/uc.c +++ b/uc.c @@ -26,17 +26,6 @@ #include "qemu/include/qemu/queue.h" -#ifdef UNICORN_HAS_AFL -#include -#include -#include -#include -#include -#include -#include "afl/config.h" -#include "afl/types.h" -#endif - UNICORN_EXPORT unsigned int uc_version(unsigned int *major, unsigned int *minor) { @@ -104,14 +93,6 @@ const char *uc_strerror(uc_err code) return "Insufficient resource (UC_ERR_RESOURCE)"; case UC_ERR_EXCEPTION: return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; - case UC_ERR_AFL_RET_ERROR: - return "Something went horribly wrong in the parent (UC_ERR_AFL_RET_ERROR)"; - case UC_ERR_AFL_RET_NO_AFL: - return "No AFL, no need to fork (UC_ERR_AFL_RET_NO_AFL)"; - case UC_ERR_AFL_RET_CALLED_TWICE: - return "AFL has already been started before (UC_ERR_AFL_RET_CALLED_TWICE)"; - case UC_ERR_AFL_RET_FINISHED: - return "We forked before but now parent is gone (UC_ERR_AFL_RET_FINISHED)"; } } @@ -162,11 +143,6 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) return UC_ERR_NOMEM; } - if (mode & UC_MODE_AFL) { - uc->afl = true; - mode &= (~UC_MODE_AFL); - } - /* qemu/exec.c: phys_map_node_reserve() */ uc->alloc_hint = 16; uc->errnum = UC_ERR_OK; @@ -771,320 +747,6 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time return uc->invalid_error; } -#ifdef UNICORN_HAS_AFL -static inline uc_afl_ret uc_afl_forkserver_start(uc_engine *uc, uint64_t *exits, size_t exit_count) -{ - /* - Why we need exits as parameter to forkserver: - In the original unicorn-afl, Unicorn needed to flush the tb cache for every iteration. - This is super slow. - Problem was, that the original forked server doesn't know about possible future exits. - The cached blocks, in the next child, therefore would have no exit set and run forever. - Also it's nice to have multiple exits, so let's just do it right. - */ - - if (!uc) { - fprintf(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); - return UC_AFL_RET_ERROR; - } - if (!exits) { - fprintf(stderr, "[!] Nullptr provided for exits.\n"); - return UC_AFL_RET_ERROR; - } - if (!exit_count) { - fprintf(stderr, "[!] No exits provided (exit_count was 0).\n"); - return UC_AFL_RET_ERROR; - } - if (unlikely(uc->afl_area_ptr)) { -#if defined(AFL_DEBUG) - fprintf(stderr, "[!] forkserver_start(...) called twice. Already fuzzing!\n"); -#endif - return UC_AFL_RET_CALLED_TWICE; // AFL has already been started before. - } - - /* Copy exits to unicorn env buffer */ - uc->exits = g_realloc(uc->exits, sizeof(exits[0]) * exit_count); - if (uc->exits == NULL) { - perror("[!] malloc failed when starting forkserver."); - return UC_AFL_RET_ERROR; - } - memcpy(uc->exits, exits, sizeof(exits[0]) * exit_count); - uc->exit_count = exit_count; - // Set addr_end to make sure unicorn will not stop at addr 0x0. - uc->addr_end = uc->exits[0]; - - /* Fork() :) */ - return uc->afl_forkserver_start(uc); - -} - -/* AFL++ supports testcase forwarding via shared map. - If the env variable is set, get the shared map here. - returns true if we enabled shmap fuzzing, false otherwise. */ -static bool uc_afl_enable_shm_testcases(uc_engine *uc) { - - char *id_str = getenv(SHM_FUZZ_ENV_VAR); - if (id_str) { - int shm_id = atoi(id_str); - char *map = (char *)shmat(shm_id, NULL, 0); - if (!map || map == (void *)-1) { - perror("[!] could not access fuzzing shared memory"); - exit(1); - } - uc->afl_testcase_size_p = (u32 *)map; - uc->afl_testcase_ptr = (map + sizeof(u32)); -#if defined(AFL_DEBUG) - printf("[d] successfully opened shared memory for testcases with id %d\n", shm_id); -#endif - return true; - - } else { -#if defined(AFL_DEBUG) - printf("[d] SHM_FUZZ_ENV_VAR not set - not using shared map fuzzing.\n"); -#endif - return false; - } - -} - -/* returns the filesize in bytes, -1 or error. */ -static inline off_t uc_afl_mmap_file(char *filename, char **buf_ptr) { - - off_t ret = -1; - - int fd = open(filename, O_RDONLY); - - struct stat st = {0}; - if (fstat(fd, &st)) goto exit; - - off_t in_len = st.st_size; - - *buf_ptr = mmap(0, in_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - - if (*buf_ptr != MAP_FAILED) ret = in_len; - -exit: - close(fd); - return ret; - -} - -/* A start with "less features" for our afl use-case */ -/* this is largely copied from uc_emu_start, just without setting the entry point, counter and timeout. */ -int uc_afl_emu_start(uc_engine *uc) { - - uc->emu_counter = 0; - uc->invalid_error = UC_ERR_OK; - uc->emulation_done = false; - uc->stop_request = false; - - // remove count hook if counting isn't necessary - if (uc->count_hook != 0) { - uc_hook_del(uc, uc->count_hook); - uc->count_hook = 0; - } - - uc->vm_start(uc); - - // emulation is done - uc->emulation_done = true; - - return uc->invalid_error; - -} - -/* afl_next that expects you know what you're doing - Specifically, it won't check for afl_area_ptr and next to be set. */ -static inline uc_afl_ret uc_afl_next_inl(uc_engine *uc, bool crash_found) -{ - // Tell the parent we need a new testcase, then stop until testcase is available. - if (uc->afl_child_request_next(uc, crash_found) == UC_AFL_RET_ERROR) return UC_AFL_RET_ERROR; - return UC_AFL_RET_CHILD; - -} - - -/* similar to __afl_persistent loop */ -static inline uc_afl_ret uc_afl_next(uc_engine *uc, bool crash_found) -{ - - if (unlikely(!uc->afl_area_ptr)) { - fprintf(stderr, "[!] uc_afl_next(...) called before forkserver_start(...)."); - return UC_AFL_RET_ERROR; - } - - // Tell the parent we need a new testcase, then stop until testcase is available. - if (uc->afl_child_request_next) { - - return uc_afl_next_inl(uc, crash_found); - - } - - return UC_AFL_RET_NO_AFL; -} -#endif - -UNICORN_EXPORT -uc_err uc_afl_fuzz( - uc_engine *uc, - char* input_file, - uc_afl_cb_place_input_t place_input_callback, - uint64_t *exits, - size_t exit_count, - uc_afl_cb_validate_crash_t validate_crash_callback, - bool always_validate, - uint32_t persistent_iters, - void *data -){ -#ifndef UNICORN_HAS_AFL - return UC_ERR_MODE; -#else - if (!uc) { - UCLOG(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); - return UC_ERR_AFL_RET_ERROR; - } - if (!(uc->afl)) { - return UC_ERR_MODE; - } - if (!input_file || input_file[0] == 0) { - UCLOG(stderr, "[!] No input file provided to uc_afl_fuzz.\n"); - return UC_ERR_AFL_RET_ERROR; - } - if (!place_input_callback) { - UCLOG(stderr, "[!] no place_input_callback set.\n"); - return UC_ERR_AFL_RET_ERROR; - } - if (always_validate && !validate_crash_callback) { - UCLOG(stderr, "[!] always_validate set but validate_crash_callback is missing.\n"); - return UC_ERR_AFL_RET_ERROR; - } - if (!exit_count) { - UCLOG(stderr, "[!] Nullptr provided for exits.\n"); - return UC_ERR_AFL_RET_ERROR; - } - - uint32_t mmap_in_len = 0; - char *in_buf = NULL; - uint32_t *in_len_p = NULL; - - bool use_shmap_input = uc_afl_enable_shm_testcases(uc); - if (use_shmap_input) { - /* For shared map fuzzing, the ptr stays the same */ - in_buf = uc->afl_testcase_ptr; - in_len_p = uc->afl_testcase_size_p; - } else { - in_len_p = &mmap_in_len; - } - - uc_afl_ret afl_ret = uc_afl_forkserver_start(uc, exits, exit_count); - switch(afl_ret) { - case UC_AFL_RET_CHILD: - break; - case UC_AFL_RET_NO_AFL: - // Not running in AFL. - persistent_iters = 1; - break; - case UC_AFL_RET_FINISHED: - // Nothing more to do - return UC_ERR_AFL_RET_FINISHED; - case UC_AFL_RET_ERROR: - return UC_ERR_AFL_RET_ERROR; - case UC_AFL_RET_CALLED_TWICE: - // Nothing more we can do - return UC_ERR_AFL_RET_CALLED_TWICE; - default: - // What have we done - UCLOG(stderr, "[!] Unexpected forkserver return: %d", afl_ret); - return UC_ERR_AFL_RET_ERROR; - } - - bool first_round = true; - bool crash_found = false; - -#if defined(AFL_DEBUG) - if (uc->afl_testcase_ptr) { - UCLOG("[d] uc->afl_testcase_ptr = %p, len = %d\n", uc->afl_testcase_ptr, *uc->afl_testcase_size_p); - } -#endif - - // 0 means never stop child in persistence mode. - uint32_t i; - for (i = 0; persistent_iters == 0 || i < persistent_iters; i++) { - - // The main fuzz loop starts here :) - if (first_round) { - first_round = false; - } else { - if (uc_afl_next_inl(uc, crash_found) == UC_AFL_RET_ERROR) { - /* parent is probably gone */ - exit(1); - } - crash_found = false; - } - - /* get input, call place input callback, emulate, unmap input (if needed) */ - if (unlikely(!use_shmap_input)) { - /* in_buf and the len are not in a shared map (as it would be for sharedmem fuzzing - No shmap fuzzing involved - Let's read a "normal" file. */ - off_t in_len = uc_afl_mmap_file(input_file, &in_buf); - if (unlikely(in_len < 0)) { - UCLOG(stderr, "[!] Unable to mmap file: %s (return was %ld)\n", input_file, (long int) in_len); - perror("mmap"); - fflush(stderr); - return UC_AFL_RET_ERROR; - } - mmap_in_len = in_len; - } - bool input_accepted = place_input_callback(uc, in_buf, *in_len_p, i, data); - - if (unlikely(!input_accepted)) { - // Apparently the input was not to the users' liking. Let's continue. - goto next_iter; - } - - uc_err uc_emu_ret = uc_afl_emu_start(uc); - - if (unlikely((uc_emu_ret != UC_ERR_OK) || (always_validate && validate_crash_callback))) { - - if (validate_crash_callback != NULL && validate_crash_callback( - uc, uc_emu_ret, in_buf, *in_len_p, i, data) != true) { - // The callback thinks this is not a valid crash. Ignore. - goto next_iter; - } - if (persistent_iters != 1) { - // We're inpersistent mode and can report the crash via afl_next. No reason to die. - crash_found = true; - goto next_iter; - } - - UCLOG(stderr, "[!] UC returned Error: '%s' - let's abort().\n", uc_strerror(uc_emu_ret)); - fflush(stderr); - - abort(); - - } -next_iter: - if (!use_shmap_input) munmap(in_buf, mmap_in_len); - } - // UC_AFL_RET_CHILD -> We looped through all iters. - // We are still in the child, nothing good will come after this. - // Exit and let the next generation run. - if (likely(afl_ret == UC_AFL_RET_CHILD)) { - exit(0); - } - - if (uc->afl_area_ptr) { - // Nothing should ever come after this but clean it up still. - // shmdt(uc->afl_area_ptr); - uc->afl_area_ptr = NULL; - uc->afl_testcase_ptr = NULL; - - } - - // UC_AFL_RET_NO_AFL -> Not fuzzing. We ran once. - return UC_AFL_RET_NO_AFL; -#endif -} UNICORN_EXPORT uc_err uc_emu_stop(uc_engine *uc)