aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-10-04 09:53:53 +1030
committerAlan Modra <amodra@gmail.com>2017-10-05 08:38:11 +1030
commitdb4677b8bd90b49f826807352c6c3c7eb0d57814 (patch)
treec73ecf5bd1a49511dfcf9e73292569557949e7a2 /bfd/elf.c
parent5cd63fda035d4ba949e6478406162c4673b3c9ef (diff)
downloadfsf-binutils-gdb-db4677b8bd90b49f826807352c6c3c7eb0d57814.zip
fsf-binutils-gdb-db4677b8bd90b49f826807352c6c3c7eb0d57814.tar.gz
fsf-binutils-gdb-db4677b8bd90b49f826807352c6c3c7eb0d57814.tar.bz2
PR21167, relocation sections not included in groups
This fixes a wart I've known about for years, but haven't done anything about because BFD treats relocation sections as an adjunct to the section they relocate. SHF_GROUP on the section thus implicitly applies to its relocation section(s), but it is an error that the reloc sections aren't part of the group. Like many patches to gas, this wasn't as straightforward as it could be due to a number of backends, i386, cr16 and others, removing relocs in tc_get_reloc rather than marking them as "done" earlier in md_apply_reloc. So it isn't possible for the group support to reliably detect the presence of relocs by looking at fixups earlier than write_relocs. However the group support needs to create signature symbols, and that must be done before the symbol table is frozen, before write_relocs. So split off the group sizing from elf_adjust_symtab and put it in elf_frob_file_after_relocs. bfd/ PR 21167 * elf.c (_bfd_elf_setup_sections): Don't trim reloc sections from groups. (_bfd_elf_init_reloc_shdr): Pass sec_hdr, use it to copy SHF_GROUP flag from section. (elf_fake_sections): Adjust calls. Exit immediately on failure. (bfd_elf_set_group_contents): Add associated reloc section indices to group contents gas/ PR 21167 * config/obj-elf.c (struct group_list): Delete elt_count. (groups): New static. (build_group_lists): Don't count elements. (elf_adjust_symtab): Use groups rather than auto list. Set up pointer from group member to SHT_GROUP section. Don't size SHT_GROUP section or clean up here.. (elf_frob_file_after_relocs): ..do so here instead. * testsuite/gas/arc/jli-1.d, * testsuite/gas/elf/groupautob.d, * testsuite/gas/mips/compact-eh-eb-2.d, * testsuite/gas/mips/compact-eh-eb-5.d, * testsuite/gas/mips/compact-eh-el-2.d, * testsuite/gas/mips/compact-eh-el-5.d: Adjust. ld/ PR 21167 * testsuite/ld-elf/group9b.d: Adjust for relocs included in group.
Diffstat (limited to 'bfd/elf.c')
-rw-r--r--bfd/elf.c46
1 files changed, 28 insertions, 18 deletions
diff --git a/bfd/elf.c b/bfd/elf.c
index 38dba48..fd7f773 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -913,15 +913,8 @@ _bfd_elf_setup_sections (bfd *abfd)
continue;
else if (idx->shdr->bfd_section)
elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
- else if (idx->shdr->sh_type == SHT_RELA
- || idx->shdr->sh_type == SHT_REL)
- /* We won't include relocation sections in section groups in
- output object files. We adjust the group section size here
- so that relocatable link will work correctly when
- relocation sections are in section group in input object
- files. */
- shdr->bfd_section->size -= 4;
- else
+ else if (idx->shdr->sh_type != SHT_RELA
+ && idx->shdr->sh_type != SHT_REL)
{
/* There are some unknown sections in the group. */
_bfd_error_handler
@@ -3068,6 +3061,7 @@ _bfd_elf_set_reloc_sh_name (bfd *abfd,
static bfd_boolean
_bfd_elf_init_reloc_shdr (bfd *abfd,
struct bfd_elf_section_reloc_data *reldata,
+ const Elf_Internal_Shdr *sec_hdr,
const char *sec_name,
bfd_boolean use_rela_p,
bfd_boolean delay_st_name_p)
@@ -3089,7 +3083,7 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
? bed->s->sizeof_rela
: bed->s->sizeof_rel);
rel_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
- rel_hdr->sh_flags = 0;
+ rel_hdr->sh_flags = sec_hdr->sh_flags & SHF_GROUP;
rel_hdr->sh_addr = 0;
rel_hdr->sh_size = 0;
rel_hdr->sh_offset = 0;
@@ -3380,15 +3374,15 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
|| arg->link_info->emitrelocations))
{
if (esd->rel.count && esd->rel.hdr == NULL
- && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, name, FALSE,
- delay_st_name_p))
+ && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, this_hdr, name,
+ FALSE, delay_st_name_p))
{
arg->failed = TRUE;
return;
}
if (esd->rela.count && esd->rela.hdr == NULL
- && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, name, TRUE,
- delay_st_name_p))
+ && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, this_hdr, name,
+ TRUE, delay_st_name_p))
{
arg->failed = TRUE;
return;
@@ -3397,17 +3391,24 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
else if (!_bfd_elf_init_reloc_shdr (abfd,
(asect->use_rela_p
? &esd->rela : &esd->rel),
+ this_hdr,
name,
asect->use_rela_p,
delay_st_name_p))
+ {
arg->failed = TRUE;
+ return;
+ }
}
/* Check for processor-specific section types. */
sh_type = this_hdr->sh_type;
if (bed->elf_backend_fake_sections
&& !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect))
- arg->failed = TRUE;
+ {
+ arg->failed = TRUE;
+ return;
+ }
if (sh_type == SHT_NOBITS && asect->size != 0)
{
@@ -3524,10 +3525,19 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
if (s != NULL
&& !bfd_is_abs_section (s))
{
- unsigned int idx = elf_section_data (s)->this_idx;
-
+ struct bfd_elf_section_data *elf_sec = elf_section_data (s);
+ if (elf_sec->rel.hdr != NULL)
+ {
+ loc -= 4;
+ H_PUT_32 (abfd, elf_sec->rel.idx, loc);
+ }
+ if (elf_sec->rela.hdr != NULL)
+ {
+ loc -= 4;
+ H_PUT_32 (abfd, elf_sec->rela.idx, loc);
+ }
loc -= 4;
- H_PUT_32 (abfd, idx, loc);
+ H_PUT_32 (abfd, elf_sec->this_idx, loc);
}
elt = elf_next_in_group (elt);
if (elt == first)