diff options
Diffstat (limited to 'bfd/elf.c')
-rw-r--r-- | bfd/elf.c | 78 |
1 files changed, 56 insertions, 22 deletions
@@ -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 |