diff --git a/bfd/aout-target.h b/bfd/aout-target.h
index 6d2f3c767a2..7765f5c80d8 100644
--- a/bfd/aout-target.h
+++ b/bfd/aout-target.h
@@ -598,18 +598,7 @@ MY_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
 #endif
 
 #ifndef MY_close_and_cleanup
-
-/* Handle closing of a BFD including the resource-releasing parts.  */
-
-static bool
-MY_close_and_cleanup (bfd *abfd)
-{
-  if (!MY_bfd_free_cached_info (abfd))
-    return false;
-
-  return _bfd_generic_close_and_cleanup (abfd);
-}
-
+#define MY_close_and_cleanup _bfd_generic_close_and_cleanup
 #endif
 
 #ifndef MY_get_dynamic_symtab_upper_bound
diff --git a/bfd/aoutx.h b/bfd/aoutx.h
index 6d6527640fe..1a8fd85cf14 100644
--- a/bfd/aoutx.h
+++ b/bfd/aoutx.h
@@ -2896,35 +2896,33 @@ NAME (aout, sizeof_headers) (bfd *abfd,
   return adata (abfd).exec_bytes_size;
 }
 
-/* Free all information we have cached for this BFD.  We can always
-   read it again later if we need it.  */
+/* Throw away most malloc'd and alloc'd information for this BFD.  */
 
 bool
 NAME (aout, bfd_free_cached_info) (bfd *abfd)
 {
-  asection *o;
-
-  if (bfd_get_format (abfd) != bfd_object
-      || abfd->tdata.aout_data == NULL)
-    return true;
-
+  if ((bfd_get_format (abfd) == bfd_object
+       || bfd_get_format (abfd) == bfd_core)
+      && abfd->tdata.aout_data != NULL)
+    {
 #define BFCI_FREE(x) do { free (x); x = NULL; } while (0)
-  BFCI_FREE (adata (abfd).line_buf);
-  BFCI_FREE (obj_aout_symbols (abfd));
+      BFCI_FREE (adata (abfd).line_buf);
+      BFCI_FREE (obj_aout_symbols (abfd));
 #ifdef USE_MMAP
-  obj_aout_external_syms (abfd) = 0;
-  bfd_free_window (&obj_aout_sym_window (abfd));
-  bfd_free_window (&obj_aout_string_window (abfd));
-  obj_aout_external_strings (abfd) = 0;
+      obj_aout_external_syms (abfd) = 0;
+      bfd_free_window (&obj_aout_sym_window (abfd));
+      bfd_free_window (&obj_aout_string_window (abfd));
+      obj_aout_external_strings (abfd) = 0;
 #else
-  BFCI_FREE (obj_aout_external_syms (abfd));
-  BFCI_FREE (obj_aout_external_strings (abfd));
+      BFCI_FREE (obj_aout_external_syms (abfd));
+      BFCI_FREE (obj_aout_external_strings (abfd));
 #endif
-  for (o = abfd->sections; o != NULL; o = o->next)
-    BFCI_FREE (o->relocation);
+      for (asection *o = abfd->sections; o != NULL; o = o->next)
+	BFCI_FREE (o->relocation);
 #undef BFCI_FREE
+    }
 
-  return true;
+  return _bfd_generic_bfd_free_cached_info (abfd);
 }
 
 /* a.out link code.  */
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 421dc8f7ee5..271a24fff69 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -4436,8 +4436,8 @@ const struct xcoff_dwsect_name xcoff_dwsect_names[] = {
 };
 
 /* For generic entry points.  */
-#define _bfd_xcoff_close_and_cleanup _bfd_coff_close_and_cleanup
-#define _bfd_xcoff_bfd_free_cached_info _bfd_bool_bfd_true
+#define _bfd_xcoff_close_and_cleanup coff_close_and_cleanup
+#define _bfd_xcoff_bfd_free_cached_info coff_bfd_free_cached_info
 #define _bfd_xcoff_new_section_hook coff_new_section_hook
 #define _bfd_xcoff_get_section_contents _bfd_generic_get_section_contents
 #define _bfd_xcoff_get_section_contents_in_window \
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index 71d21583ee5..d76c99a3eca 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -2618,8 +2618,8 @@ const bfd_target rs6000_xcoff64_vec =
     },
 
     /* Generic */
