diff --git a/aclocal.m4 b/aclocal.m4
index 0cc9dcc3dd63e29373c979556e93bfe87e105983..141a42d2174672557ef17ce85c473a72bc292d8e 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -565,6 +565,11 @@ AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS],
         $3="$$3 -D_HPUX_SOURCE"
         $5="$$5 -D_HPUX_SOURCE"
         ;;
+    arm*linux*)
+        # On arm/linux and arm/android, tell gcc to link using the gold linker.
+        # Forcing LD to be ld.gold is done in configre.ac.
+        $3="$$3 -fuse-ld=gold"
+        ;;
     esac
 
     # If gcc knows about the stack protector, turn it off.
diff --git a/configure.ac b/configure.ac
index 689ebd8ccf34714343580a360b2445ff45ba6c7f..b357f19ddd4be24bd95240f51e6956c5645f5c8e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -489,7 +489,18 @@ FP_CPP_CMD_WITH_ARGS(HaskellCPPCmd, HaskellCPPArgs)
 dnl ** Which ld to use?
 dnl --------------------------------------------------------------
 FP_ARG_WITH_PATH_GNU_PROG([LD], [ld], [ld])
-LdCmd="$LD"
+case $target in
+arm*linux*)
+	# Arm requires use of the binutils ld.gold linker.
+	# This case should catch at least arm-unknown-linux-gnueabihf and
+	# arm-linux-androideabi.
+	FP_ARG_WITH_PATH_GNU_PROG([LD_GOLD], [ld.gold], [ld.gold])
+	LdCmd="$LD_GOLD"
+	;;
+*)
+	LdCmd="$LD"
+	;;
+esac
 AC_SUBST([LdCmd])
 
 dnl ** Which nm to use?
diff --git a/libffi/ghc.mk b/libffi/ghc.mk
index abbe87f23c3074cf68481426606f6be4fd1c8977..a5645de9bab5374381c6d38131080caadd05cad4 100644
--- a/libffi/ghc.mk
+++ b/libffi/ghc.mk
@@ -100,7 +100,7 @@ $(libffi_STAMP_CONFIGURE): $(TOUCH_DEP)
 	    NM=$(NM) \
 	    RANLIB=$(REAL_RANLIB_CMD) \
         CFLAGS="$(SRC_CC_OPTS) $(CONF_CC_OPTS_STAGE1) -w" \
-        LDFLAGS="$(SRC_LD_OPTS) $(CONF_GCC_LINKER_OPTS_STAGE1) -w" \
+        LDFLAGS="$(SRC_LD_OPTS) -w" \
         "$(SHELL)" ./configure \
 	          --prefix=$(TOP)/libffi/build/inst \
 	          --libdir=$(TOP)/libffi/build/inst/lib \
diff --git a/mk/config.mk.in b/mk/config.mk.in
index 42720c8c4aebad3b227b6e3121eb8813db8022ff..49d8610533ba3ff16bc6d2adc8e436ac0d74beb6 100644
--- a/mk/config.mk.in
+++ b/mk/config.mk.in
@@ -568,7 +568,6 @@ define set_stage_HSC2HS_OPTS
 # $1 = stage
 SRC_HSC2HS_OPTS_STAGE$1 += $$(addprefix --cflag=,$$(filter-out -O,$$(SRC_CC_OPTS) $$(CONF_CC_OPTS_STAGE$1)))
 SRC_HSC2HS_OPTS_STAGE$1 += $$(addprefix --cflag=,$$(CONF_CPP_OPTS_STAGE$1))
-SRC_HSC2HS_OPTS_STAGE$1 += $$(addprefix --lflag=,$$(CONF_GCC_LINKER_OPTS_STAGE$1))
 endef
 $(eval $(call set_stage_HSC2HS_OPTS,0))
 $(eval $(call set_stage_HSC2HS_OPTS,1))
diff --git a/rules/build-package-data.mk b/rules/build-package-data.mk
index 494b89afc5a291807d503bc569fb9653b8f43635..817bf8db9eb3960bc0d85f6f759f87904506aa22 100644
--- a/rules/build-package-data.mk
+++ b/rules/build-package-data.mk
@@ -50,7 +50,7 @@ endif
 # for a feature it may not generate warning-free C code, and thus may
 # think that the feature doesn't exist if -Werror is on.
 $1_$2_CONFIGURE_CFLAGS = $$(filter-out -Werror,$$(SRC_CC_OPTS)) $$(CONF_CC_OPTS_STAGE$3) $$($1_CC_OPTS) $$($1_$2_CC_OPTS) $$(SRC_CC_WARNING_OPTS)
-$1_$2_CONFIGURE_LDFLAGS = $$(SRC_LD_OPTS) $$(CONF_GCC_LINKER_OPTS_STAGE$3) $$($1_LD_OPTS) $$($1_$2_LD_OPTS)
+$1_$2_CONFIGURE_LDFLAGS = $$(SRC_LD_OPTS) $$($1_LD_OPTS) $$($1_$2_LD_OPTS)
 $1_$2_CONFIGURE_CPPFLAGS = $$(SRC_CPP_OPTS) $$(CONF_CPP_OPTS_STAGE$3) $$($1_CPP_OPTS) $$($1_$2_CPP_OPTS)
 
 $1_$2_CONFIGURE_OPTS += --configure-option=CFLAGS="$$($1_$2_CONFIGURE_CFLAGS)"
diff --git a/rules/distdir-opts.mk b/rules/distdir-opts.mk
index 3126a8832ef436c03474a353ad124075dd569001..b2f0d1b9ffbcdb171f48b52f7be1ff87b6d416ac 100644
--- a/rules/distdir-opts.mk
+++ b/rules/distdir-opts.mk
@@ -65,7 +65,6 @@ $1_$2_DIST_LD_LIB_DIRS := $$(subst $$(space)',$$(space)-L',$$(space)$$($1_$2_DEP
 endif
 
 $1_$2_DIST_LD_OPTS = \
- $$(CONF_GCC_LINKER_OPTS_STAGE$3) \
  $$(SRC_LD_OPTS) \
  $$($1_LD_OPTS) \
  $$($1_$2_LD_OPTS) \