return encoding | DW_EH_PE_pcrel;
 }
 
-/* Called before calling _bfd_elf_parse_eh_frame on every input bfd's
-   .eh_frame section.  */
-
-void
-_bfd_elf_begin_eh_frame_parsing (struct bfd_link_info *info)
-{
-  struct eh_frame_hdr_info *hdr_info;
-
-  hdr_info = &elf_hash_table (info)->eh_info;
-  hdr_info->merge_cies = !info->relocatable;
-}
-
 /* Try to parse .eh_frame section SEC, which belongs to ABFD.  Store the
    information in the section's sec_info field on success.  COOKIE
    describes the relocations in SEC.  */
 
   htab = elf_hash_table (info);
   hdr_info = &htab->eh_info;
-  if (hdr_info->parsed_eh_frames)
-    return;
 
   if (sec->size == 0
       || sec->sec_info_type != SEC_INFO_TYPE_NONE)
          buf += initial_insn_length;
          ENSURE_NO_RELOCS (buf);
 
-         if (hdr_info->merge_cies)
+         if (!info->relocatable)
+           /* Keep info for merging cies.  */
            this_inf->u.cie.u.full_cie = cie;
          this_inf->u.cie.per_encoding_relative
            = (cie->per_encoding & 0x70) == DW_EH_PE_pcrel;
 
   elf_section_data (sec)->sec_info = sec_info;
   sec->sec_info_type = SEC_INFO_TYPE_EH_FRAME;
-  if (hdr_info->merge_cies)
+  if (!info->relocatable)
     {
+      /* Keep info for merging cies.  */
       sec_info->cies = local_cies;
       local_cies = NULL;
     }
 #undef REQUIRE
 }
 
-/* Finish a pass over all .eh_frame sections.  */
-
-void
-_bfd_elf_end_eh_frame_parsing (struct bfd_link_info *info)
-{
-  struct eh_frame_hdr_info *hdr_info;
-
-  hdr_info = &elf_hash_table (info)->eh_info;
-  hdr_info->parsed_eh_frames = TRUE;
-}
-
 /* Mark all relocations against CIE or FDE ENT, which occurs in
    .eh_frame section SEC.  COOKIE describes the relocations in SEC;
    its "rel" field can be changed freely.  */
 
   65,                                  /* RA reg.  */
   1,                                   /* Augmentation size.  */
   DW_EH_PE_pcrel | DW_EH_PE_sdata4,    /* FDE encoding.  */