-    _bfd_coff_close_and_cleanup,
-    _bfd_bool_bfd_true,
+    coff_close_and_cleanup,
+    coff_bfd_free_cached_info,
     coff_new_section_hook,
     _bfd_generic_get_section_contents,
     _bfd_generic_get_section_contents_in_window,
@@ -2891,8 +2891,8 @@ const bfd_target rs6000_xcoff64_aix_vec =
     },
 
     /* Generic */
-    _bfd_coff_close_and_cleanup,
-    _bfd_bool_bfd_true,
+    coff_close_and_cleanup,
+    coff_bfd_free_cached_info,
     coff_new_section_hook,
     _bfd_generic_get_section_contents,
     _bfd_generic_get_section_contents_in_window,
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 47562713938..62720255b7f 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -5866,11 +5866,11 @@ static const bfd_coff_backend_data bigobj_swap_table =
 #endif /* COFF_WITH_PE_BIGOBJ */
 
 #ifndef coff_close_and_cleanup
-#define coff_close_and_cleanup		    _bfd_coff_close_and_cleanup
+#define coff_close_and_cleanup		    _bfd_generic_close_and_cleanup
 #endif
 
 #ifndef coff_bfd_free_cached_info
-#define coff_bfd_free_cached_info	    _bfd_generic_bfd_free_cached_info
+#define coff_bfd_free_cached_info	    _bfd_coff_free_cached_info
 #endif
 
 #ifndef coff_get_section_contents
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index afc663c056f..9d45253178e 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -3275,43 +3275,37 @@ bfd_coff_group_name (bfd *abfd, const asection *sec)
 }
 
 bool
-_bfd_coff_close_and_cleanup (bfd *abfd)
+_bfd_coff_free_cached_info (bfd *abfd)
 {
-  struct coff_tdata *tdata = coff_data (abfd);
+  struct coff_tdata *tdata;
 
-  if (tdata != NULL)
+  if (bfd_family_coff (abfd)
+      && (bfd_get_format (abfd) == bfd_object
+	  || bfd_get_format (abfd) == bfd_core)
+      && (tdata = coff_data (abfd)) != NULL)
     {
-      if (bfd_family_coff (abfd) && bfd_get_format (abfd) == bfd_object)
+      if (tdata->section_by_index)
 	{
-	  if (tdata->section_by_index)
-	    {
-	      htab_delete (tdata->section_by_index);
-	      tdata->section_by_index = NULL;
-	    }
+	  htab_delete (tdata->section_by_index);
+	  tdata->section_by_index = NULL;
+	}
 
-	  if (tdata->section_by_target_index)
-	    {
-	      htab_delete (tdata->section_by_target_index);
-	      tdata->section_by_target_index = NULL;
-	    }
+      if (tdata->section_by_target_index)
+	{
+	  htab_delete (tdata->section_by_target_index);
+	  tdata->section_by_target_index = NULL;
 	}
 
+      _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info);
+      _bfd_stab_cleanup (abfd, &tdata->line_info);
+
       /* PR 25447:
 	 Do not clear the keep_syms and keep_strings flags.
 	 These may have been set by pe_ILF_build_a_bfd() indicating
 	 that the syms and strings pointers are not to be freed.  */
-      if (bfd_get_format (abfd) == bfd_object
-	  && bfd_family_coff (abfd)
-	  && !_bfd_coff_free_symbols (abfd))
+      if (!_bfd_coff_free_symbols (abfd))
 	return false;
-
-      if (bfd_get_format (abfd) == bfd_object
-	  || bfd_get_format (abfd) == bfd_core)
-	{
-	  _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info);
-	  _bfd_stab_cleanup (abfd, &tdata->line_info);
-	}
     }
 
-  return _bfd_generic_close_and_cleanup (abfd);
+  return _bfd_generic_bfd_free_cached_info (abfd);
 }
diff --git a/bfd/doc/bfdint.texi b/bfd/doc/bfdint.texi
index cb251b1a0d6..8cf08576c1b 100644
--- a/bfd/doc/bfdint.texi
+++ b/bfd/doc/bfdint.texi
@@ -493,22 +493,25 @@ functions which don't easily fit into other categories.
 
 @table @samp
 @item _close_and_cleanup
