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)