about summary refs log tree commit diff
path: root/frida_mode
diff options
context:
space:
mode:
Diffstat (limited to 'frida_mode')
-rw-r--r--frida_mode/GNUmakefile26
-rw-r--r--frida_mode/README.md20
-rw-r--r--frida_mode/frida.map1
-rw-r--r--frida_mode/include/entry.h3
-rw-r--r--frida_mode/include/instrument.h1
-rw-r--r--frida_mode/include/ranges.h2
-rw-r--r--frida_mode/include/seccomp.h111
-rw-r--r--frida_mode/many-linux/Dockerfile4
-rw-r--r--frida_mode/many-linux/GNUmakefile15
-rwxr-xr-xfrida_mode/many-linux/realpath2
-rw-r--r--frida_mode/src/entry.c32
-rw-r--r--frida_mode/src/instrument/instrument.c9
-rw-r--r--frida_mode/src/instrument/instrument_arm32.c4
-rw-r--r--frida_mode/src/instrument/instrument_arm64.c3
-rw-r--r--frida_mode/src/instrument/instrument_coverage.c1
-rw-r--r--frida_mode/src/instrument/instrument_x64.c318
-rw-r--r--frida_mode/src/instrument/instrument_x86.c3
-rw-r--r--frida_mode/src/js/api.js7
-rw-r--r--frida_mode/src/js/js_api.c6
-rw-r--r--frida_mode/src/main.c13
-rw-r--r--frida_mode/src/prefetch.c8
-rw-r--r--frida_mode/src/ranges.c13
-rw-r--r--frida_mode/src/seccomp/seccomp.c136
-rw-r--r--frida_mode/src/seccomp/seccomp_atomic.c10
-rw-r--r--frida_mode/src/seccomp/seccomp_callback.c144
-rw-r--r--frida_mode/src/seccomp/seccomp_child.c28
-rw-r--r--frida_mode/src/seccomp/seccomp_event.c18
-rw-r--r--frida_mode/src/seccomp/seccomp_filter.c61
-rw-r--r--frida_mode/src/seccomp/seccomp_print.c30
-rw-r--r--frida_mode/src/seccomp/seccomp_socket.c16
-rw-r--r--frida_mode/src/seccomp/seccomp_syscall.c12
-rw-r--r--frida_mode/test/freetype2/GNUmakefile192
-rw-r--r--frida_mode/test/freetype2/Makefile13
-rwxr-xr-xfrida_mode/test/freetype2/get_symbol_addr.py36
-rw-r--r--frida_mode/test/libpcap/GNUmakefile2
-rw-r--r--frida_mode/ts/lib/afl.ts12
-rw-r--r--frida_mode/ub1804/Dockerfile6
-rw-r--r--frida_mode/ub1804/GNUmakefile37
-rw-r--r--frida_mode/ub1804/Makefile9
39 files changed, 1083 insertions, 281 deletions
diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile
index 3e35e2f6..b5fee7a6 100644
--- a/frida_mode/GNUmakefile
+++ b/frida_mode/GNUmakefile
@@ -30,8 +30,7 @@ AFL_CFLAGS:=-Wno-unused-parameter \
 
 LDFLAGS+=-shared \
 		 -lpthread \
-		 -lresolv \
-		 -ldl
+		 -lresolv
 
 ifdef DEBUG
 CFLAGS+=-Werror \
@@ -71,12 +70,33 @@ ifdef DEBUG
 endif
 LDFLAGS+=	-z noexecstack \
 			-Wl,--gc-sections \
-			-Wl,--exclude-libs,ALL
+			-Wl,--exclude-libs,ALL \
+		    -ldl \
+		    -lrt
 LDSCRIPT:=-Wl,--version-script=$(PWD)frida.map
 endif
 
 ifeq "$(shell uname)" "Linux"
  OS:=linux
+ ifneq "$(findstring musl, $(shell ldd --version 2>&1 | head -n 1))" ""
+  CFLAGS+=       -D__MUSL__
+ endif
+endif
+
+ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
+ OS:=android
+ ifneq "$(findstring aarch64, $(shell $(CC) --version 2>/dev/null))" ""
+   ARCH:=arm64
+ endif
+ ifneq "$(findstring arm, $(shell $(CC) --version 2>/dev/null))" ""
+   ARCH:=arm
+ endif
+ ifneq "$(findstring x86_64, $(shell $(CC) --version 2>/dev/null))" ""
+   ARCH:=x86_64
+ endif
+ ifneq "$(findstring i686, $(shell $(CC) --version 2>/dev/null))" ""
+   ARCH:=x86
+ endif
 endif
 
 ifndef OS
diff --git a/frida_mode/README.md b/frida_mode/README.md
index 165f8089..bb194080 100644
--- a/frida_mode/README.md
+++ b/frida_mode/README.md
@@ -55,6 +55,20 @@ tests in 32-bit mode, run `make ARCH=x86 frida`. When switching between
 architectures it may be necessary to run `make clean` first for a given build
 target to remove previously generated binaries for a different architecture.
 
+### Android
+
+In order to build, you need to download the Android SDK.
+
+```
+https://developer.android.com/ndk/downloads
+```
+
+Then creating locally a standalone chain as follow.
+
+```
+https://developer.android.com/ndk/guides/standalone_toolchain
+```
+
 ## Usage
 
 FRIDA mode added some small modifications to `afl-fuzz` and similar tools
@@ -274,6 +288,12 @@ ucomisd                                 2 ( 0.86%)
 * `AFL_FRIDA_STATS_INTERVAL` - The maximum frequency to output statistics
 information. Stats will be written whenever they are updated if the given
 interval has elapsed since last time they were written.
+* `AFL_FRIDA_TRACEABLE` - Set the child process to be traceable by any process
+to aid debugging and overcome the restrictions imposed by YAMA. Supported on
+Linux only. Permits a non-root user to use `gcore` or similar to collect a core
+dump of the instrumented target. Note that in order to capture the core dump you
+must set a sufficient timeout (using `-t`) to avoid `afl-fuzz` killing the
+process whilst it is being dumped.
 
 ## FASAN - Frida Address Sanitizer Mode
 Frida mode also supports FASAN. The design of this is actually quite simple and
diff --git a/frida_mode/frida.map b/frida_mode/frida.map
index 0fc48aa6..e2ae87a7 100644
--- a/frida_mode/frida.map
+++ b/frida_mode/frida.map
@@ -33,6 +33,7 @@
     js_api_set_stats_interval;
     js_api_set_stderr;
     js_api_set_stdout;
+    js_api_set_traceable;
 
   local:
     *;
diff --git a/frida_mode/include/entry.h b/frida_mode/include/entry.h
index 3f0a4ecc..edc41467 100644
--- a/frida_mode/include/entry.h
+++ b/frida_mode/include/entry.h
@@ -4,6 +4,7 @@
 #include "frida-gumjs.h"
 
 extern guint64  entry_point;
+extern gboolean traceable;
 extern gboolean entry_compiled;
 extern gboolean entry_run;
 
@@ -15,5 +16,7 @@ void entry_start(void);
 
 void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output);
 
+void entry_on_fork(void);
+
 #endif
 
diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h
index 909b2a2c..cac5ee93 100644
--- a/frida_mode/include/instrument.h
+++ b/frida_mode/include/instrument.h
@@ -29,6 +29,7 @@ GumStalkerTransformer *instrument_get_transformer(void);
 /* Functions to be implemented by the different architectures */
 gboolean instrument_is_coverage_optimize_supported(void);
 
+void instrument_coverage_optimize_init(void);
 void instrument_coverage_optimize(const cs_insn *   instr,
                                   GumStalkerOutput *output);
 
diff --git a/frida_mode/include/ranges.h b/frida_mode/include/ranges.h
index 0220a59d..3bd9eaa6 100644
--- a/frida_mode/include/ranges.h
+++ b/frida_mode/include/ranges.h
@@ -10,6 +10,8 @@ extern gboolean ranges_inst_jit;
 void ranges_config(void);
 void ranges_init(void);
 
+void ranges_print_debug_maps(void);
+
 gboolean range_is_excluded(GumAddress address);
 
 void ranges_exclude();
diff --git a/frida_mode/include/seccomp.h b/frida_mode/include/seccomp.h
index 2c037ff7..7e8a7d25 100644
--- a/frida_mode/include/seccomp.h
+++ b/frida_mode/include/seccomp.h
@@ -1,15 +1,95 @@
 #ifndef _SECCOMP_H
 #define _SECCOMP_H
 
-#include <linux/seccomp.h>
+#ifndef __APPLE__
 
-#include "frida-gumjs.h"
+  #include <stdint.h>
+  #include <linux/filter.h>
 
