PR21167, relocation sections not included in groups
authorAlan Modra <amodra@gmail.com>
Tue, 3 Oct 2017 23:23:53 +0000 (09:53 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 4 Oct 2017 22:08:11 +0000 (08:38 +1030)
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.

12 files changed:
bfd/ChangeLog
bfd/elf.c
gas/ChangeLog
gas/config/obj-elf.c
gas/testsuite/gas/arc/jli-1.d
gas/testsuite/gas/elf/groupautob.d
gas/testsuite/gas/mips/compact-eh-eb-2.d
gas/testsuite/gas/mips/compact-eh-eb-5.d
gas/testsuite/gas/mips/compact-eh-el-2.d
gas/testsuite/gas/mips/compact-eh-el-5.d
ld/ChangeLog
ld/testsuite/ld-elf/group9b.d

index cffa777b42c9d00f9ed6fa304e11a0d2b67c0923..9b377f56780704c6012fabfc7b38b14815f31adb 100644 (file)
@@ -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
index 38dba485003af1572fe6a17bd1668b883da9881a..fd7f77373046940c0f9a944ddf110eb66d142086 100644 (file)
--- 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)
index 05e06c6ea9f85d6c6f83020ea8f828f2e03990f6..c112d86094e4274c691e2b57e790ea09c97213fc 100644 (file)
@@ -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
index 49d99a459ca1cc7d13731f4a7beea5a33612c5d2..3f641f4394bb893695af27af74a7041df2fc0810 100644 (file)
@@ -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.  */
index 10550a2d0dc00f44d6ff7767e70effb30fb3b037..46587be1c92f4c4433cab822b685ffc95454ba54 100644 (file)
@@ -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:
 
index 76c60b434ebb3c4258c561b997e6ec7231d8a8f2..5f6081fb2ac19b0e6f7f3e0a70ddbc940527f72c 100644 (file)
@@ -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
index 226a5ffe81ea0de52ae1bae8b3e6b88711279fbc..feefafa880900b0b2674f2a4e9faf118bef5812b 100644 (file)
@@ -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:
index fd278a16f4a7020ee9895a87a28f91cc42394d00..79a65bb31c2b818a126f2ffb29048108e8062f24 100644 (file)
@@ -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.*
index 80627ebddcbe478cb68f490bf8e9d7b8bec733ba..f5fe968d2e5d4dda34c6410f2c1db62b3cd670cd 100644 (file)
@@ -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:
index 7f0762290ca03d4d12d052441f8c53b20a9ddad4..aa8433290dedd18f50a95cf3a84786846883e948 100644 (file)
@@ -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.*
index 18a95f1a8b0709018033925b9610d19ea7d9ada9..7c266e611708791fbed64afe825c6f633ee2dd9e 100644 (file)
@@ -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
index 3005f8f4b7b478fc18ce68785250386ef709bd36..c237f5484519b9a797e02ea5c54e709374b0399a 100644 (file)
 
 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