diff --git a/gas/config/obj-aout.c b/gas/config/obj-aout.c
index f413e9139bb..14eb9f96aa6 100644
--- a/gas/config/obj-aout.c
+++ b/gas/config/obj-aout.c
@@ -297,6 +297,7 @@ const struct format_ops aout_format_ops =
   1,	/* dfl_leading_underscore.  */
   0,	/* emit_section_symbols.  */
   0,	/* begin.  */
+  0,	/* end.  */
   0,	/* app_file.  */
   obj_aout_frob_symbol,
   0,	/* frob_file.  */
diff --git a/gas/config/obj-coff.c b/gas/config/obj-coff.c
index 5446beffb2e..465a990ec88 100644
--- a/gas/config/obj-coff.c
+++ b/gas/config/obj-coff.c
@@ -1910,6 +1910,7 @@ const struct format_ops coff_format_ops =
   0,	/* dfl_leading_underscore */
   1,	/* emit_section_symbols */
   0,    /* begin */
+  0,	/* end.  */
   c_dot_file_symbol,
   coff_frob_symbol,
   0,	/* frob_file */
diff --git a/gas/config/obj-ecoff.c b/gas/config/obj-ecoff.c
index f30e8c74d00..092f6f2c927 100644
--- a/gas/config/obj-ecoff.c
+++ b/gas/config/obj-ecoff.c
@@ -290,6 +290,7 @@ const struct format_ops ecoff_format_ops =
      the single-format definition (0) would be in order.  */
   1,	/* emit_section_symbols.  */
   0,	/* begin.  */
+  0,	/* end.  */
   ecoff_new_file,
   obj_ecoff_frob_symbol,
   ecoff_frob_file,
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index d3a54e8659f..a4cf12b144a 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -188,25 +188,8 @@ static const pseudo_typeS ecoff_debug_pseudo_table[] =
 #undef NO_RELOC
 #include "aout/aout64.h"
 
-/* This is called when the assembler starts.  */
-
 asection *elf_com_section_ptr;
 
-void
-elf_begin (void)
-{
-  asection *s;
-
-  /* Add symbols for the known sections to the symbol table.  */
-  s = bfd_get_section_by_name (stdoutput, TEXT_SECTION_NAME);
-  symbol_table_insert (section_symbol (s));
-  s = bfd_get_section_by_name (stdoutput, DATA_SECTION_NAME);
-  symbol_table_insert (section_symbol (s));
-  s = bfd_get_section_by_name (stdoutput, BSS_SECTION_NAME);
-  symbol_table_insert (section_symbol (s));
-  elf_com_section_ptr = bfd_com_section_ptr;
-}
-
 void
 elf_pop_insert (void)
 {
@@ -2462,10 +2445,11 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+static segT comment_section;
+
 static void
 obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
 {
-  static segT comment_section;
   segT old_section = now_seg;
   int old_subsection = now_subseg;
 
@@ -2813,12 +2797,11 @@ build_additional_section_info (bfd *abfd ATTRIBUTE_UNUSED,
   str_hash_insert (list->indexes, group_name, idx_ptr, 0);
 }
 
-static int
-free_section_idx (void **slot, void *arg ATTRIBUTE_UNUSED)
+static void
+free_section_idx (void *ent)
 {
-  string_tuple_t *tuple = *((string_tuple_t **) slot);
-  free ((char *)tuple->value);
-  return 1;
+  string_tuple_t *tuple = ent;
+  free ((char *) tuple->value);
 }
 
 /* Create symbols for group signature.  */
@@ -2831,7 +2814,8 @@ elf_adjust_symtab (void)
   /* Go find section groups.  */
   groups.num_group = 0;
   groups.head = NULL;
-  groups.indexes = str_htab_create ();
+  groups.indexes = htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
+				      free_section_idx, notes_calloc, NULL);
   bfd_map_over_sections (stdoutput, build_additional_section_info,
 			 &groups);
 
@@ -3005,10 +2989,6 @@ elf_frob_file_after_relocs (void)
       frag_wane (frag_now);
     }
 
