diff options
author | Alan Modra <amodra@bigpond.net.au> | 2010-02-19 01:47:13 +0000 |
---|---|---|
committer | Alan Modra <amodra@bigpond.net.au> | 2010-02-19 01:47:13 +0000 |
commit | a37671093643f1d923ab97ff25ef6c97fda41286 (patch) | |
tree | d1b5fcd1a58b54d24496bd2c7d122dd907e12738 /bfd | |
parent | a4a91e4b48ed9055ca9f127893c6ac9b2c939e0a (diff) | |
download | binutils-redhat-a37671093643f1d923ab97ff25ef6c97fda41286.tar.gz |
bfd/
* elf.c (_bfd_elf_fixup_group_sections): New function, split out from..
(_bfd_elf_copy_private_header_data): ..here.
* elflink.c (_bfd_elf_size_group_sections): New function.
(bfd_elf_size_dynamic_sections): Call it.
* elf-bfd.h (_bfd_elf_size_group_sections): Declare.
(_bfd_elf_fixup_group_sections): Declare.
ld/
* ldlang.c (unique_section_p): Add os param. Allow group
sections to match /DISCARD/. Update all callers.
* emultempl/genelf.em (gld${EMULATION_NAME}_before_allocation): New.
(LDEMUL_BEFORE_ALLOCATION): Define.
ld/testsuite/
* ld-elf/group.ld: Discard .dropme sections.
* ld-elf/group10.d, * ld-elf/group10.s: New test.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 9 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 4 | ||||
-rw-r--r-- | bfd/elf.c | 78 | ||||
-rw-r--r-- | bfd/elflink.c | 18 |
4 files changed, 87 insertions, 22 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8e0e2ddbb0..a09058aa57 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2010-02-19 Alan Modra <amodra@gmail.com> + + * elf.c (_bfd_elf_fixup_group_sections): New function, split out from.. + (_bfd_elf_copy_private_header_data): ..here. + * elflink.c (_bfd_elf_size_group_sections): New function. + (bfd_elf_size_dynamic_sections): Call it. + * elf-bfd.h (_bfd_elf_size_group_sections): Declare. + (_bfd_elf_fixup_group_sections): Declare. + 2010-02-18 Matthew Gretton-Dann <matthew.gretton-dann@arm.com> * elf32-arm.c (elf32_arm_merge_eabi_attributes): Add support for diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 6d4b8dd173..74348d3abb 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1773,6 +1773,10 @@ extern void _bfd_elf_link_just_syms (asection *, struct bfd_link_info *); extern void _bfd_elf_copy_link_hash_symbol_type (bfd *, struct bfd_link_hash_entry *, struct bfd_link_hash_entry *); +extern bfd_boolean _bfd_elf_size_group_sections + (struct bfd_link_info *); +extern bfd_boolean _bfd_elf_fixup_group_sections +(bfd *, asection *); extern bfd_boolean _bfd_elf_copy_private_header_data (bfd *, bfd *); extern bfd_boolean _bfd_elf_copy_private_symbol_data @@ -6137,58 +6137,92 @@ _bfd_elf_copy_private_section_data (bfd *ibfd, NULL); } -/* Copy private header information. */ +/* Look at all the SHT_GROUP sections in IBFD, making any adjustments + necessary if we are removing either the SHT_GROUP section or any of + the group member sections. DISCARDED is the value that a section's + output_section has if the section will be discarded, NULL when this + function is called from objcopy, bfd_abs_section_ptr when called + from the linker. */ bfd_boolean -_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd) +_bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded) { asection *isec; - if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour - || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return TRUE; - - /* Copy over private BFD data if it has not already been copied. - This must be done here, rather than in the copy_private_bfd_data - entry point, because the latter is called after the section - contents have been set, which means that the program headers have - already been worked out. */ - if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL) - { - if (! copy_private_bfd_data (ibfd, obfd)) - return FALSE; - } - for (isec = ibfd->sections; isec != NULL; isec = isec->next) if (elf_section_type (isec) == SHT_GROUP) { asection *first = elf_next_in_group (isec); asection *s = first; + bfd_size_type removed = 0; + while (s != NULL) { /* If this member section is being output but the SHT_GROUP section is not, then clear the group info set up by _bfd_elf_copy_private_section_data. */ - if (s->output_section != NULL - && isec->output_section == NULL) + if (s->output_section != discarded + && isec->output_section == discarded) { elf_section_flags (s->output_section) &= ~SHF_GROUP; elf_group_name (s->output_section) = NULL; } /* Conversely, if the member section is not being output but the SHT_GROUP section is, then adjust its size. */ - else if (s->output_section == NULL - && isec->output_section != NULL) - isec->output_section->size -= 4; + else if (s->output_section == discarded + && isec->output_section != discarded) + removed += 4; s = elf_next_in_group (s); if (s == first) break; } + if (removed != 0) + { + if (discarded != NULL) + { + /* If we've been called for ld -r, then we need to + adjust the input section size. This function may + be called multiple times, so save the original + size. */ + if (isec->rawsize == 0) + isec->rawsize = isec->size; + isec->size = isec->rawsize - removed; + } + else + { + /* Adjust the output section size when called from + objcopy. */ + isec->output_section->size -= removed; + } + } } return TRUE; } +/* Copy private header information. */ + +bfd_boolean +_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd) +{ + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return TRUE; + + /* Copy over private BFD data if it has not already been copied. + This must be done here, rather than in the copy_private_bfd_data + entry point, because the latter is called after the section + contents have been set, which means that the program headers have + already been worked out. */ + if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL) + { + if (! copy_private_bfd_data (ibfd, obfd)) + return FALSE; + } + + return _bfd_elf_fixup_group_sections (ibfd, NULL); +} + /* Copy private symbol information. If this symbol is in a section which we did not map into a BFD section, try to map the section index correctly. We use special macro definitions for the mapped diff --git a/bfd/elflink.c b/bfd/elflink.c index a325c00ca5..9fb347b7c5 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -5481,6 +5481,20 @@ compute_bucket_count (struct bfd_link_info *info, return best_size; } +/* Size any SHT_GROUP section for ld -r. */ + +bfd_boolean +_bfd_elf_size_group_sections (struct bfd_link_info *info) +{ + bfd *ibfd; + + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour + && !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr)) + return FALSE; + return TRUE; +} + /* Set up the sizes and contents of the ELF dynamic sections. This is called by the ELF linker emulation before_allocation routine. We must set the sizes of the sections before the linker sets the @@ -5555,6 +5569,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, elf_hash_table (info)->init_plt_refcount = elf_hash_table (info)->init_plt_offset; + if (info->relocatable + && !_bfd_elf_size_group_sections (info)) + return FALSE; + /* The backend may have to create some sections regardless of whether we're dynamic or not. */ if (bed->elf_backend_always_size_sections |