  
    /* free list tracking */
    uint16_t free_count;
-@@ -180,6 +183,22 @@
+@@ -180,6 +188,21 @@ struct ffi_trampoline_table_entry
  /* Total number of trampolines that fit in one trampoline table */
  #define FFI_TRAMPOLINE_COUNT (PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE)
  
-+/* The trampoline dylib has one page for the MACHO_HEADER and one page for the trampolines.
-+ * iOS 12.0 and later require that the entire dylib needs to be remapped as a unit.
++/* The trampoline dylib has one page for the MACHO_HEADER and one page for the
++ * trampolines. iOS 12.0 and later, and macOS on Apple Silicon require that
++ * the entire dylib needs to be remapped as a unit.
 + *
 + * arm (legacy): Allocate two pages -- a config page and a placeholder for the trampolines
 + * arm64 (modern): Allocate three pages -- a config page and two placeholders for the trampoline dylib
-+ *
-+ * TODO: Update arm to be consistent with arm64.  Note that iOS12 does not support armv7.
 + */
 +#ifdef FFI_TRAMPOLINE_WHOLE_DYLIB
 +#define FFI_TRAMPOLINE_ALLOCATION_PAGE_COUNT 3

 #include <stdio.h>
 #include <stdlib.h>
 
-extern void *ffi_closure_trampoline_table_page;
-
 typedef struct ffi_trampoline_table ffi_trampoline_table;
 typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
 
@@ -160,7 +164,6 @@
 {
   /* contiguous writable and executable pages */
   vm_address_t config_page;

-  /* Remap the trampoline table on top of the placeholder page */
-  trampoline_page = config_page + PAGE_MAX_SIZE;
-  trampoline_page_template = (vm_address_t)&ffi_closure_trampoline_table_page;
+  static void *trampoline_table_page;
+
+#ifdef FFI_TRAMPOLINE_WHOLE_DYLIB
+  static dispatch_once_t trampoline_template_init_once;
+
+  dispatch_once(&trampoline_template_init_once, ^{
+    void * const trampoline_handle = dlopen("/usr/lib/libffi-trampolines.dylib", RTLD_NOW | RTLD_LOCAL | RTLD_FIRST);
+    assert(trampoline_handle);
+
+    trampoline_table_page = dlsym(trampoline_handle, "ffi_closure_trampoline_table_page");
+    assert(trampoline_table_page);
+  });
+#else
+  trampoline_table_page = &ffi_closure_trampoline_table_page;
+#endif
+
+#ifdef HAVE_PTRAUTH
+  trampoline_page_template = (uintptr_t)ptrauth_auth_data(trampoline_table_page, ptrauth_key_function_pointer, 0);
+#else
+  trampoline_page_template = (uintptr_t)trampoline_table_page;
+#endif
+
 #ifdef __arm__
   /* ffi_closure_trampoline_table_page can be thumb-biased on some ARM archs */
   trampoline_page_template &= ~1UL;
