aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--bfd/ChangeLog11
-rw-r--r--bfd/elf.c46
-rw-r--r--gas/ChangeLog17
-rw-r--r--gas/config/obj-elf.c65
-rw-r--r--gas/testsuite/gas/arc/jli-1.d1
-rw-r--r--gas/testsuite/gas/elf/groupautob.d2
-rw-r--r--gas/testsuite/gas/mips/compact-eh-eb-2.d2
-rw-r--r--gas/testsuite/gas/mips/compact-eh-eb-5.d2
-rw-r--r--gas/testsuite/gas/mips/compact-eh-el-2.d2
-rw-r--r--gas/testsuite/gas/mips/compact-eh-el-5.d2
-rw-r--r--ld/ChangeLog5
-rw-r--r--ld/testsuite/ld-elf/group9b.d9
12 files changed, 111 insertions, 53 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index cffa777..9b377f5 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,14 @@
+2017-10-05 Alan Modra <amodra@gmail.com>
+
+ 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.
+
2017-10-04 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_get_synthetic_symtab): Don't sort or
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)
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 05e06c6..c112d86 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,20 @@
+2017-10-05 Alan Modra <amodra@gmail.com>
+
+ 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.
+
2017-10-01 Alexander Fedotov <alfedotov@gmail.com>
* testsuite/gas/ppc/vle-mult-ld-st-insns.s: New file: Tests the
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index 49d99a4..3f641f4 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -2346,11 +2346,12 @@ elf_frob_symbol (symbolS *symp, int *puntp)
struct group_list
{
asection **head; /* Section lists. */
- unsigned int *elt_count; /* Number of sections in each list. */
unsigned int num_group; /* Number of lists. */
struct hash_control *indexes; /* Maps group name to index in head array. */
};
+static struct group_list groups;
+
/* Called via bfd_map_over_sections. If SEC is a member of a group,
add it to a list of sections belonging to the group. INF is a
pointer to a struct group_list, which is where we store the head of
@@ -2375,7 +2376,6 @@ build_group_lists (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
{
elf_next_in_group (sec) = list->head[*elem_idx];
list->head[*elem_idx] = sec;
- list->elt_count[*elem_idx] += 1;
return;
}
@@ -2386,10 +2386,8 @@ build_group_lists (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf)
{
unsigned int newsize = i + 128;
list->head = XRESIZEVEC (asection *, list->head, newsize);
- list->elt_count = XRESIZEVEC (unsigned int, list->elt_count, newsize);
}
list->head[i] = sec;
- list->elt_count[i] = 1;
list->num_group += 1;
/* Add index to hash. */
@@ -2403,38 +2401,37 @@ static void free_section_idx (const char *key ATTRIBUTE_UNUSED, void *val)
free ((unsigned int *) val);
}
+/* Create symbols for group signature. */
+
void
elf_adjust_symtab (void)
{
- struct group_list list;
unsigned int i;
/* Go find section groups. */
- list.num_group = 0;
- list.head = NULL;
- list.elt_count = NULL;
- list.indexes = hash_new ();
- bfd_map_over_sections (stdoutput, build_group_lists, &list);
+ groups.num_group = 0;
+ groups.head = NULL;
+ groups.indexes = hash_new ();
+ bfd_map_over_sections (stdoutput, build_group_lists, &groups);
/* Make the SHT_GROUP sections that describe each section group. We
can't set up the section contents here yet, because elf section
indices have yet to be calculated. elf.c:set_group_contents does
the rest of the work. */
- for (i = 0; i < list.num_group; i++)
+ for (i = 0; i < groups.num_group; i++)
{
- const char *group_name = elf_group_name (list.head[i]);
+ const char *group_name = elf_group_name (groups.head[i]);
const char *sec_name;
asection *s;
flagword flags;
struct symbol *sy;
- bfd_size_type size;
flags = SEC_READONLY | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_GROUP;
- for (s = list.head[i]; s != NULL; s = elf_next_in_group (s))
+ for (s = groups.head[i]; s != NULL; s = elf_next_in_group (s))
if ((s->flags ^ flags) & SEC_LINK_ONCE)
{
flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
- if (s != list.head[i])
+ if (s != groups.head[i])
{
as_warn (_("assuming all members of group `%s' are COMDAT"),
group_name);
@@ -2454,7 +2451,8 @@ elf_adjust_symtab (void)
elf_section_type (s) = SHT_GROUP;
/* Pass a pointer to the first section in this group. */
- elf_next_in_group (s) = list.head[i];
+ elf_next_in_group (s) = groups.head[i];
+ elf_sec_group (groups.head[i]) = s;
/* Make sure that the signature symbol for the group has the
name of the group. */
sy = symbol_find_exact (group_name);
@@ -2476,17 +2474,7 @@ elf_adjust_symtab (void)
symbol_table_insert (sy);
}
elf_group_id (s) = symbol_get_bfdsym (sy);
-
- size = 4 * (list.elt_count[i] + 1);
- bfd_set_section_size (stdoutput, s, size);
- s->contents = (unsigned char *) frag_more (size);
- frag_now->fr_fix = frag_now_fix_octets ();
- frag_wane (frag_now);
}
-
- /* Cleanup hash. */
- hash_traverse (list.indexes, free_section_idx);
- hash_die (list.indexes);
}
void
@@ -2550,6 +2538,31 @@ elf_frob_file_before_adjust (void)
void
elf_frob_file_after_relocs (void)
{
+ unsigned int i;
+
+ /* Set SHT_GROUP section size. */
+ for (i = 0; i < groups.num_group; i++)
+ {
+ asection *s, *head, *group;
+ bfd_size_type size;
+
+ head = groups.head[i];
+ size = 4;
+ for (s = head; s != NULL; s = elf_next_in_group (s))
+ size += (s->flags & SEC_RELOC) != 0 ? 8 : 4;
+
+ group = elf_sec_group (head);
+ subseg_set (group, 0);
+ bfd_set_section_size (stdoutput, group, size);
+ group->contents = (unsigned char *) frag_more (size);
+ frag_now->fr_fix = frag_now_fix_octets ();
+ frag_wane (frag_now);
+ }
+
+ /* Cleanup hash. */
+ hash_traverse (groups.indexes, free_section_idx);
+ hash_die (groups.indexes);
+
#ifdef NEED_ECOFF_DEBUG
if (ECOFF_DEBUGGING)
/* Generate the ECOFF debugging information. */
diff --git a/gas/testsuite/gas/arc/jli-1.d b/gas/testsuite/gas/arc/jli-1.d
index 10550a2..46587be 100644
--- a/gas/testsuite/gas/arc/jli-1.d
+++ b/gas/testsuite/gas/arc/jli-1.d
@@ -9,6 +9,7 @@ Disassembly of section .group:
00000000 <jlitab.foo>:
0: 0[10] 00 00 0[01] .word 0x00000001
4: 0[60] 00 00 0[06] .word 0x00000006
+ 8: 0[70] 00 00 0[07] .word 0x00000007
Disassembly of section .text:
diff --git a/gas/testsuite/gas/elf/groupautob.d b/gas/testsuite/gas/elf/groupautob.d
index 76c60b4..5f6081f 100644
--- a/gas/testsuite/gas/elf/groupautob.d
+++ b/gas/testsuite/gas/elf/groupautob.d
@@ -3,7 +3,7 @@
#source: groupauto.s
#...
-COMDAT group section \[ 1\] `\.group' \[some_group\] contains 2 sections:
+COMDAT group section \[ 1\] `\.group' \[some_group\] contains [23] sections:
[ ]+\[Index\][ ]+Name
[ ]+\[.*\][ ]+.text
[ ]+\[.*\][ ]+.note.bar
diff --git a/gas/testsuite/gas/mips/compact-eh-eb-2.d b/gas/testsuite/gas/mips/compact-eh-eb-2.d
index 226a5ff..feefafa 100644
--- a/gas/testsuite/gas/mips/compact-eh-eb-2.d
+++ b/gas/testsuite/gas/mips/compact-eh-eb-2.d
@@ -23,7 +23,7 @@ OFFSET TYPE VALUE
Contents of section .group:
- 0000 00000001 00000007 .*
+ 0000 00000001 00000007 00000008 .*
Contents of section .text:
0000 00000000.*
Contents of section .reginfo:
diff --git a/gas/testsuite/gas/mips/compact-eh-eb-5.d b/gas/testsuite/gas/mips/compact-eh-eb-5.d
index fd278a1..79a65bb 100644
--- a/gas/testsuite/gas/mips/compact-eh-eb-5.d
+++ b/gas/testsuite/gas/mips/compact-eh-eb-5.d
@@ -23,7 +23,7 @@ OFFSET TYPE VALUE
Contents of section .group:
- 0000 00000001 00000007 .*
+ 0000 00000001 00000007 00000008 .*
Contents of section .text:
0000 00000000 00000000 00000000 00000000 .*
0010 00000000.*
diff --git a/gas/testsuite/gas/mips/compact-eh-el-2.d b/gas/testsuite/gas/mips/compact-eh-el-2.d
index 80627eb..f5fe968 100644
--- a/gas/testsuite/gas/mips/compact-eh-el-2.d
+++ b/gas/testsuite/gas/mips/compact-eh-el-2.d
@@ -23,7 +23,7 @@ OFFSET TYPE VALUE
Contents of section .group:
- 0000 01000000 07000000 .*
+ 0000 01000000 07000000 08000000 .*
Contents of section .text:
0000 00000000.*
Contents of section .reginfo:
diff --git a/gas/testsuite/gas/mips/compact-eh-el-5.d b/gas/testsuite/gas/mips/compact-eh-el-5.d
index 7f07622..aa84332 100644
--- a/gas/testsuite/gas/mips/compact-eh-el-5.d
+++ b/gas/testsuite/gas/mips/compact-eh-el-5.d
@@ -22,7 +22,7 @@ OFFSET TYPE VALUE
Contents of section .group:
- 0000 01000000 07000000 .*
+ 0000 01000000 07000000 08000000 .*
Contents of section .text:
0000 00000000 00000000 00000000 00000000 .*
0010 00000000.*
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 18a95f1..7c266e6 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,8 @@
+2017-10-05 Alan Modra <amodra@gmail.com>
+
+ PR 21167
+ * testsuite/ld-elf/group9b.d: Adjust for relocs included in group.
+
2017-10-03 Alan Modra <amodra@gmail.com>
PR 21294
diff --git a/ld/testsuite/ld-elf/group9b.d b/ld/testsuite/ld-elf/group9b.d
index 3005f8f..c237f54 100644
--- a/ld/testsuite/ld-elf/group9b.d
+++ b/ld/testsuite/ld-elf/group9b.d
@@ -10,9 +10,10 @@
COMDAT group section \[[ 0-9]+\] `.group' \[foo\] contains 2 sections:
\[Index\] Name
- \[[ 0-9]+\] .text.foo
- \[[ 0-9]+\] .data.foo
+ \[[ 0-9]+\] \.text\.foo
+ \[[ 0-9]+\] \.data\.foo
-COMDAT group section \[[ 0-9]+\] `.group' \[bar\] contains 1 sections:
+COMDAT group section \[[ 0-9]+\] `.group' \[bar\] contains 2 sections:
\[Index\] Name
- \[[ 0-9]+\] .text.bar
+ \[[ 0-9]+\] \.text\.bar
+ \[[ 0-9]+\] \.rela?\.text\.bar