-Free any target specific information associated with the BFD.  This is
-called when any BFD is closed (the @samp{bfd_write_contents} function
-mentioned earlier is only called for a BFD opened for writing).  Most
-targets use @samp{bfd_alloc} to allocate all target specific
-information, and therefore don't have to do anything in this function.
-This function pointer is typically set to
-@samp{_bfd_generic_close_and_cleanup}, which simply returns true.
+Free any target specific information associated with the BFD that
+isn't freed by @samp{_bfd_free_cached_info}.  This is called when any
+BFD is closed (the @samp{bfd_write_contents} function mentioned
+earlier is only called for a BFD opened for writing).  This function
+pointer is typically set to @samp{_bfd_generic_close_and_cleanup},
+which simply returns true.
 
 @item _bfd_free_cached_info
-Free any cached information associated with the BFD which can be
-recreated later if necessary.  This is used to reduce the memory
-consumption required by programs using BFD.  This is normally called via
-the @samp{bfd_free_cached_info} macro.  It is used by the default
-archive routines when computing the archive map.  Most targets do not
-do anything special for this entry point, and just set it to
-@samp{_bfd_generic_free_cached_info}, which simply returns true.
+This function is designed for use by the generic archive routines, and
+is also called by bfd_close.  After creating the archive map archive
+element bfds don't need symbols and other structures.  Many targets
+use @samp{bfd_alloc} to allocate target specific information and thus
+do not need to do anything special for this entry point, and just set
+it to @samp{_bfd_generic_free_cached_info} which throws away objalloc
+memory for the bfd.  Note that this means the bfd tdata and sections
+are no longer available.  Targets that malloc memory, attaching it to
+the bfd tdata or to section used_by_bfd should implement a target
+version of this function to free that memory before calling
+@samp{_bfd_generic_free_cached_info}.
 
 @item _new_section_hook
 This is called from @samp{bfd_make_section_anyway} whenever a new
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 573f52d0299..f2626c541e2 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -110,18 +110,20 @@ _bfd_ecoff_mkobject_hook (bfd *abfd, void * filehdr, void * aouthdr)
 }
 
 bool
-_bfd_ecoff_close_and_cleanup (bfd *abfd)
+_bfd_ecoff_bfd_free_cached_info (bfd *abfd)
 {
-  struct ecoff_tdata *tdata = ecoff_data (abfd);
+  struct ecoff_tdata *tdata;
 
-  if (tdata != NULL && bfd_get_format (abfd) == bfd_object)
+  if ((bfd_get_format (abfd) == bfd_object
+       || bfd_get_format (abfd) == bfd_core)
+      && (tdata = ecoff_data (abfd)) != NULL)
     while (tdata->mips_refhi_list != NULL)
       {
 	struct mips_hi *ref = tdata->mips_refhi_list;
 	tdata->mips_refhi_list = ref->next;
 	free (ref);
       }
-  return _bfd_generic_close_and_cleanup (abfd);
+  return _bfd_generic_bfd_free_cached_info (abfd);
 }
 
 /* Initialize a new section.  */
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 2a64a1e6a03..e08c5a110e5 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2721,7 +2721,7 @@ extern bool bfd_elf_link_record_dynamic_symbol
 extern int bfd_elf_link_record_local_dynamic_symbol
   (struct bfd_link_info *, bfd *, long);
 
-extern bool _bfd_elf_close_and_cleanup
+extern bool _bfd_elf_free_cached_info
   (bfd *);
 
 extern bool _bfd_elf_common_definition
diff --git a/bfd/elf.c b/bfd/elf.c
index af2fb04dcbe..c4e2f89a16e 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -9589,21 +9589,22 @@ _bfd_elf_validate_reloc (bfd *abfd, arelent *areloc)
 }
 
 bool
