diff --git a/libffi/src/x86/sysv.S b/libffi/src/x86/sysv.S
index 7110f02f5f3..c7a0fb51b48 100644
--- a/libffi/src/x86/sysv.S
+++ b/libffi/src/x86/sysv.S
@@ -888,10 +888,27 @@ ENDF(C(ffi_closure_raw_THISCALL))
 #endif /* !FFI_NO_RAW_API */
 
 #ifdef X86_DARWIN
-# define COMDAT(X)							\
-        .section __TEXT,__text,coalesced,pure_instructions;		\
+/* The linker in use on earlier Darwin needs weak definitions to be
+   placed in a coalesced section.  That section should not be called
+   __TEXT,__text since that would be re-defining the attributes of the
+   .text section (which is an error for earlier tools). Here we use
+   '__textcoal_nt' which is what GCC emits for this.
+   Later linker versions are happy to use a normal section and, after
+   Darwin12 / OSX 10.8, the tools warn that using coalesced sections
+   for this is deprecated so we must switch to avoid build fails and/or
+   deprecation warnings.  */
+# if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) &&		\
+   __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1080
+#  define COMDAT(X)							\
+        .section __TEXT,__textcoal_nt,coalesced,pure_instructions;	\
+        .weak_definition X;						\
+        FFI_HIDDEN(X)
+# else
+#  define COMDAT(X)							\
+        .text;								\
         .weak_definition X;						\
         FFI_HIDDEN(X)
+# endif
 #elif defined __ELF__ && !(defined(__sun__) && defined(__svr4__))
 # define COMDAT(X)							\
 	.section .text.X,"axG",@progbits,X,comdat;			\
@@ -916,7 +933,37 @@ ENDF(C(__x86.get_pc_thunk.dx))
 #endif /* DARWIN || HIDDEN */
 #endif /* __PIC__ */
 
-/* Sadly, OSX cctools-as doesn't understand .cfi directives at all.  */
+/* Sadly, OSX cctools-as does not understand .cfi directives at all so
+   we build an eh frame by hand.  */
+
+#ifdef __APPLE__
+/* The cctools assembler will try to make a difference between two local
+   symbols into a relocation against, which will not work in the eh (produces
+   link-time fails).
+   To avoid this, we compute the symbol difference with a .set directive and
+   then substitute this value.  */
+# define LEN(N, P)	.set Llen$N$P,L(N)-L(P); .long Llen$N$P
+/* Note, this assume DW_CFA_advance_loc1 fits into 7 bits.  */
+# define ADV(N, P)	.set Ladv$N$P,L(N)-L(P); .byte 2, Ladv$N$P
+/* For historical reasons, the EH reg numbers for SP and FP are swapped from
+   the DWARF ones for 32b Darwin.  */
+# define SP 5
+# define FP 4
+# define ENC 0x10
+#else
+# define LEN(N, P)	.long L(N)-L(P)
+/* Assume DW_CFA_advance_loc1 fits.  */
+# define ADV(N, P)	.byte 2, L(N)-L(P)
+# define SP 4
+# define FP 5
+# define ENC 0x1b
+#endif
+
+#ifdef HAVE_AS_X86_PCREL
+# define PCREL(X)	X-.
+#else
+# define PCREL(X)	X@rel
+#endif
 
 #ifdef __APPLE__
 .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
@@ -928,17 +975,11 @@ EHFrame0:
 #else
 .section .eh_frame,EH_FRAME_FLAGS,@progbits
 #endif
-
-#ifdef HAVE_AS_X86_PCREL
-# define PCREL(X)	X - .
-#else
-# define PCREL(X)	X@rel
+#ifndef __APPLE__
+/* EH sections are already suitably aligned on Darwin.  */
+	.balign 4
 #endif
 
-/* Simplify advancing between labels.  Assume DW_CFA_advance_loc1 fits.  */
-#define ADV(N, P)	.byte 2, L(N)-L(P)
-
-	.balign 4
 L(CIE):
 	.set	L(set0),L(ECIE)-L(SCIE)
 	.long	L(set0)			/* CIE Length */
@@ -950,8 +991,8 @@ L(SCIE):
 	.byte	0x7c			/* CIE Data Alignment Factor */
 	.byte	0x8			/* CIE RA Column */
 	.byte	1			/* Augmentation size */
