Add LTO collision free llvm_mode (#223)

* first new implementation, only works with AFL_DONT_OPTIMIZE

* bug hunting

* interim commit

* finalized LTO non-collision solution

* update documentation

* merge resulted in some problems, fixing these

* added lto env to env check

* fixed llvm weirdness to messes up our instrumentation due CFG rewrite optimizations

* all llvm instrumentation issues have been resolved! :-)

* llvm 9 is required (so far)

* update lto readme
This commit is contained in:
van Hauser
2020-03-05 10:52:26 +01:00
committed by GitHub
parent 70a67ca67d
commit 9d686ba523
14 changed files with 1992 additions and 57 deletions

View File

@ -41,10 +41,23 @@ static u8* obj_path; /* Path to runtime libraries */
static u8** cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
static u8 llvm_fullpath[PATH_MAX];
static u8 lto_mode;
static u8* lto_flag = AFL_CLANG_FLTO;
static u8* march_opt = CFLAGS_OPT;
static u8 debug;
static u8 cwd[4096];
static u8 cmplog_mode;
u8 use_stdin = 0; /* dummy */
u8 be_quiet = 0;
u8* getthecwd() {
static u8 fail[] = "";
if (getcwd(cwd, sizeof(cwd)) == NULL) return fail;
return cwd;
}
/* Try to find the runtime libraries. If that fails, abort. */
static void find_obj(u8* argv0) {
@ -138,7 +151,22 @@ static void edit_params(u32 argc, char** argv) {
has_llvm_config = (strlen(LLVM_BINDIR) > 0);
if (!strcmp(name, "afl-clang-fast++")) {
if (!strncmp(name, "afl-clang-lto", strlen("afl-clang-lto"))) {
#ifdef USE_TRACE_PC
FATAL("afl-clang-lto does not work with TRACE_PC mode");
#endif
if (lto_flag[0] != '-')
FATAL(
"afl-clang-lto not possible because Makefile magic did not identify "
"the correct -flto flag");
if (getenv("AFL_LLVM_INSTRIM") != NULL)
FATAL("afl-clang-lto does not work with InsTrim mode");
lto_mode = 1;
}
if (!strcmp(name, "afl-clang-fast++") || !strcmp(name, "afl-clang-lto++")) {
u8* alt_cxx = getenv("AFL_CXX");
if (has_llvm_config)
@ -200,6 +228,8 @@ static void edit_params(u32 argc, char** argv) {
// /laf
unsetenv("AFL_LD");
unsetenv("AFL_LD_CALLER");
if (cmplog_mode) {
cc_params[cc_par_cnt++] = "-Xclang";
@ -234,6 +264,36 @@ static void edit_params(u32 argc, char** argv) {
// "-fsanitize-coverage=trace-cmp,trace-div,trace-gep";
// cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0";
#else
if (lto_mode) {
char* old_path = getenv("PATH");
char* new_path = alloc_printf("%s:%s", AFL_PATH, old_path);
setenv("PATH", new_path, 1);
setenv("AFL_LD", "1", 1);
if (getenv("AFL_LLVM_WHITELIST") != NULL) {
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] =
alloc_printf("%s/afl-llvm-lto-whitelist.so", obj_path);
}
#ifdef AFL_CLANG_FUSELD
cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s/afl-ld", AFL_PATH);
#endif
cc_params[cc_par_cnt++] = "-B";
cc_params[cc_par_cnt++] = AFL_PATH;
cc_params[cc_par_cnt++] = lto_flag;
} else
if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") ||
getenv("AFL_LLVM_USE_TRACE_PC") || getenv("AFL_TRACE_PC")) {
@ -343,6 +403,8 @@ static void edit_params(u32 argc, char** argv) {
cc_params[cc_par_cnt++] = "-g";
cc_params[cc_par_cnt++] = "-O3";
cc_params[cc_par_cnt++] = "-funroll-loops";
if (strlen(march_opt) > 1 && march_opt[0] == '-')
cc_params[cc_par_cnt++] = march_opt;
}
@ -461,21 +523,40 @@ static void edit_params(u32 argc, char** argv) {
int main(int argc, char** argv, char** envp) {
int i;
char* callname = "afl-clang-fast";
if (getenv("AFL_DEBUG")) {
debug = 1;
if (strcmp(getenv("AFL_DEBUG"), "0") == 0) unsetenv("AFL_DEBUG");
}
if (strstr(argv[0], "afl-clang-lto") == NULL) callname = "afl-clang-lto";
if (argc < 2 || strcmp(argv[1], "-h") == 0) {
#ifdef USE_TRACE_PC
printf(
cCYA
"afl-clang-fast" VERSION cRST
" [tpcg] by <lszekeres@google.com>\n"
printf(cCYA "afl-clang-fast" VERSION cRST
" [tpcg] by <lszekeres@google.com>\n")
#else
printf(
cCYA
"afl-clang-fast" VERSION cRST
" by <lszekeres@google.com>\n"
if (strstr(argv[0], "afl-clang-lto") == NULL)
printf(cCYA "afl-clang-fast" VERSION cRST " by <lszekeres@google.com>\n");
else {
printf(cCYA "afl-clang-lto" VERSION cRST
" by Marc \"vanHauser\" Heuse <mh@mh-sec.de>\n");
}
#endif /* ^USE_TRACE_PC */
SAYF(
"\n"
"afl-clang-fast[++] [options]\n"
"%s[++] [options]\n"
"\n"
"This is a helper application for afl-fuzz. It serves as a drop-in "
"replacement\n"
@ -521,7 +602,7 @@ int main(int argc, char** argv, char** envp) {
"AFL_LLVM_CMPLOG: log operands of comparisons (RedQueen mutator)\n"
"\nafl-clang-fast was built for llvm %s with the llvm binary path of "
"\"%s\".\n\n",
BIN_PATH, BIN_PATH, LLVM_VERSION, LLVM_BINDIR);
callname, BIN_PATH, BIN_PATH, LLVM_VERSION, LLVM_BINDIR);
exit(1);
@ -535,11 +616,28 @@ int main(int argc, char** argv, char** envp) {
#warning \
"You do not need to specifically compile with USE_TRACE_PC anymore, setting the environment variable AFL_LLVM_USE_TRACE_PC is enough."
#else
SAYF(cCYA "afl-clang-fast" VERSION cRST " by <lszekeres@google.com>\n");
if (strstr(argv[0], "afl-clang-lto") == NULL)
SAYF(cCYA "afl-clang-fast" VERSION cRST " by <lszekeres@google.com>\n");
else
SAYF(cCYA "afl-clang-lto" VERSION cRST
" by Marc \"vanHauser\" Heuse <mh@mh-sec.de>\n");
#endif /* ^USE_TRACE_PC */
}
if (debug) {
SAYF(cMGN "[D]" cRST " cd \"%s\";", getthecwd());
for (i = 0; i < argc; i++)
SAYF(" \"%s\"", argv[i]);
SAYF("\n");
}
check_environment_vars(envp);
cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG");
@ -551,13 +649,14 @@ int main(int argc, char** argv, char** envp) {
edit_params(argc, argv);
/*
int i = 0;
printf("EXEC:");
while (cc_params[i] != NULL)
printf(" %s", cc_params[i++]);
printf("\n");
*/
if (debug) {
SAYF(cMGN "[D]" cRST " cd \"%s\";", getthecwd());
for (i = 0; i < cc_par_cnt; i++)
SAYF(" \"%s\"", cc_params[i]);
SAYF("\n");
}
execvp(cc_params[0], (char**)cc_params);
@ -566,4 +665,3 @@ int main(int argc, char** argv, char** envp) {
return 0;
}