diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 27 |
2 files changed, 31 insertions, 3 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5fe29db..35bbb31 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2012-05-24 Alan Modra <amodra@gmail.com> + + PR ld/14158 + * elf64-ppc.c (ppc64_elf_size_stubs): Round up glink_eh_frame + size to output section alignment. + (ppc64_elf_build_stubs): Likewise, and extend last FDE to cover. + 2012-05-23 Alan Modra <amodra@gmail.com> * elf-eh-frame.c (_bfd_elf_maybe_strip_eh_frame_hdr): Handle diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 482cf4d..df1db6d 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -11664,7 +11664,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, && !bfd_is_abs_section (htab->glink_eh_frame->output_section) && (htab->glink_eh_frame->flags & SEC_EXCLUDE) == 0) { - bfd_size_type size = 0; + size_t size = 0, align; for (stub_sec = htab->stub_bfd->sections; stub_sec != NULL; @@ -11675,6 +11675,10 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size, size += 24; if (size != 0) size += sizeof (glink_eh_frame_cie); + align = 1; + align <<= htab->glink_eh_frame->output_section->alignment_power; + align -= 1; + size = (size + align) & ~align; htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size; htab->glink_eh_frame->size = size; } @@ -11916,17 +11920,21 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, && 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). */ - bfd_put_32 (htab->elf.dynobj, sizeof (glink_eh_frame_cie) - 4, p); + 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->stub_bfd->sections; @@ -11934,6 +11942,8 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, 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; @@ -11966,6 +11976,8 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, } 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; @@ -12003,7 +12015,16 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms, *p++ = DW_CFA_restore_extended; *p++ = 65; } - htab->glink_eh_frame->size = p - htab->glink_eh_frame->contents; + /* 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. */ |