-	.byte	0x1b			/* FDE Encoding (pcrel sdata4) */
-	.byte	0xc, 4, 4		/* DW_CFA_def_cfa, %esp offset 4 */
+	.byte	ENC			/* FDE Encoding (pcrel abs/4byte) */
+	.byte	0xc, SP, 4		/* DW_CFA_def_cfa, %esp offset 4 */
 	.byte	0x80+8, 1		/* DW_CFA_offset, %eip offset 1*-4 */
 	.balign 4
 L(ECIE):
@@ -959,20 +1000,20 @@ L(ECIE):
 	.set	L(set1),L(EFDE1)-L(SFDE1)
 	.long	L(set1)			/* FDE Length */
 L(SFDE1):
-	.long	L(SFDE1)-L(CIE)		/* FDE CIE offset */
+	LEN(SFDE1, CIE)			/* FDE CIE offset */
 	.long	PCREL(L(UW0))		/* Initial location */
-	.long	L(UW5)-L(UW0)		/* Address range */
+	LEN(UW5, UW0)			/* Address range */
 	.byte	0			/* Augmentation size */
 	ADV(UW1, UW0)
-	.byte	0xc, 5, 8		/* DW_CFA_def_cfa, %ebp 8 */
-	.byte	0x80+5, 2		/* DW_CFA_offset, %ebp 2*-4 */
+	.byte	0xc, FP, 8		/* DW_CFA_def_cfa, %ebp 8 */
+	.byte	0x80+FP, 2		/* DW_CFA_offset, %ebp 2*-4 */
 	ADV(UW2, UW1)
 	.byte	0x80+3, 0		/* DW_CFA_offset, %ebx 0*-4 */
 	ADV(UW3, UW2)
 	.byte	0xa			/* DW_CFA_remember_state */
-	.byte	0xc, 4, 4		/* DW_CFA_def_cfa, %esp 4 */
+	.byte	0xc, SP, 4		/* DW_CFA_def_cfa, %esp 4 */
 	.byte	0xc0+3			/* DW_CFA_restore, %ebx */
-	.byte	0xc0+5			/* DW_CFA_restore, %ebp */
+	.byte	0xc0+FP			/* DW_CFA_restore, %ebp */
 	ADV(UW4, UW3)
 	.byte	0xb			/* DW_CFA_restore_state */
 	.balign	4
@@ -981,9 +1022,9 @@ L(EFDE1):
 	.set	L(set2),L(EFDE2)-L(SFDE2)
 	.long	L(set2)			/* FDE Length */
 L(SFDE2):
-	.long	L(SFDE2)-L(CIE)		/* FDE CIE offset */
+	LEN(SFDE2, CIE)			/* FDE CIE offset */
 	.long	PCREL(L(UW6))		/* Initial location */
-	.long	L(UW8)-L(UW6)		/* Address range */
+	LEN(UW8,UW6)			/* Address range */
 	.byte	0			/* Augmentation size */
 	ADV(UW7, UW6)
 	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
@@ -993,9 +1034,9 @@ L(EFDE2):
 	.set	L(set3),L(EFDE3)-L(SFDE3)
 	.long	L(set3)			/* FDE Length */
 L(SFDE3):
-	.long	L(SFDE3)-L(CIE)		/* FDE CIE offset */
+	LEN(SFDE3, CIE)			/* FDE CIE offset */
 	.long	PCREL(L(UW9))		/* Initial location */
-	.long	L(UW11)-L(UW9)		/* Address range */
+	LEN(UW11, UW9)			/* Address range */
 	.byte	0			/* Augmentation size */
 	ADV(UW10, UW9)
 	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
@@ -1005,9 +1046,9 @@ L(EFDE3):
 	.set	L(set4),L(EFDE4)-L(SFDE4)
 	.long	L(set4)			/* FDE Length */
 L(SFDE4):
-	.long	L(SFDE4)-L(CIE)		/* FDE CIE offset */
+	LEN(SFDE4, CIE)		/* FDE CIE offset */
 	.long	PCREL(L(UW12))		/* Initial location */
-	.long	L(UW20)-L(UW12)		/* Address range */
+	LEN(UW20, UW12)			/* Address range */
 	.byte	0			/* Augmentation size */
 	ADV(UW13, UW12)
 	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
@@ -1033,9 +1074,9 @@ L(EFDE4):
 	.set	L(set5),L(EFDE5)-L(SFDE5)
 	.long	L(set5)			/* FDE Length */
 L(SFDE5):