-  DW_CFA_def_cfa, 1, 0                 /* def_cfa: r1 offset 0.  */
+  DW_CFA_def_cfa, 1, 0,                        /* def_cfa: r1 offset 0.  */
+  0, 0, 0, 0
 };
 
 /* Stripping output sections is normally done before dynamic section
               stub_sec != NULL;
               stub_sec = stub_sec->next)
            if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
-             size += 20;
+             size += 24;
          if (htab->glink != NULL && htab->glink->size != 0)
            size += 24;
          if (size != 0)
       (*htab->params->layout_sections_again) ();
     }
 
+  if (htab->glink_eh_frame != NULL
+      && htab->glink_eh_frame->size != 0)
+    {
+      bfd_vma val;
+      bfd_byte *p, *last_fde;
+      size_t last_fde_len, size, align, pad;
+      asection *stub_sec;
+
+      p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
+      if (p == NULL)
+       return FALSE;
+      htab->glink_eh_frame->contents = p;
+      last_fde = p;
+
+      memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
+      /* CIE length (rewrite in case little-endian).  */
+      last_fde_len = sizeof (glink_eh_frame_cie) - 4;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
+      p += sizeof (glink_eh_frame_cie);
+
+      for (stub_sec = htab->params->stub_bfd->sections;
+          stub_sec != NULL;
+          stub_sec = stub_sec->next)
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+         {
+           last_fde = p;
+           last_fde_len = 20;
+           /* FDE length.  */
+           bfd_put_32 (htab->elf.dynobj, 20, p);
+           p += 4;
+           /* CIE pointer.  */
+           val = p - htab->glink_eh_frame->contents;
+           bfd_put_32 (htab->elf.dynobj, val, p);
+           p += 4;
+           /* Offset to stub section, written later.  */
+           p += 4;
+           /* stub section size.  */
+           bfd_put_32 (htab->elf.dynobj, stub_sec->size, p);
+           p += 4;
+           /* Augmentation.  */
+           p += 1;
+           /* Pad.  */
+           p += 7;
+         }
+      if (htab->glink != NULL && htab->glink->size != 0)
+       {
+         last_fde = p;
+         last_fde_len = 20;
+         /* FDE length.  */
+         bfd_put_32 (htab->elf.dynobj, 20, p);
+         p += 4;
+         /* CIE pointer.  */
+         val = p - htab->glink_eh_frame->contents;
+         bfd_put_32 (htab->elf.dynobj, val, p);
+         p += 4;
+         /* Offset to .glink, written later.  */
+         p += 4;
+         /* .glink size.  */
+         bfd_put_32 (htab->elf.dynobj, htab->glink->size - 8, p);
+         p += 4;
+         /* Augmentation.  */
+         p += 1;
+
+         *p++ = DW_CFA_advance_loc + 1;
+         *p++ = DW_CFA_register;
+         *p++ = 65;
+         *p++ = 12;
+         *p++ = DW_CFA_advance_loc + 4;
+         *p++ = DW_CFA_restore_extended;
+         *p++ = 65;
+       }
+      /* Subsume any padding into the last FDE if user .eh_frame
+        sections are aligned more than glink_eh_frame.  Otherwise any
+        zero padding will be seen as a terminator.  */
+      size = p - htab->glink_eh_frame->contents;
+      align = 1;
+      align <<= htab->glink_eh_frame->output_section->alignment_power;
+      align -= 1;
+      pad = ((size + align) & ~align) - size;
+      htab->glink_eh_frame->size = size + pad;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len + pad, last_fde);
+    }
+
   maybe_strip_output (info, htab->brlt);
   if (htab->glink_eh_frame != NULL)
     maybe_strip_output (info, htab->glink_eh_frame);
        return FALSE;
     }
 
