about summary refs log tree commit diff
path: root/llvm_mode/afl-llvm-rt.o.c
diff options
context:
space:
mode:
Diffstat (limited to 'llvm_mode/afl-llvm-rt.o.c')
-rw-r--r--llvm_mode/afl-llvm-rt.o.c194
1 files changed, 160 insertions, 34 deletions
diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c
index fcacc675..d00fd26f 100644
--- a/llvm_mode/afl-llvm-rt.o.c
+++ b/llvm_mode/afl-llvm-rt.o.c
@@ -35,6 +35,8 @@
 #include <string.h>
 #include <assert.h>
 #include <stdint.h>
+#include <stddef.h>
+#include <limits.h>
 #include <errno.h>
 
 #include <sys/mman.h>
@@ -42,6 +44,8 @@
 #include <sys/wait.h>
 #include <sys/types.h>
 
+#include "llvm/Config/llvm-config.h"
+
 #ifdef __linux__
   #include "snapshot-inl.h"
 #endif
@@ -50,8 +54,6 @@
    Basically, we need to make sure that the forkserver is initialized after
    the LLVM-generated runtime initialization pass, not before. */
 
-#define CONST_PRIO 5
-
 #ifndef MAP_FIXED_NOREPLACE
   #ifdef MAP_EXCL
     #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
@@ -60,6 +62,8 @@
   #endif
 #endif
 
+#define CTOR_PRIO 3
+
 #include <sys/mman.h>
 #include <fcntl.h>
 
@@ -73,11 +77,7 @@
   #define MAP_INITIAL_SIZE MAP_SIZE
 #endif
 
-#ifdef AFL_REAL_LD
-u8 __afl_area_initial[MAP_INITIAL_SIZE];
-#else
-u8                  __afl_area_initial[MAP_SIZE];
-#endif
+u8   __afl_area_initial[MAP_INITIAL_SIZE];
 u8 * __afl_area_ptr = __afl_area_initial;
 u8 * __afl_dictionary;
 u8 * __afl_fuzz_ptr;
@@ -107,6 +107,10 @@ struct cmp_map *__afl_cmp_map;
 
 static u8 is_persistent;
 