-#define SECCOMP_SOCKET_SEND_FD 0x1D3
-#define SECCOMP_SOCKET_RECV_FD 0x1D4
+  #include "frida-gumjs.h"
 
-#define SECCOMP_OUTPUT_FILE_FD 0x1D5
-#define SECCOMP_PARENT_EVENT_FD 0x1D6
+  /******************************************************************************/
+  #define PR_SET_NO_NEW_PRIVS 38
+
+  #define SECCOMP_SET_MODE_STRICT 0
+  #define SECCOMP_SET_MODE_FILTER 1
+  #define SECCOMP_GET_ACTION_AVAIL 2
+  #define SECCOMP_GET_NOTIF_SIZES 3
+
+  #define SECCOMP_IOC_MAGIC '!'
+  #define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr)
+  #define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type)
+  #define SECCOMP_IOW(nr, type) _IOW(SECCOMP_IOC_MAGIC, nr, type)
+  #define SECCOMP_IOWR(nr, type) _IOWR(SECCOMP_IOC_MAGIC, nr, type)
+
+  /* Flags for seccomp notification fd ioctl. */
+  #define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif)
+  #define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, struct seccomp_notif_resp)
+  #define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOW(2, __u64)
+
+  #define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3)
+  #define SECCOMP_RET_ALLOW 0x7fff0000U
+  #define SECCOMP_RET_USER_NOTIF 0x7fc00000U
+
+  #define SYS_seccomp __NR_seccomp
+  #ifndef __NR_seccomp
+    #if defined(__arm__)
+      #define __NR_seccomp 383
+    #elif defined(__aarch64__)
+      #define __NR_seccomp 277
+    #elif defined(__x86_64__)
+      #define __NR_seccomp 317
+    #elif defined(__i386__)
+      #define __NR_seccomp 354
+    #else
+      #pragma error "Unsupported architecture"
+    #endif
+  #endif
+
+  #define SECCOMP_USER_NOTIF_FLAG_CONTINUE (1UL << 0)
+
+struct seccomp_notif_resp {
+
+  __u64 id;
+  __s64 val;
+  __s32 error;
+  __u32 flags;
+
+};
+
+struct seccomp_data {
+
+  int   nr;
+  __u32 arch;
+  __u64 instruction_pointer;
+  __u64 args[6];
+
+};
+
+struct seccomp_notif {
+
+  __u64               id;
+  __u32               pid;
+  __u32               flags;
+  struct seccomp_data data;
+
+};
+
+struct seccomp_notif_sizes {
+
+  __u16 seccomp_notif;
+  __u16 seccomp_notif_resp;
+  __u16 seccomp_data;
+
+};
+
+  /******************************************************************************/
+
+  #define SECCOMP_SOCKET_SEND_FD 0x1D3
+  #define SECCOMP_SOCKET_RECV_FD 0x1D4
+
+  #define SECCOMP_OUTPUT_FILE_FD 0x1D5
+  #define SECCOMP_PARENT_EVENT_FD 0x1D6
 
 enum {
 
@@ -319,23 +399,19 @@ enum {
 
 };
 
-extern char *seccomp_filename;
-
 typedef void (*seccomp_child_func_t)(int event_fd, void *ctx);
 
 typedef void (*seccomp_filter_callback_t)(struct seccomp_notif *     req,
                                           struct seccomp_notif_resp *resp,
                                           GumReturnAddressArray *    frames);
 
-void seccomp_config(void);
-void seccomp_init(void);
-void seccomp_on_fork(void);
-void seccomp_print(char *format, ...);
-
 void seccomp_atomic_set(volatile bool *ptr, bool val);
 bool seccomp_atomic_try_set(volatile bool *ptr, bool val);
 void seccomp_atomic_wait(volatile bool *ptr, bool val);
 
+void seccomp_callback_parent(void);
+void seccomp_callback_initialize(void);
+
 void seccomp_child_run(seccomp_child_func_t child_func, void *ctx, pid_t *child,
                        int *event_fd);
 void seccomp_child_wait(int event_fd);
@@ -349,6 +425,8 @@ int  seccomp_filter_install(pid_t child);
 void seccomp_filter_child_install(void);
 void seccomp_filter_run(int fd, seccomp_filter_callback_t callback);
 
+void seccomp_print(char *format, ...);
+
 void seccomp_socket_create(int *sock);
 void seccomp_socket_send(int sockfd, int fd);
 int  seccomp_socket_recv(int sockfd);
@@ -356,4 +434,11 @@ int  seccomp_socket_recv(int sockfd);
 char *seccomp_syscall_lookup(int id);
 
 #endif
+extern char *seccomp_filename;
+
+void seccomp_config(void);
+void seccomp_init(void);
+void seccomp_on_fork(void);
+
+#endif
 
diff --git a/frida_mode/many-linux/Dockerfile b/frida_mode/many-linux/Dockerfile
index 170f0757..6d077dad 100644
--- a/frida_mode/many-linux/Dockerfile
+++ b/frida_mode/many-linux/Dockerfile
@@ -1,10 +1,6 @@
 FROM fridadotre/manylinux-x86_64
 
-COPY realpath /bin/realpath
-RUN chmod +x /bin/realpath
-
 RUN yum -y install xz
-RUN yum -y install vim-common
 
 WORKDIR /AFLplusplus
 ENV CFLAGS="\
diff --git a/frida_mode/many-linux/GNUmakefile b/frida_mode/many-linux/GNUmakefile
index 03b619f6..9992d4fe 100644
--- a/frida_mode/many-linux/GNUmakefile
+++ b/frida_mode/many-linux/GNUmakefile
@@ -2,17 +2,22 @@ PWD:=$(shell pwd)/
 ROOT:=$(PWD)../../
 BUILD_DIR:=$(PWD)build/
 
-.PHONY: all clean shell
+.PHONY: all build docker clean shell
 
-all:
-	docker build --tag many-afl-frida .
+all: docker
 	docker run --rm \
 		-v $(ROOT):/AFLplusplus \
 		many-afl-frida \
 		make -C /AFLplusplus/frida_mode clean all
 
-$(BUILD_DIR):
-	mkdir -p $@
+build:
+	docker run --rm \
+		-v $(ROOT):/AFLplusplus \
+		many-afl-frida \
+		make -C /AFLplusplus/frida_mode
+
+docker:
+	docker build --tag many-afl-frida .
 
 clean:
 	docker images --filter 'dangling=true' -q --no-trunc | xargs -L1 docker rmi --force
diff --git a/frida_mode/many-linux/realpath b/frida_mode/many-linux/realpath
deleted file mode 100755
index 1fdc49a7..00000000
--- a/frida_mode/many-linux/realpath
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-readlink -f -- "$@"
diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c
index 186ddd3a..c51e202f 100644
--- a/frida_mode/src/entry.c
+++ b/frida_mode/src/entry.c
@@ -1,5 +1,9 @@
 #include <dlfcn.h>
 
+#if defined(__linux__) && !defined(__ANDROID__)
+  #include <sys/prctl.h>
+#endif
+
 #include "frida-gumjs.h"
 
 #include "debug.h"
@@ -16,6 +20,7 @@
 extern void __afl_manual_init();
 
 guint64  entry_point = 0;
+gboolean traceable = FALSE;
 gboolean entry_compiled = FALSE;
 gboolean entry_run = FALSE;
 
@@ -26,21 +31,48 @@ static void entry_launch(void) {
 
   /* Child here */
   entry_run = TRUE;
+  entry_on_fork();
   instrument_on_fork();
   seccomp_on_fork();
   stats_on_fork();
 
 }
 
+#if defined(__linux__) && !defined(__ANDROID__)
+void entry_on_fork(void) {
+
+  if (traceable) {
+
+    if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) < 0) {
+
+      FATAL("Failed to PR_SET_PTRACER");
+
+    }
+
+  }
+
+}
+
+#else
+void entry_on_fork(void) {
+
+  if (traceable) { WARNF("AFL_FRIDA_TRACEABLE unsupported"); }
+
+}
+
+#endif
+
 void entry_config(void) {
 
   entry_point = util_read_address("AFL_ENTRYPOINT");
+  if (getenv("AFL_FRIDA_TRACEABLE") != NULL) { traceable = TRUE; }
 
 }
 
 void entry_init(void) {
 
   OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point);
