code-format

This commit is contained in:
van Hauser
2020-09-08 17:54:01 +02:00
parent 2802245da7
commit ab744abc4b
4 changed files with 485 additions and 486 deletions

View File

@ -166,8 +166,8 @@ int plugin_is_GPL_compatible = 1;
namespace { namespace {
static const struct pass_data afl_pass_data = static const struct pass_data afl_pass_data = {
{
.type = GIMPLE_PASS, .type = GIMPLE_PASS,
.name = "afl", .name = "afl",
.optinfo_flags = OPTGROUP_NONE, .optinfo_flags = OPTGROUP_NONE,
@ -176,12 +176,12 @@ static const struct pass_data afl_pass_data =
.properties_provided = 0, .properties_provided = 0,
.properties_destroyed = 0, .properties_destroyed = 0,
.todo_flags_start = 0, .todo_flags_start = 0,
.todo_flags_finish = (TODO_update_ssa .todo_flags_finish = (TODO_update_ssa | TODO_cleanup_cfg | TODO_verify_il),
| TODO_cleanup_cfg
| TODO_verify_il),
}; };
struct afl_pass : gimple_opt_pass { struct afl_pass : gimple_opt_pass {
afl_pass(bool quiet, unsigned int ratio) afl_pass(bool quiet, unsigned int ratio)
: gimple_opt_pass(afl_pass_data, g), : gimple_opt_pass(afl_pass_data, g),
be_quiet(quiet), be_quiet(quiet),
@ -193,9 +193,10 @@ struct afl_pass : gimple_opt_pass {
out_of_line(getenv("AFL_GCC_OUT_OF_LINE")), out_of_line(getenv("AFL_GCC_OUT_OF_LINE")),
#endif #endif
neverZero(!getenv("AFL_GCC_SKIP_NEVERZERO")), neverZero(!getenv("AFL_GCC_SKIP_NEVERZERO")),
inst_blocks (0) inst_blocks(0) {
{
initInstrumentList(); initInstrumentList();
} }
/* Are we outputting to a non-terminal, or running with AFL_QUIET /* Are we outputting to a non-terminal, or running with AFL_QUIET
@ -218,24 +219,21 @@ struct afl_pass : gimple_opt_pass {
/* Count instrumented blocks. */ /* Count instrumented blocks. */
int inst_blocks; int inst_blocks;
virtual unsigned int virtual unsigned int execute(function *fn) {
execute (function *fn)
{ if (!isInInstrumentList(fn)) return 0;
if (!isInInstrumentList(fn))
return 0;
int blocks = 0; int blocks = 0;
/* These are temporaries used by inline instrumentation only, that /* These are temporaries used by inline instrumentation only, that
are live throughout the function. */ are live throughout the function. */
tree ploc = NULL, indx = NULL, map = NULL, map_ptr = NULL, tree ploc = NULL, indx = NULL, map = NULL, map_ptr = NULL, ntry = NULL,
ntry = NULL, cntr = NULL, xaddc = NULL, xincr = NULL; cntr = NULL, xaddc = NULL, xincr = NULL;
basic_block bb; basic_block bb;
FOR_EACH_BB_FN (bb, fn) FOR_EACH_BB_FN(bb, fn) {
{
if (!instrument_block_p (bb)) if (!instrument_block_p(bb)) continue;
continue;
/* Generate the block identifier. */ /* Generate the block identifier. */
unsigned bid = R(MAP_SIZE); unsigned bid = R(MAP_SIZE);
@ -243,16 +241,16 @@ struct afl_pass : gimple_opt_pass {
gimple_seq seq = NULL; gimple_seq seq = NULL;
if (out_of_line) if (out_of_line) {
{
static tree afl_trace = get_afl_trace_decl(); static tree afl_trace = get_afl_trace_decl();
/* Call __afl_trace with bid, the new location; */ /* Call __afl_trace with bid, the new location; */
gcall *call = gimple_build_call(afl_trace, 1, bidt); gcall *call = gimple_build_call(afl_trace, 1, bidt);
gimple_seq_add_stmt(&seq, call); gimple_seq_add_stmt(&seq, call);
}
else } else {
{
static tree afl_prev_loc = get_afl_prev_loc_decl(); static tree afl_prev_loc = get_afl_prev_loc_decl();
static tree afl_area_ptr = get_afl_area_ptr_decl(); static tree afl_area_ptr = get_afl_area_ptr_decl();
@ -264,33 +262,29 @@ struct afl_pass : gimple_opt_pass {
/* Compute the index into the map referenced by area_ptr /* Compute the index into the map referenced by area_ptr
that we're to update: indx = (sizetype) ploc ^ bid. */ that we're to update: indx = (sizetype) ploc ^ bid. */
if (blocks == 0) if (blocks == 0) indx = create_tmp_var(TREE_TYPE(bidt), ".afl_index");
indx = create_tmp_var (TREE_TYPE (bidt), ".afl_index"); gimple *conv_ploc =
gimple *conv_ploc gimple_build_assign(indx, fold_convert(TREE_TYPE(indx), ploc));
= gimple_build_assign (indx,
fold_convert (TREE_TYPE (indx),
ploc));
gimple_seq_add_stmt(&seq, conv_ploc); gimple_seq_add_stmt(&seq, conv_ploc);
gimple *xor_loc = gimple_build_assign (indx, BIT_XOR_EXPR, gimple *xor_loc = gimple_build_assign(indx, BIT_XOR_EXPR, indx, bidt);
indx, bidt);
gimple_seq_add_stmt(&seq, xor_loc); gimple_seq_add_stmt(&seq, xor_loc);
/* Compute the address of that map element. */ /* Compute the address of that map element. */
if (blocks == 0) if (blocks == 0) {
{
map = afl_area_ptr; map = afl_area_ptr;
map_ptr = create_tmp_var (TREE_TYPE (afl_area_ptr), map_ptr = create_tmp_var(TREE_TYPE(afl_area_ptr), ".afl_map_ptr");
".afl_map_ptr"); ntry = create_tmp_var(TREE_TYPE(afl_area_ptr), ".afl_map_entry");
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 *idx_map =
gimple_build_assign(ntry, POINTER_PLUS_EXPR, map_ptr, indx);
gimple_seq_add_stmt(&seq, idx_map); gimple_seq_add_stmt(&seq, idx_map);
/* Increment the counter in idx_map. */ /* Increment the counter in idx_map. */
tree memref = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (ntry)), tree memref = build2(MEM_REF, TREE_TYPE(TREE_TYPE(ntry)), ntry,
ntry, build_zero_cst (TREE_TYPE (ntry))); build_zero_cst(TREE_TYPE(ntry)));
if (blocks == 0) if (blocks == 0)
cntr = create_tmp_var(TREE_TYPE(memref), ".afl_edge_count"); cntr = create_tmp_var(TREE_TYPE(memref), ".afl_edge_count");
@ -300,47 +294,44 @@ struct afl_pass : gimple_opt_pass {
tree cntrb = cntr; tree cntrb = cntr;
tree incrv = build_one_cst(TREE_TYPE(cntr)); tree incrv = build_one_cst(TREE_TYPE(cntr));
if (neverZero) if (neverZero) {
{
/* NeverZero: if count wrapped around to zero, advance to /* NeverZero: if count wrapped around to zero, advance to
one. */ one. */
if (blocks == 0) if (blocks == 0) {
{
xaddc = create_tmp_var (build_complex_type xaddc = create_tmp_var(build_complex_type(TREE_TYPE(memref)),
(TREE_TYPE (memref)),
".afl_edge_xaddc"); ".afl_edge_xaddc");
xincr = create_tmp_var (TREE_TYPE (memref), xincr = create_tmp_var(TREE_TYPE(memref), ".afl_edge_xincr");
".afl_edge_xincr");
} }
auto_vec<tree> vargs(2); auto_vec<tree> vargs(2);
vargs.quick_push(cntr); vargs.quick_push(cntr);
vargs.quick_push(incrv); vargs.quick_push(incrv);
gcall *add1_cntr gcall *add1_cntr =
= gimple_build_call_internal_vec (IFN_ADD_OVERFLOW, vargs); gimple_build_call_internal_vec(IFN_ADD_OVERFLOW, vargs);
gimple_call_set_lhs(add1_cntr, xaddc); gimple_call_set_lhs(add1_cntr, xaddc);
gimple_seq_add_stmt(&seq, add1_cntr); gimple_seq_add_stmt(&seq, add1_cntr);
cntrb = build1(REALPART_EXPR, TREE_TYPE(cntr), xaddc); cntrb = build1(REALPART_EXPR, TREE_TYPE(cntr), xaddc);
incrv = build1(IMAGPART_EXPR, TREE_TYPE(xincr), xaddc); incrv = build1(IMAGPART_EXPR, TREE_TYPE(xincr), xaddc);
} }
gimple *incr_cntr = gimple_build_assign (cntr, PLUS_EXPR, gimple *incr_cntr = gimple_build_assign(cntr, PLUS_EXPR, cntrb, incrv);
cntrb, incrv);
gimple_seq_add_stmt(&seq, incr_cntr); gimple_seq_add_stmt(&seq, incr_cntr);
gimple *store_cntr = gimple_build_assign (unshare_expr (memref), gimple *store_cntr = gimple_build_assign(unshare_expr(memref), cntr);
cntr);
gimple_seq_add_stmt(&seq, store_cntr); gimple_seq_add_stmt(&seq, store_cntr);
/* Store bid >> 1 in __afl_prev_loc. */ /* Store bid >> 1 in __afl_prev_loc. */
gimple *shift_loc = gimple_build_assign (ploc, gimple *shift_loc =
build_int_cst gimple_build_assign(ploc, build_int_cst(TREE_TYPE(ploc), bid >> 1));
(TREE_TYPE (ploc),
bid >> 1));
gimple_seq_add_stmt(&seq, shift_loc); gimple_seq_add_stmt(&seq, shift_loc);
gimple *store_loc = gimple_build_assign(afl_prev_loc, ploc); gimple *store_loc = gimple_build_assign(afl_prev_loc, ploc);
gimple_seq_add_stmt(&seq, store_loc); gimple_seq_add_stmt(&seq, store_loc);
} }
/* Insert the generated sequence. */ /* Insert the generated sequence. */
@ -349,15 +340,15 @@ struct afl_pass : gimple_opt_pass {
/* Bump this function's instrumented block counter. */ /* Bump this function's instrumented block counter. */
blocks++; blocks++;
} }
/* Aggregate the instrumented block count. */ /* Aggregate the instrumented block count. */
inst_blocks += blocks; inst_blocks += blocks;
if (blocks) if (blocks) {
{
if (out_of_line) if (out_of_line) return TODO_rebuild_cgraph_edges;
return TODO_rebuild_cgraph_edges;
gimple_seq seq = NULL; gimple_seq seq = NULL;
@ -372,35 +363,34 @@ struct afl_pass : gimple_opt_pass {
another block. */ another block. */
edge e = single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(fn)); edge e = single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(fn));
gsi_insert_seq_on_edge_immediate(e, seq); gsi_insert_seq_on_edge_immediate(e, seq);
} }
return 0; return 0;
} }
/* Decide whether to instrument block BB. Skip it due to the random /* Decide whether to instrument block BB. Skip it due to the random
distribution, or if it's the single successor of all its distribution, or if it's the single successor of all its
predecessors. */ predecessors. */
inline bool inline bool instrument_block_p(basic_block bb) {
instrument_block_p (basic_block bb)
{
if (R (100) >= inst_ratio)
return false;
edge e; edge_iterator ei; if (R(100) >= inst_ratio) return false;
edge e;
edge_iterator ei;
FOR_EACH_EDGE(e, ei, bb->preds) FOR_EACH_EDGE(e, ei, bb->preds)
if (!single_succ_p (e->src)) if (!single_succ_p(e->src)) return true;
return true;
return false; return false;
} }
/* Create and return a declaration for the __afl_trace rt function. */ /* Create and return a declaration for the __afl_trace rt function. */
static inline tree static inline tree get_afl_trace_decl() {
get_afl_trace_decl ()
{ tree type =
tree type = build_function_type_list (void_type_node, build_function_type_list(void_type_node, uint16_type_node, NULL_TREE);
uint16_type_node,
NULL_TREE);
tree decl = build_fn_decl("__afl_trace", type); tree decl = build_fn_decl("__afl_trace", type);
TREE_PUBLIC(decl) = 1; TREE_PUBLIC(decl) = 1;
@ -408,53 +398,50 @@ struct afl_pass : gimple_opt_pass {
DECL_ARTIFICIAL(decl) = 1; DECL_ARTIFICIAL(decl) = 1;
return decl; return decl;
} }
/* Create and return a declaration for the __afl_prev_loc /* Create and return a declaration for the __afl_prev_loc
thread-local variable. */ thread-local variable. */
static inline tree static inline tree get_afl_prev_loc_decl() {
get_afl_prev_loc_decl ()
{
tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
get_identifier ("__afl_prev_loc"), get_identifier("__afl_prev_loc"), uint32_type_node);
uint32_type_node);
TREE_PUBLIC(decl) = 1; TREE_PUBLIC(decl) = 1;
DECL_EXTERNAL(decl) = 1; DECL_EXTERNAL(decl) = 1;
DECL_ARTIFICIAL(decl) = 1; DECL_ARTIFICIAL(decl) = 1;
TREE_STATIC(decl) = 1; TREE_STATIC(decl) = 1;
set_decl_tls_model (decl, set_decl_tls_model(
(flag_pic decl, (flag_pic ? TLS_MODEL_INITIAL_EXEC : TLS_MODEL_LOCAL_EXEC));
? TLS_MODEL_INITIAL_EXEC
: TLS_MODEL_LOCAL_EXEC));
return decl; return decl;
} }
/* Create and return a declaration for the __afl_prev_loc /* Create and return a declaration for the __afl_prev_loc
thread-local variable. */ thread-local variable. */
static inline tree static inline tree get_afl_area_ptr_decl() {
get_afl_area_ptr_decl ()
{
tree type = build_pointer_type(unsigned_char_type_node); tree type = build_pointer_type(unsigned_char_type_node);
tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL,
get_identifier ("__afl_area_ptr"), get_identifier("__afl_area_ptr"), type);
type);
TREE_PUBLIC(decl) = 1; TREE_PUBLIC(decl) = 1;
DECL_EXTERNAL(decl) = 1; DECL_EXTERNAL(decl) = 1;
DECL_ARTIFICIAL(decl) = 1; DECL_ARTIFICIAL(decl) = 1;
TREE_STATIC(decl) = 1; TREE_STATIC(decl) = 1;
return decl; return decl;
} }
/* This is registered as a plugin finalize callback, to print an /* This is registered as a plugin finalize callback, to print an
instrumentation summary unless in quiet mode. */ instrumentation summary unless in quiet mode. */
static void static void plugin_finalize(void *, void *p) {
plugin_finalize (void *, void *p)
{
opt_pass *op = (opt_pass *)p; opt_pass *op = (opt_pass *)p;
afl_pass &self = (afl_pass &)*op; afl_pass &self = (afl_pass &)*op;
if (!self.be_quiet) { if (!self.be_quiet) {
if (!self.inst_blocks) if (!self.inst_blocks)
WARNF("No instrumentation targets found."); WARNF("No instrumentation targets found.");
else else
@ -463,7 +450,9 @@ struct afl_pass : gimple_opt_pass {
getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened"), getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened"),
self.out_of_line ? G_("out of line") : G_("inline"), self.out_of_line ? G_("out of line") : G_("inline"),
self.inst_ratio); self.inst_ratio);
} }
} }
#define report_fatal_error(msg) BADF(msg) #define report_fatal_error(msg) BADF(msg)
@ -871,11 +860,10 @@ struct afl_pass : gimple_opt_pass {
} }
}; };
static struct plugin_info afl_plugin = static struct plugin_info afl_plugin = {
{
.version = "20200907", .version = "20200907",
.help = G_("AFL gcc plugin\n\ .help = G_("AFL gcc plugin\n\
\n\ \n\
@ -886,16 +874,16 @@ to control how likely a block will be chosen for instrumentation.\n\
\n\ \n\
Specify -frandom-seed for reproducible instrumentation.\n\ Specify -frandom-seed for reproducible instrumentation.\n\
"), "),
}; };
} } // namespace
/* This is the function GCC calls when loading a plugin. Initialize /* This is the function GCC calls when loading a plugin. Initialize
and register further callbacks. */ and register further callbacks. */
int int plugin_init(struct plugin_name_args * info,
plugin_init (struct plugin_name_args *info, struct plugin_gcc_version *version) {
struct plugin_gcc_version *version)
{
if (!plugin_default_version_check(version, &gcc_version)) if (!plugin_default_version_check(version, &gcc_version))
FATAL(G_("GCC and plugin have incompatible versions, expected GCC %d.%d"), FATAL(G_("GCC and plugin have incompatible versions, expected GCC %d.%d"),
GCCPLUGIN_VERSION_MAJOR, GCCPLUGIN_VERSION_MINOR); GCCPLUGIN_VERSION_MAJOR, GCCPLUGIN_VERSION_MINOR);
@ -923,13 +911,15 @@ plugin_init (struct plugin_name_args *info,
register_callback(name, PLUGIN_INFO, NULL, &afl_plugin); register_callback(name, PLUGIN_INFO, NULL, &afl_plugin);
afl_pass * aflp = new afl_pass(quiet, inst_ratio); afl_pass * aflp = new afl_pass(quiet, inst_ratio);
struct register_pass_info pass_info = struct register_pass_info pass_info = {
{
.pass = aflp, .pass = aflp,
.reference_pass_name = "ssa", .reference_pass_name = "ssa",
.ref_pass_instance_number = 1, .ref_pass_instance_number = 1,
.pos_op = PASS_POS_INSERT_AFTER, .pos_op = PASS_POS_INSERT_AFTER,
}; };
register_callback(name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); register_callback(name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
register_callback(name, PLUGIN_FINISH, afl_pass::plugin_finalize, register_callback(name, PLUGIN_FINISH, afl_pass::plugin_finalize,
pass_info.pass); pass_info.pass);
@ -940,4 +930,6 @@ plugin_init (struct plugin_name_args *info,
getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened")); getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened"));
return 0; return 0;
} }

View File

@ -1287,7 +1287,8 @@ int main(int argc, char **argv, char **envp) {
"\nGCC Plugin-specific environment variables:\n" "\nGCC Plugin-specific environment variables:\n"
" AFL_GCC_OUT_OF_LINE: disable inlined instrumentation\n" " AFL_GCC_OUT_OF_LINE: disable inlined instrumentation\n"
" AFL_GCC_SKIP_NEVERZERO: do not skip zero on trace counters\n" " AFL_GCC_SKIP_NEVERZERO: do not skip zero on trace counters\n"
" AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by filename\n"); " AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
"filename\n");
if (have_llvm) if (have_llvm)
SAYF( SAYF(
@ -1313,7 +1314,8 @@ int main(int argc, char **argv, char **envp) {
if (have_llvm) if (have_llvm)
SAYF( SAYF(
" AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n" " AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen "
"mutator)\n"
" AFL_LLVM_INSTRUMENT: set instrumentation mode:\n" " AFL_LLVM_INSTRUMENT: set instrumentation mode:\n"
" CLASSIC, INSTRIM, PCGUARD, LTO, CTX, NGRAM-2 ... NGRAM-16\n" " CLASSIC, INSTRIM, PCGUARD, LTO, CTX, NGRAM-2 ... NGRAM-16\n"
" You can also use the old environment variables instead:\n" " You can also use the old environment variables instead:\n"
@ -1330,17 +1332,22 @@ int main(int argc, char **argv, char **envp) {
if (have_lto) if (have_lto)
SAYF( SAYF(
"\nLTO/afl-clang-lto specific environment variables:\n" "\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" "0x10000\n"
" AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding functions\n" " AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
"functions\n"
" into this file\n" " into this file\n"
" AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a " " AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
"global var\n" "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" "bb\n"
" AFL_REAL_LD: use this lld linker instead of the compiled in path\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 anything fails - be sure to read README.lto.md!\n");
#endif #endif
} }
SAYF( SAYF(