PR22836, "-r -s" doesn't work with -g3 using GCC 7

This fixes the case where all of a group is removed with ld -r, the
situation in the PR, and failures where part of a group is removed
that contain relocs.

bfd/
	PR 22836
	* elf.c (_bfd_elf_fixup_group_sections): Account for removed
	relocation sections.  If size reduces to just the flag word,
	remove that too and mark with SEC_EXCLUDE.
	* elflink.c (bfd_elf_final_link): Strip empty group sections.
binutils/
	* testsuite/binutils-all/group-7.s,
	* testsuite/binutils-all/group-7a.d,
	* testsuite/binutils-all/group-7b.d,
	* testsuite/binutils-all/group-7c.d: New tests.
	* testsuite/binutils-all/objcopy.exp: Run them.
ld/
	* testsuite/ld-elf/pr22836-2.d,
	* testsuite/ld-elf/pr22836-2.s: New test.
This commit is contained in:
Alan Modra
2018-02-13 14:09:48 +10:30
parent f2731e0c37
commit 6e5e9d58c1
12 changed files with 117 additions and 4 deletions

View File

@@ -7604,7 +7604,16 @@ _bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded)
but the SHT_GROUP section is, then adjust its size. */
else if (s->output_section == discarded
&& isec->output_section != discarded)
removed += 4;
{
struct bfd_elf_section_data *elf_sec = elf_section_data (s);
removed += 4;
if (elf_sec->rel.hdr != NULL
&& (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0)
removed += 4;
if (elf_sec->rela.hdr != NULL
&& (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0)
removed += 4;
}
s = elf_next_in_group (s);
if (s == first)
break;
@@ -7614,18 +7623,26 @@ _bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded)
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. */
adjust the input section size. */
if (isec->rawsize == 0)
isec->rawsize = isec->size;
isec->size = isec->rawsize - removed;
if (isec->size <= 4)
{
isec->size = 0;
isec->flags |= SEC_EXCLUDE;
}
}
else
{
/* Adjust the output section size when called from
objcopy. */
isec->output_section->size -= removed;
if (isec->output_section->size <= 4)
{
isec->output_section->size = 0;
isec->output_section->flags |= SEC_EXCLUDE;
}
}
}
}