-_bfd_elf_close_and_cleanup (bfd *abfd)
+_bfd_elf_free_cached_info (bfd *abfd)
 {
-  struct elf_obj_tdata *tdata = elf_tdata (abfd);
-  if (tdata != NULL
-      && (bfd_get_format (abfd) == bfd_object
-	  || bfd_get_format (abfd) == bfd_core))
+  struct elf_obj_tdata *tdata;
+
+  if ((bfd_get_format (abfd) == bfd_object
+       || bfd_get_format (abfd) == bfd_core)
+      && (tdata = elf_tdata (abfd)) != NULL)
     {
-      if (elf_tdata (abfd)->o != NULL && elf_shstrtab (abfd) != NULL)
+      if (tdata->o != NULL && elf_shstrtab (abfd) != NULL)
 	_bfd_elf_strtab_free (elf_shstrtab (abfd));
       _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info);
       _bfd_dwarf1_cleanup_debug_info (abfd, &tdata->dwarf1_find_line_info);
       _bfd_stab_cleanup (abfd, &tdata->line_info);
     }
 
-  return _bfd_generic_close_and_cleanup (abfd);
+  return _bfd_generic_bfd_free_cached_info (abfd);
 }
 
 /* For Rel targets, we encode meaningful data for BFD_RELOC_VTABLE_ENTRY
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index 65e8131d5b1..27bd98607fe 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -2599,7 +2599,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 					_bfd_mips_elf_print_private_bfd_data
 #define bfd_elf32_bfd_relax_section	_bfd_mips_elf_relax_section
 #define bfd_elf32_mkobject		_bfd_mips_elf_mkobject
-#define bfd_elf32_close_and_cleanup	_bfd_mips_elf_close_and_cleanup
+#define bfd_elf32_free_cached_info	_bfd_mips_elf_free_cached_info
 
 /* Support for SGI-ish mips targets.  */
 #define TARGET_LITTLE_SYM		mips_elf32_le_vec
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index 81d58c8cbc1..5cf9a665ae5 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -1519,13 +1519,6 @@ elf64_alpha_find_nearest_line (bfd *abfd, asymbol **symbols,
 	    (*swap->swap_fdr_in) (abfd, fraw_src, fdr_ptr);
 
 	  alpha_elf_tdata (abfd)->find_line_info = fi;
-
-	  /* Note that we don't bother to ever free this information.
-	     find_nearest_line is either called all the time, as in
-	     objdump -l, so the information should be saved, or it is
-	     rarely called, as in ld error messages, so the memory
-	     wasted is unimportant.  Still, it would probably be a
-	     good idea for free_cached_info to throw it away.  */
 	}
 
       if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
diff --git a/bfd/elf64-ia64-vms.c b/bfd/elf64-ia64-vms.c
index 1866a5798fa..a260c7ee6d8 100644
--- a/bfd/elf64-ia64-vms.c
+++ b/bfd/elf64-ia64-vms.c
@@ -4728,7 +4728,7 @@ elf64_vms_close_and_cleanup (bfd *abfd)
 	}
     }
 
-  return _bfd_elf_close_and_cleanup (abfd);
+  return _bfd_generic_close_and_cleanup (abfd);
 }
 
 /* Add symbols from an ELF object file to the linker hash table.  */
diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c
index 696083e33a2..1179f622193 100644
--- a/bfd/elf64-mips.c
+++ b/bfd/elf64-mips.c
@@ -4815,7 +4815,7 @@ const struct elf_size_info mips_elf64_size_info =
 
 #define bfd_elf64_get_dynamic_reloc_upper_bound mips_elf64_get_dynamic_reloc_upper_bound
 #define bfd_elf64_mkobject		_bfd_mips_elf_mkobject
-#define bfd_elf64_close_and_cleanup	_bfd_mips_elf_close_and_cleanup
+#define bfd_elf64_free_cached_info	_bfd_mips_elf_free_cached_info
 
 /* The SGI style (n)64 NewABI.  */
 #define TARGET_LITTLE_SYM		mips_elf64_le_vec
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index a977bec2f50..9c0762a15ef 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -18406,7 +18406,7 @@ ppc64_elf_free_cached_info (bfd *abfd)
       if (opd->reloc_count == 0)
 	free (ppc64_elf_section_data (opd)->u.opd.u.contents);
 
-  return _bfd_free_cached_info (abfd);
+  return _bfd_generic_bfd_free_cached_info (abfd);
 }
 
 #include "elf64-target.h"
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c
index 9e943f2d25a..e6aa1673586 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -4197,7 +4197,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 #define bfd_elf32_bfd_print_private_bfd_data \
 					_bfd_mips_elf_print_private_bfd_data
 #define bfd_elf32_mkobject		mips_elf_n32_mkobject
