about summary refs log tree commit diff
path: root/src/afl-cc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/afl-cc.c')
-rw-r--r--src/afl-cc.c267
1 files changed, 174 insertions, 93 deletions
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 19dc9a6a..c43ac2c1 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -48,6 +48,7 @@
 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   clang_mode;                /* Invoked as afl-clang*?            */
 static u8   llvm_fullpath[PATH_MAX];
 static u8   instrument_mode, instrument_opt_mode, ngram_size, lto_mode;
 static u8   compiler_mode, plusplus_mode, have_instr_env = 0;
@@ -105,7 +106,24 @@ u8 *getthecwd() {
 
 }
 
-/* Try to find the runtime libraries. If that fails, abort. */
+/* Try to find a specific runtime we need, returns NULL on fail. */
+
+/*
+  in find_object() we look here:
+
+  1. if obj_path is already set we look there first
+  2. then we check the $AFL_PATH environment variable location if set
+  3. next we check argv[0] if it has path information and use it
+    a) we also check ../lib/afl
+  4. if 3. failed we check /proc (only Linux, Android, NetBSD, DragonFly, and
+     FreeBSD with procfs)
+    a) and check here in ../lib/afl too
+  5. we look into the AFL_PATH define (usually /usr/local/lib/afl)
+  6. we finally try the current directory
+
+  if all these attempts fail - we return NULL and the caller has to decide
+  what to do.
+*/
 
 static u8 *find_object(u8 *obj, u8 *argv0) {
 
@@ -114,11 +132,9 @@ static u8 *find_object(u8 *obj, u8 *argv0) {
 
   if (afl_path) {
 
-#ifdef __ANDROID__
     tmp = alloc_printf("%s/%s", afl_path, obj);
-#else
-    tmp = alloc_printf("%s/%s", afl_path, obj);
-#endif
+
+    if (debug) DEBUGF("Trying %s\n", tmp);
 
     if (!access(tmp, R_OK)) {
 
@@ -131,125 +147,139 @@ static u8 *find_object(u8 *obj, u8 *argv0) {
 
   }
 
-  if (argv0) slash = strrchr(argv0, '/');
+  if (argv0) {
 
-  if (slash) {
+    slash = strrchr(argv0, '/');
 
-    u8 *dir;
+    if (slash) {
 
-    *slash = 0;
-    dir = ck_strdup(argv0);
-    *slash = '/';
+      u8 *dir = ck_strdup(argv0);
 
-#ifdef __ANDROID__
-    tmp = alloc_printf("%s/%s", dir, obj);
-#else
-    tmp = alloc_printf("%s/%s", dir, obj);
-#endif
+      slash = strrchr(dir, '/');
+      *slash = 0;
 
-    if (!access(tmp, R_OK)) {
+      tmp = alloc_printf("%s/%s", dir, obj);
 
-      obj_path = dir;
-      return tmp;
-
-    }
+      if (debug) DEBUGF("Trying %s\n", tmp);
 
-    ck_free(tmp);
-    ck_free(dir);
+      if (!access(tmp, R_OK)) {
 
-  }
+        obj_path = dir;
+        return tmp;
 
-  tmp = alloc_printf("%s/%s", AFL_PATH, obj);
-#ifdef __ANDROID__
-  if (!access(tmp, R_OK)) {
+      }
 
-#else
-  if (!access(tmp, R_OK)) {
+      ck_free(tmp);
+      tmp = alloc_printf("%s/../lib/afl/%s", dir, obj);
 
-#endif
+      if (debug) DEBUGF("Trying %s\n", tmp);
 
-    obj_path = AFL_PATH;
-    return tmp;
+      if (!access(tmp, R_OK)) {
 
-  }
+        u8 *dir2 = alloc_printf("%s/../lib/afl", dir);
+        obj_path = dir2;
+        ck_free(dir);
+        return tmp;
 
-  ck_free(tmp);
-  return NULL;
+      }
 
-}
+      ck_free(tmp);
+      ck_free(dir);
 
-/* Try to find the runtime libraries. If that fails, abort. */
+    }
 
-static void find_obj(u8 *argv0) {
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__linux__) || \
+    defined(__ANDROID__) || defined(__NetBSD__)
+  #define HAS_PROC_FS 1
+#endif
+#ifdef HAS_PROC_FS
+    else {
+
+      char *procname = NULL;
+  #if defined(__FreeBSD__) || defined(__DragonFly__)
+      procname = "/proc/curproc/file";
+  #elif defined(__linux__) || defined(__ANDROID__)
+      procname = "/proc/self/exe";
+  #elif defined(__NetBSD__)
+      procname = "/proc/curproc/exe";
+  #endif
+      if (procname) {
 
-  u8 *afl_path = getenv("AFL_PATH");
-  u8 *slash, *tmp;
+        char    exepath[PATH_MAX];
+        ssize_t exepath_len = readlink(procname, exepath, sizeof(exepath));
+        if (exepath_len > 0 && exepath_len < PATH_MAX) {
 
-  if (afl_path) {
+          exepath[exepath_len] = 0;
+          slash = strrchr(exepath, '/');
 
-#ifdef __ANDROID__
-    tmp = alloc_printf("%s/afl-compiler-rt.so", afl_path);
-#else
-    tmp = alloc_printf("%s/afl-compiler-rt.o", afl_path);
-#endif
+          if (slash) {
 
-    if (!access(tmp, R_OK)) {
+            *slash = 0;
+            tmp = alloc_printf("%s/%s", exepath, obj);
 
-      obj_path = afl_path;
-      ck_free(tmp);
-      return;
+            if (!access(tmp, R_OK)) {
 
-    }
+              u8 *dir = alloc_printf("%s", exepath);
+              obj_path = dir;
+              return tmp;
 
-    ck_free(tmp);
+            }
 
-  }
+            ck_free(tmp);
+            tmp = alloc_printf("%s/../lib/afl/%s", exepath, obj);
 
-  slash = strrchr(argv0, '/');
+            if (debug) DEBUGF("Trying %s\n", tmp);
 
-  if (slash) {
+            if (!access(tmp, R_OK)) {
 
-    u8 *dir;
+              u8 *dir = alloc_printf("%s/../lib/afl/", exepath);
+              obj_path = dir;
+              return tmp;
 
-    *slash = 0;
-    dir = ck_strdup(argv0);
-    *slash = '/';
+            }
 
-#ifdef __ANDROID__
-    tmp = alloc_printf("%s/afl-compiler-rt.so", dir);
-#else
-    tmp = alloc_printf("%s/afl-compiler-rt.o", dir);
-#endif
+          }
 
-    if (!access(tmp, R_OK)) {
+        }
 
-      obj_path = dir;
-      ck_free(tmp);
-      return;
+      }
 
     }
 
-    ck_free(tmp);
-    ck_free(dir);
+#endif
+#undef HAS_PROC_FS
 
   }
 
-#ifdef __ANDROID__
-  if (!access(AFL_PATH "/afl-compiler-rt.so", R_OK)) {
+  tmp = alloc_printf("%s/%s", AFL_PATH, obj);
 
-#else
-  if (!access(AFL_PATH "/afl-compiler-rt.o", R_OK)) {
+  if (debug) DEBUGF("Trying %s\n", tmp);
 
-#endif
+  if (!access(tmp, R_OK)) {
 
     obj_path = AFL_PATH;
-    return;
+    return tmp;
+
+  }
+
+  ck_free(tmp);
+
+  tmp = alloc_printf("./%s", obj);
+
+  if (debug) DEBUGF("Trying %s\n", tmp);
+
+  if (!access(tmp, R_OK)) {
+
+    obj_path = ".";
+    return tmp;
 
   }
 
-  FATAL(
-      "Unable to find 'afl-compiler-rt.o' or 'afl-llvm-pass.so'. Please set "
-      "AFL_PATH");
+  ck_free(tmp);
+
+  if (debug) DEBUGF("Trying ... giving up\n");
+
+  return NULL;
 
 }
 
@@ -288,7 +318,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
       if (compiler_mode >= GCC_PLUGIN) {
 
-        alt_cxx = "g++";
+        if (compiler_mode == GCC) {
+
+          alt_cxx = clang_mode ? "clang++" : "g++";
+
+        } else {
+
+          alt_cxx = "g++";
+
+        }
 
       } else {
 
@@ -313,7 +351,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
 
       if (compiler_mode >= GCC_PLUGIN) {
 
-        alt_cc = "gcc";
+        if (compiler_mode == GCC) {
+
+          alt_cc = clang_mode ? "clang" : "gcc";
+
+        } else {
+
+          alt_cc = "gcc";
+
+        }
 
       } else {
 
@@ -337,12 +383,13 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     cc_params[cc_par_cnt++] = "-B";
     cc_params[cc_par_cnt++] = obj_path;
 
+    if (clang_mode) { cc_params[cc_par_cnt++] = "-no-integrated-as"; }
+
   }
 
   if (compiler_mode == GCC_PLUGIN) {
 
-    char *fplugin_arg =
-        alloc_printf("-fplugin=%s", find_object("afl-gcc-pass.so", argvnull));
+    char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
     cc_params[cc_par_cnt++] = fplugin_arg;
 
   }
@@ -686,7 +733,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
   }
 
   if (getenv("AFL_NO_BUILTIN") || getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
-      getenv("LAF_TRANSFORM_COMPARES") || lto_mode) {
+      getenv("LAF_TRANSFORM_COMPARES") || getenv("AFL_LLVM_LAF_ALL") ||
+      lto_mode) {
 
     cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
     cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
@@ -843,6 +891,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
           alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
   #endif
 
+  #ifdef USEMMAP
+    cc_params[cc_par_cnt++] = "-lrt";
+  #endif
+
   }
 
 #endif
@@ -934,7 +986,9 @@ int main(int argc, char **argv, char **envp) {
 
   } else if (strncmp(callname, "afl-gcc", 7) == 0 ||
 
-             strncmp(callname, "afl-g++", 7) == 0) {
+             strncmp(callname, "afl-g++", 7) == 0 ||
+
+             strncmp(callname, "afl-clang", 9) == 0) {
 
     compiler_mode = GCC;
 
@@ -978,6 +1032,14 @@ int main(int argc, char **argv, char **envp) {
 
   }
 
+  if (strncmp(callname, "afl-clang", 9) == 0) {
+
+    clang_mode = 1;
+
+    if (strncmp(callname, "afl-clang++", 11) == 0) { plusplus_mode = 1; }
+
+  }
+
   for (i = 1; i < argc; i++) {
 
     if (strncmp(argv[i], "--afl", 5) == 0) {
@@ -1030,7 +1092,7 @@ int main(int argc, char **argv, char **envp) {
     if (instrument_mode == 0)
       instrument_mode = INSTRUMENT_PCGUARD;
     else if (instrument_mode != INSTRUMENT_PCGUARD)
-      FATAL("you can not set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together");
+      FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_TRACE_PC together");
 
   }
 
@@ -1048,8 +1110,7 @@ int main(int argc, char **argv, char **envp) {
     if (instrument_mode == 0)
       instrument_mode = INSTRUMENT_CFG;
     else if (instrument_mode != INSTRUMENT_CFG)
-      FATAL(
-          "you can not set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
+      FATAL("you cannot set AFL_LLVM_INSTRUMENT and AFL_LLVM_INSTRIM together");
 
   }
 
@@ -1403,9 +1464,15 @@ int main(int argc, char **argv, char **envp) {
     if (have_llvm)
       SAYF("afl-cc LLVM version %d with the the binary path \"%s\".\n",
            LLVM_MAJOR, LLVM_BINDIR);
-    if (have_lto || have_llvm) SAYF("\n");
 #endif
 
+#ifdef USEMMAP
+    SAYF("Compiled with shm_open support (adds -lrt when linking).\n");
+#else
+    SAYF("Compiled with shmat support.\n");
+#endif
+    SAYF("\n");
+
     SAYF(
         "Do not be overwhelmed :) afl-cc uses good defaults if no options are "
         "selected.\n"
@@ -1545,7 +1612,7 @@ int main(int argc, char **argv, char **envp) {
 
   if (debug) {
 
-    SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
+    DEBUGF("cd '%s';", getthecwd());
     for (i = 0; i < argc; i++)
       SAYF(" '%s'", argv[i]);
     SAYF("\n");
@@ -1565,15 +1632,29 @@ int main(int argc, char **argv, char **envp) {
   if (!be_quiet && cmplog_mode)
     printf("CmpLog mode by <andreafioraldi@gmail.com>\n");
 
-#ifndef __ANDROID__
-  find_obj(argv[0]);
+#ifdef __ANDROID__
+  ptr = find_object("afl-compiler-rt.so", argv[0]);
+#else
+  ptr = find_object("afl-compiler-rt.o", argv[0]);
 #endif
 
+  if (!ptr) {
+
+    FATAL(
+        "Unable to find 'afl-compiler-rt.o'. Please set the AFL_PATH "
+        "environment variable.");
+
+  }
+
+  if (debug) { DEBUGF("rt=%s obj_path=%s\n", ptr, obj_path); }
+
+  ck_free(ptr);
+
   edit_params(argc, argv, envp);
 
   if (debug) {
 
-    SAYF(cMGN "[D]" cRST " cd '%s';", getthecwd());
+    DEBUGF("cd '%s';", getthecwd());
     for (i = 0; i < (s32)cc_par_cnt; i++)
       SAYF(" '%s'", cc_params[i]);
     SAYF("\n");