From 9544b3dbf22f1007f7d3f77593ec746a0345a587 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Mon, 7 Sep 2020 12:35:31 -0300 Subject: rewrite gcc plugin When we started using AFL, it did not have an integrated GCC plugin. There was one proposed by Austin Seipp, but for various reasons we ended up using some of its infrastructure (runtime and wrapper), but writing the GCC plugin proper from scratch. With AFL++'s renewed interest in a GCC plugin, we rebased ours, with some features that are or were missing in the one that was integrated: * efficient, fully-functional inline and out-of-line instrumentation Inline instrumentation was work in progress in the original plugin. Controlled by AFL_GCC_OUT_OF_LINE. * reproducible instrumentation Obey -frandom-seed for pseudorandom number generation. * licensing clarity and strict compliance GPLv3+ for the plugin, that uses GCC internals; add a copy of the license, as required. * allow/deny list support Copied and adjusted from the LLVM plugin implementation. * neverZero support Not as compact as the asm-wrapper version, but likely more efficient. Both are quite thread-unsafe, with different caveats. Controlled with AFL_GCC_SKIP_NEVERZERO. --- src/afl-cc.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/afl-cc.c') diff --git a/src/afl-cc.c b/src/afl-cc.c index ddda3845..78245d4b 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1335,6 +1335,12 @@ int main(int argc, char **argv, char **envp) { AFL_REAL_LD, AFL_CLANG_FLTO); #endif + SAYF( + "\nGCC Plugin-specific environment variables:\n" + "AFL_GCC_OUT_OF_LINE: disable inlined instrumentation\n" + "AFL_GCC_SKIP_NEVERZERO: do not skip zero on trace counters\n" + "AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by " + "filename\n"); } SAYF( -- cgit 1.4.1 From c091340a85694c5de1125a93366f2733959487f5 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 8 Sep 2020 16:15:31 +0200 Subject: new gcc_plugin integration --- GNUmakefile.llvm | 2 +- README.md | 2 ++ docs/Changelog.md | 2 ++ docs/INSTALL.md | 2 +- src/afl-cc.c | 76 +++++++++++++++++++++++++++---------------------------- 5 files changed, 44 insertions(+), 40 deletions(-) (limited to 'src/afl-cc.c') diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 3eefdf90..604fb291 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -229,7 +229,7 @@ CFLAGS_SAFE := -Wall -g -Wno-pointer-sign -I ./include/ -I ./instrumentation -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \ -DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \ -DLLVM_LIBDIR=\"$(LLVM_LIBDIR)\" -DLLVM_VERSION=\"$(LLVMVER)\" \ - -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \ + -Wno-deprecated -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \ -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" \ -DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" \ -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \ diff --git a/README.md b/README.md index c886489d..fb59835c 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ behaviours: only one compiler: afl-cc. All previous compilers now symlink to this one compiler. All instrumentation source code is now in the `instrumentation/` folder. + * The gcc_plugin was replaced with a new version submitted by AdaCore, that + supports more features, thank you! * qemu_mode got upgraded to QEMU 5.1, but to be able to build this a current ninja build tool version and python3 setuptools are required. qemu_mode also got new options like snapshotting, instrumenting specific diff --git a/docs/Changelog.md b/docs/Changelog.md index 73613452..c42ab629 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -25,6 +25,8 @@ sending a mail to . skipped. They are used for splicing though. - set the default power schedule to the superiour "seek" schedule - instrumentation + - We received an enhanced gcc_plugin module from AdaCore, thank you + very much!! - not overriding -Ox or -fno-unroll-loops anymore - new llvm pass: dict2file via AFL_LLVM_DICT2FILE, create afl-fuzz -x dictionary of string comparisons found during compilation diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 93a46caf..8e1e266f 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -28,7 +28,7 @@ If you are using clang, please review README.llvm.md; the LLVM integration mode can offer substantial performance gains compared to the traditional approach. -Likewise, if you are using GCC, please review gcc_plugin/README.md. +Likewise, if you are using GCC, please review instrumentation/README.gcc_plugin.md. You may have to change several settings to get optimal results (most notably, disable crash reporting utilities and switch to a different CPU governor), but diff --git a/src/afl-cc.c b/src/afl-cc.c index 78245d4b..47a33cd0 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1196,7 +1196,7 @@ int main(int argc, char **argv, char **envp) { " - NGRAM-{2-16}\n" " [GCC_PLUGIN] gcc plugin: %s%s\n" " CLASSIC DEFAULT no yes yes no no no " - " simple\n" + " yes\n" " [GCC] simple gcc: %s%s\n" " CLASSIC DEFAULT no no no no no no " " no\n\n", @@ -1270,8 +1270,29 @@ int main(int argc, char **argv, char **envp) { " AFL_CXX: path to the C++ compiler to use\n" " AFL_DEBUG: enable developer debugging output\n" " AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n" - " AFL_HARDEN: adds code hardening to catch memory bugs\n" + " AFL_NO_BUILTIN: no builtins for string compare functions (for " + "libtokencap.so)\n" + " AFL_PATH: path to instrumenting pass and runtime " + "(afl-compiler-rt.*o)\n" " AFL_INST_RATIO: percentage of branches to instrument\n" + " AFL_QUIET: suppress verbose output\n" + " AFL_HARDEN: adds code hardening to catch memory bugs\n" + " AFL_USE_ASAN: activate address sanitizer\n" + " AFL_USE_CFISAN: activate control flow sanitizer\n" + " AFL_USE_MSAN: activate memory sanitizer\n" + " AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"); + + if (have_gcc_plugin) + SAYF( + "\nGCC Plugin-specific environment variables:\n" + " AFL_GCC_OUT_OF_LINE: disable inlined instrumentation\n" + " AFL_GCC_SKIP_NEVERZERO: do not skip zero on trace counters\n" + " AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by filename\n"); + + if (have_llvm) + SAYF( + "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " + "variables:\n" #if LLVM_MAJOR < 9 " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" #else @@ -1288,25 +1309,13 @@ int main(int argc, char **argv, char **envp) { "functions\n" " AFL_LLVM_INSTRUMENT_ALLOW/AFL_LLVM_INSTRUMENT_DENY: enable " "instrument allow/\n" - " deny listing (selective instrumentation)\n" - " AFL_NO_BUILTIN: no builtins for string compare functions (for " - "libtokencap.so)\n" - " AFL_PATH: path to instrumenting pass and runtime " - "(afl-compiler-rt.*o)\n" - " AFL_LLVM_DOCUMENT_IDS: document edge IDs given to which function " - "(LTO only)\n" - " AFL_QUIET: suppress verbose output\n" - " AFL_USE_ASAN: activate address sanitizer\n" - " AFL_USE_CFISAN: activate control flow sanitizer\n" - " AFL_USE_MSAN: activate memory sanitizer\n" - " AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"); + " deny listing (selective instrumentation)\n"); + if (have_llvm) SAYF( - "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " - "variables:\n" " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n" - " AFL_LLVM_INSTRUMENT: set instrumentation mode: CLASSIC, INSTRIM, " - "PCGUARD, LTO, CTX, NGRAM-2 ... NGRAM-16\n" + " AFL_LLVM_INSTRUMENT: set instrumentation mode:\n" + " CLASSIC, INSTRIM, PCGUARD, LTO, CTX, NGRAM-2 ... NGRAM-16\n" " You can also use the old environment variables instead:\n" " AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n" " AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n" @@ -1315,36 +1324,27 @@ int main(int argc, char **argv, char **envp) { " AFL_LLVM_CTX: use context sensitive coverage (for CLASSIC and " "INSTRIM)\n" " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for " - "CLASSIC and INSTRIM)\n"); + "CLASSIC & INSTRIM)\n"); #ifdef AFL_CLANG_FLTO - SAYF( + if (have_lto) + SAYF( "\nLTO/afl-clang-lto specific environment variables:\n" - "AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), e.g. " + " AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), e.g. " "0x10000\n" - "AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding " - "functions they are in into this file\n" - "AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " + " AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding functions\n" + " into this file\n" + " AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " "global var\n" - "AFL_LLVM_LTO_STARTID: from which ID to start counting from for a " + " AFL_LLVM_LTO_STARTID: from which ID to start counting from for a " "bb\n" - "AFL_REAL_LD: use this lld linker instead of the compiled in path\n" - "\nafl-clang-lto was built with linker target \"%s\" and LTO flags " - "\"%s\"\n" - "If anything fails - be sure to read README.lto.md!\n", - AFL_REAL_LD, AFL_CLANG_FLTO); + " AFL_REAL_LD: use this lld linker instead of the compiled in path\n" + "If anything fails - be sure to read README.lto.md!\n"); #endif - - SAYF( - "\nGCC Plugin-specific environment variables:\n" - "AFL_GCC_OUT_OF_LINE: disable inlined instrumentation\n" - "AFL_GCC_SKIP_NEVERZERO: do not skip zero on trace counters\n" - "AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by " - "filename\n"); } SAYF( - "For any information on the available instrumentations and options " + "\nFor any information on the available instrumentations and options " "please \n" "consult the README.md, especially section 3.1 about instrumenting " "targets.\n\n"); -- cgit 1.4.1 From ab744abc4b3c90bee355807e7b6e40ba86f23e74 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 8 Sep 2020 17:54:01 +0200 Subject: code-format --- instrumentation/afl-compiler-rt.o.c | 12 +- instrumentation/afl-gcc-pass.so.cc | 888 ++++++++++++++++++------------------ src/afl-cc.c | 105 +++-- src/afl-forkserver.c | 6 +- 4 files changed, 505 insertions(+), 506 deletions(-) (limited to 'src/afl-cc.c') diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 05e2d50d..0e8b97a2 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -38,8 +38,8 @@ #include #include -#if ! __GNUC__ -#include "llvm/Config/llvm-config.h" +#if !__GNUC__ + #include "llvm/Config/llvm-config.h" #endif #ifdef __linux__ @@ -117,12 +117,12 @@ void __afl_trace(const u32 x) { u8 *p = &__afl_area_ptr[prev ^ x]; #if 1 /* enable for neverZero feature. */ -# if __GNUC__ - u8 c = __builtin_add_overflow (*p, 1, p); + #if __GNUC__ + u8 c = __builtin_add_overflow(*p, 1, p); *p += c; -# else + #else *p += 1 + ((u8)(1 + *p == 0); -# endif + #endif #else ++*p; #endif diff --git a/instrumentation/afl-gcc-pass.so.cc b/instrumentation/afl-gcc-pass.so.cc index 6d6f4636..f8d5fd9e 100644 --- a/instrumentation/afl-gcc-pass.so.cc +++ b/instrumentation/afl-gcc-pass.so.cc @@ -132,10 +132,10 @@ #include #ifdef likely -# undef likely + #undef likely #endif #ifdef unlikely -# undef unlikely + #undef unlikely #endif #include @@ -166,8 +166,8 @@ int plugin_is_GPL_compatible = 1; namespace { -static const struct pass_data afl_pass_data = - { +static const struct pass_data afl_pass_data = { + .type = GIMPLE_PASS, .name = "afl", .optinfo_flags = OPTGROUP_NONE, @@ -176,26 +176,27 @@ static const struct pass_data afl_pass_data = .properties_provided = 0, .properties_destroyed = 0, .todo_flags_start = 0, - .todo_flags_finish = (TODO_update_ssa - | TODO_cleanup_cfg - | TODO_verify_il), - }; + .todo_flags_finish = (TODO_update_ssa | TODO_cleanup_cfg | TODO_verify_il), + +}; struct afl_pass : gimple_opt_pass { - afl_pass (bool quiet, unsigned int ratio) - : gimple_opt_pass (afl_pass_data, g), - be_quiet (quiet), - debug (!!getenv ("AFL_DEBUG")), - inst_ratio (ratio), + + afl_pass(bool quiet, unsigned int ratio) + : gimple_opt_pass(afl_pass_data, g), + be_quiet(quiet), + debug(!!getenv("AFL_DEBUG")), + inst_ratio(ratio), #ifdef AFL_GCC_OUT_OF_LINE - out_of_line (!!(AFL_GCC_OUT_OF_LINE)), + out_of_line(!!(AFL_GCC_OUT_OF_LINE)), #else - out_of_line (getenv ("AFL_GCC_OUT_OF_LINE")), + out_of_line(getenv("AFL_GCC_OUT_OF_LINE")), #endif - neverZero (!getenv ("AFL_GCC_SKIP_NEVERZERO")), - inst_blocks (0) - { - initInstrumentList (); + neverZero(!getenv("AFL_GCC_SKIP_NEVERZERO")), + inst_blocks(0) { + + initInstrumentList(); + } /* Are we outputting to a non-terminal, or running with AFL_QUIET @@ -218,252 +219,240 @@ struct afl_pass : gimple_opt_pass { /* Count instrumented blocks. */ int inst_blocks; - virtual unsigned int - execute (function *fn) - { - if (!isInInstrumentList(fn)) - return 0; + virtual unsigned int execute(function *fn) { + + if (!isInInstrumentList(fn)) return 0; int blocks = 0; /* These are temporaries used by inline instrumentation only, that are live throughout the function. */ - tree ploc = NULL, indx = NULL, map = NULL, map_ptr = NULL, - ntry = NULL, cntr = NULL, xaddc = NULL, xincr = NULL; + tree ploc = NULL, indx = NULL, map = NULL, map_ptr = NULL, ntry = NULL, + cntr = NULL, xaddc = NULL, xincr = NULL; basic_block bb; - FOR_EACH_BB_FN (bb, fn) - { - if (!instrument_block_p (bb)) - continue; - - /* Generate the block identifier. */ - unsigned bid = R (MAP_SIZE); - tree bidt = build_int_cst (sizetype, bid); - - gimple_seq seq = NULL; - - if (out_of_line) - { - static tree afl_trace = get_afl_trace_decl (); - - /* Call __afl_trace with bid, the new location; */ - gcall *call = gimple_build_call (afl_trace, 1, bidt); - gimple_seq_add_stmt (&seq, call); - } - else - { - static tree afl_prev_loc = get_afl_prev_loc_decl (); - static tree afl_area_ptr = get_afl_area_ptr_decl (); - - /* Load __afl_prev_loc to a temporary ploc. */ - if (blocks == 0) - ploc = create_tmp_var (TREE_TYPE (afl_prev_loc), ".afl_prev_loc"); - gimple *load_loc = gimple_build_assign (ploc, afl_prev_loc); - gimple_seq_add_stmt (&seq, load_loc); - - /* Compute the index into the map referenced by area_ptr - that we're to update: indx = (sizetype) ploc ^ bid. */ - if (blocks == 0) - indx = create_tmp_var (TREE_TYPE (bidt), ".afl_index"); - gimple *conv_ploc - = gimple_build_assign (indx, - fold_convert (TREE_TYPE (indx), - ploc)); - gimple_seq_add_stmt (&seq, conv_ploc); - gimple *xor_loc = gimple_build_assign (indx, BIT_XOR_EXPR, - indx, bidt); - gimple_seq_add_stmt (&seq, xor_loc); - - /* Compute the address of that map element. */ - if (blocks == 0) - { - map = afl_area_ptr; - map_ptr = create_tmp_var (TREE_TYPE (afl_area_ptr), - ".afl_map_ptr"); - ntry = create_tmp_var (TREE_TYPE (afl_area_ptr), - ".afl_map_entry"); - } - gimple *idx_map = gimple_build_assign (ntry, POINTER_PLUS_EXPR, - map_ptr, indx); - gimple_seq_add_stmt (&seq, idx_map); - - /* Increment the counter in idx_map. */ - tree memref = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (ntry)), - ntry, build_zero_cst (TREE_TYPE (ntry))); - if (blocks == 0) - cntr = create_tmp_var (TREE_TYPE (memref), ".afl_edge_count"); - - gimple *load_cntr = gimple_build_assign (cntr, memref); - gimple_seq_add_stmt (&seq, load_cntr); - - tree cntrb = cntr; - tree incrv = build_one_cst (TREE_TYPE (cntr)); - - if (neverZero) - { - /* NeverZero: if count wrapped around to zero, advance to - one. */ - if (blocks == 0) - { - xaddc = create_tmp_var (build_complex_type - (TREE_TYPE (memref)), - ".afl_edge_xaddc"); - xincr = create_tmp_var (TREE_TYPE (memref), - ".afl_edge_xincr"); - } - - auto_vec vargs (2); - vargs.quick_push (cntr); - vargs.quick_push (incrv); - gcall *add1_cntr - = gimple_build_call_internal_vec (IFN_ADD_OVERFLOW, vargs); - gimple_call_set_lhs (add1_cntr, xaddc); - gimple_seq_add_stmt (&seq, add1_cntr); - - cntrb = build1 (REALPART_EXPR, TREE_TYPE (cntr), xaddc); - incrv = build1 (IMAGPART_EXPR, TREE_TYPE (xincr), xaddc); - } - - gimple *incr_cntr = gimple_build_assign (cntr, PLUS_EXPR, - cntrb, incrv); - gimple_seq_add_stmt (&seq, incr_cntr); - - gimple *store_cntr = gimple_build_assign (unshare_expr (memref), - cntr); - gimple_seq_add_stmt (&seq, store_cntr); - - /* Store bid >> 1 in __afl_prev_loc. */ - gimple *shift_loc = gimple_build_assign (ploc, - build_int_cst - (TREE_TYPE (ploc), - bid >> 1)); - gimple_seq_add_stmt (&seq, shift_loc); - gimple *store_loc = gimple_build_assign (afl_prev_loc, ploc); - gimple_seq_add_stmt (&seq, store_loc); - } - - /* Insert the generated sequence. */ - gimple_stmt_iterator insp = gsi_after_labels (bb); - gsi_insert_seq_before (&insp, seq, GSI_SAME_STMT); - - /* Bump this function's instrumented block counter. */ - blocks++; + FOR_EACH_BB_FN(bb, fn) { + + if (!instrument_block_p(bb)) continue; + + /* Generate the block identifier. */ + unsigned bid = R(MAP_SIZE); + tree bidt = build_int_cst(sizetype, bid); + + gimple_seq seq = NULL; + + if (out_of_line) { + + static tree afl_trace = get_afl_trace_decl(); + + /* Call __afl_trace with bid, the new location; */ + gcall *call = gimple_build_call(afl_trace, 1, bidt); + gimple_seq_add_stmt(&seq, call); + + } else { + + static tree afl_prev_loc = get_afl_prev_loc_decl(); + static tree afl_area_ptr = get_afl_area_ptr_decl(); + + /* Load __afl_prev_loc to a temporary ploc. */ + if (blocks == 0) + ploc = create_tmp_var(TREE_TYPE(afl_prev_loc), ".afl_prev_loc"); + gimple *load_loc = gimple_build_assign(ploc, afl_prev_loc); + gimple_seq_add_stmt(&seq, load_loc); + + /* Compute the index into the map referenced by area_ptr + that we're to update: indx = (sizetype) ploc ^ bid. */ + if (blocks == 0) indx = create_tmp_var(TREE_TYPE(bidt), ".afl_index"); + gimple *conv_ploc = + gimple_build_assign(indx, fold_convert(TREE_TYPE(indx), ploc)); + gimple_seq_add_stmt(&seq, conv_ploc); + gimple *xor_loc = gimple_build_assign(indx, BIT_XOR_EXPR, indx, bidt); + gimple_seq_add_stmt(&seq, xor_loc); + + /* Compute the address of that map element. */ + if (blocks == 0) { + + map = afl_area_ptr; + map_ptr = create_tmp_var(TREE_TYPE(afl_area_ptr), ".afl_map_ptr"); + ntry = create_tmp_var(TREE_TYPE(afl_area_ptr), ".afl_map_entry"); + + } + + gimple *idx_map = + gimple_build_assign(ntry, POINTER_PLUS_EXPR, map_ptr, indx); + gimple_seq_add_stmt(&seq, idx_map); + + /* Increment the counter in idx_map. */ + tree memref = build2(MEM_REF, TREE_TYPE(TREE_TYPE(ntry)), ntry, + build_zero_cst(TREE_TYPE(ntry))); + if (blocks == 0) + cntr = create_tmp_var(TREE_TYPE(memref), ".afl_edge_count"); + + gimple *load_cntr = gimple_build_assign(cntr, memref); + gimple_seq_add_stmt(&seq, load_cntr); + + tree cntrb = cntr; + tree incrv = build_one_cst(TREE_TYPE(cntr)); + + if (neverZero) { + + /* NeverZero: if count wrapped around to zero, advance to + one. */ + if (blocks == 0) { + + xaddc = create_tmp_var(build_complex_type(TREE_TYPE(memref)), + ".afl_edge_xaddc"); + xincr = create_tmp_var(TREE_TYPE(memref), ".afl_edge_xincr"); + + } + + auto_vec vargs(2); + vargs.quick_push(cntr); + vargs.quick_push(incrv); + gcall *add1_cntr = + gimple_build_call_internal_vec(IFN_ADD_OVERFLOW, vargs); + gimple_call_set_lhs(add1_cntr, xaddc); + gimple_seq_add_stmt(&seq, add1_cntr); + + cntrb = build1(REALPART_EXPR, TREE_TYPE(cntr), xaddc); + incrv = build1(IMAGPART_EXPR, TREE_TYPE(xincr), xaddc); + + } + + gimple *incr_cntr = gimple_build_assign(cntr, PLUS_EXPR, cntrb, incrv); + gimple_seq_add_stmt(&seq, incr_cntr); + + gimple *store_cntr = gimple_build_assign(unshare_expr(memref), cntr); + gimple_seq_add_stmt(&seq, store_cntr); + + /* Store bid >> 1 in __afl_prev_loc. */ + gimple *shift_loc = + gimple_build_assign(ploc, build_int_cst(TREE_TYPE(ploc), bid >> 1)); + gimple_seq_add_stmt(&seq, shift_loc); + gimple *store_loc = gimple_build_assign(afl_prev_loc, ploc); + gimple_seq_add_stmt(&seq, store_loc); + } + /* Insert the generated sequence. */ + gimple_stmt_iterator insp = gsi_after_labels(bb); + gsi_insert_seq_before(&insp, seq, GSI_SAME_STMT); + + /* Bump this function's instrumented block counter. */ + blocks++; + + } + /* Aggregate the instrumented block count. */ inst_blocks += blocks; - if (blocks) - { - if (out_of_line) - return TODO_rebuild_cgraph_edges; + if (blocks) { - gimple_seq seq = NULL; + if (out_of_line) return TODO_rebuild_cgraph_edges; - /* Load afl_area_ptr into map_ptr. We want to do this only - once per function. */ - gimple *load_ptr = gimple_build_assign (map_ptr, map); - gimple_seq_add_stmt (&seq, load_ptr); + gimple_seq seq = NULL; - /* Insert it in the edge to the entry block. We don't want to - insert it in the first block, since there might be a loop - or a goto back to it. Insert in the edge, which may create - another block. */ - edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (fn)); - gsi_insert_seq_on_edge_immediate (e, seq); - } + /* Load afl_area_ptr into map_ptr. We want to do this only + once per function. */ + gimple *load_ptr = gimple_build_assign(map_ptr, map); + gimple_seq_add_stmt(&seq, load_ptr); + + /* Insert it in the edge to the entry block. We don't want to + insert it in the first block, since there might be a loop + or a goto back to it. Insert in the edge, which may create + another block. */ + edge e = single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(fn)); + gsi_insert_seq_on_edge_immediate(e, seq); + + } return 0; + } /* Decide whether to instrument block BB. Skip it due to the random distribution, or if it's the single successor of all its predecessors. */ - inline bool - instrument_block_p (basic_block bb) - { - if (R (100) >= inst_ratio) - return false; + inline bool instrument_block_p(basic_block bb) { - edge e; edge_iterator ei; - FOR_EACH_EDGE (e, ei, bb->preds) - if (!single_succ_p (e->src)) - return true; + if (R(100) >= inst_ratio) return false; + + edge e; + edge_iterator ei; + FOR_EACH_EDGE(e, ei, bb->preds) + if (!single_succ_p(e->src)) return true; return false; + } /* Create and return a declaration for the __afl_trace rt function. */ - static inline tree - get_afl_trace_decl () - { - tree type = build_function_type_list (void_type_node, - uint16_type_node, - NULL_TREE); - tree decl = build_fn_decl ("__afl_trace", type); - - TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; + static inline tree get_afl_trace_decl() { + + tree type = + build_function_type_list(void_type_node, uint16_type_node, NULL_TREE); + tree decl = build_fn_decl("__afl_trace", type); + + TREE_PUBLIC(decl) = 1; + DECL_EXTERNAL(decl) = 1; + DECL_ARTIFICIAL(decl) = 1; return decl; + } /* Create and return a declaration for the __afl_prev_loc thread-local variable. */ - static inline tree - get_afl_prev_loc_decl () - { - tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL, - get_identifier ("__afl_prev_loc"), - uint32_type_node); - TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - TREE_STATIC (decl) = 1; - set_decl_tls_model (decl, - (flag_pic - ? TLS_MODEL_INITIAL_EXEC - : TLS_MODEL_LOCAL_EXEC)); + static inline tree get_afl_prev_loc_decl() { + + tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, + get_identifier("__afl_prev_loc"), uint32_type_node); + TREE_PUBLIC(decl) = 1; + DECL_EXTERNAL(decl) = 1; + DECL_ARTIFICIAL(decl) = 1; + TREE_STATIC(decl) = 1; + set_decl_tls_model( + decl, (flag_pic ? TLS_MODEL_INITIAL_EXEC : TLS_MODEL_LOCAL_EXEC)); return decl; + } /* Create and return a declaration for the __afl_prev_loc thread-local variable. */ - static inline tree - get_afl_area_ptr_decl () - { - tree type = build_pointer_type (unsigned_char_type_node); - tree decl = build_decl (BUILTINS_LOCATION, VAR_DECL, - get_identifier ("__afl_area_ptr"), - type); - TREE_PUBLIC (decl) = 1; - DECL_EXTERNAL (decl) = 1; - DECL_ARTIFICIAL (decl) = 1; - TREE_STATIC (decl) = 1; + static inline tree get_afl_area_ptr_decl() { + + tree type = build_pointer_type(unsigned_char_type_node); + tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, + get_identifier("__afl_area_ptr"), type); + TREE_PUBLIC(decl) = 1; + DECL_EXTERNAL(decl) = 1; + DECL_ARTIFICIAL(decl) = 1; + TREE_STATIC(decl) = 1; return decl; + } /* This is registered as a plugin finalize callback, to print an instrumentation summary unless in quiet mode. */ - static void - plugin_finalize (void *, void *p) - { + static void plugin_finalize(void *, void *p) { + opt_pass *op = (opt_pass *)p; afl_pass &self = (afl_pass &)*op; if (!self.be_quiet) { + if (!self.inst_blocks) - WARNF ("No instrumentation targets found."); + WARNF("No instrumentation targets found."); else - OKF ("Instrumented %u locations (%s mode, %s, ratio %u%%).", - self.inst_blocks, - getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened"), - self.out_of_line ? G_("out of line") : G_("inline"), - self.inst_ratio); + OKF("Instrumented %u locations (%s mode, %s, ratio %u%%).", + self.inst_blocks, + getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened"), + self.out_of_line ? G_("out of line") : G_("inline"), + self.inst_ratio); + } + } #define report_fatal_error(msg) BADF(msg) @@ -481,36 +470,36 @@ struct afl_pass : gimple_opt_pass { static const char *ignoreList[] = { - "asan.", - "llvm.", - "sancov.", - "__ubsan_", - "ign.", - "__afl_", - "_fini", - "__libc_csu", - "__asan", - "__msan", - "__cmplog", - "__sancov", - "msan.", - "LLVMFuzzer", - "__decide_deferred", - "maybe_duplicate_stderr", - "discard_output", - "close_stdout", - "dup_and_close_stderr", - "maybe_close_fd_mask", - "ExecuteFilesOnyByOne" + "asan.", + "llvm.", + "sancov.", + "__ubsan_", + "ign.", + "__afl_", + "_fini", + "__libc_csu", + "__asan", + "__msan", + "__cmplog", + "__sancov", + "msan.", + "LLVMFuzzer", + "__decide_deferred", + "maybe_duplicate_stderr", + "discard_output", + "close_stdout", + "dup_and_close_stderr", + "maybe_close_fd_mask", + "ExecuteFilesOnyByOne" }; - const char *name = IDENTIFIER_POINTER (DECL_NAME (F->decl)); - int len = IDENTIFIER_LENGTH (DECL_NAME (F->decl)); + const char *name = IDENTIFIER_POINTER(DECL_NAME(F->decl)); + int len = IDENTIFIER_LENGTH(DECL_NAME(F->decl)); for (auto const &ignoreListFunc : ignoreList) { - if (strncmp (name, ignoreListFunc, len) == 0) { return true; } + if (strncmp(name, ignoreListFunc, len) == 0) { return true; } } @@ -533,8 +522,8 @@ struct afl_pass : gimple_opt_pass { if (allowlist && denylist) FATAL( - "You can only specify either AFL_GCC_ALLOWLIST or AFL_GCC_DENYLIST " - "but not both!"); + "You can only specify either AFL_GCC_ALLOWLIST or AFL_GCC_DENYLIST " + "but not both!"); if (allowlist) { @@ -546,68 +535,68 @@ struct afl_pass : gimple_opt_pass { while (fileStream) { - int is_file = -1; - std::size_t npos; - std::string original_line = line; + int is_file = -1; + std::size_t npos; + std::string original_line = line; - line.erase(std::remove_if(line.begin(), line.end(), ::isspace), - line.end()); + line.erase(std::remove_if(line.begin(), line.end(), ::isspace), + line.end()); - // remove # and following - if ((npos = line.find("#")) != std::string::npos) - line = line.substr(0, npos); + // remove # and following + if ((npos = line.find("#")) != std::string::npos) + line = line.substr(0, npos); - if (line.compare(0, 4, "fun:") == 0) { + if (line.compare(0, 4, "fun:") == 0) { - is_file = 0; - line = line.substr(4); + is_file = 0; + line = line.substr(4); - } else if (line.compare(0, 9, "function:") == 0) { + } else if (line.compare(0, 9, "function:") == 0) { - is_file = 0; - line = line.substr(9); + is_file = 0; + line = line.substr(9); - } else if (line.compare(0, 4, "src:") == 0) { + } else if (line.compare(0, 4, "src:") == 0) { - is_file = 1; - line = line.substr(4); + is_file = 1; + line = line.substr(4); - } else if (line.compare(0, 7, "source:") == 0) { + } else if (line.compare(0, 7, "source:") == 0) { - is_file = 1; - line = line.substr(7); + is_file = 1; + line = line.substr(7); - } + } - if (line.find(":") != std::string::npos) { + if (line.find(":") != std::string::npos) { - FATAL("invalid line in AFL_GCC_ALLOWLIST: %s", original_line.c_str()); + FATAL("invalid line in AFL_GCC_ALLOWLIST: %s", original_line.c_str()); - } + } - if (line.length() > 0) { + if (line.length() > 0) { - // if the entry contains / or . it must be a file - if (is_file == -1) - if (line.find("/") != std::string::npos || - line.find(".") != std::string::npos) - is_file = 1; - // otherwise it is a function + // if the entry contains / or . it must be a file + if (is_file == -1) + if (line.find("/") != std::string::npos || + line.find(".") != std::string::npos) + is_file = 1; + // otherwise it is a function - if (is_file == 1) - allowListFiles.push_back(line); - else - allowListFunctions.push_back(line); - getline(fileStream, line); + if (is_file == 1) + allowListFiles.push_back(line); + else + allowListFunctions.push_back(line); + getline(fileStream, line); - } + } } if (debug) - SAYF(cMGN "[D] " cRST - "loaded allowlist with %zu file and %zu function entries\n", - allowListFiles.size(), allowListFunctions.size()); + SAYF(cMGN "[D] " cRST + "loaded allowlist with %zu file and %zu function entries\n", + allowListFiles.size(), allowListFunctions.size()); } @@ -621,68 +610,68 @@ struct afl_pass : gimple_opt_pass { while (fileStream) { - int is_file = -1; - std::size_t npos; - std::string original_line = line; + int is_file = -1; + std::size_t npos; + std::string original_line = line; - line.erase(std::remove_if(line.begin(), line.end(), ::isspace), - line.end()); + line.erase(std::remove_if(line.begin(), line.end(), ::isspace), + line.end()); - // remove # and following - if ((npos = line.find("#")) != std::string::npos) - line = line.substr(0, npos); + // remove # and following + if ((npos = line.find("#")) != std::string::npos) + line = line.substr(0, npos); - if (line.compare(0, 4, "fun:") == 0) { + if (line.compare(0, 4, "fun:") == 0) { - is_file = 0; - line = line.substr(4); + is_file = 0; + line = line.substr(4); - } else if (line.compare(0, 9, "function:") == 0) { + } else if (line.compare(0, 9, "function:") == 0) { - is_file = 0; - line = line.substr(9); + is_file = 0; + line = line.substr(9); - } else if (line.compare(0, 4, "src:") == 0) { + } else if (line.compare(0, 4, "src:") == 0) { - is_file = 1; - line = line.substr(4); + is_file = 1; + line = line.substr(4); - } else if (line.compare(0, 7, "source:") == 0) { + } else if (line.compare(0, 7, "source:") == 0) { - is_file = 1; - line = line.substr(7); + is_file = 1; + line = line.substr(7); - } + } - if (line.find(":") != std::string::npos) { + if (line.find(":") != std::string::npos) { - FATAL("invalid line in AFL_GCC_DENYLIST: %s", original_line.c_str()); + FATAL("invalid line in AFL_GCC_DENYLIST: %s", original_line.c_str()); - } + } - if (line.length() > 0) { + if (line.length() > 0) { - // if the entry contains / or . it must be a file - if (is_file == -1) - if (line.find("/") != std::string::npos || - line.find(".") != std::string::npos) - is_file = 1; - // otherwise it is a function + // if the entry contains / or . it must be a file + if (is_file == -1) + if (line.find("/") != std::string::npos || + line.find(".") != std::string::npos) + is_file = 1; + // otherwise it is a function - if (is_file == 1) - denyListFiles.push_back(line); - else - denyListFunctions.push_back(line); - getline(fileStream, line); + if (is_file == 1) + denyListFiles.push_back(line); + else + denyListFunctions.push_back(line); + getline(fileStream, line); - } + } } if (debug) - SAYF(cMGN "[D] " cRST - "loaded denylist with %zu file and %zu function entries\n", - denyListFiles.size(), denyListFunctions.size()); + SAYF(cMGN "[D] " cRST + "loaded denylist with %zu file and %zu function entries\n", + denyListFiles.size(), denyListFunctions.size()); } @@ -707,74 +696,74 @@ struct afl_pass : gimple_opt_pass { if (!denyListFunctions.empty()) { - std::string instFunction = IDENTIFIER_POINTER (DECL_NAME (F->decl)); + std::string instFunction = IDENTIFIER_POINTER(DECL_NAME(F->decl)); - for (std::list::iterator it = denyListFunctions.begin(); - it != denyListFunctions.end(); ++it) { + for (std::list::iterator it = denyListFunctions.begin(); + it != denyListFunctions.end(); ++it) { - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. We also allow UNIX-style pattern - * matching */ + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. We also allow UNIX-style pattern + * matching */ - if (instFunction.length() >= it->length()) { + if (instFunction.length() >= it->length()) { - if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) { + if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) { - if (debug) - SAYF(cMGN "[D] " cRST - "Function %s is in the deny function list, " - "not instrumenting ... \n", - instFunction.c_str()); - return false; + if (debug) + SAYF(cMGN "[D] " cRST + "Function %s is in the deny function list, " + "not instrumenting ... \n", + instFunction.c_str()); + return false; - } + } - } + } - } + } } if (!denyListFiles.empty()) { - std::string source_file = getSourceName(F); + std::string source_file = getSourceName(F); - if (!source_file.empty()) { + if (!source_file.empty()) { - for (std::list::iterator it = denyListFiles.begin(); - it != denyListFiles.end(); ++it) { + for (std::list::iterator it = denyListFiles.begin(); + it != denyListFiles.end(); ++it) { - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. We also allow UNIX-style pattern - * matching */ + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. We also allow UNIX-style pattern + * matching */ - if (source_file.length() >= it->length()) { + if (source_file.length() >= it->length()) { - if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) { + if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) { - return false; + return false; - } + } - } + } - } + } - } else { + } else { - // we could not find out the location. in this case we say it is not - // in the instrument file list - if (!be_quiet) - WARNF( - "No debug information found for function %s, will be " - "instrumented (recompile with -g -O[1-3]).", - IDENTIFIER_POINTER (DECL_NAME (F->decl))); + // we could not find out the location. in this case we say it is not + // in the instrument file list + if (!be_quiet) + WARNF( + "No debug information found for function %s, will be " + "instrumented (recompile with -g -O[1-3]).", + IDENTIFIER_POINTER(DECL_NAME(F->decl))); - } + } } @@ -787,81 +776,81 @@ struct afl_pass : gimple_opt_pass { if (!allowListFunctions.empty()) { - std::string instFunction = IDENTIFIER_POINTER(DECL_NAME(F->decl)); + std::string instFunction = IDENTIFIER_POINTER(DECL_NAME(F->decl)); - for (std::list::iterator it = allowListFunctions.begin(); - it != allowListFunctions.end(); ++it) { + for (std::list::iterator it = allowListFunctions.begin(); + it != allowListFunctions.end(); ++it) { - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. We also allow UNIX-style pattern - * matching */ + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. We also allow UNIX-style pattern + * matching */ - if (instFunction.length() >= it->length()) { + if (instFunction.length() >= it->length()) { - if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) { + if (fnmatch(("*" + *it).c_str(), instFunction.c_str(), 0) == 0) { - if (debug) - SAYF(cMGN "[D] " cRST - "Function %s is in the allow function list, " - "instrumenting ... \n", - instFunction.c_str()); - return true; + if (debug) + SAYF(cMGN "[D] " cRST + "Function %s is in the allow function list, " + "instrumenting ... \n", + instFunction.c_str()); + return true; - } + } - } + } - } + } } if (!allowListFiles.empty()) { - std::string source_file = getSourceName(F); + std::string source_file = getSourceName(F); - if (!source_file.empty()) { + if (!source_file.empty()) { - for (std::list::iterator it = allowListFiles.begin(); - it != allowListFiles.end(); ++it) { + for (std::list::iterator it = allowListFiles.begin(); + it != allowListFiles.end(); ++it) { - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. We also allow UNIX-style pattern - * matching */ + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. We also allow UNIX-style pattern + * matching */ - if (source_file.length() >= it->length()) { + if (source_file.length() >= it->length()) { - if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) { + if (fnmatch(("*" + *it).c_str(), source_file.c_str(), 0) == 0) { - if (debug) - SAYF(cMGN "[D] " cRST - "Function %s is in the allowlist (%s), " - "instrumenting ... \n", - IDENTIFIER_POINTER (DECL_NAME (F->decl)), - source_file.c_str()); - return true; + if (debug) + SAYF(cMGN "[D] " cRST + "Function %s is in the allowlist (%s), " + "instrumenting ... \n", + IDENTIFIER_POINTER(DECL_NAME(F->decl)), + source_file.c_str()); + return true; - } + } - } + } - } + } - } else { + } else { - // we could not find out the location. In this case we say it is not - // in the instrument file list - if (!be_quiet) - WARNF( - "No debug information found for function %s, will not be " - "instrumented (recompile with -g -O[1-3]).", - IDENTIFIER_POINTER (DECL_NAME (F->decl))); - return false; + // we could not find out the location. In this case we say it is not + // in the instrument file list + if (!be_quiet) + WARNF( + "No debug information found for function %s, will not be " + "instrumented (recompile with -g -O[1-3]).", + IDENTIFIER_POINTER(DECL_NAME(F->decl))); + return false; - } + } } @@ -871,13 +860,12 @@ struct afl_pass : gimple_opt_pass { } - }; -static struct plugin_info afl_plugin = - { - .version = "20200907", - .help = G_("AFL gcc plugin\n\ +static struct plugin_info afl_plugin = { + + .version = "20200907", + .help = G_("AFL gcc plugin\n\ \n\ Set AFL_QUIET in the environment to silence it.\n\ \n\ @@ -886,58 +874,62 @@ to control how likely a block will be chosen for instrumentation.\n\ \n\ Specify -frandom-seed for reproducible instrumentation.\n\ "), - }; -} +}; + +} // namespace /* This is the function GCC calls when loading a plugin. Initialize and register further callbacks. */ -int -plugin_init (struct plugin_name_args *info, - struct plugin_gcc_version *version) -{ - if (!plugin_default_version_check (version, &gcc_version)) - FATAL (G_("GCC and plugin have incompatible versions, expected GCC %d.%d"), - GCCPLUGIN_VERSION_MAJOR, GCCPLUGIN_VERSION_MINOR); +int plugin_init(struct plugin_name_args * info, + struct plugin_gcc_version *version) { + + if (!plugin_default_version_check(version, &gcc_version)) + FATAL(G_("GCC and plugin have incompatible versions, expected GCC %d.%d"), + GCCPLUGIN_VERSION_MAJOR, GCCPLUGIN_VERSION_MINOR); /* Show a banner. */ bool quiet = false; - if (isatty (2) && !getenv ("AFL_QUIET")) - SAYF (cCYA "afl-gcc-pass " cBRI VERSION cRST " by \n"); + if (isatty(2) && !getenv("AFL_QUIET")) + SAYF(cCYA "afl-gcc-pass " cBRI VERSION cRST " by \n"); else quiet = true; /* Decide instrumentation ratio. */ int inst_ratio = 100; - if (char *inst_ratio_str = getenv ("AFL_INST_RATIO")) - if (sscanf (inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio || - inst_ratio > 100) - FATAL (G_("Bad value of AFL_INST_RATIO (must be between 1 and 100)")); + if (char *inst_ratio_str = getenv("AFL_INST_RATIO")) + if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio || + inst_ratio > 100) + FATAL(G_("Bad value of AFL_INST_RATIO (must be between 1 and 100)")); /* Initialize the random number generator with GCC's random seed, in case it was specified in the command line's -frandom-seed for reproducible instrumentation. */ - srandom (get_random_seed (false)); + srandom(get_random_seed(false)); const char *name = info->base_name; - register_callback (name, PLUGIN_INFO, NULL, &afl_plugin); - - afl_pass *aflp = new afl_pass (quiet, inst_ratio); - struct register_pass_info pass_info = - { - .pass = aflp, - .reference_pass_name = "ssa", - .ref_pass_instance_number = 1, - .pos_op = PASS_POS_INSERT_AFTER, - }; - register_callback (name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - register_callback (name, PLUGIN_FINISH, afl_pass::plugin_finalize, - pass_info.pass); + register_callback(name, PLUGIN_INFO, NULL, &afl_plugin); + + afl_pass * aflp = new afl_pass(quiet, inst_ratio); + struct register_pass_info pass_info = { + + .pass = aflp, + .reference_pass_name = "ssa", + .ref_pass_instance_number = 1, + .pos_op = PASS_POS_INSERT_AFTER, + + }; + + register_callback(name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); + register_callback(name, PLUGIN_FINISH, afl_pass::plugin_finalize, + pass_info.pass); if (!quiet) ACTF(G_("%s instrumentation at ratio of %u%% in %s mode."), - aflp->out_of_line ? G_("Call-based") : G_("Inline"), inst_ratio, - getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened")); + aflp->out_of_line ? G_("Call-based") : G_("Inline"), inst_ratio, + getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened")); return 0; + } + diff --git a/src/afl-cc.c b/src/afl-cc.c index 47a33cd0..6bee8b38 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1282,65 +1282,72 @@ int main(int argc, char **argv, char **envp) { " AFL_USE_MSAN: activate memory sanitizer\n" " AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"); - if (have_gcc_plugin) - SAYF( - "\nGCC Plugin-specific environment variables:\n" - " AFL_GCC_OUT_OF_LINE: disable inlined instrumentation\n" - " AFL_GCC_SKIP_NEVERZERO: do not skip zero on trace counters\n" - " AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by filename\n"); - + if (have_gcc_plugin) + SAYF( + "\nGCC Plugin-specific environment variables:\n" + " AFL_GCC_OUT_OF_LINE: disable inlined instrumentation\n" + " AFL_GCC_SKIP_NEVERZERO: do not skip zero on trace counters\n" + " AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by " + "filename\n"); + if (have_llvm) SAYF( - "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " - "variables:\n" + "\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment " + "variables:\n" #if LLVM_MAJOR < 9 - " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" + " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" #else - " AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n" + " AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n" #endif - " AFL_LLVM_DICT2FILE: generate an afl dictionary based on found " - "comparisons\n" - " AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n" - " AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n" - " AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n" - " AFL_LLVM_LAF_SPLIT_SWITCHES: cascaded comparisons on switches\n" - " AFL_LLVM_LAF_SPLIT_FLOATS: cascaded comparisons on floats\n" - " AFL_LLVM_LAF_TRANSFORM_COMPARES: cascade comparisons for string " - "functions\n" - " AFL_LLVM_INSTRUMENT_ALLOW/AFL_LLVM_INSTRUMENT_DENY: enable " - "instrument allow/\n" - " deny listing (selective instrumentation)\n"); + " AFL_LLVM_DICT2FILE: generate an afl dictionary based on found " + "comparisons\n" + " AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n" + " AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n" + " AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n" + " AFL_LLVM_LAF_SPLIT_SWITCHES: cascaded comparisons on switches\n" + " AFL_LLVM_LAF_SPLIT_FLOATS: cascaded comparisons on floats\n" + " AFL_LLVM_LAF_TRANSFORM_COMPARES: cascade comparisons for string " + "functions\n" + " AFL_LLVM_INSTRUMENT_ALLOW/AFL_LLVM_INSTRUMENT_DENY: enable " + "instrument allow/\n" + " deny listing (selective instrumentation)\n"); if (have_llvm) - SAYF( - " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n" - " AFL_LLVM_INSTRUMENT: set instrumentation mode:\n" - " CLASSIC, INSTRIM, PCGUARD, LTO, CTX, NGRAM-2 ... NGRAM-16\n" - " You can also use the old environment variables instead:\n" - " AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n" - " AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n" - " AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed " - "(option to INSTRIM)\n" - " AFL_LLVM_CTX: use context sensitive coverage (for CLASSIC and " - "INSTRIM)\n" - " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for " - "CLASSIC & INSTRIM)\n"); + SAYF( + " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen " + "mutator)\n" + " AFL_LLVM_INSTRUMENT: set instrumentation mode:\n" + " CLASSIC, INSTRIM, PCGUARD, LTO, CTX, NGRAM-2 ... NGRAM-16\n" + " You can also use the old environment variables instead:\n" + " AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n" + " AFL_LLVM_INSTRIM: use light weight instrumentation InsTrim\n" + " AFL_LLVM_INSTRIM_LOOPHEAD: optimize loop tracing for speed " + "(option to INSTRIM)\n" + " AFL_LLVM_CTX: use context sensitive coverage (for CLASSIC and " + "INSTRIM)\n" + " AFL_LLVM_NGRAM_SIZE: use ngram prev_loc count coverage (for " + "CLASSIC & INSTRIM)\n"); #ifdef AFL_CLANG_FLTO - if (have_lto) - SAYF( - "\nLTO/afl-clang-lto specific environment variables:\n" - " AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), e.g. " - "0x10000\n" - " AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding functions\n" - " into this file\n" - " AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " - "global var\n" - " AFL_LLVM_LTO_STARTID: from which ID to start counting from for a " - "bb\n" - " AFL_REAL_LD: use this lld linker instead of the compiled in path\n" - "If anything fails - be sure to read README.lto.md!\n"); + if (have_lto) + SAYF( + "\nLTO/afl-clang-lto specific environment variables:\n" + " AFL_LLVM_MAP_ADDR: use a fixed coverage map address (speed), " + "e.g. " + "0x10000\n" + " AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding " + "functions\n" + " into this file\n" + " AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " + "global var\n" + " AFL_LLVM_LTO_STARTID: from which ID to start counting from for " + "a " + "bb\n" + " AFL_REAL_LD: use this lld linker instead of the compiled in " + "path\n" + "If anything fails - be sure to read README.lto.md!\n"); #endif + } SAYF( diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index c8056b9e..33b16817 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1043,11 +1043,11 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } - if (fsrv->child_pid <= 0) { - + if (fsrv->child_pid <= 0) { + if (*stop_soon_p) { return 0; } FATAL("Fork server is misbehaving (OOM?)"); - + } exec_ms = read_s32_timed(fsrv->fsrv_st_fd, &fsrv->child_status, timeout, -- cgit 1.4.1