+  OKF("dumpable: [%c]", traceable ? 'X' : ' ');
 
   if (dlopen(NULL, RTLD_NOW) == NULL) { FATAL("Failed to dlopen: %d", errno); }
 
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c
index fd0982f8..81d85aa1 100644
--- a/frida_mode/src/instrument/instrument.c
+++ b/frida_mode/src/instrument/instrument.c
@@ -341,8 +341,14 @@ void instrument_init(void) {
      * parallel fuzzing. The seed itself, doesn't have to be random, it
      * just needs to be different for each instance.
      */
+    guint64 tid;
+#if defined(__APPLE__)
+    pthread_threadid_np(NULL, &tid);
+#else
+    tid = syscall(SYS_gettid);
+#endif
     instrument_hash_seed = g_get_monotonic_time() ^
-                           (((guint64)getpid()) << 32) ^ syscall(SYS_gettid);
+                           (((guint64)getpid()) << 32) ^ tid;
 
   }
 
@@ -350,6 +356,7 @@ void instrument_init(void) {
       instrument_hash_seed);
   instrument_hash_zero = instrument_get_offset_hash(0);
 
+  instrument_coverage_optimize_init();
   instrument_debug_init();
   instrument_coverage_init();
   asan_init();
diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c
index 0e15940a..4b0a648e 100644
--- a/frida_mode/src/instrument/instrument_arm32.c
+++ b/frida_mode/src/instrument/instrument_arm32.c
@@ -22,6 +22,10 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
 }
 
+void instrument_coverage_optimize_init(void) {
+  WARNF("Optimized coverage not supported on this architecture");
+}
+
 void instrument_flush(GumStalkerOutput *output) {
 
   gum_arm_writer_flush(output->writer.arm);
diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c
index cf37e048..80d1d845 100644
--- a/frida_mode/src/instrument/instrument_arm64.c
+++ b/frida_mode/src/instrument/instrument_arm64.c
@@ -95,6 +95,9 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
 }
 
