diff --git a/elf/Makefile b/elf/Makefile
index 2dcd2b88e0..cb203d58b4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -328,7 +328,7 @@ tests-internal += \
 	 ifuncmain1staticpic \
 	 ifuncmain2 ifuncmain2pic ifuncmain3 ifuncmain4 \
 	 ifuncmain5 ifuncmain5pic ifuncmain5staticpic \
-	 ifuncmain7 ifuncmain7pic
+	 ifuncmain7 ifuncmain7pic ifuncpreload1
 ifunc-test-modules = ifuncdep1 ifuncdep1pic ifuncdep2 ifuncdep2pic \
 		     ifuncdep5 ifuncdep5pic
 extra-test-objs += $(ifunc-test-modules:=.o)
@@ -339,7 +339,8 @@ ifunc-pie-tests = ifuncmain1pie ifuncmain1vispie ifuncmain1staticpie \
 tests-internal += $(ifunc-pie-tests)
 tests-pie += $(ifunc-pie-tests)
 endif
-modules-names += ifuncmod1 ifuncmod3 ifuncmod5 ifuncmod6
+modules-names += ifuncmod1 ifuncmod3 ifuncmod5 ifuncmod6 \
+		 ifuncpreloadmod1a ifuncpreloadmod1b
 endif
 endif
 
@@ -1454,3 +1455,8 @@ tst-libc_dlvsym-static-ENV = \
 $(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so
 
 $(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so
+
+$(objpfx)ifuncpreload1: $(objpfx)ifuncpreloadmod1a.so
+$(objpfx)ifuncpreload1.out: $(objpfx)ifuncpreloadmod1b.so
+ifuncpreload1-ENV = \
+  LD_PRELOAD=$(objpfx)ifuncpreloadmod1b.so LD_BIND_NOW=1
diff --git a/elf/ifuncpreload1.c b/elf/ifuncpreload1.c
new file mode 100644
index 0000000000..172df33ac3
--- /dev/null
+++ b/elf/ifuncpreload1.c
@@ -0,0 +1,39 @@
+/* Test for relocation over with IFUNC symbols.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+
+extern void bar (char *, const char *, unsigned int);
+
+static int
+do_test (void)
+{
+  char dst[50];
+  const char src[] =
+    {
+      "This is a test"
+    };
+  bar (dst, src, sizeof (src));
+  if (__builtin_memcmp (dst, src, sizeof (src)) != 0)
+    __builtin_abort ();
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/ifuncpreloadmod1a.c b/elf/ifuncpreloadmod1a.c
new file mode 100644
index 0000000000..be9f8832b8
--- /dev/null
+++ b/elf/ifuncpreloadmod1a.c
@@ -0,0 +1,23 @@
+/* Shared module to test for relocation over with IFUNC symbols.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+void
+bar (char *dst, const char *src, unsigned int size)
+{
+  __builtin_memmove (dst, src, size);
+}
diff --git a/elf/ifuncpreloadmod1b.c b/elf/ifuncpreloadmod1b.c
new file mode 100644
index 0000000000..1194ae20e4
--- /dev/null
+++ b/elf/ifuncpreloadmod1b.c
@@ -0,0 +1,49 @@
+/* Shared module to test for relocation over with IFUNC symbols.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+
+void *
+my_memmove(void *dst_p, const void *src_p, size_t n)
+{
+  const char *src = src_p;
+  char *dst = dst_p;
+  char *ret = dst;
+  if (src < dst)
+    {
+      dst += n;
+      src += n;
+      while (n--)
+	*--dst = *--src;
+    }
+  else
+    while (n--)
+      *dst++ = *src++;
+  return ret;
+}
+
+void *memmove (void *, const void *, size_t)
+  __attribute__ ((ifunc ("resolve_memmove")));
+
+typedef void *(*memmove_t) (void *, const void *, size_t);
+
+static memmove_t
+resolve_memmove (void)
+{
+  return my_memmove;
+}
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 1afdcbd9ea..4d0afad074 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -68,7 +68,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden;
   extern void _dl_runtime_profile (Elf32_Word) attribute_hidden;
 
-  if (l->l_info[DT_JMPREL] && lazy)
+  /* Always set up GOT since we may have to fall back to lazy binding
+     even with non-lazy binding is requested.   */
+  if (l->l_info[DT_JMPREL])
     {
       /* The GOT entries for functions in the PLT have not yet been filled
 	 in.  Their initial contents will arrange when called to push an
@@ -332,16 +334,18 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	      && sym_map->l_type != lt_executable
 	      && !sym_map->l_relocated)
 	    {
-	      const char *strtab
-		= (const char *) D_PTR (map, l_info[DT_STRTAB]);
-	      _dl_error_printf ("\
-%s: Relink `%s' with `%s' for IFUNC symbol `%s'\n",
-				RTLD_PROGNAME, map->l_name,
-				sym_map->l_name,
-				strtab + refsym->st_name);
+	      /* NB: The symbol reference is resolved to IFUNC symbol
+	         from a shared object which hasn't been relocated yet.
+		 Relocate the GOT entry to enable lazy binding.  */
+	      value = map->l_addr + *reloc_addr;
+	      /* Disable RELRO so that the GOT entry can updated by lazy
+		 binding later.  */
+	      if (map->l_info[DT_BIND_NOW] != NULL)
+		map->l_relro_size = 0;
 	    }
+	  else
 # endif
-	  value = ((Elf32_Addr (*) (void)) value) ();
+	    value = ((Elf32_Addr (*) (void)) value) ();
 	}
 
       switch (r_type)
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
index 1942ed5061..2aff922f96 100644
--- a/sysdeps/x86_64/dl-machine.h
+++ b/sysdeps/x86_64/dl-machine.h
@@ -73,7 +73,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   extern void _dl_runtime_profile_avx (ElfW(Word)) attribute_hidden;
   extern void _dl_runtime_profile_avx512 (ElfW(Word)) attribute_hidden;
 
-  if (l->l_info[DT_JMPREL] && lazy)
+  /* Always set up GOT since we may have to fall back to lazy binding
+     even with non-lazy binding is requested.   */
+  if (l->l_info[DT_JMPREL])
     {
       /* The GOT entries for functions in the PLT have not yet been filled
 	 in.  Their initial contents will arrange when called to push an
@@ -318,16 +320,18 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
 	      && sym_map->l_type != lt_executable
 	      && !sym_map->l_relocated)
 	    {
-	      const char *strtab
-		= (const char *) D_PTR (map, l_info[DT_STRTAB]);
-	      _dl_error_printf ("\
-%s: Relink `%s' with `%s' for IFUNC symbol `%s'\n",
-				RTLD_PROGNAME, map->l_name,
-				sym_map->l_name,
-				strtab + refsym->st_name);
+	      /* NB: The symbol reference is resolved to IFUNC symbol
+	         from a shared object which hasn't been relocated yet.
+		 Relocate the GOT entry to enable lazy binding.  */
+	      value = map->l_addr + *reloc_addr;
+	      /* Disable RELRO so that the GOT entry can updated by lazy
+		 binding later.  */
+	      if (map->l_info[DT_BIND_NOW] != NULL)
+		map->l_relro_size = 0;
 	    }
+	  else
 # endif
-	  value = ((ElfW(Addr) (*) (void)) value) ();
+	    value = ((ElfW(Addr) (*) (void)) value) ();
 	}
 
       switch (r_type)
