about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2022-02-01 11:09:39 +0100
committerGitHub <noreply@github.com>2022-02-01 11:09:39 +0100
commitf336aa463b65aac0544118dc82eded463f2c3d83 (patch)
treee94d273b7d7b036ef9d7275871bfbe8a72dfe47e
parent60e126c615a892b329d494ddcc5b84a8e560ca4b (diff)
parent5f6bbc7dea04cf3ef8fc37c9876e000fb35e9f86 (diff)
downloadafl++-f336aa463b65aac0544118dc82eded463f2c3d83.tar.gz
Merge pull request #1307 from WorksButNotTested/arm64
ARM64
-rw-r--r--frida_mode/GNUmakefile130
-rw-r--r--frida_mode/src/instrument/instrument_arm64.c144
-rw-r--r--frida_mode/src/stalker.c5
-rw-r--r--frida_mode/test/persistent_ret/testinstr.c8
4 files changed, 222 insertions, 65 deletions
diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile
index 010c12d9..0b5f52cb 100644
--- a/frida_mode/GNUmakefile
+++ b/frida_mode/GNUmakefile
@@ -66,9 +66,12 @@ ifeq "$(ARCH)" "i686"
 endif
 endif
 
+GUM_ARCH="-$(ARCH)"
+
 ifeq "$(shell uname)" "Darwin"
  OS:=macos
  AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations
+ GUM_ARCH:=""
 else
 ifdef DEBUG
  AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor
@@ -113,13 +116,13 @@ ifndef OS
  $(error "Operating system unsupported")
 endif
 
-GUM_DEVKIT_VERSION=15.1.13
+GUM_DEVKIT_VERSION=15.1.15
 GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz
 GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
 
 GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
 ifdef FRIDA_SOURCE
-GUM_DEVIT_LIBRARY=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gumjs-1.0.a
+GUM_DEVIT_LIBRARY=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gumjs-1.0.a
 else
 GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gumjs.a
 endif
@@ -177,7 +180,7 @@ $(FRIDA_MAKEFILE): | $(BUILD_DIR)
 .PHONY: $(GUM_DEVIT_LIBRARY)
 
 $(GUM_DEVIT_LIBRARY): $(FRIDA_MAKEFILE)
-	cd $(FRIDA_DIR) && make gum-linux-$(ARCH)
+	cd $(FRIDA_DIR) && make gum-$(OS)$(GUM_ARCH)
 
 $(GUM_DEVIT_HEADER): $(FRIDA_MAKEFILE) | $(FRIDA_BUILD_DIR)
 	echo "#include <stdio.h>" > $@
@@ -189,62 +192,87 @@ $(GUM_DEVIT_HEADER): $(FRIDA_MAKEFILE) | $(FRIDA_BUILD_DIR)
 	echo "#include <gum/gumlibc.h>" >> $@
 	echo "#include <gumjs/gumscriptbackend.h>" >> $@
 
