about summary refs log tree commit diff
path: root/llvm_mode/afl-clang-fast.c
diff options
context:
space:
mode:
Diffstat (limited to 'llvm_mode/afl-clang-fast.c')
-rw-r--r--llvm_mode/afl-clang-fast.c179
1 files changed, 136 insertions, 43 deletions
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
index ef99e3f3..72b81922 100644
--- a/llvm_mode/afl-clang-fast.c
+++ b/llvm_mode/afl-clang-fast.c
@@ -161,7 +161,8 @@ static void find_obj(u8 *argv0) {
 
 static void edit_params(u32 argc, char **argv, char **envp) {
 
-  u8  fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0;
+  u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0,
+     preprocessor_only = 0;
   u8  have_pic = 0;
   u8 *name;
 
@@ -229,7 +230,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
   if (lto_mode) {
 
     if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
-        getenv("AFL_LLVM_WHITELIST")) {
+        getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
+        getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
 
       cc_params[cc_par_cnt++] = "-Xclang";
       cc_params[cc_par_cnt++] = "-load";
@@ -244,33 +246,60 @@ static void edit_params(u32 argc, char **argv, char **envp) {
   // laf
   if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
 
-    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/split-switches-pass.so", obj_path);
+    if (lto_mode) {
+
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
+
+    } else {
+
+      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/split-switches-pass.so", obj_path);
+
+    }
 
   }
 
   if (getenv("LAF_TRANSFORM_COMPARES") ||
       getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
 
-    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/compare-transform-pass.so", obj_path);
+    if (lto_mode) {
+
+      cc_params[cc_par_cnt++] = alloc_printf(
+          "-Wl,-mllvm=-load=%s/compare-transform-pass.so", obj_path);
+
+    } else {
+
+      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/compare-transform-pass.so", obj_path);
+
+    }
 
   }
 
   if (getenv("LAF_SPLIT_COMPARES") || getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
       getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
 
-    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/split-compares-pass.so", obj_path);
+    if (lto_mode) {
+
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-Wl,-mllvm=-load=%s/split-compares-pass.so", obj_path);
+
+    } else {
+
+      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/split-compares-pass.so", obj_path);
+
+    }
 
   }
 
@@ -280,24 +309,37 @@ static void edit_params(u32 argc, char **argv, char **envp) {
   unsetenv("AFL_LD_CALLER");
   if (cmplog_mode) {
 
-    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/cmplog-routines-pass.so", obj_path);
+    if (lto_mode) {
 
-    // reuse split switches from laf
-    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/split-switches-pass.so", obj_path);
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path);
+      cc_params[cc_par_cnt++] =
+          alloc_printf("-Wl,-mllvm=-load=%s/split-switches-pass.so", obj_path);
+      cc_params[cc_par_cnt++] = alloc_printf(
+          "-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path);
 
-    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/cmplog-instructions-pass.so", obj_path);
+    } else {
+
+      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/cmplog-routines-pass.so", obj_path);
+
+      // reuse split switches from laf
+      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/split-switches-pass.so", obj_path);
+
+      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/cmplog-instructions-pass.so", obj_path);
+
+    }
 
     cc_params[cc_par_cnt++] = "-fno-inline";
 
@@ -310,8 +352,17 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     else
       setenv("AFL_LLVM_LTO_AUTODICTIONARY", "1", 1);
 
+#if defined(AFL_CLANG_LDPATH) && LLVM_VERSION_MAJOR >= 12
+    u8 *ld_ptr = strrchr(AFL_REAL_LD, '/');
+    if (!ld_ptr) ld_ptr = "ld.lld";
+    cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_ptr);
+    cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", AFL_REAL_LD);
+#else
     cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", AFL_REAL_LD);
+#endif
+
     cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
+
     /*
         The current LTO instrim mode is not good, so we disable it
         if (instrument_mode == INSTRUMENT_CFG)
@@ -319,6 +370,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
               alloc_printf("-Wl,-mllvm=-load=%s/afl-llvm-lto-instrim.so",
        obj_path); else
     */
+
     cc_params[cc_par_cnt++] = alloc_printf(
         "-Wl,-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", obj_path);
     cc_params[cc_par_cnt++] = lto_flag;
@@ -327,8 +379,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
     if (instrument_mode == INSTRUMENT_PCGUARD) {
 
+#if LLVM_VERSION_MAJOR > 4 ||   \
+    (LLVM_VERSION_MAJOR == 4 && \
+     (LLVM_VERSION_MINOR > 0 || LLVM_VERSION_PATCH >= 1))
       cc_params[cc_par_cnt++] =
           "-fsanitize-coverage=trace-pc-guard";  // edge coverage by default
+#else
+      FATAL("pcguard instrumentation requires llvm 4.0.1+");
+#endif
 
     } else {
 
@@ -399,6 +457,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
     if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
 
+    if (!strcmp(cur, "-E")) preprocessor_only = 1;
+    if (!strcmp(cur, "-shared")) shared_linking = 1;
+
     cc_params[cc_par_cnt++] = cur;
 
   }
@@ -563,6 +624,18 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
   }
 
+  if (preprocessor_only) {
+
+    /* In the preprocessor_only case (-E), we are not actually compiling at
+       all but requesting the compiler to output preprocessed sources only.
+       We must not add the runtime in this case because the compiler will
+       simply output its binary content back on stdout, breaking any build
+       systems that rely on a separate source preprocessing step. */
+    cc_params[cc_par_cnt] = NULL;
+    return;
+
+  }
+
 #ifndef __ANDROID__
   switch (bit_mode) {
 
@@ -605,6 +678,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
   }
 
+  if (!shared_linking)
+    cc_params[cc_par_cnt++] =
+        alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
+
 #endif
 
   cc_params[cc_par_cnt] = NULL;
@@ -637,9 +714,13 @@ int main(int argc, char **argv, char **envp) {
 
   }
 
-  if ((getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")) &&
+  if ((getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
+       getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
+       getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) &&
       getenv("AFL_DONT_OPTIMIZE"))
-    FATAL("AFL_LLVM_INSTRUMENT_FILE and AFL_DONT_OPTIMIZE cannot be combined");
+    WARNF(
+        "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined "
+        "for file matching, only function matching!");
 
   if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") ||
       getenv("INSTRIM_LIB")) {
@@ -787,15 +868,17 @@ int main(int argc, char **argv, char **envp) {
 #if LLVM_VERSION_MAJOR <= 6
     instrument_mode = INSTRUMENT_AFL;
 #else
-    if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")) {
+    if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
+        getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
+        getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
 
       instrument_mode = INSTRUMENT_AFL;
       WARNF(
           "switching to classic instrumentation because "
-          "AFL_LLVM_INSTRUMENT_FILE does not work with PCGUARD. Use "
-          "-fsanitize-coverage-allowlist=allowlist.txt if you want to use "
-          "PCGUARD. Requires llvm 12+. See "
-          "https://clang.llvm.org/docs/"
+          "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD. Use "
+          "-fsanitize-coverage-allowlist=allowlist.txt or "
+          "-fsanitize-coverage-blocklist=denylist.txt if you want to use "
+          "PCGUARD. Requires llvm 12+. See https://clang.llvm.org/docs/ "
           "SanitizerCoverage.html#partially-disabling-instrumentation");
 
     } else
@@ -846,11 +929,14 @@ int main(int argc, char **argv, char **envp) {
         "together");
 
   if (instrument_mode == INSTRUMENT_PCGUARD &&
-      (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")))
+      (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
+       getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
+       getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")))
     FATAL(
         "Instrumentation type PCGUARD does not support "
-        "AFL_LLVM_INSTRUMENT_FILE! Use "
-        "-fsanitize-coverage-allowlist=allowlist.txt instead (requires llvm "
+        "AFL_LLVM_ALLOWLIST/DENYLIST! Use "
+        "-fsanitize-coverage-allowlist=allowlist.txt or "
+        "-fsanitize-coverage-blocklist=denylist.txt instead (requires llvm "
         "12+), see "
         "https://clang.llvm.org/docs/"
         "SanitizerCoverage.html#partially-disabling-instrumentation");
@@ -892,8 +978,11 @@ int main(int argc, char **argv, char **envp) {
         "AFL_DONT_OPTIMIZE: disable optimization instead of -O3\n"
         "AFL_HARDEN: adds code hardening to catch memory bugs\n"
         "AFL_INST_RATIO: percentage of branches to instrument\n"
+#if LLVM_VERSION_MAJOR < 9
         "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"
+#endif
         "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: casc. comp. in 'switch'\n"
@@ -935,6 +1024,10 @@ int main(int argc, char **argv, char **envp) {
 #ifdef AFL_CLANG_FLTO
     SAYF(
         "\nafl-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 they are in 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 "