Merge pull request #116 from frida/fix/darwin-aarch64-variadic Fix handling of variadic calls on Darwin/AArch64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
diff --git a/src/aarch64/ffi.c b/src/aarch64/ffi.c
index 7d5aa40..b807a2d 100644
--- a/src/aarch64/ffi.c
+++ b/src/aarch64/ffi.c
@@ -408,6 +408,10 @@ struct arg_state
unsigned ngrn; /* Next general-purpose register number. */
unsigned nsrn; /* Next vector register number. */
size_t nsaa; /* Next stack offset. */
+
+#if defined (__APPLE__)
+ unsigned allocating_variadic;
+#endif
};
/* Initialize a procedure call argument marshalling state. */
@@ -417,6 +421,10 @@ arg_init (struct arg_state *state, size_t call_frame_size)
state->ngrn = 0;
state->nsrn = 0;
state->nsaa = 0;
+
+#if defined (__APPLE__)
+ state->allocating_variadic = 0;
+#endif
}
/* Return the number of available consecutive core argument
@@ -476,7 +484,10 @@ allocate_to_stack (struct arg_state *state, void *stack, size_t alignment,
alignment of the argument's type. */
state->nsaa = ALIGN (state->nsaa, alignment);
state->nsaa = ALIGN (state->nsaa, alignment);
-#if !defined (__APPLE__)
+#if defined (__APPLE__)
+ if (state->allocating_variadic)
+ state->nsaa = ALIGN (state->nsaa, 8);
+#else
state->nsaa = ALIGN (state->nsaa, 8);
#endif
@@ -725,6 +736,16 @@ aarch64_prep_args (struct call_context *context, unsigned char *stack,
FFI_ASSERT (0);
break;
}
+
+#if defined (__APPLE__)
+ if (i + 1 == ecif->cif->aarch64_nfixedargs)
+ {
+ state.ngrn = N_X_ARG_REG;
+ state.nsrn = N_V_ARG_REG;
+
+ state.allocating_variadic = 1;
+ }
+#endif
}
return ecif->cif->aarch64_flags;
@@ -761,6 +782,20 @@ ffi_prep_cif_machdep (ffi_cif *cif)
return FFI_OK;
}
+#if defined (__APPLE__)
+
+/* Perform Apple-specific cif processing for variadic calls */
+ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
+ unsigned int nfixedargs,
+ unsigned int ntotalargs)
+{
+ cif->aarch64_nfixedargs = nfixedargs;
+
+ return ffi_prep_cif_machdep(cif);
+}
+
+#endif
+
/* Call a function with the provided arguments and capture the return
value. */
void
diff --git a/src/aarch64/ffitarget.h b/src/aarch64/ffitarget.h
index 6f1a348..4bbced2 100644
--- a/src/aarch64/ffitarget.h
+++ b/src/aarch64/ffitarget.h
@@ -47,8 +47,12 @@ typedef enum ffi_abi
/* ---- Internal ---- */
-
+#if defined (__APPLE__)
+#define FFI_TARGET_SPECIFIC_VARIADIC
+#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags; unsigned aarch64_nfixedargs
+#else
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
+#endif
#define AARCH64_FFI_WITH_V_BIT 0