+/* Are we in sancov mode? */
+
+static u8 _is_sancov;
+
 /* Error reporting to forkserver controller */
 
 void send_forkserver_error(int error) {
@@ -183,14 +187,17 @@ static void __afl_map_shm_fuzz() {
 
 static void __afl_map_shm(void) {
 
+  // we we are not running in afl ensure the map exists
+  if (!__afl_area_ptr) { __afl_area_ptr = __afl_area_initial; }
+
   char *id_str = getenv(SHM_ENV_VAR);
 
   if (__afl_final_loc) {
 
     if (__afl_final_loc % 8)
       __afl_final_loc = (((__afl_final_loc + 7) >> 3) << 3);
-
     __afl_map_size = __afl_final_loc;
+
     if (__afl_final_loc > MAP_SIZE) {
 
       char *ptr;
@@ -200,10 +207,12 @@ static void __afl_map_shm(void) {
 
         if (__afl_final_loc > FS_OPT_MAX_MAPSIZE) {
 
-          fprintf(stderr,
-                  "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to "
-                  "be able to run this instrumented program!\n",
-                  __afl_final_loc);
+          if (!getenv("AFL_QUIET"))
+            fprintf(stderr,
+                    "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u "
+                    "to be able to run this instrumented program!\n",
+                    __afl_final_loc);
+
           if (id_str) {
 
             send_forkserver_error(FS_ERROR_MAP_SIZE);
@@ -213,10 +222,11 @@ static void __afl_map_shm(void) {
 
         } else {
 
-          fprintf(stderr,
-                  "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to "
-                  "be able to run this instrumented program!\n",
-                  __afl_final_loc);
+          if (!getenv("AFL_QUIET"))
+            fprintf(stderr,
+                    "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u "
+                    "to be able to run this instrumented program!\n",
+                    __afl_final_loc);
 
         }
 
@@ -232,13 +242,25 @@ static void __afl_map_shm(void) {
 
   if (getenv("AFL_DEBUG"))
     fprintf(stderr,
-            "DEBUG: id_str %s, __afl_map_addr 0x%llx, MAP_SIZE %u, "
-            "__afl_final_loc %u, max_size_forkserver %u/0x%x\n",
-            id_str == NULL ? "<null>" : id_str, __afl_map_addr, MAP_SIZE,
-            __afl_final_loc, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
+            "DEBUG: id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
+            "__afl_map_addr 0x%llx, MAP_SIZE %u, __afl_final_loc %u, "
+            "max_size_forkserver %u/0x%x\n",
+            id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
+            __afl_area_initial, __afl_map_addr, MAP_SIZE, __afl_final_loc,
+            FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
 
   if (id_str) {
 
+    if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) {
+
+      if (__afl_map_addr)
+        munmap((void *)__afl_map_addr, __afl_final_loc);
+      else
+        free(__afl_area_ptr);
+      __afl_area_ptr = __afl_area_initial;
+
+    }
+
 #ifdef USEMMAP
     const char *   shm_file_path = id_str;
     int            shm_fd = -1;
@@ -307,11 +329,14 @@ static void __afl_map_shm(void) {
 
     __afl_area_ptr[0] = 1;
 
-  } else if (__afl_map_addr) {
+  } else if ((!__afl_area_ptr || __afl_area_ptr == __afl_area_initial) &&
+
+             __afl_map_addr) {
 
     __afl_area_ptr =
         mmap((void *)__afl_map_addr, __afl_map_size, PROT_READ | PROT_WRITE,
              MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+
     if (__afl_area_ptr == MAP_FAILED) {
 
       fprintf(stderr, "can not aquire mmap for address %p\n",
@@ -320,14 +345,25 @@ static void __afl_map_shm(void) {
 
     }
 
+  } else if (_is_sancov && __afl_area_ptr != __afl_area_initial) {
+
+    free(__afl_area_ptr);
+    __afl_area_ptr = NULL;
+    if (__afl_final_loc > MAP_INITIAL_SIZE)
+      __afl_area_ptr = malloc(__afl_final_loc);
+    if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial;
+
   }
 
   id_str = getenv(CMPLOG_SHM_ENV_VAR);
 
-  if (getenv("AFL_DEBUG"))
+  if (getenv("AFL_DEBUG")) {
+
     fprintf(stderr, "DEBUG: cmplog id_str %s\n",
             id_str == NULL ? "<null>" : id_str);
 
+  }
+
   if (id_str) {
 
 #ifdef USEMMAP
@@ -399,9 +435,12 @@ static void __afl_start_snapshots(void) {
 
     if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
 
-    if (getenv("AFL_DEBUG"))
+    if (getenv("AFL_DEBUG")) {
+
       fprintf(stderr, "target forkserver recv: %08x\n", was_killed);
 
+    }
+
     if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
         (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
 
@@ -608,9 +647,12 @@ static void __afl_start_forkserver(void) {
 
     if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
 
-    if (getenv("AFL_DEBUG"))
+    if (getenv("AFL_DEBUG")) {
+
       fprintf(stderr, "target forkserver recv: %08x\n", was_killed);
 
+    }
+
     if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
         (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
 
@@ -828,9 +870,22 @@ void __afl_manual_init(void) {
 
   static u8 init_done;
 
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) {
+
+    init_done = 1;
+    is_persistent = 0;
+    __afl_sharedmem_fuzzing = 0;
+    if (__afl_area_ptr == NULL) __afl_area_ptr = __afl_area_initial;
+
+    if (getenv("AFL_DEBUG"))
+      fprintf(stderr,
+              "DEBUG: disabled instrumentation because of "
+              "AFL_DISABLE_LLVM_INSTRUMENTATION\n");
+
+  }
+
   if (!init_done) {
 
-    __afl_map_shm();
     __afl_start_forkserver();
     init_done = 1;
 
@@ -838,11 +893,11 @@ void __afl_manual_init(void) {
 
 }
 
-/* Proper initialization routine. */
+/* Initialization of the forkserver - latest possible */
 
-__attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
+__attribute__((constructor())) void __afl_auto_init(void) {
 
-  is_persistent = !!getenv(PERSIST_ENV_VAR);
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
 
   if (getenv(DEFER_ENV_VAR)) return;
 
@@ -850,6 +905,57 @@ __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
 
 }
 
+/* Initialization of the shmem - earliest possible because of LTO fixed mem. */
+
+__attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) {
+
+  is_persistent = !!getenv(PERSIST_ENV_VAR);
+
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
+
+  __afl_map_shm();
+
+}
+
+/* preset __afl_area_ptr #2 */
+
+__attribute__((constructor(1))) void __afl_auto_second(void) {
+
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
+  u8 *ptr;
+
+  if (__afl_final_loc) {
+
+    if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial)
+      free(__afl_area_ptr);
+
+    if (__afl_map_addr)
+      ptr = (u8 *)mmap((void *)__afl_map_addr, __afl_final_loc,
+                       PROT_READ | PROT_WRITE,
+                       MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+    else
+      ptr = (u8 *)malloc(__afl_final_loc);
+
+    if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
+
+  }
+
+}
+
+/* preset __afl_area_ptr #1 - at constructor level 0 global variables have
+   not been set */
+
+__attribute__((constructor(0))) void __afl_auto_first(void) {
+
+  if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
+  u8 *ptr;
+
+  ptr = (u8 *)malloc(1024000);
+
+  if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
+
+}
+
 /* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard.
    It remains non-operational in the traditional, plugin-backed LLVM mode.
    For more info about 'trace-pc-guard', see llvm_mode/README.md.
@@ -860,7 +966,7 @@ __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
 void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
 
   // For stability analysis, if you want to know to which function unstable
-  // edge IDs belong to - uncomment, recompile+install llvm_mode, recompile
+  // edge IDs belong - uncomment, recompile+install llvm_mode, recompile
   // the target. libunwind and libbacktrace are better solutions.
   // Set AFL_DEBUG_CHILD_OUTPUT=1 and run afl-fuzz with 2>file to capture
   // the backtrace output
@@ -892,8 +998,17 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
 
   */
 
+#if (LLVM_VERSION_MAJOR < 9)
+
   __afl_area_ptr[*guard]++;
 
+#else
+
+  __afl_area_ptr[*guard] =
+      __afl_area_ptr[*guard] + 1 + (__afl_area_ptr[*guard] == 255 ? 1 : 0);
+
+#endif
+
 }
 
 /* Init callback. Populates instrumentation IDs. Note that we're using
@@ -905,6 +1020,15 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
   u32   inst_ratio = 100;
   char *x;
 
+  _is_sancov = 1;
+
+  if (getenv("AFL_DEBUG")) {
+
+    fprintf(stderr, "Running __sanitizer_cov_trace_pc_guard_init: %p-%p\n",
+            start, stop);
+
+  }
+
   if (start == stop || *start) return;
 
   x = getenv("AFL_INST_RATIO");
@@ -940,7 +1064,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
 
 void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
@@ -963,7 +1087,7 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2) {
 
 void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
@@ -984,7 +1108,7 @@ void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2) {
 
 void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
@@ -1005,7 +1129,7 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2) {
 
 void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   uintptr_t k = (uintptr_t)__builtin_return_address(0);
   k = (k >> 4) ^ (k << 8);
@@ -1056,6 +1180,8 @@ void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2)
 
 void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
 
+  if (unlikely(!__afl_cmp_map)) return;
+
   for (uint64_t i = 0; i < cases[0]; i++) {
 
     uintptr_t k = (uintptr_t)__builtin_return_address(0) + i;
@@ -1093,7 +1219,7 @@ static int area_is_mapped(void *ptr, size_t len) {
 
 void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
 
-  if (!__afl_cmp_map) return;
+  if (unlikely(!__afl_cmp_map)) return;
 
   if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return;