-ifeq "$(ARCH)" "arm64"
-
-CFLAGS+=-I $(FRIDA_DIR)build/frida_thin-linux-$(ARCH)/include/frida-1.0 \
-	    -I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/glib-2.0/ \
-		-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/glib-2.0/include/ \
-		-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/capstone/ \
-		-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/json-glib-1.0/ \
-
-TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gum-1.0.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libsoup-2.4.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libsqlite3.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libtcc.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libjson-glib-1.0.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libquickjs.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libcapstone.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libunwind-*.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libunwind.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libffi.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libdwarf.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libelf.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libgio-2.0.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libgobject-2.0.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libglib-2.0.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/liblzma.a \
-			   $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libz.a \
+ifeq "$(OS)" "macos"
+
+CFLAGS+=-I $(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/include/frida-1.0 \
+	    -I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/glib-2.0/ \
+		-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \
+		-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/capstone/ \
+		-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ \
+
+TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libsoup-2.4.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libsqlite3.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libtcc.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libjson-glib-1.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libquickjs.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libcapstone.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libffi.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgio-2.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgobject-2.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libglib-2.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/liblzma.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libz.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libiconv.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libv8-8.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgmodule-2.0.a \
+
+else ifeq "$(ARCH)" "arm64"
+
+CFLAGS+=-I $(FRIDA_DIR)build/frida_thin-$(OS)-$(ARCH)/include/frida-1.0 \
+	    -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/glib-2.0/ \
+		-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \
+		-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/capstone/ \
+		-I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ \
+
+TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libsoup-2.4.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libsqlite3.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libtcc.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libjson-glib-1.0.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libquickjs.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libcapstone.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libunwind.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libffi.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libdwarf.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libelf.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libgio-2.0.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libgobject-2.0.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libglib-2.0.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/liblzma.a \
+			   $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libz.a \
 
 else
 
-CFLAGS+=-I $(FRIDA_DIR)build/frida-linux-$(ARCH)/include/frida-1.0 \
-	    -I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/glib-2.0/ \
-		-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/glib-2.0/include/ \
-		-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/capstone/ \
-		-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/json-glib-1.0/ \
-
-TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gum-1.0.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libsoup-2.4.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libsqlite3.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libtcc.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libjson-glib-1.0.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libquickjs.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libcapstone.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libunwind-*.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libunwind.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libffi.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libdwarf.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libelf.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libgio-2.0.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libgobject-2.0.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libglib-2.0.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/liblzma.a \
-			   $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libz.a \
+CFLAGS+=-I $(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/include/frida-1.0 \
+	    -I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/glib-2.0/ \
+		-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \
+		-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/capstone/ \
+		-I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ \
+
+TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libsoup-2.4.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libsqlite3.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libtcc.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libjson-glib-1.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libquickjs.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libcapstone.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libunwind.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libffi.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libdwarf.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libelf.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgio-2.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libgobject-2.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libglib-2.0.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/liblzma.a \
+			   $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libz.a \
 
 endif
 
 
 
+
+
 else
 $(GUM_DEVKIT_TARBALL): | $(FRIDA_BUILD_DIR)
 	wget -O $@ $(GUM_DEVKIT_URL) || curl -L -o $@ $(GUM_DEVKIT_URL)
diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c
index 57b60317..1a704585 100644
--- a/frida_mode/src/instrument/instrument_arm64.c
+++ b/frida_mode/src/instrument/instrument_arm64.c
@@ -14,9 +14,12 @@
 
 #define PAGE_MASK (~(GUM_ADDRESS(0xfff)))
 #define PAGE_ALIGNED(x) ((GUM_ADDRESS(x) & PAGE_MASK) == GUM_ADDRESS(x))
+#define GUM_RESTORATION_PROLOG_SIZE 4
 
 #if defined(__aarch64__)
 
+static GHashTable *coverage_blocks = NULL;
+
 __attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE];
 
   #pragma pack(push, 1)
@@ -44,6 +47,9 @@ typedef struct {
   // b       0x7fb6f0dee4
   // ldp     x16, x17, [sp], #144
 
+  uint32_t b_imm8;                                                /* br #68 */
+  uint32_t restoration_prolog;                 /* ldp x16, x17, [sp], #0x90 */
+
   uint32_t stp_x0_x1;                           /* stp x0, x1, [sp, #-0xa0] */
 
   uint32_t adrp_x0_prev_loc1;                           /* adrp x0, #0xXXXX */
@@ -66,9 +72,6 @@ typedef struct {
 
   uint32_t ldp_x0_x1;                           /* ldp x0, x1, [sp, #-0xa0] */
 
-  uint32_t b_imm8;                                                 /* br #8 */
-  uint32_t restoration_prolog;                 /* ldp x16, x17, [sp], #0x90 */
-
 } afl_log_code_asm_t;
 
   #pragma pack(pop)
@@ -83,6 +86,9 @@ typedef union {
 static const afl_log_code_asm_t template =
     {
 
+        .b_imm8 = 0x14000011,
+
+        .restoration_prolog = 0xa8c947f0,
         .stp_x0_x1 = 0xa93607e0,
 
         .adrp_x0_prev_loc1 = 0x90000000,
@@ -107,9 +113,6 @@ static const afl_log_code_asm_t template =
 
         .ldp_x0_x1 = 0xa97607e0,
 
-        .b_imm8 = 0x14000002,
-        .restoration_prolog = 0xa8c947f0,
-
 }
 
 ;
@@ -120,6 +123,110 @@ gboolean instrument_is_coverage_optimize_supported(void) {
 
 }
 
+static gboolean instrument_is_deterministic(const cs_insn *from_insn) {
+
+  cs_arm64 *arm64;
+  arm64_cc  cc;
+
+  if (from_insn == NULL) { return FALSE; }
+
+  arm64 = &from_insn->detail->arm64;
+  cc = arm64->cc;
+
+  switch (from_insn->id) {
+
+    case ARM64_INS_B:
+    case ARM64_INS_BL:
+      if (cc == ARM64_CC_INVALID) { return TRUE; }
+      break;
+
+    case ARM64_INS_RET:
+    case ARM64_INS_RETAA:
+    case ARM64_INS_RETAB:
+      if (arm64->op_count == 0) { return TRUE; }
+      break;
+    default:
+      return FALSE;
+
+  }
+
+  return FALSE;
+
+}
+
+static void instrument_coverage_switch(GumStalkerObserver *self,
+                                       gpointer            start_address,
+                                       const cs_insn *     from_insn,
+                                       gpointer *          target) {
+
+  UNUSED_PARAMETER(self);
+  UNUSED_PARAMETER(start_address);
+
+  gsize fixup_offset;
+
+  if (!g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target)) &&
+      !g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target + 4))) {
+
+    return;
+
+  }
+
+  if (instrument_is_deterministic(from_insn)) { return; }
+
+  /*
+   * Since each block is prefixed with a restoration prologue, we need to be
+   * able to begin execution at an offset into the block and execute both this
+   * restoration prologue and the instrumented block without the coverage code.
+   * We therefore layout our block as follows:
+   *
+   *  +-----+------------------+-----+--------------------------+-------------+
+   *  | LDP | BR <TARGET CODE> | LDP | COVERAGE INSTRUMENTATION | TARGET CODE |
+   *  +-----+------------------+-----+--------------------------+-------------+
+   *
+   *  ^     ^                  ^     ^
+   *  |     |                  |     |
+   *  A     B                  C     D
+   *
+   * Without instrumentation suppression, the block is either executed at point
+   * (C) if it is reached by an indirect branch (and registers need to be
+   * restored) or point (D) if it is reached by an direct branch (and hence the
+   * registers don't need restoration). Similarly, we can start execution of the
+   * block at points (A) or (B) to achieve the same functionality, but without
+   * executing the coverage instrumentation.
+   *
+   * In either case, Stalker will call us back with the address of the target
+   * block to be executed as the destination. We can then check if the branch is
+   * a deterministic one and if so branch to point (C) or (D) rather than (A)
+   * or (B). We lay the code out in this fashion so that in the event we can't
+   * suppress coverage (the most likely), we can vector directly to the coverage
+   * instrumentation code and execute entirely without any branches. If we
+   * suppress the coverage, we simply branch beyond it instead.
+   */
+  fixup_offset = GUM_RESTORATION_PROLOG_SIZE +
+                 G_STRUCT_OFFSET(afl_log_code_asm_t, restoration_prolog);
+  *target += fixup_offset;
+
+}
+
+static void instrument_coverage_suppress_init(void) {
+
+  static gboolean initialized = false;
+  if (initialized) { return; }
+  initialized = true;
+
+  GumStalkerObserver *         observer = stalker_get_observer();
+  GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer);
+  iface->switch_callback = instrument_coverage_switch;
+
+  coverage_blocks = g_hash_table_new(g_direct_hash, g_direct_equal);
+  if (coverage_blocks == NULL) {
+
+    FATAL("Failed to g_hash_table_new, errno: %d", errno);
+
+  }
+
+}
+
 static gboolean instrument_coverage_in_range(gssize offset) {
 
   return (offset >= G_MININT33 && offset <= G_MAXINT33);
@@ -151,6 +258,7 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
   afl_log_code    code = {0};
   GumArm64Writer *cw = output->writer.arm64;
+  gpointer        block_start;
   guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
   gsize   map_size_pow2;
   gsize   area_offset_ror;
@@ -171,8 +279,32 @@ void instrument_coverage_optimize(const cs_insn *   instr,
 
   // gum_arm64_writer_put_brk_imm(cw, 0x0);
 
+  instrument_coverage_suppress_init();
+
   code_addr = cw->pc;
 
+  /*
+   * On AARCH64, immediate branches can only be encoded with a 28-bit offset. To
+   * make a longer branch, it is necessary to load a register with the target
+   * address, this register must be saved beyond the red-zone before the branch
+   * is taken. To restore this register each block is prefixed by Stalker with
+   * an instruction to load x16,x17 from beyond the red-zone on the stack. A
+   * pair of registers are saved/restored because on AARCH64, the stack pointer
+   * must be 16 byte aligned. This instruction is emitted into the block before
+   * the tranformer (from which we are called) is executed. If is is possible
+   * for Stalker to make a direct branch (the target block is close enough), it
+   * can forego pushing the registers and instead branch at an offset into the
+   * block to skip this restoration prolog.
+   */
+  block_start =
+      GSIZE_TO_POINTER(GUM_ADDRESS(cw->code) - GUM_RESTORATION_PROLOG_SIZE);
+
+  if (!g_hash_table_add(coverage_blocks, block_start)) {
+
+    FATAL("Failed - g_hash_table_add");
+
+  }
+
   code.code = template;
 
   /*
diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c
index 3a421867..80e4e707 100644
--- a/frida_mode/src/stalker.c
+++ b/frida_mode/src/stalker.c
@@ -100,7 +100,7 @@ void stalker_init(void) {
   FOKF(cBLU "Stalker" cRST " - " cGRN "adjacent_blocks:" cYEL " [%u]",
        stalker_adjacent_blocks);
 
-#if !(defined(__x86_64__) || defined(__i386__))
+#if !(defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))
   if (getenv("AFL_FRIDA_STALKER_IC_ENTRIES") != NULL) {
 
     FFATAL("AFL_FRIDA_STALKER_IC_ENTRIES not supported");
@@ -134,6 +134,9 @@ void stalker_init(void) {
 #if defined(__x86_64__) || defined(__i386__)
   stalker = g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries,
                          "adjacent-blocks", stalker_adjacent_blocks, NULL);
+#elif defined(__aarch64__)
+  stalker =
+      g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries, NULL);
 #else
   stalker = gum_stalker_new();
 #endif
diff --git a/frida_mode/test/persistent_ret/testinstr.c b/frida_mode/test/persistent_ret/testinstr.c
index d383c340..b2bc19ef 100644
--- a/frida_mode/test/persistent_ret/testinstr.c
+++ b/frida_mode/test/persistent_ret/testinstr.c
@@ -16,12 +16,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-#ifdef __APPLE__
-  #define MAIN_SECTION
-#else
-  #define MAIN_SECTION __attribute__((section(".main")))
-#endif
-
 void LLVMFuzzerTestOneInput(char *buf, int len) {
 
   printf (">>> LLVMFuzzerTestOneInput >>>\n");
@@ -44,7 +38,7 @@ void slow() {
 
 }
 
-MAIN_SECTION int main(int argc, char **argv) {
+int main(int argc, char **argv) {
 
   char * file;
   int    fd = -1;