+void instrument_coverage_optimize_init(void) {
+}
+
 void instrument_flush(GumStalkerOutput *output) {
 
   gum_arm64_writer_flush(output->writer.arm64);
diff --git a/frida_mode/src/instrument/instrument_coverage.c b/frida_mode/src/instrument/instrument_coverage.c
index 46c816bc..513df29a 100644
--- a/frida_mode/src/instrument/instrument_coverage.c
+++ b/frida_mode/src/instrument/instrument_coverage.c
@@ -711,7 +711,6 @@ void instrument_coverage_normal_init(void) {
 
 void instrument_coverage_unstable_find_output(void) {
 
-  pid_t  parent = getpid();
   gchar *fds_name = g_strdup_printf("/proc/%d/fd/", getppid());
 
   gchar *root = g_file_read_link("/proc/self/root", NULL);
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
index fec8afbb..a7eb650a 100644
--- a/frida_mode/src/instrument/instrument_x64.c
+++ b/frida_mode/src/instrument/instrument_x64.c
@@ -1,105 +1,307 @@
+#include <fcntl.h>
+#include <stddef.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+
+#if defined(__linux__)
+#if !defined(__ANDROID__)
+#include <asm/prctl.h>
+#include <sys/syscall.h>
+#else
+#include <linux/ashmem.h>
+#endif
+#endif
+
 #include "frida-gumjs.h"
 
 #include "config.h"
+#include "debug.h"
 
 #include "instrument.h"
+#include "ranges.h"
 
 #if defined(__x86_64__)
 
-static GumAddress current_log_impl = GUM_ADDRESS(0);
+#ifndef MAP_FIXED_NOREPLACE
+  #ifdef MAP_EXCL
+    #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
+  #else
+    #define MAP_FIXED_NOREPLACE MAP_FIXED
+  #endif
+#endif
 
-static const guint8 afl_log_code[] = {
+gboolean instrument_is_coverage_optimize_supported(void) {
 
-    0x9c,                                                         /* pushfq */
-    0x51,                                                       /* push rcx */
-    0x52,                                                       /* push rdx */
+  return true;
 
-    0x48, 0x8b, 0x0d, 0x26,
-    0x00, 0x00, 0x00,                          /* mov rcx, sym.&previous_pc */
-    0x48, 0x8b, 0x11,                               /* mov rdx, qword [rcx] */
-    0x48, 0x31, 0xfa,                                       /* xor rdx, rdi */
+}
 
-    0x48, 0x03, 0x15, 0x11,
-    0x00, 0x00, 0x00,                     /* add rdx, sym._afl_area_ptr_ptr */
+static gboolean instrument_coverage_in_range(gssize offset) {
 
-    0x80, 0x02, 0x01,                              /* add byte ptr [rdx], 1 */
-    0x80, 0x12, 0x00,                              /* adc byte ptr [rdx], 0 */
-    0x66, 0xd1, 0xcf,                                          /* ror di, 1 */
-    0x48, 0x89, 0x39,                               /* mov qword [rcx], rdi */
+  return (offset >= G_MININT32 && offset <= G_MAXINT32);
 
-    0x5a,                                                        /* pop rdx */
-    0x59,                                                        /* pop rcx */
-    0x9d,                                                          /* popfq */
+}
 
-    0xc3,                                                            /* ret */
+  #pragma pack(push, 1)
+typedef struct {
 
-    0x90
+  // cur_location = (block_address >> 4) ^ (block_address << 8);
+  // shared_mem[cur_location ^ prev_location]++;
+  // prev_location = cur_location >> 1;
 
-    /* Read-only data goes here: */
-    /* uint8_t* __afl_area_ptr */
-    /* uint64_t* &previous_pc */
+  // => 0x7ffff6cfb086:      lea    rsp,[rsp-0x80]
+  //    0x7ffff6cfb08b:      pushf
+  //    0x7ffff6cfb08c:      push   rsi
+  //    0x7ffff6cfb08d:      mov    rsi,0x228
+  //    0x7ffff6cfb094:      xchg   QWORD PTR [rip+0x3136a5],rsi        # 0x7ffff700e740
+  //    0x7ffff6cfb09b:      xor    rsi,0x451
+  //    0x7ffff6cfb0a2:      add    BYTE PTR [rsi+0x10000],0x1
+  //    0x7ffff6cfb0a9:      adc    BYTE PTR [rsi+0x10000],0x0
+  //    0x7ffff6cfb0b0:      pop    rsi
+  //    0x7ffff6cfb0b1:      popf
+  //    0x7ffff6cfb0b2:      lea    rsp,[rsp+0x80]
 
-};
 
-gboolean instrument_is_coverage_optimize_supported(void) {
+  uint8_t lea_rsp_rsp_sub_rz[5];
+  uint8_t push_fq;
+  uint8_t push_rsi;
 
-  return true;
+  uint8_t mov_rsi_curr_loc_shr_1[7];
+  uint8_t xchg_rsi_prev_loc_curr_loc[7];
+  uint8_t xor_rsi_curr_loc[7];
+
+  uint8_t add_rsi_1[7];
+  uint8_t adc_rsi_0[7];
+
+  uint8_t pop_rsi;
+  uint8_t pop_fq;
+  uint8_t lsa_rsp_rsp_add_rz[8];
+
+} afl_log_code_asm_t;
+
+  #pragma pack(pop)
+
+typedef union {
+
+  afl_log_code_asm_t code;
+  uint8_t            bytes[0];
+
+} afl_log_code;
+
+static const afl_log_code_asm_t template =
+    {
+
+        .lea_rsp_rsp_sub_rz = {0x48, 0x8D, 0x64, 0x24, 0x80},
+        .push_fq = 0x9c,
+        .push_rsi = 0x56,
+
+        .mov_rsi_curr_loc_shr_1 = {0x48, 0xC7, 0xC6},
+        .xchg_rsi_prev_loc_curr_loc = {0x48, 0x87, 0x35},
+        .xor_rsi_curr_loc = {0x48, 0x81, 0xF6},
+
+        .add_rsi_1 = {0x80, 0x86, 0x00, 0x00, 0x00, 0x00, 0x01},
+        .adc_rsi_0 = {0x80, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+        .pop_rsi = 0x5E,
+        .pop_fq = 0x9D,
+        .lsa_rsp_rsp_add_rz = {0x48, 0x8D, 0xA4, 0x24, 0x80, 0x00, 0x00, 0x00},
 
 }
 
-static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+;
 
-static void instrument_coverate_write_function(GumStalkerOutput *output) {
+static gboolean instrument_coverage_find_low(const GumRangeDetails *details,
+                                             gpointer               user_data) {
 
-  guint64       misalign = 0;
-  GumX86Writer *cw = output->writer.x86;
+  static GumAddress last_limit = (64ULL << 10);
+  gpointer *        address = (gpointer *)user_data;
 
-  if (current_log_impl == 0 ||
-      !gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) ||
-      !gum_x86_writer_can_branch_directly_between(cw->pc + 128,
-                                                  current_log_impl)) {
+  if ((details->range->base_address - last_limit) > __afl_map_size) {
 
-    gconstpointer after_log_impl = cw->code + 1;
+    *address = GSIZE_TO_POINTER(last_limit);
+    return FALSE;
 
-    gum_x86_writer_put_jmp_near_label(cw, after_log_impl);
+  }
 
-    misalign = (cw->pc & 0x7);
-    if (misalign != 0) {
+  if (details->range->base_address > ((2ULL << 20) - __afl_map_size)) {
 
-      gum_x86_writer_put_bytes(cw, align_pad, 8 - misalign);
+    return FALSE;
 
-    }
+  }
+
+  last_limit = details->range->base_address + details->range->size;
+  return TRUE;
+
+}
+
+static void instrument_coverage_optimize_map_mmap_anon(gpointer address) {
+
+  __afl_area_ptr =
+      mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
+           MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+  if (__afl_area_ptr != address) {
+
+    FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
+
+  }
+
+}
+
+static void instrument_coverage_optimize_map_mmap(char *   shm_file_path,
+                                                  gpointer address) {
+
+  int shm_fd = -1;
+
+  if (munmap(__afl_area_ptr, __afl_map_size) != 0) {
+
+    FATAL("Failed to unmap previous __afl_area_ptr");
+
+  }
+
+  __afl_area_ptr = NULL;
+
+#if !defined(__ANDROID__)
+  shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION);
+  if (shm_fd == -1) { FATAL("shm_open() failed\n"); }
+#else
+  shm_fd = open("/dev/ashmem", O_RDWR);
+  if (shm_fd == -1) { FATAL("open() failed\n"); }
+  if (ioctl(shm_fd, ASHMEM_SET_NAME, shm_file_path) == -1) { FATAL("ioctl(ASHMEM_SET_NAME) failed"); }
+  if (ioctl(shm_fd, ASHMEM_SET_SIZE, __afl_map_size) == -1) { FATAL("ioctl(ASHMEM_SET_SIZE) failed"); }
+
+#endif
+
+  __afl_area_ptr = mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
+                        MAP_FIXED_NOREPLACE | MAP_SHARED, shm_fd, 0);
+  if (__afl_area_ptr != address) {
+
+    FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
+
+  }
+
+  if (close(shm_fd) != 0) { FATAL("Failed to close shm_fd"); }
+
+}
 
-    current_log_impl = cw->pc;
-    gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
+static void instrument_coverage_optimize_map_shm(guint64  shm_env_val,
+                                                 gpointer address) {
 
-    uint64_t *afl_prev_loc_ptr = &instrument_previous_pc;
-    gum_x86_writer_put_bytes(cw, (const guint8 *)&__afl_area_ptr,
-                             sizeof(__afl_area_ptr));
-    gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
-                             sizeof(afl_prev_loc_ptr));
+  if (shmdt(__afl_area_ptr) != 0) {
 
-    gum_x86_writer_put_label(cw, after_log_impl);
+    FATAL("Failed to detach previous __afl_area_ptr");
+
+  }
+
+  __afl_area_ptr = shmat(shm_env_val, address, 0);
+  if (__afl_area_ptr != address) {
+
+    FATAL("Failed to map shm __afl_area_ptr: %d", errno);
 
   }
 
 }
 
+void instrument_coverage_optimize_init(void) {
+
+  gpointer low_address = NULL;
+
+  gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, instrument_coverage_find_low,
+                               &low_address);
+
+  OKF("Low address: %p", low_address);
+
+  if (low_address == 0 ||
+      GPOINTER_TO_SIZE(low_address) > ((2UL << 20) - __afl_map_size)) {
+
+    FATAL("Invalid low_address: %p", low_address);
+
+  }
+
+  ranges_print_debug_maps();
+
+  char *shm_env = getenv(SHM_ENV_VAR);
+  OKF("SHM_ENV_VAR: %s", shm_env);
+
+  if (shm_env == NULL) {
+
+    WARNF("SHM_ENV_VAR not set, using anonymous map for debugging purposes");
+
+    instrument_coverage_optimize_map_mmap_anon(low_address);
+
+  } else {
+
+    guint64 shm_env_val = g_ascii_strtoull(shm_env, NULL, 10);
+
+    if (shm_env_val == 0) {
+
+      instrument_coverage_optimize_map_mmap(shm_env, low_address);
+
+    } else {
+
+      instrument_coverage_optimize_map_shm(shm_env_val, low_address);
+
+    }
+
+  }
+
+  OKF("__afl_area_ptr: %p", __afl_area_ptr);
+  OKF("instrument_previous_pc: %p", &instrument_previous_pc);
+
+}
+
 void instrument_coverage_optimize(const cs_insn *   instr,
                                   GumStalkerOutput *output) {
 
+  afl_log_code  code = {0};
   GumX86Writer *cw = output->writer.x86;
   guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
-  instrument_coverate_write_function(output);
-
-  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
-                                        -GUM_RED_ZONE_SIZE);
-  gum_x86_writer_put_push_reg(cw, GUM_REG_RDI);
-  gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDI, area_offset);
-  gum_x86_writer_put_call_address(cw, current_log_impl);
-  gum_x86_writer_put_pop_reg(cw, GUM_REG_RDI);
-  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
-                                        GUM_RED_ZONE_SIZE);
+  GumAddress code_addr = 0;
+
+  // gum_x86_writer_put_breakpoint(cw);
+  code_addr = cw->pc;
+  code.code = template;
+
+  gssize curr_loc_shr_1_offset =
+      offsetof(afl_log_code, code.mov_rsi_curr_loc_shr_1) +
+      sizeof(code.code.mov_rsi_curr_loc_shr_1) - sizeof(guint32);
+
+  *((guint32 *)&code.bytes[curr_loc_shr_1_offset]) =
+      (guint32)(area_offset >> 1);
+
+  gssize prev_loc_value =
+      GPOINTER_TO_SIZE(&instrument_previous_pc) -
+      (code_addr + offsetof(afl_log_code, code.xchg_rsi_prev_loc_curr_loc) +
+       sizeof(code.code.xchg_rsi_prev_loc_curr_loc));
+  gssize prev_loc_value_offset =
+      offsetof(afl_log_code, code.xchg_rsi_prev_loc_curr_loc) +
+      sizeof(code.code.xchg_rsi_prev_loc_curr_loc) - sizeof(gint);
+  if (!instrument_coverage_in_range(prev_loc_value)) {
+
+    FATAL("Patch out of range (current_pc_value1): 0x%016lX", prev_loc_value);
+
+  }
+
+  *((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value;
+
+  gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_rsi_curr_loc) +
+                               sizeof(code.code.xor_rsi_curr_loc) -
+                               sizeof(guint32);
+
+  *((guint32 *)&code.bytes[xor_curr_loc_offset]) = (guint32)(area_offset);
+
+  gssize add_rsi_1_offset = offsetof(afl_log_code, code.add_rsi_1) +
+                            sizeof(code.code.add_rsi_1) - sizeof(guint32) - 1;
+
+  *((guint32 *)&code.bytes[add_rsi_1_offset]) =
+      (guint32)GPOINTER_TO_SIZE(__afl_area_ptr);
+
+  gssize adc_rsi_0_ffset = offsetof(afl_log_code, code.adc_rsi_0) +
+                           sizeof(code.code.adc_rsi_0) - sizeof(guint32) - 1;
+
+  *((guint32 *)&code.bytes[adc_rsi_0_ffset]) =
+      (guint32)GPOINTER_TO_SIZE(__afl_area_ptr);
+
+  gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
 
 }
 
diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c
index 7bf48f96..1ff5c920 100644
--- a/frida_mode/src/instrument/instrument_x86.c
+++ b/frida_mode/src/instrument/instrument_x86.c
@@ -83,6 +83,9 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
 }
 
+void instrument_coverage_optimize_init(void) {
+}
+
 void instrument_flush(GumStalkerOutput *output) {
 
   gum_x86_writer_flush(output->writer.x86);
diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js
index 40bb4a16..6f9f05d8 100644
--- a/frida_mode/src/js/api.js
+++ b/frida_mode/src/js/api.js
@@ -243,6 +243,12 @@ class Afl {
         const buf = Memory.allocUtf8String(file);
         Afl.jsApiSetStdOut(buf);
     }
+    /**
+     * See `AFL_FRIDA_TRACEABLE`.
+     */
+    static setTraceable() {
+        Afl.jsApiSetTraceable();
+    }
     static jsApiGetFunction(name, retType, argTypes) {
         const addr = Afl.module.getExportByName(name);
         return new NativeFunction(addr, retType, argTypes);
@@ -286,6 +292,7 @@ Afl.jsApiSetStatsFile = Afl.jsApiGetFunction("js_api_set_stats_file", "void", ["
 Afl.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "void", ["uint64"]);
 Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]);
 Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "void", ["pointer"]);
