about summary refs log tree commit diff
path: root/gcc_plugin
diff options
context:
space:
mode:
Diffstat (limited to 'gcc_plugin')
-rw-r--r--gcc_plugin/Makefile6
-rw-r--r--gcc_plugin/afl-gcc-fast.c2
-rw-r--r--gcc_plugin/afl-gcc-rt.o.c100
3 files changed, 95 insertions, 13 deletions
diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile
index a603df78..287b6545 100644
--- a/gcc_plugin/Makefile
+++ b/gcc_plugin/Makefile
@@ -27,7 +27,7 @@ CFLAGS      ?= -O3 -g -funroll-loops
 CFLAGS      += -Wall -D_FORTIFY_SOURCE=2 -Wno-pointer-sign \
                -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
 
-CXXFLAGS	?= -O3 -g -funroll-loops
+CXXFLAGS    ?= -O3 -g -funroll-loops
 CXXEFLAGS   := $(CXXFLAGS) -Wall -D_FORTIFY_SOURCE=2
 
 CC          ?= gcc
@@ -35,8 +35,6 @@ CXX         ?= g++
 
 PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(shell $(CC) -print-file-name=plugin)/include"
 
-PROGS        = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o
-
 ifeq "$(shell echo '\#include <sys/ipc.h>@\#include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 )" "1"
 	SHMAT_OK=1
 else
@@ -51,6 +49,8 @@ ifeq "$(TEST_MMAP)" "1"
 	LDFLAGS += -lrt
 endif
 
+PROGS        = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o
+
 
 all: test_shm test_deps $(PROGS) afl-gcc-fast.8 test_build all_done
 
diff --git a/gcc_plugin/afl-gcc-fast.c b/gcc_plugin/afl-gcc-fast.c
index b0461584..093249a0 100644
--- a/gcc_plugin/afl-gcc-fast.c
+++ b/gcc_plugin/afl-gcc-fast.c
@@ -282,6 +282,8 @@ int main(int argc, char** argv) {
         "afl-gcc-fast" VERSION cRST
         " initially by <aseipp@pobox.com>, maintainer: hexcoder-\n"
         "\n"
+        "afl-gcc-fast [options]\n"
+        "\n"
         "This is a helper application for afl-fuzz. It serves as a drop-in "
         "replacement\n"
         "for gcc, letting you recompile third-party code with the required "
diff --git a/gcc_plugin/afl-gcc-rt.o.c b/gcc_plugin/afl-gcc-rt.o.c
index dd79a0ec..5b70a247 100644
--- a/gcc_plugin/afl-gcc-rt.o.c
+++ b/gcc_plugin/afl-gcc-rt.o.c
@@ -21,12 +21,16 @@
 
 */
 
+#ifdef __ANDROID__
+#include "android-ashmem.h"
+#endif
 #include "../config.h"
 #include "../types.h"
 
 #include <stdlib.h>
 #include <signal.h>
 #include <unistd.h>
+#include <string.h>
 #include <assert.h>
 
 #include <sys/mman.h>
@@ -34,29 +38,43 @@
 #include <sys/wait.h>
 #include <sys/types.h>
 
+#include <sys/mman.h>
+#include <fcntl.h>
+
 /* Globals needed by the injected instrumentation. The __afl_area_initial region
    is used for instrumentation output before __afl_map_shm() has a chance to
    run. It will end up as .comm, so it shouldn't be too wasteful. */
 
 u8  __afl_area_initial[MAP_SIZE];
 u8 *__afl_area_ptr = __afl_area_initial;
-u32 __afl_prev_loc;
 
-/* Running in persistent mode? */
-
-static u8 is_persistent;
+#ifdef __ANDROID__
+u32 __afl_prev_loc;
+#else
+__thread u32 __afl_prev_loc;
+#endif
 
 /* Trace a basic block with some ID */
 void __afl_trace(u32 x) {
 
   u32 l = __afl_prev_loc;
-  u32 n = l ^ x;
-  *(__afl_area_ptr + n) += 1;
+
+#if 0 /* enable for neverZero feature. By default disabled since too inefficient :-( */
+  /* @Marc: avoid conditional jumps here */
+  __afl_area_ptr[l ^ x] += 1 + (__afl_area_ptr[l ^ x] == (u8)~0);
+#else
+  ++__afl_area_ptr[l ^ x];
+#endif
+
   __afl_prev_loc = (x >> 1);
   return;
 
 }
 
+/* Running in persistent mode? */
+
+static u8 is_persistent;
+
 /* SHM setup. */
 
 static void __afl_map_shm(void) {
@@ -69,9 +87,38 @@ static void __afl_map_shm(void) {
 
   if (id_str) {
 
+#ifdef USEMMAP
+    const char*    shm_file_path = id_str;
+    int            shm_fd = -1;
+    unsigned char* shm_base = NULL;
+
+    /* create the shared memory segment as if it was a file */
+    shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
+    if (shm_fd == -1) {
+
+      printf("shm_open() failed\n");
+      exit(1);
+
+    }
+
+    /* map the shared memory segment to the address space of the process */
+    shm_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
+    if (shm_base == MAP_FAILED) {
+
+      close(shm_fd);
+      shm_fd = -1;
+
+      printf("mmap() failed\n");
+      exit(2);
+
+    }
+
+    __afl_area_ptr = shm_base;
+#else
     u32 shm_id = atoi(id_str);
 
     __afl_area_ptr = shmat(shm_id, NULL, 0);
+#endif
 
     /* Whooooops. */
 
@@ -95,6 +142,8 @@ static void __afl_start_forkserver(void) {
 
   u8 child_stopped = 0;
 
+  void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
+
   /* Phone home and tell the parent that we're OK. If parent isn't there,
      assume we're not running in forkserver mode and just execute program. */
 
@@ -131,6 +180,8 @@ static void __afl_start_forkserver(void) {
 
       if (!child_pid) {
 
+        signal(SIGCHLD, old_sigchld_handler);
+
         close(FORKSRV_FD);
         close(FORKSRV_FD + 1);
         return;
@@ -176,18 +227,47 @@ int __afl_persistent_loop(unsigned int max_cnt) {
 
   if (first_pass) {
 
+    /* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
+       On subsequent calls, the parent will take care of that, but on the first
+       iteration, it's our job to erase any trace of whatever happened
+       before the loop. */
+
+    if (is_persistent) {
+
+      memset(__afl_area_ptr, 0, MAP_SIZE);
+      __afl_area_ptr[0] = 1;
+      __afl_prev_loc = 0;
+
+    }
+
     cycle_cnt = max_cnt;
     first_pass = 0;
     return 1;
 
   }
 
-  if (is_persistent && --cycle_cnt) {
+  if (is_persistent) {
 
-    raise(SIGSTOP);
-    return 1;
+    if (--cycle_cnt) {
 
-  } else
+      raise(SIGSTOP);
+
+      __afl_area_ptr[0] = 1;
+      __afl_prev_loc = 0;
+
+      return 1;
+
+    } else {
+
+      /* When exiting __AFL_LOOP(), make sure that the subsequent code that
+         follows the loop is not traced. We do that by pivoting back to the
+         dummy output region. */
+
+      __afl_area_ptr = __afl_area_initial;
+
+    }
+
+  }
 
     return 0;