libffi provides functionality for dynamically marshalling arguments to/from C
functions.

First, make it compile using the cross compiler.

Secondly, apply a big patch to the ARM assembly code, which is needed because
Apple ships a pre-historic version of the GNU assembler which isn't good at
macros.

--- ghc-6.10.2.orig/libffi/Makefile	2009-03-31 06:13:16.000000000 +1300
+++ ghc-6.10.2/libffi/Makefile	2009-06-18 15:54:37.000000000 +1200
@@ -79,15 +79,22 @@
 stamp.ffi:
 	$(RM) -rf $(LIBFFI_DIR) build
 	$(TAR) -zxf $(LIBFFI_TARBALL)
+	cat iphone.patch | (cd $(LIBFFI_DIR) && patch -p1)
 	mv $(LIBFFI_DIR) build
 	chmod +x ln
 	    PATH=`pwd`:$$PATH; \
 	    export PATH; \
 	    cd build && \
-	    CC=$(WhatGccIsCalled) $(SHELL) configure \
+	        CC="$(TARGET_GCC)" \
+                AR="$(TARGET_AR)" \
+                LD="$(TARGET_LD)" \
+                CFLAGS="$(TARGET_CFLAGS)" \
+                CPPFLAGS="$(TARGET_CPPFLAGS)" \
+                LDFLAGS="$(TARGET_LDFLAGS)" \
+                  $(SHELL) configure \
 		  --enable-static=yes \
 	          --enable-shared=$(EnableShared) \
-		  --host=$(PLATFORM) --build=$(PLATFORM)
+		  --host=$(PLATFORM)
 	touch $@
 
 ffi.h: stamp.ffi