+Afl.jsApiSetTraceable = Afl.jsApiGetFunction("js_api_set_traceable", "void", []);
 Afl.jsApiWrite = new NativeFunction(
 /* tslint:disable-next-line:no-null-keyword */
 Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c
index 9dba79aa..f3d81a32 100644
--- a/frida_mode/src/js/js_api.c
+++ b/frida_mode/src/js/js_api.c
@@ -231,3 +231,9 @@ __attribute__((visibility("default"))) void js_api_set_stalker_ic_entries(
 
 }
 
+__attribute__((visibility("default"))) void js_api_set_traceable(void) {
+
+  traceable = TRUE;
+
+}
+
diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c
index c0de9c6b..c8183d8f 100644
--- a/frida_mode/src/main.c
+++ b/frida_mode/src/main.c
@@ -6,6 +6,7 @@
 #ifdef __APPLE__
   #include <mach/mach.h>
   #include <mach-o/dyld_images.h>
+  #include <crt_externs.h>
 #else
   #include <sys/wait.h>
   #include <sys/personality.h>
@@ -90,6 +91,7 @@ static void embedded_init(void) {
 
 static void afl_print_cmdline(void) {
 
+#if defined(__linux__)
   char * buffer = g_malloc0(PROC_MAX);
   gchar *fname = g_strdup_printf("/proc/%d/cmdline", getppid());
   int    fd = open(fname, O_RDONLY);
@@ -123,6 +125,17 @@ static void afl_print_cmdline(void) {
   close(fd);
   g_free(fname);
   g_free(buffer);
+#elif defined(__APPLE__)
+  int idx;
+  char **argv = *_NSGetArgv();
+  int nargv = *_NSGetArgc();
+
+  for (idx = 0; idx < nargv; idx ++) {
+
+    OKF("AFL - COMMANDLINE: argv[%d] = %s", idx, argv[idx]);
+
+  }
+#endif
 
 }
 
diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c
index 0efbc9bf..c30ca65c 100644
--- a/frida_mode/src/prefetch.c
+++ b/frida_mode/src/prefetch.c
@@ -44,8 +44,9 @@ static void gum_afl_stalker_backpatcher_notify(GumStalkerObserver *self,
       sizeof(prefetch_data->backpatch_data) - prefetch_data->backpatch_size;
   if (sizeof(gsize) + size > remaining) { return; }
 
-  *(gsize *)(&prefetch_data->backpatch_data[prefetch_data->backpatch_size]) =
-      size;
+  gsize *dst_backpatch_size = (gsize *)
+      &prefetch_data->backpatch_data[prefetch_data->backpatch_size];
+  *dst_backpatch_size = size;
   prefetch_data->backpatch_size += sizeof(gsize);
 
   memcpy(&prefetch_data->backpatch_data[prefetch_data->backpatch_size],
@@ -115,7 +116,8 @@ static void prefetch_read_patches(void) {
        remaining > sizeof(gsize);
        remaining = prefetch_data->backpatch_size - offset) {
 
-    gsize size = *(gsize *)(&prefetch_data->backpatch_data[offset]);
+    gsize *src_backpatch_data = (gsize *)&prefetch_data->backpatch_data[offset];
+    gsize size = *src_backpatch_data;
     offset += sizeof(gsize);
 
     if (prefetch_data->backpatch_size - offset < size) {
diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c
index 5b6eb462..1b666fce 100644
--- a/frida_mode/src/ranges.c
+++ b/frida_mode/src/ranges.c
@@ -549,18 +549,19 @@ static GArray *merge_ranges(GArray *a) {
 
 }
 
+void ranges_print_debug_maps(void) {
+
+  gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
+
+}
+
 void ranges_config(void) {
 
   if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; }
   if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; }
   if (getenv("AFL_FRIDA_INST_JIT") != NULL) { ranges_inst_jit = TRUE; }
 
-  if (ranges_debug_maps) {
-
-    gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback,
-                                 NULL);
-
-  }
+  if (ranges_debug_maps) { ranges_print_debug_maps(); }
 
   include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES");
   exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES");
diff --git a/frida_mode/src/seccomp/seccomp.c b/frida_mode/src/seccomp/seccomp.c
index 7683cd71..99111591 100644
--- a/frida_mode/src/seccomp/seccomp.c
+++ b/frida_mode/src/seccomp/seccomp.c
@@ -1,9 +1,3 @@
-#include <execinfo.h>
-#include <fcntl.h>
-#include <linux/seccomp.h>
-#include <stdio.h>
-#include <unistd.h>
-
 #include "frida-gumjs.h"
 
 #include "debug.h"
@@ -13,111 +7,15 @@
 
 char *seccomp_filename = NULL;
 
-static void seccomp_vprint(int fd, char *format, va_list ap) {
-
-  char buffer[4096] = {0};
-  int  len;
-
-  if (vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; }
-
-  len = strnlen(buffer, sizeof(buffer));
-  IGNORED_RETURN(write(fd, buffer, len));
-
-}
-
-void seccomp_print(char *format, ...) {
-
-  va_list ap;
-  va_start(ap, format);
-  seccomp_vprint(SECCOMP_OUTPUT_FILE_FD, format, ap);
-  va_end(ap);
-
-}
-
-static void seccomp_filter_callback(struct seccomp_notif *     req,
-                                    struct seccomp_notif_resp *resp,
-                                    GumReturnAddressArray *    frames) {
-
-  GumDebugSymbolDetails details = {0};
-  if (req->data.nr == SYS_OPENAT) {
-
-    seccomp_print("SYS_OPENAT: (%s)\n", (char *)req->data.args[1]);
-
-  }
-
-  seccomp_print(
-      "\nID (%#llx) for PID %d - %d (%s) [0x%llx 0x%llx 0x%llx 0x%llx 0x%llx "
-      "0x%llx ]\n",
-      req->id, req->pid, req->data.nr, seccomp_syscall_lookup(req->data.nr),
-      req->data.args[0], req->data.args[1], req->data.args[2],
-      req->data.args[3], req->data.args[4], req->data.args[5]);
-
-  seccomp_print("FRAMES: (%u)\n", frames->len);
-  char **syms = backtrace_symbols(frames->items, frames->len);
-  if (syms == NULL) { FATAL("Failed to get symbols"); }
-
-  for (guint i = 0; i < frames->len; i++) {
-
-    if (gum_symbol_details_from_address(frames->items[i], &details)) {
-
-      seccomp_print("\t%3d. %s!%s\n", i, details.module_name,
-                    details.symbol_name);
-
-    } else {
-
-      seccomp_print("\t%3d. %s\n", i, syms[i]);
-
-    }
-
-  }
-
-  free(syms);
-
-  resp->error = 0;
-  resp->val = 0;
-  resp->id = req->id;
-  resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
-
-}
-
-static void seccomp_child(int signal_parent, void *ctx) {
-
-  int sock_fd = *((int *)ctx);
-  int fd = seccomp_socket_recv(sock_fd);
-
-  if (close(sock_fd) < 0) { FATAL("child - close"); }
-
-  seccomp_event_signal(signal_parent);
-  seccomp_filter_child_install();
-  seccomp_filter_run(fd, seccomp_filter_callback);
-
-}
-
 void seccomp_on_fork(void) {
 
-  int   sock[2] = {-1, -1};
-  pid_t child = -1;
-  int   child_fd = -1;
-
   if (seccomp_filename == NULL) { return; }
 
-  seccomp_socket_create(sock);
-  seccomp_child_run(seccomp_child, sock, &child, &child_fd);
-
-  if (dup2(child_fd, SECCOMP_PARENT_EVENT_FD) < 0) { FATAL("dup2"); }
-
-  if (close(child_fd) < 0) { FATAL("seccomp_on_fork - close (1)"); }
-
-  if (close(sock[STDIN_FILENO]) < 0) { FATAL("grandparent - close (2)"); }
-
-  int fd = seccomp_filter_install(child);
-  seccomp_socket_send(sock[STDOUT_FILENO], fd);
-
-  if (close(sock[STDOUT_FILENO]) < 0) { FATAL("grandparent - close (3)"); }
-
-  if (close(fd) < 0) { FATAL("grandparent - close (4)"); }
-
-  seccomp_child_wait(SECCOMP_PARENT_EVENT_FD);
+#ifdef __APPLE__
+  FATAL("Seccomp not supported on OSX");
+#else
+  seccomp_callback_parent();
+#endif
 
 }
 
@@ -129,29 +27,15 @@ void seccomp_config(void) {
 
 void seccomp_init(void) {
 
-  char *path = NULL;
-  int   fd;
-
   OKF("Seccomp - file [%s]", seccomp_filename);
 
   if (seccomp_filename == NULL) { return; }
 
-  path = g_canonicalize_filename(seccomp_filename, g_get_current_dir());
-
-  OKF("Seccomp - path [%s]", path);
-
-  fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
-            S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
-
-  if (dup2(fd, SECCOMP_OUTPUT_FILE_FD) < 0) {
-
-    FATAL("Failed to duplicate seccomp output file");
-
-  }
-
-  if (close(fd) < 0) { FATAL("Failed to close seccomp output file fd"); }
-
-  g_free(path);
+#ifdef __APPLE__
+  FATAL("Seccomp not supported on OSX");
+#else
+  seccomp_callback_initialize();
+#endif
 
 }
 
diff --git a/frida_mode/src/seccomp/seccomp_atomic.c b/frida_mode/src/seccomp/seccomp_atomic.c
index 1720a726..c2042f97 100644
--- a/frida_mode/src/seccomp/seccomp_atomic.c
+++ b/frida_mode/src/seccomp/seccomp_atomic.c
@@ -1,7 +1,9 @@
-#include <stdbool.h>
-#include <stdio.h>
+#if defined(__linux__) && !defined(__ANDROID__)
 
-#include "debug.h"
+  #include <stdbool.h>
+  #include <stdio.h>
+
+  #include "debug.h"
 
 void seccomp_atomic_set(volatile bool *ptr, bool val) {
 
@@ -26,3 +28,5 @@ void seccomp_atomic_wait(volatile bool *ptr, bool val) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_callback.c b/frida_mode/src/seccomp/seccomp_callback.c
new file mode 100644
index 00000000..4232d842
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_callback.c
@@ -0,0 +1,144 @@
+#if defined(__linux__) && !defined(__ANDROID__)
+
+#if !defined(__MUSL__)
+  #include <execinfo.h>
+#endif
+  #include <fcntl.h>
+
+  #include "seccomp.h"
+
+  #include "debug.h"
+
+static void seccomp_callback_filter(struct seccomp_notif *     req,
+                                    struct seccomp_notif_resp *resp,
+                                    GumReturnAddressArray *    frames) {
+
+  GumDebugSymbolDetails details = {0};
+  if (req->data.nr == SYS_OPENAT) {
+
+#if UINTPTR_MAX == 0xffffffffffffffffu
+    seccomp_print("SYS_OPENAT: (%s)\n", (char *)req->data.args[1]);
+#endif
+#if UINTPTR_MAX == 0xffffffff
+    seccomp_print("SYS_OPENAT: (%s)\n", (char *)(__u32)req->data.args[1]);
+#endif
+  }
+
+  seccomp_print(
+      "\nID (%#llx) for PID %d - %d (%s) [0x%llx 0x%llx 0x%llx 0x%llx 0x%llx "
+      "0x%llx ]\n",
+      req->id, req->pid, req->data.nr, seccomp_syscall_lookup(req->data.nr),
+      req->data.args[0], req->data.args[1], req->data.args[2],
+      req->data.args[3], req->data.args[4], req->data.args[5]);
+
+#if !defined(__MUSL__)
+  seccomp_print("FRAMES: (%u)\n", frames->len);
+  char **syms = backtrace_symbols(frames->items, frames->len);
+  if (syms == NULL) { FATAL("Failed to get symbols"); }
+
+  for (guint i = 0; i < frames->len; i++) {
+
+    if (gum_symbol_details_from_address(frames->items[i], &details)) {
+
+      seccomp_print("\t%3d. %s!%s\n", i, details.module_name,
+                    details.symbol_name);
+
+    } else {
+
+      seccomp_print("\t%3d. %s\n", i, syms[i]);
+
+    }
+
+  }
+
+  free(syms);
+#else
+  void **syms = (void **)__builtin_frame_address(0);
+  void *framep = __builtin_frame_address(1);
+  int i = 0;
+
+  syms = framep;
+  while (syms) {
+   
+    framep = *syms;   
+    syms = framep;
+
+    if (!syms) break;
+
+    seccomp_print("\%3d. %s\n", i ++, (char *)framep);
+
+  }
+#endif
+
+  resp->error = 0;
+  resp->val = 0;
+  resp->id = req->id;
+  resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
+
+}
+
+static void seccomp_callback_child(int signal_parent, void *ctx) {
+
+  int sock_fd = *((int *)ctx);
+  int fd = seccomp_socket_recv(sock_fd);
+
+  if (close(sock_fd) < 0) { FATAL("child - close"); }
+
+  seccomp_event_signal(signal_parent);
+  seccomp_filter_child_install();
+  seccomp_filter_run(fd, seccomp_callback_filter);
+
+}
+
+void seccomp_callback_parent(void) {
+
+  int   sock[2] = {-1, -1};
+  pid_t child = -1;
+  int   child_fd = -1;
+
+  seccomp_socket_create(sock);
+  seccomp_child_run(seccomp_callback_child, sock, &child, &child_fd);
+
+  if (dup2(child_fd, SECCOMP_PARENT_EVENT_FD) < 0) { FATAL("dup2"); }
+
+  if (close(child_fd) < 0) { FATAL("seccomp_on_fork - close (1)"); }
+
+  if (close(sock[STDIN_FILENO]) < 0) { FATAL("grandparent - close (2)"); }
+
+  int fd = seccomp_filter_install(child);
+  seccomp_socket_send(sock[STDOUT_FILENO], fd);
+
+  if (close(sock[STDOUT_FILENO]) < 0) { FATAL("grandparent - close (3)"); }
+
+  if (close(fd) < 0) { FATAL("grandparent - close (4)"); }
+
+  seccomp_child_wait(SECCOMP_PARENT_EVENT_FD);
+
+}
+
+void seccomp_callback_initialize(void) {
+
+  char *path = NULL;
+  int   fd;
+
+  path = g_canonicalize_filename(seccomp_filename, g_get_current_dir());
+
+  OKF("Seccomp - path [%s]", path);
+
+  fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
+            S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+
+  if (dup2(fd, SECCOMP_OUTPUT_FILE_FD) < 0) {
+
+    FATAL("Failed to duplicate seccomp output file");
+
+  }
+
+  if (close(fd) < 0) { FATAL("Failed to close seccomp output file fd"); }
+
+  g_free(path);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_child.c b/frida_mode/src/seccomp/seccomp_child.c
index 4d494137..43a79894 100644
--- a/frida_mode/src/seccomp/seccomp_child.c
+++ b/frida_mode/src/seccomp/seccomp_child.c
@@ -1,18 +1,20 @@
-#include <fcntl.h>
-#include <sched.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/prctl.h>
-#include <sys/types.h>
-#include <unistd.h>
+#if defined(__linux__) && !defined(__ANDROID__)
 
-#include "debug.h"
+  #include <fcntl.h>
+  #include <sched.h>
+  #include <signal.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <sys/mman.h>
+  #include <sys/prctl.h>
+  #include <sys/types.h>
+  #include <unistd.h>
 
-#include "seccomp.h"
+  #include "debug.h"
 
-#define SECCOMP_CHILD_STACK_SIZE (1UL << 20)
+  #include "seccomp.h"
+
+  #define SECCOMP_CHILD_STACK_SIZE (1UL << 20)
 
 typedef void (*seccomp_child_func_t)(int event_fd, void *ctx);
 
@@ -67,3 +69,5 @@ void seccomp_child_wait(int event_fd) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_event.c b/frida_mode/src/seccomp/seccomp_event.c
index ecb9be32..e2f592ca 100644
--- a/frida_mode/src/seccomp/seccomp_event.c
+++ b/frida_mode/src/seccomp/seccomp_event.c
@@ -1,15 +1,17 @@
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
+#if defined(__linux__) && !defined(__ANDROID__)
 
-#include "debug.h"
+  #include <stdint.h>
+  #include <stdio.h>
+  #include <sys/syscall.h>
+  #include <unistd.h>
 
-#include "seccomp.h"
+  #include "debug.h"
+
+  #include "seccomp.h"
 
 int seccomp_event_create(void) {
 
-  int fd = eventfd(0, 0);
+  int fd = syscall(SYS_eventfd, 0, 0);
   if (fd < 0) { FATAL("seccomp_event_create"); }
   return fd;
 
@@ -43,3 +45,5 @@ void seccomp_event_destroy(int fd) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_filter.c b/frida_mode/src/seccomp/seccomp_filter.c
index c16e7ebd..7ee5ead1 100644
--- a/frida_mode/src/seccomp/seccomp_filter.c
+++ b/frida_mode/src/seccomp/seccomp_filter.c
@@ -1,27 +1,30 @@
-#include <alloca.h>
-#include <errno.h>
-#include <execinfo.h>
-#include <linux/filter.h>
-#include <linux/seccomp.h>
-#include <sys/ioctl.h>
-#include <sys/prctl.h>
-#include <sys/syscall.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "debug.h"
-
-#include "frida-gumjs.h"
-
-#include "seccomp.h"
-#include "util.h"
-
-#define SECCOMP_FILTER_NUM_FRAMES 512
+#if defined(__linux__) && !defined(__ANDROID__)
+
+  #include <alloca.h>
+  #include <errno.h>
+#if !defined(__MUSL__)
+  #include <execinfo.h>
+#endif
+  #include <linux/filter.h>
+  #include <sys/ioctl.h>
+  #include <sys/prctl.h>
+  #include <sys/syscall.h>
+  #include <signal.h>
+  #include <stdbool.h>
+  #include <stddef.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  #include <unistd.h>
+
+  #include "debug.h"
+
+  #include "frida-gumjs.h"
+
+  #include "seccomp.h"
+  #include "util.h"
+
+  #define SECCOMP_FILTER_NUM_FRAMES 512
 
 extern void gum_linux_parse_ucontext(const ucontext_t *uc, GumCpuContext *ctx);
 
@@ -127,7 +130,10 @@ static GumBacktracer *       seccomp_filter_backtracer = NULL;
 static void seccomp_filter_child_handler(int sig, siginfo_t *info,
                                          void *ucontext) {
 
-  GumCpuContext cpu_context;
+  UNUSED_PARAMETER(sig);
+  UNUSED_PARAMETER(info);
+  UNUSED_PARAMETER(ucontext);
+
   if (seccomp_filter_backtracer == NULL) {
 
     seccomp_filter_backtracer = gum_backtracer_make_fuzzy();
@@ -150,7 +156,8 @@ static void seccomp_filter_parent_handler(int sig, siginfo_t *info,
   ucontext_t *uc = (ucontext_t *)ucontext;
   gum_linux_parse_ucontext(uc, &seccomp_filter_cpu_context);
 
-  if (tgkill(seccomp_filter_child, seccomp_filter_child, SIGUSR1) < 0) {
+  if (syscall(SYS_tgkill, seccomp_filter_child, seccomp_filter_child, SIGUSR1) <
+      0) {
 
     FATAL("kill");
 
@@ -256,3 +263,5 @@ void seccomp_filter_run(int fd, seccomp_filter_callback_t callback) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_print.c b/frida_mode/src/seccomp/seccomp_print.c
new file mode 100644
index 00000000..3cea1239
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_print.c
@@ -0,0 +1,30 @@
+#if defined(__linux__) && !defined(__ANDROID__)
+
+  #include <stdarg.h>
+
+  #include "seccomp.h"
+  #include "util.h"
+
+static void seccomp_print_v(int fd, char *format, va_list ap) {
+
+  char buffer[4096] = {0};
+  int  len;
+
+  if (vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; }
+
+  len = strnlen(buffer, sizeof(buffer));
+  IGNORED_RETURN(write(fd, buffer, len));
+
+}
+
+void seccomp_print(char *format, ...) {
+
+  va_list ap;
+  va_start(ap, format);
+  seccomp_print_v(SECCOMP_OUTPUT_FILE_FD, format, ap);
+  va_end(ap);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_socket.c b/frida_mode/src/seccomp/seccomp_socket.c
index ca42e158..ef937420 100644
--- a/frida_mode/src/seccomp/seccomp_socket.c
+++ b/frida_mode/src/seccomp/seccomp_socket.c
@@ -1,11 +1,13 @@
-#include <stdio.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <unistd.h>
+#if defined(__linux__) && !defined(__ANDROID__)
 
-#include "debug.h"
+  #include <stdio.h>
+  #include <string.h>
+  #include <sys/socket.h>
+  #include <unistd.h>
 
-#include "seccomp.h"
+  #include "debug.h"
+
+  #include "seccomp.h"
 
 union cmsg {
 
@@ -119,3 +121,5 @@ int seccomp_socket_recv(int sockfd) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_syscall.c b/frida_mode/src/seccomp/seccomp_syscall.c
index b2c084c8..8335b93c 100644
--- a/frida_mode/src/seccomp/seccomp_syscall.c
+++ b/frida_mode/src/seccomp/seccomp_syscall.c
@@ -1,9 +1,11 @@
-#include <limits.h>
-#include <stdio.h>
+#if defined(__linux__) && !defined(__ANDROID__)
 
-#include "debug.h"
+  #include <limits.h>
+  #include <stdio.h>
 
-#include "seccomp.h"
+  #include "debug.h"
+
+  #include "seccomp.h"
 
 typedef struct {
 
@@ -333,3 +335,5 @@ char *seccomp_syscall_lookup(int id) {
 
 }
 
+#endif
+
diff --git a/frida_mode/test/freetype2/GNUmakefile b/frida_mode/test/freetype2/GNUmakefile
new file mode 100644
index 00000000..891660ca
--- /dev/null
+++ b/frida_mode/test/freetype2/GNUmakefile
@@ -0,0 +1,192 @@
+PWD:=$(shell pwd)/
+ROOT:=$(PWD)../../../
+BUILD_DIR:=$(PWD)build/
+
+AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so
+AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so
+
+# git clone git://git.sv.nongnu.org/freetype/freetype2.git
+# git clone https://github.com/unicode-org/text-rendering-tests.git TRT
+# wget https://github.com/libarchive/libarchive/releases/download/v3.4.3/libarchive-3.4.3.tar.xz
+
+# cp TRT/fonts/TestKERNOne.otf $OUT/seeds/
+# cp TRT/fonts/TestGLYFOne.ttf $OUT/seeds/
+
+# $CXX $CXXFLAGS -std=c++11 -I include -I . src/tools/ftfuzzer/ftfuzzer.cc \
+#     objs/.libs/libfreetype.a $FUZZER_LIB -L /usr/local/lib -larchive \
+#     -o $OUT/ftfuzzer
+
+LIBARCHIVE_URL:=https://github.com/libarchive/libarchive/releases/download/v3.4.3/libarchive-3.4.3.tar.xz
+LIBARCHIVE_BUILD_DIR:=$(BUILD_DIR)libarchive/
+LIBARCHIVE_TARBALL:=$(LIBARCHIVE_BUILD_DIR)libarchive-3.4.3.tar.xz
+LIBARCHIVE_DIR:=$(LIBARCHIVE_BUILD_DIR)libarchive-3.4.3/
+LIBARCHIVE_LIB:=$(LIBARCHIVE_DIR).libs/libarchive.a
+
+FREETYPE2_GIT_REPO:=git://git.sv.nongnu.org/freetype/freetype2.git
+FREETYPE2_BUILD_DIR:=$(BUILD_DIR)freetype2/
+FREETYPE2_DIR:=$(FREETYPE2_BUILD_DIR)freetype2/
+FREETYPE2_LIB:=$(FREETYPE2_DIR)objs/.libs/libfreetype.a
+
+HARNESS_URL:=https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c
+HARNESS_SRC:=$(BUILD_DIR)StandaloneFuzzTargetMain.c
+HARNESS_OBJ:=$(BUILD_DIR)StandaloneFuzzTargetMain.o
+
+TRT_GIT_REPO:=https://github.com/unicode-org/text-rendering-tests.git
+TRT_DIR:=$(BUILD_DIR)TRT/
+
+FUZZER_SRC:=$(FREETYPE2_DIR)src/tools/ftfuzzer/ftfuzzer.cc
+
+
+LDFLAGS += -lpthread
+
+TEST_BIN:=$(BUILD_DIR)test
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup -Wl,-no_pie
+endif
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+TEST_DATA_FILE:=$(TEST_DATA_DIR)default_seed
+
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
+
+AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
+
+ifeq "$(ARCH)" "aarch64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
+endif
+
+.PHONY: all clean frida hook
+
+all: $(TEST_BIN)
+	make -C $(ROOT)frida_mode/
+
+32:
+	CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+	mkdir -p $@
+
+########## LIBARCHIVE #######
+
+$(LIBARCHIVE_BUILD_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+$(LIBARCHIVE_TARBALL): | $(LIBARCHIVE_BUILD_DIR)
+	wget -O $@ $(LIBARCHIVE_URL)
+
+$(LIBARCHIVE_DIR): | $(LIBARCHIVE_TARBALL)
+	tar Jxvf $(LIBARCHIVE_TARBALL) -C $(LIBARCHIVE_BUILD_DIR)
+
+$(LIBARCHIVE_DIR)Makefile: | $(LIBARCHIVE_DIR)
+	cd $(LIBARCHIVE_DIR) && ./configure --disable-shared
+
+$(LIBARCHIVE_LIB): $(LIBARCHIVE_DIR)Makefile
+	make -C $(LIBARCHIVE_DIR) clean all
+
+########## FREETYPE2 #######
+
+$(FREETYPE2_BUILD_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+$(FREETYPE2_DIR): | $(FREETYPE2_BUILD_DIR)
+	git clone $(FREETYPE2_GIT_REPO) $@
+	git -C $(FREETYPE2_DIR) checkout cd02d359a6d0455e9d16b87bf9665961c4699538
+
+$(FREETYPE2_LIB): | $(FREETYPE2_DIR)
+	cd $(FREETYPE2_DIR) && ./autogen.sh
+	cd $(FREETYPE2_DIR) && ./configure --with-harfbuzz=no --with-bzip2=no --with-png=no --without-zlib
+	make -C $(FREETYPE2_DIR) all
+
+########## HARNESS #######
+
+$(HARNESS_SRC):
+	wget -O $@ $(HARNESS_URL)
+
+$(HARNESS_OBJ): $(HARNESS_SRC)
+	$(CC) -o $@ -c $<
+
+########## TEST #######
+
+$(TEST_BIN): $(LIBARCHIVE_LIB) $(FREETYPE2_LIB) $(HARNESS_OBJ)
+	$(CXX) \
+		$(CXXFLAGS) \
+		-std=c++11 \
+		-I $(FREETYPE2_DIR)include \
+		-I $(FREETYPE2_DIR) \
+		-I $(LIBARCHIVE_DIR)/libarchive \
+		$(FUZZER_SRC) \
+     	$(FREETYPE2_LIB) \
+		$(LIBARCHIVE_LIB) \
+		$(HARNESS_OBJ) \
+	    -o $@
+
+########## DUMMY #######
+
+$(TRT_DIR): | $(BUILD_DIR)
+	git clone $(TRT_GIT_REPO) $@
+
+$(TEST_DATA_DIR): | $(TRT_DIR)
+	mkdir -p $@
+	cp $(TRT_DIR)fonts/TestKERNOne.otf $@
+	cp $(TRT_DIR)fonts/TestGLYFOne.ttf $@
+
+$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
+	dd if=/dev/zero bs=1048576 count=1 of=$@
+
+###### TEST DATA #######
+
+clean:
+	rm -rf $(BUILD_DIR)
+
+frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE)
+	AFL_FRIDA_PERSISTENT_CNT=1000000 \
+	AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
+	AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+	$(ROOT)afl-fuzz \
+		-i $(TEST_DATA_DIR) \
+		-o $(FRIDA_OUT) \
+		-m none \
+		-d \
+		-O \
+		-V 30 \
+		-- \
+			$(TEST_BIN) $(TEST_DATA_FILE)
+
+qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE)
+	AFL_QEMU_PERSISTENT_CNT=1000000 \
+	AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \
+	AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
+	AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \
+	$(ROOT)afl-fuzz \
+		-i $(TEST_DATA_DIR) \
+		-o $(QEMU_OUT) \
+		-m none \
+		-d \
+		-Q \
+		-V 30 \
+		-- \
+			$(TEST_BIN) $(TEST_DATA_FILE)
diff --git a/frida_mode/test/freetype2/Makefile b/frida_mode/test/freetype2/Makefile
new file mode 100644
index 00000000..07b139e9
--- /dev/null
+++ b/frida_mode/test/freetype2/Makefile
@@ -0,0 +1,13 @@
+all:
+	@echo trying to use GNU make...
+	@gmake all || echo please install GNUmake
+
+32:
+	@echo trying to use GNU make...
+	@gmake 32 || echo please install GNUmake
+
+clean:
+	@gmake clean
+
+frida:
+	@gmake frida
diff --git a/frida_mode/test/freetype2/get_symbol_addr.py b/frida_mode/test/freetype2/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/freetype2/get_symbol_addr.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+import argparse
+from elftools.elf.elffile import ELFFile
+
+def process_file(file, symbol, base):
+    with open(file, 'rb') as f:
+        elf = ELFFile(f)
+        symtab = elf.get_section_by_name('.symtab')
+        mains = symtab.get_symbol_by_name(symbol)
+        if len(mains) != 1:
+            print ("Failed to find main")
+            return 1
+
+        main_addr = mains[0]['st_value']
+        main = base + main_addr
+        print ("0x%016x" % main)
+        return 0
+
+def hex_value(x):
+    return int(x, 16)
+
+def main():
+    parser = argparse.ArgumentParser(description='Process some integers.')
+    parser.add_argument('-f', '--file', dest='file', type=str,
+                    help='elf file name', required=True)
+    parser.add_argument('-s', '--symbol', dest='symbol', type=str,
+                    help='symbol name', required=True)
+    parser.add_argument('-b', '--base', dest='base', type=hex_value,
+                    help='elf base address', required=True)
+
+    args = parser.parse_args()
+    return process_file (args.file, args.symbol, args.base)
+
+if __name__ == "__main__":
+    ret = main()
+    exit(ret)
diff --git a/frida_mode/test/libpcap/GNUmakefile b/frida_mode/test/libpcap/GNUmakefile
index 6f2b58af..f8dc3db7 100644
--- a/frida_mode/test/libpcap/GNUmakefile
+++ b/frida_mode/test/libpcap/GNUmakefile
@@ -59,7 +59,7 @@ GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
 
 AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
 
-ifeq "$(ARCH)" "aarch64"
+ifeq "$(ARCH)" "arm64"
  AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
 endif
 
diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts
index 8a1ebf1b..538d9b70 100644
--- a/frida_mode/ts/lib/afl.ts
+++ b/frida_mode/ts/lib/afl.ts
@@ -284,6 +284,13 @@ class Afl {
     Afl.jsApiSetStdOut(buf);
   }
 
+  /**
+   * See `AFL_FRIDA_TRACEABLE`.
+   */
+  public static setTraceable(): void {
+    Afl.jsApiSetTraceable();
+  }
+
   private static readonly jsApiAddExcludeRange = Afl.jsApiGetFunction(
     "js_api_add_exclude_range",
     "void",
@@ -431,6 +438,11 @@ class Afl {
     "void",
     ["pointer"]);
 
+  private static readonly jsApiSetTraceable = Afl.jsApiGetFunction(
+    "js_api_set_traceable",
+    "void",
+    []);
+
   private static readonly jsApiWrite = new NativeFunction(
     /* tslint:disable-next-line:no-null-keyword */
     Module.getExportByName(null, "write"),
diff --git a/frida_mode/ub1804/Dockerfile b/frida_mode/ub1804/Dockerfile
new file mode 100644
index 00000000..e1f5a339
--- /dev/null
+++ b/frida_mode/ub1804/Dockerfile
@@ -0,0 +1,6 @@
+FROM ubuntu:xenial
+
+WORKDIR /AFLplusplus
+
+RUN apt-get update
+RUN apt-get install -y make gcc g++ xz-utils curl wget clang zlib1g-dev
\ No newline at end of file
diff --git a/frida_mode/ub1804/GNUmakefile b/frida_mode/ub1804/GNUmakefile
new file mode 100644
index 00000000..4247916e
--- /dev/null
+++ b/frida_mode/ub1804/GNUmakefile
@@ -0,0 +1,37 @@
+PWD:=$(shell pwd)/
+ROOT:=$(PWD)../../
+
+.PHONY: all build docker clean shell test
+
+all: docker
+	docker run --rm \
+		-v $(ROOT):/AFLplusplus \
+		ub1804-afl-frida \
+		/bin/sh -c \
+			'make -C /AFLplusplus/ clean all && \
+			make -C /AFLplusplus/frida_mode clean all'
+
+test:
+	docker run --rm \
+		-v $(ROOT):/AFLplusplus \
+		ub1804-afl-frida \
+		/bin/sh -c \
+			'make -C /AFLplusplus/frida_mode/test/png clean all && \
+			make -C /AFLplusplus/frida_mode/test/png/persistent/hook frida'
+
+build:
+	docker run --rm \
+		-v $(ROOT):/AFLplusplus \
+		ub1804-afl-frida \
+		/bin/sh -c \
+			'make -C /AFLplusplus/ all && \
+			make -C /AFLplusplus/frida_mode all'
+
+docker:
+	docker build --tag ub1804-afl-frida .
+
+clean:
+	docker images --filter 'dangling=true' -q --no-trunc | xargs -L1 docker rmi --force
+
+shell:
+	docker run -ti --rm ub1804-afl-frida /bin/bash
diff --git a/frida_mode/ub1804/Makefile b/frida_mode/ub1804/Makefile
new file mode 100644
index 00000000..f3c3cd55
--- /dev/null
+++ b/frida_mode/ub1804/Makefile
@@ -0,0 +1,9 @@
+all:
+	@echo trying to use GNU make...
+	@gmake all || echo please install GNUmake
+
+clean:
+	@gmake clean
+
+shell:
+	@gmake shell