Index PowerPC64 linker generated .eh_frame in .eh_frame_hdr
I noticed recently that .eh_frame FDEs generated by the linker for call stubs and .glink weren't being indexed in .eh_frame_hdr, due to bfd_elf_discard_info being run before the linker generated .eh_frame sections were available for parsing. This patch moves code around in elf64-ppc.c and ppc64elf.em to avoid that problem. Another problem fixed here is that --gc-sections parses .eh_frame early, and the existing machinery allows only one go at parsing the .eh_frame sections. That resulted in the linker generated .eh_frame CIEs not being merged and no .eh_frame_hdr index entries for those FDEs. It turns out that all the info from parsing .eh_frame is attached to the section, so order of parsing isn't important, and after parsing sec_info_type being set will prevent a section being parsed again. At least, when parsing doesn't hit an error. So there isn't really any need for "parsed_eh_frame". "merge_cies" is also redundant, which means _bfd_elf_{begin,end}_eh_frame_parsing can also disappear. bfd/ * elf-bfd.h (struct eh_frame_hdr_info): Delete merge_cies and parsed_eh_frames. (_bfd_elf_begin_eh_frame_parsing): Delete. (_bfd_elf_end_eh_frame_parsing): Delete. * elf-eh-frame.c (_bfd_elf_begin_eh_frame_parsing): Delete. (_bfd_elf_end_eh_frame_parsing): Delete. (_bfd_elf_parse_eh_frame): Don't test parsed_eh_frame. Test !info->relocatable in place of merge_cies. * elflink.c (bfd_elf_gc_sections, bfd_elf_discard_info): Adjust. * elf64-ppc.c (glink_eh_frame_cie): Pad to multiple of 8. (ppc64_elf_size_stubs): Likewise pad stub FDE. (ppc64_elf_build_stubs): Move code setting glink .eh_frame to.. (ppc64_elf_size_stubs): ..here and.. (ppc64_elf_finish_dynamic_sections): ..here. ld/ * emultempl/ppc64elf.em (gld${EMULATION_NAME}_after_allocation): Call bfd_elf_discard_info after generating glink .eh_frame. Delete redundant test on ppc64_elf_setup_section_lists status.
This commit is contained in:
parent
7f85237141
commit
da44f4e546
7 changed files with 210 additions and 183 deletions
|
@ -1,3 +1,20 @@
|
||||||
|
2014-08-22 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* elf-bfd.h (struct eh_frame_hdr_info): Delete merge_cies and
|
||||||
|
parsed_eh_frames.
|
||||||
|
(_bfd_elf_begin_eh_frame_parsing): Delete.
|
||||||
|
(_bfd_elf_end_eh_frame_parsing): Delete.
|
||||||
|
* elf-eh-frame.c (_bfd_elf_begin_eh_frame_parsing): Delete.
|
||||||
|
(_bfd_elf_end_eh_frame_parsing): Delete.
|
||||||
|
(_bfd_elf_parse_eh_frame): Don't test parsed_eh_frame. Test
|
||||||
|
!info->relocatable in place of merge_cies.
|
||||||
|
* elflink.c (bfd_elf_gc_sections, bfd_elf_discard_info): Adjust.
|
||||||
|
* elf64-ppc.c (glink_eh_frame_cie): Pad to multiple of 8.
|
||||||
|
(ppc64_elf_size_stubs): Likewise pad stub FDE.
|
||||||
|
(ppc64_elf_build_stubs): Move code setting glink .eh_frame to..
|
||||||
|
(ppc64_elf_size_stubs): ..here and..
|
||||||
|
(ppc64_elf_finish_dynamic_sections): ..here.
|
||||||
|
|
||||||
2014-08-21 Maciej W. Rozycki <macro@codesourcery.com>
|
2014-08-21 Maciej W. Rozycki <macro@codesourcery.com>
|
||||||
|
|
||||||
* elf64-ppc.h (ppc64_elf_set_toc): Fix indentation.
|
* elf64-ppc.h (ppc64_elf_set_toc): Fix indentation.
|
||||||
|
|
|
@ -383,10 +383,6 @@ struct eh_frame_hdr_info
|
||||||
asection *hdr_sec;
|
asection *hdr_sec;
|
||||||
unsigned int fde_count, array_count;
|
unsigned int fde_count, array_count;
|
||||||
struct eh_frame_array_ent *array;
|
struct eh_frame_array_ent *array;
|
||||||
/* TRUE if we should try to merge CIEs between input sections. */
|
|
||||||
bfd_boolean merge_cies;
|
|
||||||
/* TRUE if all .eh_frames have been parsd. */
|
|
||||||
bfd_boolean parsed_eh_frames;
|
|
||||||
/* TRUE if .eh_frame_hdr should contain the sorted search table.
|
/* TRUE if .eh_frame_hdr should contain the sorted search table.
|
||||||
We build it if we successfully read all .eh_frame input sections
|
We build it if we successfully read all .eh_frame input sections
|
||||||
and recognize them. */
|
and recognize them. */
|
||||||
|
@ -1968,13 +1964,8 @@ extern bfd_boolean _bfd_elf_strtab_emit
|
||||||
extern void _bfd_elf_strtab_finalize
|
extern void _bfd_elf_strtab_finalize
|
||||||
(struct elf_strtab_hash *);
|
(struct elf_strtab_hash *);
|
||||||
|
|
||||||
extern void _bfd_elf_begin_eh_frame_parsing
|
|
||||||
(struct bfd_link_info *info);
|
|
||||||
extern void _bfd_elf_parse_eh_frame
|
extern void _bfd_elf_parse_eh_frame
|
||||||
(bfd *, struct bfd_link_info *, asection *, struct elf_reloc_cookie *);
|
(bfd *, struct bfd_link_info *, asection *, struct elf_reloc_cookie *);
|
||||||
extern void _bfd_elf_end_eh_frame_parsing
|
|
||||||
(struct bfd_link_info *info);
|
|
||||||
|
|
||||||
extern bfd_boolean _bfd_elf_discard_section_eh_frame
|
extern bfd_boolean _bfd_elf_discard_section_eh_frame
|
||||||
(bfd *, struct bfd_link_info *, asection *,
|
(bfd *, struct bfd_link_info *, asection *,
|
||||||
bfd_boolean (*) (bfd_vma, void *), struct elf_reloc_cookie *);
|
bfd_boolean (*) (bfd_vma, void *), struct elf_reloc_cookie *);
|
||||||
|
|
|
@ -452,18 +452,6 @@ make_pc_relative (unsigned char encoding, unsigned int ptr_size)
|
||||||
return encoding | DW_EH_PE_pcrel;
|
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
|
/* Try to parse .eh_frame section SEC, which belongs to ABFD. Store the
|
||||||
information in the section's sec_info field on success. COOKIE
|
information in the section's sec_info field on success. COOKIE
|
||||||
describes the relocations in SEC. */
|
describes the relocations in SEC. */
|
||||||
|
@ -494,8 +482,6 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
||||||
|
|
||||||
htab = elf_hash_table (info);
|
htab = elf_hash_table (info);
|
||||||
hdr_info = &htab->eh_info;
|
hdr_info = &htab->eh_info;
|
||||||
if (hdr_info->parsed_eh_frames)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (sec->size == 0
|
if (sec->size == 0
|
||||||
|| sec->sec_info_type != SEC_INFO_TYPE_NONE)
|
|| sec->sec_info_type != SEC_INFO_TYPE_NONE)
|
||||||
|
@ -777,7 +763,8 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
||||||
buf += initial_insn_length;
|
buf += initial_insn_length;
|
||||||
ENSURE_NO_RELOCS (buf);
|
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.u.full_cie = cie;
|
||||||
this_inf->u.cie.per_encoding_relative
|
this_inf->u.cie.per_encoding_relative
|
||||||
= (cie->per_encoding & 0x70) == DW_EH_PE_pcrel;
|
= (cie->per_encoding & 0x70) == DW_EH_PE_pcrel;
|
||||||
|
@ -911,8 +898,9 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
||||||
|
|
||||||
elf_section_data (sec)->sec_info = sec_info;
|
elf_section_data (sec)->sec_info = sec_info;
|
||||||
sec->sec_info_type = SEC_INFO_TYPE_EH_FRAME;
|
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;
|
sec_info->cies = local_cies;
|
||||||
local_cies = NULL;
|
local_cies = NULL;
|
||||||
}
|
}
|
||||||
|
@ -933,17 +921,6 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info,
|
||||||
#undef REQUIRE
|
#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
|
/* Mark all relocations against CIE or FDE ENT, which occurs in
|
||||||
.eh_frame section SEC. COOKIE describes the relocations in SEC;
|
.eh_frame section SEC. COOKIE describes the relocations in SEC;
|
||||||
its "rel" field can be changed freely. */
|
its "rel" field can be changed freely. */
|
||||||
|
|
282
bfd/elf64-ppc.c
282
bfd/elf64-ppc.c
|
@ -11894,7 +11894,8 @@ static const unsigned char glink_eh_frame_cie[] =
|
||||||
65, /* RA reg. */
|
65, /* RA reg. */
|
||||||
1, /* Augmentation size. */
|
1, /* Augmentation size. */
|
||||||
DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding. */
|
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
|
/* Stripping output sections is normally done before dynamic section
|
||||||
|
@ -12326,7 +12327,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||||
stub_sec != NULL;
|
stub_sec != NULL;
|
||||||
stub_sec = stub_sec->next)
|
stub_sec = stub_sec->next)
|
||||||
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
|
||||||
size += 20;
|
size += 24;
|
||||||
if (htab->glink != NULL && htab->glink->size != 0)
|
if (htab->glink != NULL && htab->glink->size != 0)
|
||||||
size += 24;
|
size += 24;
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
|
@ -12366,6 +12367,89 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||||
(*htab->params->layout_sections_again) ();
|
(*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);
|
maybe_strip_output (info, htab->brlt);
|
||||||
if (htab->glink_eh_frame != NULL)
|
if (htab->glink_eh_frame != NULL)
|
||||||
maybe_strip_output (info, htab->glink_eh_frame);
|
maybe_strip_output (info, htab->glink_eh_frame);
|
||||||
|
@ -12723,117 +12807,6 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
|
||||||
return FALSE;
|
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. */
|
/* Build the stubs as directed by the stub hash table. */
|
||||||
bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
|
bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
|
||||||
|
|
||||||
|
@ -12859,6 +12832,9 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
|
||||||
break;
|
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
|
if (stub_sec != NULL
|
||||||
|| (htab->glink_eh_frame != NULL
|
|| (htab->glink_eh_frame != NULL
|
||||||
&& htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
|
&& htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
|
||||||
|
@ -15126,13 +15102,81 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||||
NULL))
|
NULL))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
||||||
if (htab->glink_eh_frame != NULL
|
if (htab->glink_eh_frame != NULL
|
||||||
&& htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
|
&& htab->glink_eh_frame->size != 0)
|
||||||
&& !_bfd_elf_write_section_eh_frame (output_bfd, info,
|
{
|
||||||
htab->glink_eh_frame,
|
bfd_vma val;
|
||||||
htab->glink_eh_frame->contents))
|
bfd_byte *p;
|
||||||
return FALSE;
|
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,
|
/* We need to handle writing out multiple GOT sections ourselves,
|
||||||
since we didn't add them to DYNOBJ. We know dynobj is the first
|
since we didn't add them to DYNOBJ. We know dynobj is the first
|
||||||
|
|
|
@ -12154,6 +12154,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
|
||||||
bfd *sub;
|
bfd *sub;
|
||||||
elf_gc_mark_hook_fn gc_mark_hook;
|
elf_gc_mark_hook_fn gc_mark_hook;
|
||||||
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
||||||
|
struct elf_link_hash_table *htab;
|
||||||
|
|
||||||
if (!bed->can_gc_sections
|
if (!bed->can_gc_sections
|
||||||
|| !is_elf_hash_table (info->hash))
|
|| !is_elf_hash_table (info->hash))
|
||||||
|
@ -12163,10 +12164,10 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
bed->gc_keep (info);
|
bed->gc_keep (info);
|
||||||
|
htab = elf_hash_table (info);
|
||||||
|
|
||||||
/* Try to parse each bfd's .eh_frame section. Point elf_eh_frame_section
|
/* 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. */
|
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)
|
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
|
||||||
{
|
{
|
||||||
asection *sec;
|
asection *sec;
|
||||||
|
@ -12183,27 +12184,20 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
|
||||||
sec = bfd_get_next_section_by_name (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. */
|
/* Apply transitive closure to the vtable entry usage info. */
|
||||||
elf_link_hash_traverse (elf_hash_table (info),
|
elf_link_hash_traverse (htab, elf_gc_propagate_vtable_entries_used, &ok);
|
||||||
elf_gc_propagate_vtable_entries_used,
|
|
||||||
&ok);
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Kill the vtable relocations that were not used. */
|
/* Kill the vtable relocations that were not used. */
|
||||||
elf_link_hash_traverse (elf_hash_table (info),
|
elf_link_hash_traverse (htab, elf_gc_smash_unused_vtentry_relocs, &ok);
|
||||||
elf_gc_smash_unused_vtentry_relocs,
|
|
||||||
&ok);
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Mark dynamically referenced symbols. */
|
/* Mark dynamically referenced symbols. */
|
||||||
if (elf_hash_table (info)->dynamic_sections_created)
|
if (htab->dynamic_sections_created)
|
||||||
elf_link_hash_traverse (elf_hash_table (info),
|
elf_link_hash_traverse (htab, bed->gc_mark_dynamic_ref, info);
|
||||||
bed->gc_mark_dynamic_ref,
|
|
||||||
info);
|
|
||||||
|
|
||||||
/* Grovel through relocs to find out who stays ... */
|
/* Grovel through relocs to find out who stays ... */
|
||||||
gc_mark_hook = bed->gc_mark_hook;
|
gc_mark_hook = bed->gc_mark_hook;
|
||||||
|
@ -12682,7 +12676,6 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
|
||||||
{
|
{
|
||||||
asection *i;
|
asection *i;
|
||||||
|
|
||||||
_bfd_elf_begin_eh_frame_parsing (info);
|
|
||||||
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
|
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
|
||||||
{
|
{
|
||||||
if (i->size == 0)
|
if (i->size == 0)
|
||||||
|
@ -12703,7 +12696,6 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
|
||||||
|
|
||||||
fini_reloc_cookie_for_section (&cookie, i);
|
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)
|
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
2014-08-22 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* emultempl/ppc64elf.em (gld${EMULATION_NAME}_after_allocation): Call
|
||||||
|
bfd_elf_discard_info after generating glink .eh_frame. Delete
|
||||||
|
redundant test on ppc64_elf_setup_section_lists status.
|
||||||
|
|
||||||
2014-08-20 Maciej W. Rozycki <macro@codesourcery.com>
|
2014-08-20 Maciej W. Rozycki <macro@codesourcery.com>
|
||||||
|
|
||||||
* emultempl/armelf.em (OPTION_STUBGROUP_SIZE): Fix formatting.
|
* emultempl/armelf.em (OPTION_STUBGROUP_SIZE): Fix formatting.
|
||||||
|
|
|
@ -460,19 +460,6 @@ gld${EMULATION_NAME}_after_allocation (void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* bfd_elf_discard_info just plays with data and debugging sections,
|
|
||||||
ie. doesn't affect code size, so we can delay resizing the
|
|
||||||
sections. It's likely we'll resize everything in the process of
|
|
||||||
adding stubs. */
|
|
||||||
ret = bfd_elf_discard_info (link_info.output_bfd, &link_info);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
einfo ("%X%P: .eh_frame/.stab edit: %E\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (ret > 0)
|
|
||||||
need_laying_out = 1;
|
|
||||||
|
|
||||||
/* If generating a relocatable output file, then we don't have any
|
/* If generating a relocatable output file, then we don't have any
|
||||||
stubs. */
|
stubs. */
|
||||||
if (stub_file != NULL && !link_info.relocatable)
|
if (stub_file != NULL && !link_info.relocatable)
|
||||||
|
@ -480,7 +467,7 @@ gld${EMULATION_NAME}_after_allocation (void)
|
||||||
ret = ppc64_elf_setup_section_lists (&link_info);
|
ret = ppc64_elf_setup_section_lists (&link_info);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
einfo ("%X%P: can not size stub section: %E\n");
|
einfo ("%X%P: can not size stub section: %E\n");
|
||||||
else if (ret > 0)
|
else
|
||||||
{
|
{
|
||||||
ppc64_elf_start_multitoc_partition (&link_info);
|
ppc64_elf_start_multitoc_partition (&link_info);
|
||||||
|
|
||||||
|
@ -510,6 +497,19 @@ gld${EMULATION_NAME}_after_allocation (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We can't parse and merge .eh_frame until the glink .eh_frame has
|
||||||
|
been generated. Otherwise the glink .eh_frame CIE won't be
|
||||||
|
merged with other CIEs, and worse, the glink .eh_frame FDEs won't
|
||||||
|
be listed in .eh_frame_hdr. */
|
||||||
|
ret = bfd_elf_discard_info (link_info.output_bfd, &link_info);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
einfo ("%X%P: .eh_frame/.stab edit: %E\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (ret > 0)
|
||||||
|
need_laying_out = 1;
|
||||||
|
|
||||||
if (need_laying_out != -1)
|
if (need_laying_out != -1)
|
||||||
{
|
{
|
||||||
gld${EMULATION_NAME}_map_segments (need_laying_out);
|
gld${EMULATION_NAME}_map_segments (need_laying_out);
|
||||||
|
|
Loading…
Reference in a new issue