-  if (htab->glink_eh_frame != NULL
-      && htab->glink_eh_frame->size != 0)
-    {
-      bfd_vma val;
-      bfd_byte *last_fde;
-      size_t last_fde_len, size, align, pad;
-
-      p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
-      if (p == NULL)
-       return FALSE;
-      htab->glink_eh_frame->contents = p;
-      last_fde = p;
-
-      htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
-
-      memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
-      /* CIE length (rewrite in case little-endian).  */
-      last_fde_len = sizeof (glink_eh_frame_cie) - 4;
-      bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
-      p += sizeof (glink_eh_frame_cie);
-
-      for (stub_sec = htab->params->stub_bfd->sections;
-          stub_sec != NULL;
-          stub_sec = stub_sec->next)
-       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
-         {
-           last_fde = p;
-           last_fde_len = 16;
-           /* FDE length.  */
-           bfd_put_32 (htab->elf.dynobj, 16, p);
-           p += 4;
-           /* CIE pointer.  */
-           val = p - htab->glink_eh_frame->contents;
-           bfd_put_32 (htab->elf.dynobj, val, p);
-           p += 4;
-           /* Offset to stub section.  */
-           val = (stub_sec->output_section->vma
-                  + stub_sec->output_offset);
-           val -= (htab->glink_eh_frame->output_section->vma
-                   + htab->glink_eh_frame->output_offset);
-           val -= p - htab->glink_eh_frame->contents;
-           if (val + 0x80000000 > 0xffffffff)
-             {
-               info->callbacks->einfo
-                 (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
-                  stub_sec->name);
-               return FALSE;
-             }
-           bfd_put_32 (htab->elf.dynobj, val, p);
-           p += 4;
-           /* stub section size.  */
-           bfd_put_32 (htab->elf.dynobj, stub_sec->rawsize, p);
-           p += 4;
-           /* Augmentation.  */
-           p += 1;
-           /* Pad.  */
-           p += 3;
-         }
-      if (htab->glink != NULL && htab->glink->size != 0)
-       {
-         last_fde = p;
-         last_fde_len = 20;
-         /* FDE length.  */
-         bfd_put_32 (htab->elf.dynobj, 20, p);
-         p += 4;
-         /* CIE pointer.  */
-         val = p - htab->glink_eh_frame->contents;
-         bfd_put_32 (htab->elf.dynobj, val, p);
-         p += 4;
-         /* Offset to .glink.  */
-         val = (htab->glink->output_section->vma
-                + htab->glink->output_offset
-                + 8);
-         val -= (htab->glink_eh_frame->output_section->vma
-                 + htab->glink_eh_frame->output_offset);
-         val -= p - htab->glink_eh_frame->contents;
-         if (val + 0x80000000 > 0xffffffff)
-           {
-             info->callbacks->einfo
-               (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
-                htab->glink->name);
-             return FALSE;
-           }
-         bfd_put_32 (htab->elf.dynobj, val, p);
-         p += 4;
-         /* .glink size.  */
-         bfd_put_32 (htab->elf.dynobj, htab->glink->size - 8, p);
-         p += 4;
-         /* Augmentation.  */
-         p += 1;
-
-         *p++ = DW_CFA_advance_loc + 1;
-         *p++ = DW_CFA_register;
-         *p++ = 65;
-         *p++ = 12;
-         *p++ = DW_CFA_advance_loc + 4;
-         *p++ = DW_CFA_restore_extended;
-         *p++ = 65;
-       }
-      /* Subsume any padding into the last FDE if user .eh_frame
-        sections are aligned more than glink_eh_frame.  Otherwise any
-        zero padding will be seen as a terminator.  */
-      size = p - htab->glink_eh_frame->contents;
-      align = 1;
-      align <<= htab->glink_eh_frame->output_section->alignment_power;
-      align -= 1;
-      pad = ((size + align) & ~align) - size;
-      htab->glink_eh_frame->size = size + pad;
-      bfd_put_32 (htab->elf.dynobj, last_fde_len + pad, last_fde);
-    }
-
   /* Build the stubs as directed by the stub hash table.  */
   bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
 
          break;
       }
 
+  /* Note that the glink_eh_frame check here is not only testing that
+     the generated size matched the calculated size but also that
+     bfd_elf_discard_info didn't make any changes to the section.  */
   if (stub_sec != NULL
       || (htab->glink_eh_frame != NULL
          && htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
                                       NULL))
     return FALSE;
 