-  /* Cleanup hash.  */
-  htab_traverse_noresize (groups.indexes, free_section_idx, NULL);
-  htab_delete (groups.indexes);
-
 #ifdef NEED_ECOFF_DEBUG
   if (ECOFF_DEBUGGING)
     /* Generate the ECOFF debugging information.  */
@@ -3121,12 +3101,56 @@ elf_init_stab_section (segT seg)
     obj_elf_init_stab_section (seg);
 }
 
+/* This is called when the assembler starts.  */
+
+void
+elf_begin (void)
+{
+  asection *s;
+
+  /* Add symbols for the known sections to the symbol table.  */
+  s = bfd_get_section_by_name (stdoutput, TEXT_SECTION_NAME);
+  symbol_table_insert (section_symbol (s));
+  s = bfd_get_section_by_name (stdoutput, DATA_SECTION_NAME);
+  symbol_table_insert (section_symbol (s));
+  s = bfd_get_section_by_name (stdoutput, BSS_SECTION_NAME);
+  symbol_table_insert (section_symbol (s));
+  elf_com_section_ptr = bfd_com_section_ptr;
+  previous_section = NULL;
+  previous_subsection = 0;
+  comment_section = NULL;
+  memset (&groups, 0, sizeof (groups));
+}
+
+void
+elf_end (void)
+{
+  while (section_stack)
+    {
+      struct section_stack *top = section_stack;
+      section_stack = top->next;
+      free (top);
+    }
+  while (recorded_attributes)
+    {
+      struct recorded_attribute_info *rai = recorded_attributes;
+      recorded_attributes = rai->next;
+      free (rai);
+    }
+  if (groups.indexes)
+    {
+      htab_delete (groups.indexes);
+      free (groups.head);
+    }
+}
+
 const struct format_ops elf_format_ops =
 {
   bfd_target_elf_flavour,
   0,	/* dfl_leading_underscore */
   1,	/* emit_section_symbols */
   elf_begin,
+  elf_end,
   elf_file_symbol,
   elf_frob_symbol,
   elf_frob_file,
diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h
index c97d4fd04dd..727924ce234 100644
--- a/gas/config/obj-elf.h
+++ b/gas/config/obj-elf.h
@@ -119,6 +119,11 @@ struct elf_section_match
 #endif
 extern void elf_begin (void);
 
+#ifndef obj_end
+#define obj_end() elf_end ()
+#endif
+extern void elf_end (void);
+
 #ifndef LOCAL_LABEL_PREFIX
 #define LOCAL_LABEL_PREFIX '.'
 #endif
diff --git a/gas/config/obj-multi.h b/gas/config/obj-multi.h
index b88f81bc3eb..d4c94799edf 100644
--- a/gas/config/obj-multi.h
+++ b/gas/config/obj-multi.h
@@ -36,6 +36,11 @@
 	 ? (*this_format->begin) ()			\
 	 : (void) 0)
 
+#define obj_end()					\
+	(this_format->end				\
+	 ? (*this_format->end) ()			\
+	 : (void) 0)
+
 #define obj_app_file(NAME)				\
 	(this_format->app_file				\
 	 ? (*this_format->app_file) (NAME)		\
diff --git a/gas/obj.h b/gas/obj.h
index 586ed2622c1..e1036928cc2 100644
--- a/gas/obj.h
+++ b/gas/obj.h
@@ -42,6 +42,7 @@ struct format_ops {
   unsigned dfl_leading_underscore : 1;
   unsigned emit_section_symbols : 1;
   void (*begin) (void);
+  void (*end) (void);
   void (*app_file) (const char *);
   void (*frob_symbol) (symbolS *, int *);
   void (*frob_file) (void);
diff --git a/gas/output-file.c b/gas/output-file.c
index 88f40116513..664bc88e9c1 100644
--- a/gas/output-file.c
+++ b/gas/output-file.c
@@ -109,6 +109,9 @@ output_file_close (void)
 
 #ifdef md_end
   md_end ();
+#endif
+#ifdef obj_end
+  obj_end ();
 #endif
   macro_end ();
   expr_end ();