-#define bfd_elf32_close_and_cleanup	_bfd_mips_elf_close_and_cleanup
+#define bfd_elf32_free_cached_info	_bfd_mips_elf_free_cached_info
 
 /* Support for SGI-ish mips targets using n32 ABI.  */
 
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 3ad5cb95b40..a75cd365a02 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -8742,7 +8742,7 @@ elfNN_aarch64_bfd_free_cached_info (bfd *abfd)
     bfd_map_over_sections (abfd,
 			   unrecord_section_via_map_over_sections, NULL);
 
-  return _bfd_free_cached_info (abfd);
+  return _bfd_generic_bfd_free_cached_info (abfd);
 }
 
 /* Create dynamic sections. This is different from the ARM backend in that
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 49355a42f7d..7d29ec2d105 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -1419,25 +1419,25 @@ free_ecoff_debug (struct ecoff_debug_info *debug)
 }
 
 bool
-_bfd_mips_elf_close_and_cleanup (bfd *abfd)
+_bfd_mips_elf_free_cached_info (bfd *abfd)
 {
-  if (bfd_get_format (abfd) == bfd_object)
+  struct mips_elf_obj_tdata *tdata;
+
+  if ((bfd_get_format (abfd) == bfd_object
+       || bfd_get_format (abfd) == bfd_core)
+      && (tdata = mips_elf_tdata (abfd)) != NULL)
     {
-      struct mips_elf_obj_tdata *tdata = mips_elf_tdata (abfd);
-      if (tdata != NULL)
+      BFD_ASSERT (tdata->root.object_id == MIPS_ELF_DATA);
+      while (tdata->mips_hi16_list != NULL)
 	{
-	  BFD_ASSERT (tdata->root.object_id == MIPS_ELF_DATA);
-	  while (tdata->mips_hi16_list != NULL)
-	    {
-	      struct mips_hi16 *hi = tdata->mips_hi16_list;
-	      tdata->mips_hi16_list = hi->next;
-	      free (hi);
-	    }
-	  if (tdata->find_line_info != NULL)
-	    free_ecoff_debug (&tdata->find_line_info->d);
+	  struct mips_hi16 *hi = tdata->mips_hi16_list;
+	  tdata->mips_hi16_list = hi->next;
+	  free (hi);
 	}
+      if (tdata->find_line_info != NULL)
+	free_ecoff_debug (&tdata->find_line_info->d);
     }
-  return _bfd_elf_close_and_cleanup (abfd);
+  return _bfd_elf_free_cached_info (abfd);
 }
 
 bool
diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
index 2c790ed5ed6..d78b6798754 100644
--- a/bfd/elfxx-mips.h
+++ b/bfd/elfxx-mips.h
@@ -37,7 +37,7 @@ struct ecoff_debug_info;
 
 extern bool _bfd_mips_elf_mkobject
   (bfd *);
-extern bool _bfd_mips_elf_close_and_cleanup
+extern bool _bfd_mips_elf_free_cached_info
   (bfd *);
 extern bool _bfd_mips_elf_new_section_hook
   (bfd *, asection *);
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 9bcbdfb27dd..8eabad4bd3f 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -28,10 +28,10 @@
    one for little-endian machines.   */
 
 #ifndef bfd_elfNN_close_and_cleanup
-#define	bfd_elfNN_close_and_cleanup _bfd_elf_close_and_cleanup
+#define	bfd_elfNN_close_and_cleanup _bfd_generic_close_and_cleanup
 #endif
 #ifndef bfd_elfNN_bfd_free_cached_info
-#define bfd_elfNN_bfd_free_cached_info _bfd_free_cached_info
+#define bfd_elfNN_bfd_free_cached_info _bfd_elf_free_cached_info
 #endif
 #ifndef bfd_elfNN_get_section_contents
 #define bfd_elfNN_get_section_contents _bfd_generic_get_section_contents
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 07ef59a24e1..ae1b61aa4e3 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -261,7 +261,7 @@ extern int bfd_generic_stat_arch_elt
 extern bool _bfd_archive_close_and_cleanup
   (bfd *) ATTRIBUTE_HIDDEN;
 extern void _bfd_unlink_from_archive_parent (bfd *) ATTRIBUTE_HIDDEN;