-
   if (htab->glink_eh_frame != NULL
-      && htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
-      && !_bfd_elf_write_section_eh_frame (output_bfd, info,
-                                          htab->glink_eh_frame,
-                                          htab->glink_eh_frame->contents))
-    return FALSE;
+      && htab->glink_eh_frame->size != 0)
+    {
+      bfd_vma val;
+      bfd_byte *p;
+      asection *stub_sec;
+
+      p = htab->glink_eh_frame->contents + sizeof (glink_eh_frame_cie);
+      for (stub_sec = htab->params->stub_bfd->sections;
+          stub_sec != NULL;
+          stub_sec = stub_sec->next)
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+         {
+           /* FDE length.  */
+           p += 4;
+           /* CIE pointer.  */
+           p += 4;
+           /* Offset to stub section.  */
+           val = (stub_sec->output_section->vma
+                  + stub_sec->output_offset);
+           val -= (htab->glink_eh_frame->output_section->vma
+                   + htab->glink_eh_frame->output_offset
+                   + (p - htab->glink_eh_frame->contents));
+           if (val + 0x80000000 > 0xffffffff)
+             {
+               info->callbacks->einfo
+                 (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+                  stub_sec->name);
+               return FALSE;
+             }
+           bfd_put_32 (dynobj, val, p);
+           p += 4;
+           /* stub section size.  */
+           p += 4;
+           /* Augmentation.  */
+           p += 1;
+           /* Pad.  */
+           p += 7;
+         }
+      if (htab->glink != NULL && htab->glink->size != 0)
+       {
+         /* FDE length.  */
+         p += 4;
+         /* CIE pointer.  */
+         p += 4;
+         /* Offset to .glink.  */
+         val = (htab->glink->output_section->vma
+                + htab->glink->output_offset
+                + 8);
+         val -= (htab->glink_eh_frame->output_section->vma
+                 + htab->glink_eh_frame->output_offset
+                 + (p - htab->glink_eh_frame->contents));
+         if (val + 0x80000000 > 0xffffffff)
+           {
+             info->callbacks->einfo
+               (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+                htab->glink->name);
+             return FALSE;
+           }
+         bfd_put_32 (dynobj, val, p);
+         p += 4;
+         /* .glink size.  */
+         p += 4;
+         /* Augmentation.  */
+         p += 1;
+         /* Ops.  */
+         p += 7;
+       }
+
+      if (htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
+         && !_bfd_elf_write_section_eh_frame (output_bfd, info,
+                                              htab->glink_eh_frame,
+                                              htab->glink_eh_frame->contents))
+       return FALSE;
+    }
 
   /* We need to handle writing out multiple GOT sections ourselves,
      since we didn't add them to DYNOBJ.  We know dynobj is the first
 
   bfd *sub;
   elf_gc_mark_hook_fn gc_mark_hook;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  struct elf_link_hash_table *htab;
 
   if (!bed->can_gc_sections
       || !is_elf_hash_table (info->hash))
     }
 
   bed->gc_keep (info);
+  htab = elf_hash_table (info);
 
   /* Try to parse each bfd's .eh_frame section.  Point elf_eh_frame_section
      at the .eh_frame section if we can mark the FDEs individually.  */
-  _bfd_elf_begin_eh_frame_parsing (info);
   for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
     {
       asection *sec;
          sec = bfd_get_next_section_by_name (sec);
        }
     }
-  _bfd_elf_end_eh_frame_parsing (info);
 
   /* Apply transitive closure to the vtable entry usage info.  */
-  elf_link_hash_traverse (elf_hash_table (info),
-                         elf_gc_propagate_vtable_entries_used,
-                         &ok);
+  elf_link_hash_traverse (htab, elf_gc_propagate_vtable_entries_used, &ok);
   if (!ok)
     return FALSE;
 
   /* Kill the vtable relocations that were not used.  */
-  elf_link_hash_traverse (elf_hash_table (info),
-                         elf_gc_smash_unused_vtentry_relocs,
-                         &ok);
+  elf_link_hash_traverse (htab, elf_gc_smash_unused_vtentry_relocs, &ok);
   if (!ok)
     return FALSE;
 
   /* Mark dynamically referenced symbols.  */
-  if (elf_hash_table (info)->dynamic_sections_created)
-    elf_link_hash_traverse (elf_hash_table (info),
-                           bed->gc_mark_dynamic_ref,
-                           info);
+  if (htab->dynamic_sections_created)
+    elf_link_hash_traverse (htab, bed->gc_mark_dynamic_ref, info);
 
   /* Grovel through relocs to find out who stays ...  */
   gc_mark_hook = bed->gc_mark_hook;
     {
       asection *i;
 
-      _bfd_elf_begin_eh_frame_parsing (info);
       for (i = o->map_head.s; i != NULL; i = i->map_head.s)
        {
          if (i->size == 0)
 
          fini_reloc_cookie_for_section (&cookie, i);
        }
-      _bfd_elf_end_eh_frame_parsing (info);
     }
 
   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)