-	.long	L(SFDE5)-L(CIE)		/* FDE CIE offset */
+	LEN(SFDE5, CIE)			/* FDE CIE offset */
 	.long	PCREL(L(UW21))		/* Initial location */
-	.long	L(UW23)-L(UW21)		/* Address range */
+	LEN(UW23, UW21)			/* Address range */
 	.byte	0			/* Augmentation size */
 	ADV(UW22, UW21)
 	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
@@ -1045,9 +1086,9 @@ L(EFDE5):
 	.set	L(set6),L(EFDE6)-L(SFDE6)
 	.long	L(set6)			/* FDE Length */
 L(SFDE6):
-	.long	L(SFDE6)-L(CIE)		/* FDE CIE offset */
+	LEN(SFDE6, CIE)			/* FDE CIE offset */
 	.long	PCREL(L(UW24))		/* Initial location */
-	.long	L(UW26)-L(UW24)		/* Address range */
+	LEN(UW26, UW24)			/* Address range */
 	.byte	0			/* Augmentation size */
 	.byte	0xe, 8			/* DW_CFA_def_cfa_offset */
 	.byte	0x80+8, 2		/* DW_CFA_offset %eip, 2*-4 */
@@ -1059,9 +1100,9 @@ L(EFDE6):
 	.set	L(set7),L(EFDE7)-L(SFDE7)
 	.long	L(set7)			/* FDE Length */
 L(SFDE7):
-	.long	L(SFDE7)-L(CIE)		/* FDE CIE offset */
+	LEN(SFDE7, CIE)			/* FDE CIE offset */
 	.long	PCREL(L(UW27))		/* Initial location */
-	.long	L(UW31)-L(UW27)		/* Address range */
+	LEN(UW31, UW27)			/* Address range */
 	.byte	0			/* Augmentation size */
 	ADV(UW28, UW27)
 	.byte	0xe, closure_FS+4	/* DW_CFA_def_cfa_offset */
@@ -1073,14 +1114,13 @@ L(SFDE7):
 #endif
 	.balign	4
 L(EFDE7):
-
 #if !FFI_NO_RAW_API
 	.set	L(set8),L(EFDE8)-L(SFDE8)
 	.long	L(set8)			/* FDE Length */
 L(SFDE8):
-	.long	L(SFDE8)-L(CIE)		/* FDE CIE offset */
+	LEN(SFDE8, CIE)			/* FDE CIE offset */
 	.long	PCREL(L(UW32))		/* Initial location */
-	.long	L(UW40)-L(UW32)		/* Address range */
+	LEN(UW40, UW32)			/* Address range */
 	.byte	0			/* Augmentation size */
 	ADV(UW33, UW32)
 	.byte	0xe, raw_closure_S_FS+4	/* DW_CFA_def_cfa_offset */
@@ -1102,9 +1142,9 @@ L(EFDE8):
 	.set	L(set9),L(EFDE9)-L(SFDE9)
 	.long	L(set9)			/* FDE Length */
 L(SFDE9):
-	.long	L(SFDE9)-L(CIE)		/* FDE CIE offset */
+	LEN(SFDE9, CIE)			/* FDE CIE offset */
 	.long	PCREL(L(UW41))		/* Initial location */
-	.long	L(UW52)-L(UW41)		/* Address range */
+	LEN(UW52, UW41)			/* Address range */
 	.byte	0			/* Augmentation size */
 	ADV(UW42, UW41)
 	.byte	0xe, 0			/* DW_CFA_def_cfa_offset */
@@ -1141,8 +1181,12 @@ L(EFDE9):
 @feat.00 = 1
 #endif
 
-#ifdef __APPLE__
+#if defined(__APPLE__)
     .subsections_via_symbols
+# if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) &&		\
+   __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1070 && __clang__
+/* compact unwind is not used with GCC at present, was not present before 10.6
+   but has some bugs there, so do not emit until 10.7.  */
     .section __LD,__compact_unwind,regular,debug
 
     /* compact unwind for ffi_call_i386 */
@@ -1216,6 +1260,7 @@ L(EFDE9):
     .long    0x04000000 /* use dwarf unwind info */
     .long    0
     .long    0
+#endif /* use compact unwind */
 #endif /* __APPLE__ */
 
 #endif /* ifndef _MSC_VER */
