From 9866ffe25a0fe73f5153f2720650baf0dd9cc828 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 31 Aug 2017 19:39:14 +0930 Subject: [PATCH] Remove .eh_frame zero terminators The machinery to do this was there, but not enabled if the terminator was the only thing in the section. bfd/ * elf-eh-frame.c (_bfd_elf_parse_eh_frame): Don't exit early for a section containing just a terminator. Allow multiple terminators at end of section. * elflink.c (bfd_elf_discard_info): Iterate over .eh_frame sections when not adding alignment. Assert on terminator in the middle of FDEs. ld/ * testsuite/ld-elf/eh3.d: Update. * testsuite/ld-elf/eh4.d: Update. --- bfd/ChangeLog | 9 +++++++ bfd/elf-eh-frame.c | 20 ++++++-------- bfd/elflink.c | 57 +++++++++++++++++++-------------------- ld/ChangeLog | 5 ++++ ld/testsuite/ld-elf/eh3.d | 12 ++------- ld/testsuite/ld-elf/eh4.d | 4 +-- 6 files changed, 52 insertions(+), 55 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index edc447e781a..08dfa79e461 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2017-08-31 Alan Modra + + * elf-eh-frame.c (_bfd_elf_parse_eh_frame): Don't exit early + for a section containing just a terminator. Allow multiple + terminators at end of section. + * elflink.c (bfd_elf_discard_info): Iterate over .eh_frame + sections when not adding alignment. Assert on terminator in + the middle of FDEs. + 2017-08-31 Alan Modra PR 21441 diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index 7e0d63f569d..f0ede2d6f7c 100644 --- a/bfd/elf-eh-frame.c +++ b/bfd/elf-eh-frame.c @@ -619,15 +619,6 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, REQUIRE (bfd_malloc_and_get_section (abfd, sec, &ehbuf)); - if (sec->size >= 4 - && bfd_get_32 (abfd, ehbuf) == 0 - && cookie->rel == cookie->relend) - { - /* Empty .eh_frame section. */ - free (ehbuf); - return; - } - /* If .eh_frame section size doesn't fit into int, we cannot handle it (it would need to use 64-bit .eh_frame format anyway). */ REQUIRE (sec->size == (unsigned int) sec->size); @@ -669,8 +660,11 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, REQUIRE (sec_info); /* We need to have a "struct cie" for each CIE in this section. */ - local_cies = (struct cie *) bfd_zmalloc (num_cies * sizeof (*local_cies)); - REQUIRE (local_cies); + if (num_cies) + { + local_cies = (struct cie *) bfd_zmalloc (num_cies * sizeof (*local_cies)); + REQUIRE (local_cies); + } /* FIXME: octets_per_byte. */ #define ENSURE_NO_RELOCS(buf) \ @@ -724,7 +718,9 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, if (hdr_length == 0) { /* A zero-length CIE should only be found at the end of - the section. */ + the section, but allow multiple terminators. */ + while (skip_bytes (&buf, ehbuf + sec->size, 4)) + REQUIRE (bfd_get_32 (abfd, buf - 4) == 0); REQUIRE ((bfd_size_type) (buf - ehbuf) == sec->size); ENSURE_NO_RELOCS (buf); sec_info->count++; diff --git a/bfd/elflink.c b/bfd/elflink.c index f6f57fa4154..6008915fed3 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -13862,39 +13862,36 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) fini_reloc_cookie_for_section (&cookie, i); } + eh_alignment = 1 << o->alignment_power; - if (eh_alignment > 4) - { - /* Skip over zero terminator, and prevent empty sections - from adding alignment padding at the end. */ - for (i = o->map_tail.s; i != NULL; i = i->map_tail.s) - if (i->size == 0) - i->flags |= SEC_EXCLUDE; - else if (i->size > 4) - break; - /* The last non-empty eh_frame section doesn't need padding. */ - if (i != NULL) - i = i->map_tail.s; - /* Any prior sections must pad the last FDE out to the - output section alignment. Otherwise we might have zero - padding between sections, which would be seen as a - terminator. If there is a terminator in the middle of - FDEs, don't increase its size as that will write bogus - data of whatever was after the terminator in the input - file, to the output file. */ - for (; i != NULL; i = i->map_tail.s) - if (i->size != 4) + /* Skip over zero terminator, and prevent empty sections from + adding alignment padding at the end. */ + for (i = o->map_tail.s; i != NULL; i = i->map_tail.s) + if (i->size == 0) + i->flags |= SEC_EXCLUDE; + else if (i->size > 4) + break; + /* The last non-empty eh_frame section doesn't need padding. */ + if (i != NULL) + i = i->map_tail.s; + /* Any prior sections must pad the last FDE out to the output + section alignment. Otherwise we might have zero padding + between sections, which would be seen as a terminator. */ + for (; i != NULL; i = i->map_tail.s) + if (i->size == 4) + /* All but the last zero terminator should have been removed. */ + BFD_FAIL (); + else + { + bfd_size_type size + = (i->size + eh_alignment - 1) & -eh_alignment; + if (i->size != size) { - bfd_size_type size - = (i->size + eh_alignment - 1) & -eh_alignment; - if (i->size != size) - { - i->size = size; - changed = 1; - eh_changed = 1; - } + i->size = size; + changed = 1; + eh_changed = 1; } - } + } if (eh_changed) elf_link_hash_traverse (elf_hash_table (info), _bfd_elf_adjust_eh_frame_global_symbol, NULL); diff --git a/ld/ChangeLog b/ld/ChangeLog index 1dcb981353b..670f3562eb3 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2017-08-31 Alan Modra + + * testsuite/ld-elf/eh3.d: Update. + * testsuite/ld-elf/eh4.d: Update. + 2017-08-30 Maciej W. Rozycki * testsuite/ld-elf/orphan-11.ld: Also discard `.MIPS.options' diff --git a/ld/testsuite/ld-elf/eh3.d b/ld/testsuite/ld-elf/eh3.d index 38113411582..6ac584a6222 100644 --- a/ld/testsuite/ld-elf/eh3.d +++ b/ld/testsuite/ld-elf/eh3.d @@ -23,20 +23,12 @@ Contents of the .eh_frame section: DW_CFA_nop DW_CFA_nop -0+0018 0+0024 0+001c FDE cie=0+0000 pc=0+400078\.\.0+400090 +0+0018 0+001c 0+001c FDE cie=0+0000 pc=0+400078\.\.0+400090 DW_CFA_advance_loc: 8 to 0+400080 DW_CFA_def_cfa_offset: 16 DW_CFA_offset: r6 \(rbp\) at cfa-16 DW_CFA_advance_loc: 8 to 0+400088 DW_CFA_def_cfa_register: r6 \(rbp\) - DW_CFA_nop - DW_CFA_nop - DW_CFA_nop - DW_CFA_nop - DW_CFA_nop - DW_CFA_nop - DW_CFA_nop - DW_CFA_nop -0+0040 ZERO terminator +0+0038 ZERO terminator #pass diff --git a/ld/testsuite/ld-elf/eh4.d b/ld/testsuite/ld-elf/eh4.d index b5eec2f4d14..6c1cb320d10 100644 --- a/ld/testsuite/ld-elf/eh4.d +++ b/ld/testsuite/ld-elf/eh4.d @@ -28,14 +28,12 @@ Contents of the .eh_frame section: DW_CFA_set_loc: 0+0417 DW_CFA_def_cfa_offset: 80 -0+0048 0+0024 0+004c FDE cie=0+0000 pc=[0-9a-f]+\.\.[0-9a-f]+ +0+0048 0+002[04] 0+004c FDE cie=0+0000 pc=[0-9a-f]+\.\.[0-9a-f]+ DW_CFA_def_cfa_offset: 16 DW_CFA_advance_loc: [0-9a-f]+ to [0-9a-f]+ DW_CFA_def_cfa_offset: 24 DW_CFA_advance_loc: [0-9a-f]+ to [0-9a-f]+ DW_CFA_def_cfa_expression \(DW_OP_breg7 \(rsp\): 8; DW_OP_breg16 \(rip\): 0;.* - DW_CFA_nop #... - [0-9a-f]+ ZERO terminator #pass -- 2.30.2