-#define _bfd_generic_bfd_free_cached_info _bfd_bool_bfd_true
+#define _bfd_generic_bfd_free_cached_info _bfd_free_cached_info
 extern bool _bfd_generic_new_section_hook
   (bfd *, asection *) ATTRIBUTE_HIDDEN;
 extern bool _bfd_generic_get_section_contents
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 4f082ac75d6..92fbf0195ee 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -267,7 +267,7 @@ extern int bfd_generic_stat_arch_elt
 extern bool _bfd_archive_close_and_cleanup
   (bfd *) ATTRIBUTE_HIDDEN;
 extern void _bfd_unlink_from_archive_parent (bfd *) ATTRIBUTE_HIDDEN;
-#define _bfd_generic_bfd_free_cached_info _bfd_bool_bfd_true
+#define _bfd_generic_bfd_free_cached_info _bfd_free_cached_info
 extern bool _bfd_generic_new_section_hook
   (bfd *, asection *) ATTRIBUTE_HIDDEN;
 extern bool _bfd_generic_get_section_contents
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 96f44512ac5..4e2203656de 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -405,7 +405,7 @@ extern bfd_vma bfd_coff_reloc16_get_value
   (arelent *, struct bfd_link_info *, asection *);
 extern void bfd_perform_slip
   (bfd *, unsigned int, asection *, bfd_vma);
-extern bool _bfd_coff_close_and_cleanup
+extern bool _bfd_coff_free_cached_info
   (bfd *);
 
 /* Functions and types in cofflink.c.  */
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index 61561c5a471..b53c3117f50 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -409,7 +409,7 @@ extern bfd_vma bfd_coff_reloc16_get_value
   (arelent *, struct bfd_link_info *, asection *);
 extern void bfd_perform_slip
   (bfd *, unsigned int, asection *, bfd_vma);
-extern bool _bfd_coff_close_and_cleanup
+extern bool _bfd_coff_free_cached_info
   (bfd *);
 
 /* Functions and types in cofflink.c.  */
diff --git a/bfd/libecoff.h b/bfd/libecoff.h
index 12664b890c4..0c4bb43c39a 100644
--- a/bfd/libecoff.h
+++ b/bfd/libecoff.h
@@ -243,8 +243,8 @@ extern bool _bfd_ecoff_slurp_symbolic_info
 
 extern bool _bfd_ecoff_write_object_contents (bfd *);
 
-extern bool _bfd_ecoff_close_and_cleanup (bfd *);
-#define _bfd_ecoff_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define _bfd_ecoff_close_and_cleanup _bfd_generic_close_and_cleanup
+extern bool _bfd_ecoff_bfd_free_cached_info (bfd *);
 extern bool _bfd_ecoff_new_section_hook
   (bfd *, asection *);
 extern bool _bfd_ecoff_get_section_contents
diff --git a/bfd/mach-o-target.c b/bfd/mach-o-target.c
index f8e8dc73dc8..5211486696b 100644
--- a/bfd/mach-o-target.c
+++ b/bfd/mach-o-target.c
@@ -24,7 +24,6 @@
 #ifndef MACH_O_TARGET_COMMON_DEFINED
 #define MACH_O_TARGET_COMMON_DEFINED
 