--- ghc-6.10.2.orig/libffi/iphone.patch	1970-01-01 12:00:00.000000000 +1200
+++ ghc-6.10.2/libffi/iphone.patch	2009-06-18 15:54:37.000000000 +1200
@@ -0,0 +1,187 @@
+--- build.orig/src/arm/sysv.S	2008-02-27 08:01:52.000000000 +1300
++++ build/src/arm/sysv.S	2009-05-22 11:49:57.000000000 +1200
+@@ -29,17 +29,6 @@
+ #include <ffi.h>
+ #ifdef HAVE_MACHINE_ASM_H
+ #include <machine/asm.h>
+-#else
+-#ifdef __USER_LABEL_PREFIX__
+-#define CONCAT1(a, b) CONCAT2(a, b)
+-#define CONCAT2(a, b) a ## b
+-
+-/* Use the right prefix for global labels.  */
+-#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+-#else
+-#define CNAME(x) x
+-#endif
+-#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+ #endif
+ 
+ #ifdef __ELF__
+@@ -83,54 +72,29 @@
+ # define call_reg(x)	mov	lr, pc ; mov	pc, x
+ #endif
+ 
+-/* Conditionally compile unwinder directives.  */
+-#ifdef __ARM_EABI__
+-#define UNWIND
+-#else
+-#define UNWIND @
+-#endif	
+-
+-	
+ #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+-.macro	ARM_FUNC_START name
+-	.text
+-	.align 0
+-	.thumb
+-	.thumb_func
+-	ENTRY(\name)
+-	bx	pc
+-	nop
+-	.arm
+-	UNWIND .fnstart
+-/* A hook to tell gdb that we've switched to ARM mode.  Also used to call
+-   directly from other local arm routines.  */
+-_L__\name:		
+-.endm
+-#else
+-.macro	ARM_FUNC_START name
+-	.text
+-	.align 0
+-	.arm
+-	ENTRY(\name)
+-	UNWIND .fnstart
+-.endm
++#define ARM_FUNC_START(name) \
++	.text ; \
++	.align 0 ; \
++	.thumb ; \
++	.thumb_func ; \
++	.globl _ ## name ; \
++_ ## name: ; \
++	bx	pc ; \
++	nop ; \
++	.arm ; \
++_L__\name:
++
++#else
++#define ARM_FUNC_START(name) \
++	.text ; \
++	.align 0 ; \
++	.arm ; \
++	.globl _ ## name ; \
++_ ## name:
+ #endif
+ 
+-.macro	RETLDM	regs=, cond=, dirn=ia
+-#if defined (__INTERWORKING__)
+-	.ifc "\regs",""
+-	ldr\cond	lr, [sp], #4
+-	.else
+-	ldm\cond\dirn	sp!, {\regs, lr}
+-	.endif
+-	bx\cond	lr
+-#else
+-	.ifc "\regs",""
+-	ldr\cond	pc, [sp], #4
+-	.else
+-	ldm\cond\dirn	sp!, {\regs, pc}
+-	.endif
+-#endif
++.macro	RETLDM	regs=
+ .endm
+ 
+ 
+@@ -142,16 +106,14 @@
+ 	@ sp+4: fn
+ 
+ 	@ This assumes we are using gas.
+-ARM_FUNC_START ffi_call_SYSV
++ARM_FUNC_START(ffi_call_SYSV)
+ 	@ Save registers
+-        stmfd	sp!, {r0-r3, fp, lr}
+-	UNWIND .save	{r0-r3, fp, lr}
+-	mov	fp, sp
++        stmfd	sp!, {r0-r3, r11, lr}
++	mov	r11, sp
+ 
+-	UNWIND .setfp	fp, sp
+ 
+ 	@ Make room for all of the new args.
+-	sub	sp, fp, r2
++	sub	sp, r11, r2
+ 
+ 	@ Place all of the ffi_prep_args in position
+ 	mov	ip, r0
+@@ -165,17 +127,17 @@
+ 	ldmia	sp, {r0-r3}
+ 
+ 	@ and adjust stack
+-	ldr	ip, [fp, #8]
++	ldr	ip, [r11, #8]
+         cmp	ip, #16
+ 	movhs	ip, #16
+         add	sp, sp, ip
+ 
+ 	@ call (fn) (...)
+-	ldr	ip, [fp, #28]
++	ldr	ip, [r11, #28]
+ 	call_reg(ip)
+ 	
+ 	@ Remove the space we pushed for the args
+-	mov	sp, fp
++	mov	sp, r11
+ 
+ 	@ Load r2 with the pointer to storage for the return value
+ 	ldr	r2, [sp, #24]
+@@ -216,11 +178,15 @@
+ #endif
+ 
+ LSYM(Lepilogue):
+-	RETLDM	"r0-r3,fp"
++#if defined (__INTERWORKING__)
++	ldmia	sp!, {r0-r3,r11,lr}
++	bx	lr
++#else
++	ldmia	sp!, {r0-r3,r11,pc}
++#endif
+ 
+ .ffi_call_SYSV_end:
+-	UNWIND .fnend
+-        .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
++        @ .size    CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+ 
+ /*
+ 	unsigned int FFI_HIDDEN
+@@ -230,17 +196,15 @@
+   	     void *args;
+ */
+ 
+-ARM_FUNC_START ffi_closure_SYSV
+-	UNWIND .pad #16
++ARM_FUNC_START(ffi_closure_SYSV)
+ 	add	ip, sp, #16
+ 	stmfd	sp!, {ip, lr}
+-	UNWIND .save	{r0, lr}
+ 	add	r2, sp, #8
+-	.pad #16
++	@ .pad #16
+ 	sub	sp, sp, #16
+ 	str	sp, [sp, #8]
+ 	add	r1, sp, #8
+-	bl	ffi_closure_SYSV_inner
++	bl	_ffi_closure_SYSV_inner
+ 	cmp	r0, #FFI_TYPE_INT
+ 	beq	.Lretint
+ 
+@@ -291,8 +255,7 @@
+ #endif
+ 
+ .ffi_closure_SYSV_end:
+-	UNWIND .fnend
+-        .size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
++        @.size    CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
+ 
+ #if defined __ELF__ && defined __linux__
+ 	.section	.note.GNU-stack,"",%progbits

