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

@ -38,8 +38,8 @@
#include <sys/wait.h>
#include <sys/types.h>
#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

View File

@ -132,10 +132,10 @@
#include <unistd.h>
#ifdef likely
# undef likely
#undef likely
#endif
#ifdef unlikely
# undef unlikely
#undef unlikely
#endif
#include <list>
@ -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;
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);
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 ();
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 ();
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);
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);
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)
{
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");
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);
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)));
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");
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);
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));
tree incrv = build_one_cst(TREE_TYPE(cntr));
if (neverZero) {
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)),
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");
xincr = create_tmp_var(TREE_TYPE(memref), ".afl_edge_xincr");
}
auto_vec<tree> 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);
auto_vec<tree> 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);
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 *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);
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);
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);
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) {
if (out_of_line) return TODO_rebuild_cgraph_edges;
gimple_seq seq = NULL;
/* 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 *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);
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);
static inline tree get_afl_trace_decl() {
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
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%%).",
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)
@ -505,12 +494,12 @@ struct afl_pass : gimple_opt_pass {
};
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; }
}
@ -707,7 +696,7 @@ 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<std::string>::iterator it = denyListFunctions.begin();
it != denyListFunctions.end(); ++it) {
@ -772,7 +761,7 @@ struct afl_pass : gimple_opt_pass {
WARNF(
"No debug information found for function %s, will be "
"instrumented (recompile with -g -O[1-3]).",
IDENTIFIER_POINTER (DECL_NAME (F->decl)));
IDENTIFIER_POINTER(DECL_NAME(F->decl)));
}
@ -840,7 +829,7 @@ struct afl_pass : gimple_opt_pass {
SAYF(cMGN "[D] " cRST
"Function %s is in the allowlist (%s), "
"instrumenting ... \n",
IDENTIFIER_POINTER (DECL_NAME (F->decl)),
IDENTIFIER_POINTER(DECL_NAME(F->decl)),
source_file.c_str());
return true;
@ -858,7 +847,7 @@ struct afl_pass : gimple_opt_pass {
WARNF(
"No debug information found for function %s, will not be "
"instrumented (recompile with -g -O[1-3]).",
IDENTIFIER_POINTER (DECL_NAME (F->decl)));
IDENTIFIER_POINTER(DECL_NAME(F->decl)));
return false;
}
@ -871,11 +860,10 @@ struct afl_pass : gimple_opt_pass {
}
};
static struct plugin_info afl_plugin =
{
static struct plugin_info afl_plugin = {
.version = "20200907",
.help = G_("AFL gcc plugin\n\
\n\
@ -886,52 +874,54 @@ 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"),
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 <oliva@adacore.com>\n");
if (isatty(2) && !getenv("AFL_QUIET"))
SAYF(cCYA "afl-gcc-pass " cBRI VERSION cRST " by <oliva@adacore.com>\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 ||
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)"));
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);
register_callback(name, PLUGIN_INFO, NULL, &afl_plugin);
afl_pass * aflp = new afl_pass(quiet, inst_ratio);
struct register_pass_info pass_info = {
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,
register_callback(name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
register_callback(name, PLUGIN_FINISH, afl_pass::plugin_finalize,
pass_info.pass);
if (!quiet)
@ -940,4 +930,6 @@ plugin_init (struct plugin_name_args *info,
getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened"));
return 0;
}

View File

@ -1287,7 +1287,8 @@ int main(int argc, char **argv, char **envp) {
"\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");
" AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
"filename\n");
if (have_llvm)
SAYF(
@ -1313,7 +1314,8 @@ int main(int argc, char **argv, char **envp) {
if (have_llvm)
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"
" CLASSIC, INSTRIM, PCGUARD, LTO, CTX, NGRAM-2 ... NGRAM-16\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)
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\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 "
" 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"
" 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(