-#define bfd_mach_o_bfd_free_cached_info		      _bfd_generic_bfd_free_cached_info
 #define bfd_mach_o_get_section_contents_in_window     _bfd_generic_get_section_contents_in_window
 #define bfd_mach_o_bfd_print_private_bfd_data	      bfd_mach_o_bfd_print_private_bfd_data
 #define bfd_mach_o_bfd_is_target_special_symbol	      _bfd_bool_bfd_asymbol_false
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 9b9aba5ae89..55407fa347d 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -6199,8 +6199,6 @@ bfd_mach_o_close_and_cleanup (bfd *abfd)
   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
   if (bfd_get_format (abfd) == bfd_object && mdata != NULL)
     {
-      _bfd_dwarf2_cleanup_debug_info (abfd, &mdata->dwarf2_find_line_info);
-      bfd_mach_o_free_cached_info (abfd);
       if (mdata->dsym_bfd != NULL)
 	{
 	  bfd *fat_bfd = mdata->dsym_bfd->my_archive;
@@ -6231,18 +6229,27 @@ bfd_mach_o_close_and_cleanup (bfd *abfd)
 }
 
 bool
-bfd_mach_o_free_cached_info (bfd *abfd)
+bfd_mach_o_bfd_free_cached_info (bfd *abfd)
 {
-  bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
-  asection *asect;
-  free (mdata->dyn_reloc_cache);
-  mdata->dyn_reloc_cache = NULL;
-  for (asect = abfd->sections; asect != NULL; asect = asect->next)
+  bfd_mach_o_data_struct *mdata;
+
+  if ((bfd_get_format (abfd) == bfd_object
+       || bfd_get_format (abfd) == bfd_core)
+      && (mdata = bfd_mach_o_get_data (abfd)) != NULL)
     {
-      free (asect->relocation);
-      asect->relocation = NULL;
+      _bfd_dwarf2_cleanup_debug_info (abfd, &mdata->dwarf2_find_line_info);
+      free (mdata->dyn_reloc_cache);
+      mdata->dyn_reloc_cache = NULL;
+
+      for (asection *asect = abfd->sections; asect; asect = asect->next)
+	{
+	  free (asect->relocation);
+	  asect->relocation = NULL;
+	}
     }
 
+  /* Do not call _bfd_generic_bfd_free_cached_info here.
+     bfd_mach_o_close_and_cleanup uses tdata.  */
   return true;
 }
 
diff --git a/bfd/mach-o.h b/bfd/mach-o.h
index 8d99c93ea5f..1c71163bb3a 100644
--- a/bfd/mach-o.h
+++ b/bfd/mach-o.h
@@ -733,7 +733,7 @@ bool bfd_mach_o_find_nearest_line (bfd *, asymbol **,
   _bfd_nosymbols_find_nearest_line_with_alt
 #define bfd_mach_o_find_line _bfd_nosymbols_find_line
 bool bfd_mach_o_close_and_cleanup (bfd *);
-bool bfd_mach_o_free_cached_info (bfd *);
+bool bfd_mach_o_bfd_free_cached_info (bfd *);
 
 unsigned int bfd_mach_o_section_get_nbr_indirect (bfd *, bfd_mach_o_section *);
 unsigned int bfd_mach_o_section_get_entry_size (bfd *, bfd_mach_o_section *);
diff --git a/bfd/pdp11.c b/bfd/pdp11.c
index 9edbba92c82..68809e5340c 100644
--- a/bfd/pdp11.c
+++ b/bfd/pdp11.c
@@ -2531,35 +2531,33 @@ NAME (aout, sizeof_headers) (bfd *abfd,
   return adata (abfd).exec_bytes_size;
 }
 
-/* Free all information we have cached for this BFD.  We can always
-   read it again later if we need it.  */
+/* Throw away most malloc'd and alloc'd information for this BFD.  */
 
 bool
 NAME (aout, bfd_free_cached_info) (bfd *abfd)
 {
-  asection *o;
-
-  if (bfd_get_format (abfd) != bfd_object
-      || abfd->tdata.aout_data == NULL)
-    return true;
-
+  if ((bfd_get_format (abfd) == bfd_object
+       || bfd_get_format (abfd) == bfd_core)
+      && abfd->tdata.aout_data != NULL)
+    {
 #define BFCI_FREE(x) do { free (x); x = NULL; } while (0)
-  BFCI_FREE (adata (abfd).line_buf);
-  BFCI_FREE (obj_aout_symbols (abfd));
+      BFCI_FREE (adata (abfd).line_buf);
+      BFCI_FREE (obj_aout_symbols (abfd));
 #ifdef USE_MMAP
-  obj_aout_external_syms (abfd) = 0;
-  bfd_free_window (&obj_aout_sym_window (abfd));
-  bfd_free_window (&obj_aout_string_window (abfd));
-  obj_aout_external_strings (abfd) = 0;
+      obj_aout_external_syms (abfd) = 0;
+      bfd_free_window (&obj_aout_sym_window (abfd));
+      bfd_free_window (&obj_aout_string_window (abfd));
+      obj_aout_external_strings (abfd) = 0;
 #else
-  BFCI_FREE (obj_aout_external_syms (abfd));
-  BFCI_FREE (obj_aout_external_strings (abfd));
+      BFCI_FREE (obj_aout_external_syms (abfd));
+      BFCI_FREE (obj_aout_external_strings (abfd));
 #endif
-  for (o = abfd->sections; o != NULL; o = o->next)
-    BFCI_FREE (o->relocation);
+      for (asection *o = abfd->sections; o != NULL; o = o->next)
+	BFCI_FREE (o->relocation);
 #undef BFCI_FREE
+    }
 
-  return true;
+  return _bfd_generic_bfd_free_cached_info (abfd);
 }
 
 /* Routine to create an entry in an a.out link hash table.  */
diff --git a/bfd/som.c b/bfd/som.c
index ef1f6dc3eb6..61f755e0444 100644
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -6789,13 +6789,13 @@ som_write_armap (bfd *abfd,
   return true;
 }
 
-/* Free all information we have cached for this BFD.  We can always
-   read it again later if we need it.  */
+/* Throw away some malloc'd information for this BFD.  */
 
 static bool
 som_bfd_free_cached_info (bfd *abfd)
 {
-  if (bfd_get_format (abfd) == bfd_object)
+  if (bfd_get_format (abfd) == bfd_object
+      || bfd_get_format (abfd) == bfd_core)
     {
       asection *o;
 
@@ -6813,8 +6813,8 @@ som_bfd_free_cached_info (bfd *abfd)
 #undef FREE
     }
 
-  /* Do not call _bfd_free_cached_info here.  som_write_armap needs
-     to access the bfd obj_alloc memory.  */
+  /* Do not call _bfd_generic_bfd_free_cached_info here.
+     som_write_armap needs to access the bfd objalloc memory.  */
   return true;
 }
 
diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c
index b0ad4016da3..704dc631b7d 100644
--- a/bfd/vms-alpha.c
+++ b/bfd/vms-alpha.c
@@ -10103,25 +10103,12 @@ bfd_vms_get_data (bfd *abfd)
   return (struct vms_private_data_struct *)abfd->tdata.any;
 }
 
-#define vms_bfd_is_target_special_symbol  _bfd_bool_bfd_asymbol_false
-#define vms_bfd_link_just_syms		  _bfd_generic_link_just_syms
-#define vms_bfd_copy_link_hash_symbol_type \
-  _bfd_generic_copy_link_hash_symbol_type
-#define vms_bfd_is_group_section	  bfd_generic_is_group_section
-#define vms_bfd_group_name		  bfd_generic_group_name
-#define vms_bfd_discard_group		  bfd_generic_discard_group
-#define vms_section_already_linked	  _bfd_generic_section_already_linked
-#define vms_bfd_define_common_symbol	  bfd_generic_define_common_symbol
-#define vms_bfd_link_hide_symbol	  _bfd_generic_link_hide_symbol
-#define vms_bfd_define_start_stop         bfd_generic_define_start_stop
-#define vms_bfd_copy_private_header_data  _bfd_generic_bfd_copy_private_header_data
-
 #define vms_bfd_copy_private_bfd_data	  _bfd_generic_bfd_copy_private_bfd_data
-#define vms_bfd_free_cached_info	  _bfd_generic_bfd_free_cached_info
+#define vms_bfd_merge_private_bfd_data	  _bfd_generic_bfd_merge_private_bfd_data
 #define vms_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
 #define vms_bfd_copy_private_symbol_data  _bfd_generic_bfd_copy_private_symbol_data
+#define vms_bfd_copy_private_header_data  _bfd_generic_bfd_copy_private_header_data
 #define vms_bfd_set_private_flags	  _bfd_generic_bfd_set_private_flags
-#define vms_bfd_merge_private_bfd_data	  _bfd_generic_bfd_merge_private_bfd_data
 
 /* Symbols table.  */
 #define alpha_vms_make_empty_symbol	   _bfd_generic_make_empty_symbol
@@ -10144,7 +10131,7 @@ bfd_vms_get_data (bfd *abfd)
 
 /* Generic table.  */
 #define alpha_vms_close_and_cleanup	   vms_close_and_cleanup
-#define alpha_vms_bfd_free_cached_info	   vms_bfd_free_cached_info
+#define alpha_vms_bfd_free_cached_info	   _bfd_bool_bfd_true
 #define alpha_vms_new_section_hook	   vms_new_section_hook
 #define alpha_vms_set_section_contents	   _bfd_vms_set_section_contents
 #define alpha_vms_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
