diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index e7c2cd19bed..b9ec590cd4e 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -3144,6 +3144,9 @@ extern bool _bfd_elf_mmap_section_contents
 extern void _bfd_elf_munmap_section_contents
   (asection *, void *);
 
+extern bool _bfd_elf_link_keep_memory
+  (struct bfd_link_info *);
+
 /* Large common section.  */
 extern asection _bfd_elf_large_com_section;
 
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 0f963c373be..d1bd11094de 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1932,7 +1932,7 @@ elf_i386_scan_relocs (bfd *abfd,
 
   if (elf_section_data (sec)->this_hdr.contents != contents)
     {
-      if (!converted && !_bfd_link_keep_memory (info))
+      if (!converted && !_bfd_elf_link_keep_memory (info))
 	_bfd_elf_munmap_section_contents (sec, contents);
       else
 	{
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 2e3f86840e5..5e1fad069d1 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2590,7 +2590,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
 
   if (elf_section_data (sec)->this_hdr.contents != contents)
     {
-      if (!converted && !_bfd_link_keep_memory (info))
+      if (!converted && !_bfd_elf_link_keep_memory (info))
 	_bfd_elf_munmap_section_contents (sec, contents);
       else
 	{
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 9162df60bfa..877bb9874ae 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -4182,10 +4182,9 @@ _bfd_elf_link_iterate_on_relocs
 	      || bfd_is_abs_section (o->output_section))
 	    continue;
 
-	  internal_relocs = _bfd_elf_link_info_read_relocs (abfd, info,
-							    o, NULL,
-							    NULL,
-							    _bfd_link_keep_memory (info));
+	  internal_relocs = _bfd_elf_link_info_read_relocs
+	    (abfd, info, o, NULL, NULL,
+	     _bfd_elf_link_keep_memory (info));
 	  if (internal_relocs == NULL)
 	    return false;
 
@@ -5551,10 +5550,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 		  && (s->flags & SEC_DEBUGGING) != 0))
 	    continue;
 
-	  internal_relocs = _bfd_elf_link_info_read_relocs (abfd, info,
-							    s, NULL,
-							    NULL,
-							    _bfd_link_keep_memory (info));
+	  internal_relocs = _bfd_elf_link_info_read_relocs
+	    (abfd, info, s, NULL, NULL,
+	     _bfd_elf_link_keep_memory (info));
 	  if (internal_relocs == NULL)
 	    goto error_free_vers;
 
@@ -13614,7 +13612,7 @@ init_reloc_cookie (struct elf_reloc_cookie *cookie,
 	  info->callbacks->einfo (_("%P%X: can not read symbols: %E\n"));
 	  return false;
 	}
-      if (_bfd_link_keep_memory (info) )
+      if (_bfd_elf_link_keep_memory (info) )
 	{
 	  symtab_hdr->contents = (bfd_byte *) cookie->locsyms;
 	  info->cache_size += (cookie->locsymcount
@@ -13651,9 +13649,9 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
     }
   else
     {
-      cookie->rels = _bfd_elf_link_info_read_relocs (abfd, info, sec,
-						     NULL, NULL,
-						     _bfd_link_keep_memory (info));
+      cookie->rels = _bfd_elf_link_info_read_relocs
+	(abfd, info, sec, NULL, NULL,
+	 _bfd_elf_link_keep_memory (info));
       if (cookie->rels == NULL)
 	return false;
       cookie->rel = cookie->rels;
@@ -15583,3 +15581,50 @@ _bfd_elf_add_dynamic_tags (bfd *output_bfd, struct bfd_link_info *info,
 
   return true;
 }
+
+/* Return false if linker should avoid caching relocation information
+   and symbol tables of input files in memory.  */
+
+bool
+_bfd_elf_link_keep_memory (struct bfd_link_info *info)
+{
+#ifdef USE_MMAP
+  /* Don't cache symbol nor relocation tables if they are mapped in.
+     NB: Since the --no-keep-memory linker option causes:
+
+     https://sourceware.org/bugzilla/show_bug.cgi?id=31458
+
+     this is opt-in by each backend.  */
+  const struct elf_backend_data *bed
+    = get_elf_backend_data (info->output_bfd);
+  if (bed->use_mmap)
+    return false;
+#endif
+  bfd *abfd;
+  bfd_size_type size;
+
+  if (!info->keep_memory)
+    return false;
+
+  if (info->max_cache_size == (bfd_size_type) -1)
+    return true;
+
+  abfd = info->input_bfds;
+  size = info->cache_size;
+  do
+    {
+      if (size >= info->max_cache_size)
+	{
+	  /* Over the limit.  Reduce the memory usage.  */
+	  info->keep_memory = false;
+	  return false;
+	}
+      if (!abfd)
+	break;
+      size += abfd->alloc_size;
+      abfd = abfd->link.next;
+    }
+  while (1);
+
+  return true;
+}
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 889b221a950..7bfc58f12d8 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -848,9 +848,6 @@ extern bfd_byte * _bfd_write_unsigned_leb128
 extern struct bfd_link_info *_bfd_get_link_info (bfd *)
   ATTRIBUTE_HIDDEN;
 
-extern bool _bfd_link_keep_memory (struct bfd_link_info *)
-  ATTRIBUTE_HIDDEN;
-
 extern uintptr_t _bfd_pagesize ATTRIBUTE_HIDDEN;
 extern uintptr_t _bfd_pagesize_m1 ATTRIBUTE_HIDDEN;
 extern uintptr_t _bfd_minimum_mmap_size ATTRIBUTE_HIDDEN;
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 876c1f223c7..36fe6c0ebd0 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -854,9 +854,6 @@ extern bfd_byte * _bfd_write_unsigned_leb128
 extern struct bfd_link_info *_bfd_get_link_info (bfd *)
   ATTRIBUTE_HIDDEN;
 
-extern bool _bfd_link_keep_memory (struct bfd_link_info *)
-  ATTRIBUTE_HIDDEN;
-
 extern uintptr_t _bfd_pagesize ATTRIBUTE_HIDDEN;
 extern uintptr_t _bfd_pagesize_m1 ATTRIBUTE_HIDDEN;
 extern uintptr_t _bfd_minimum_mmap_size ATTRIBUTE_HIDDEN;
diff --git a/bfd/linker.c b/bfd/linker.c
index 36cca9624c2..eb42a78b622 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -3556,38 +3556,3 @@ _bfd_nolink_bfd_define_start_stop (struct bfd_link_info *info ATTRIBUTE_UNUSED,
 {
   return (struct bfd_link_hash_entry *) _bfd_ptr_bfd_null_error (sec->owner);
 }
-
-/* Return false if linker should avoid caching relocation infomation
-   and symbol tables of input files in memory.  */
-
-bool
-_bfd_link_keep_memory (struct bfd_link_info * info)
-{
-  bfd *abfd;
-  bfd_size_type size;
-
-  if (!info->keep_memory)
-    return false;
-
-  if (info->max_cache_size == (bfd_size_type) -1)
-    return true;
-
-  abfd = info->input_bfds;
-  size = info->cache_size;
-  do
-    {
-      if (size >= info->max_cache_size)
-	{
-	  /* Over the limit.  Reduce the memory usage.  */
-	  info->keep_memory = false;
-	  return false;
-	}
-      if (!abfd)
-	break;
-      size += abfd->alloc_size;
-      abfd = abfd->link.next;
-    }
-  while (1);
-
-  return true;
-}
