* elf-bfd.h (struct bfd_elf_section_data): Add "group" and
authorAlan Modra <amodra@gmail.com>
Tue, 9 Oct 2001 06:05:17 +0000 (06:05 +0000)
committerAlan Modra <amodra@gmail.com>
Tue, 9 Oct 2001 06:05:17 +0000 (06:05 +0000)
"next_in_group".  Fix gp and gp_size comments.
* elf.c (union elf_internal_group): New.
(setup_group): New function.
(_bfd_elf_make_section_from_shdr): Set BFD flags for SHT_GROUP.
Call setup_group for SHF_GROUP sections.
(bfd_section_from_shdr): Build a BFD section for SHT_GROUP.
(elf_fake_sections): Set header type for SEC_GROUP, and header
flags for sections in a group.
(set_group_contents): New function.
(_bfd_elf_compute_section_file_positions): Call it.
(assign_section_numbers): Set sh_link for SHT_GROUP.
* elflink.h (gc_mark_hook): Handle section groups.
* elfxx-target.h: Add SEC_GROUP to applicable_flags.
* section.c (SEC_GROUP): Define.
(struct sec): Comment fixes.
* bfd-in2.h: Regenerate.

* elf.c (bfd_elf_print_symbol): Formatting fix; migrate expression
out of function args.
(_bfd_elf_canonicalize_reloc): Similarly.
(_bfd_elf_get_symtab): Here too.
(_bfd_elf_canonicalize_dynamic_symtab): And here.
* elfcode.h (elf_slurp_symbol_table): Don't recalculate size for
bfd_bread, and remove unnecessary cast.

bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf-bfd.h
bfd/elf.c
bfd/elfcode.h
bfd/elflink.h
bfd/elfxx-target.h
bfd/section.c

index aad8211e06d2d10750e841fbc2cf87edfcbe986d..9aa571c073c1f67dd0d276348a3d485bbd5a6cfb 100644 (file)
@@ -1,3 +1,31 @@
+2001-10-09  Alan Modra  <amodra@bigpond.net.au>
+
+       * elf-bfd.h (struct bfd_elf_section_data): Add "group" and
+       "next_in_group".  Fix gp and gp_size comments.
+       * elf.c (union elf_internal_group): New.
+       (setup_group): New function.
+       (_bfd_elf_make_section_from_shdr): Set BFD flags for SHT_GROUP.
+       Call setup_group for SHF_GROUP sections.
+       (bfd_section_from_shdr): Build a BFD section for SHT_GROUP.
+       (elf_fake_sections): Set header type for SEC_GROUP, and header
+       flags for sections in a group.
+       (set_group_contents): New function.
+       (_bfd_elf_compute_section_file_positions): Call it.
+       (assign_section_numbers): Set sh_link for SHT_GROUP.
+       * elflink.h (gc_mark_hook): Handle section groups.
+       * elfxx-target.h: Add SEC_GROUP to applicable_flags.
+       * section.c (SEC_GROUP): Define.
+       (struct sec): Comment fixes.
+       * bfd-in2.h: Regenerate.
+
+       * elf.c (bfd_elf_print_symbol): Formatting fix; migrate expression
+       out of function args.
+       (_bfd_elf_canonicalize_reloc): Similarly.
+       (_bfd_elf_get_symtab): Here too.
+       (_bfd_elf_canonicalize_dynamic_symtab): And here.
+       * elfcode.h (elf_slurp_symbol_table): Don't recalculate size for
+       bfd_bread, and remove unnecessary cast.
+
 2001-10-08  Aldy Hernandez  <aldyh@redhat.com>
 
         * bfd/config.bfd (targ_cpu): Add arm9e-*-elf.
index c040bba30fb20dcd4558f8d0d4c069fbcda979b4..fcdd1db631543880e1a3115db47820ae921141df 100644 (file)
@@ -983,7 +983,7 @@ typedef struct sec
 
   int id;
 
-  /* Which section is it; 0..nth.  */
+  /* Which section in the bfd; 0..n-1 as sections are created in a bfd.  */
 
   int index;
 
@@ -1098,9 +1098,10 @@ typedef struct sec
      objects are to be further relocated.  */
 #define SEC_EXCLUDE 0x40000
 
-  /* The contents of this section are to be sorted by the
-     based on the address specified in the associated symbol
-     table.  */
+  /* The contents of this section are to be sorted based on the sum of
+     the symbol and addend values specified by the associated relocation
+     entries.  Entries without associated relocation entries will be
+     appended to the end of the section in an unspecified order.  */
 #define SEC_SORT_ENTRIES 0x80000
 
   /* When linking, duplicate sections of the same name should be
@@ -1167,6 +1168,9 @@ typedef struct sec
      size entries.  */
 #define SEC_STRINGS 0x40000000
 
+  /* This section contains data about section groups.  */
+#define SEC_GROUP 0x80000000
+
   /*  End of section flags.  */
 
   /* Some internal packed boolean fields.  */
@@ -1187,7 +1191,8 @@ typedef struct sec
   /* A mark flag used by some linker backends for garbage collection.  */
   unsigned int gc_mark : 1;
 
-  /* Used by the ELF code to mark sections which have been allocated to segments.  */
+  /* Used by the ELF code to mark sections which have been allocated
+     to segments.  */
   unsigned int segment_mark : 1;
 
   /* End of internal packed boolean fields.  */
index 5b2da9877697ccdf87e560e8028aee3bc605c1c1..50c8b2b5dd9b39c8efb533430646e3d309209549 100644 (file)
@@ -815,6 +815,13 @@ struct bfd_elf_section_data
   /* A pointer used for SEC_MERGE optimizations.  */
   PTR merge_info;
 
+  /* Group name, if this section is part of a group.  */
+  const char *group;
+
+  /* A linked list of sections in the group.  Circular when used by
+     the linker.  */
+  asection *next_in_group;
+
   /* A pointer available for the processor specific ELF backend.  */
   PTR tdata;
 
@@ -905,8 +912,11 @@ struct elf_obj_tdata
   void *prstatus;                      /* The raw /proc prstatus structure */
   void *prpsinfo;                      /* The raw /proc prpsinfo structure */
 #endif
-  bfd_vma gp;                          /* The gp value (MIPS only, for now) */
-  unsigned int gp_size;                        /* The gp size (MIPS only, for now) */
+  bfd_vma gp;                          /* The gp value */
+  unsigned int gp_size;                        /* The gp size */
+
+  Elf_Internal_Shdr **group_sect_ptr;
+  int num_group;
 
   /* Information grabbed from an elf core file.  */
   int core_signal;
index 289c06c8958ba67576ba71d03ac3e4c8abfdd111..a3a83e4b32e5e89f10520bf479a984f024f83177 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -51,7 +51,9 @@ static boolean prep_headers PARAMS ((bfd *));
 static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **, int));
 static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *));
 static char *elf_read PARAMS ((bfd *, file_ptr, bfd_size_type));
+static boolean setup_group PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
 static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
+static void set_group_contents PARAMS ((bfd *, asection *, PTR));
 static boolean assign_section_numbers PARAMS ((bfd *));
 static INLINE int sym_is_global PARAMS ((bfd *, asymbol *));
 static boolean elf_map_symbols PARAMS ((bfd *));
@@ -345,6 +347,191 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex)
   return ((char *) hdr->contents) + strindex;
 }
 
+/* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP
+   sections.  The first element is the flags, the rest are section
+   pointers.  */
+
+typedef union elf_internal_group {
+  Elf_Internal_Shdr *shdr;
+  unsigned int flags;
+} Elf_Internal_Group;
+
+/* Set next_in_group list pointer, and group name for NEWSECT.  */
+
+static boolean
+setup_group (abfd, hdr, newsect)
+     bfd *abfd;
+     Elf_Internal_Shdr *hdr;
+     asection *newsect;
+{
+  unsigned int num_group = elf_tdata (abfd)->num_group;
+
+  /* If num_group is zero, read in all SHT_GROUP sections.  The count
+     is set to -1 if there are no SHT_GROUP sections.  */
+  if (num_group == 0)
+    {
+      unsigned int i, shnum;
+
+      /* First count the number of groups.  If we have a SHT_GROUP
+        section with just a flag word (ie. sh_size is 4), ignore it.  */
+      shnum = elf_elfheader (abfd)->e_shnum;
+      num_group = 0;
+      for (i = 0; i < shnum; i++)
+       {
+         Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
+         if (shdr->sh_type == SHT_GROUP && shdr->sh_size >= 8)
+           num_group += 1;
+       }
+
+      if (num_group == 0)
+       num_group = -1;
+      elf_tdata (abfd)->num_group = num_group;
+
+      if (num_group > 0)
+       {
+         /* We keep a list of elf section headers for group sections,
+            so we can find them quickly.  */
+         bfd_size_type amt = num_group * sizeof (Elf_Internal_Shdr *);
+         elf_tdata (abfd)->group_sect_ptr = bfd_alloc (abfd, amt);
+         if (elf_tdata (abfd)->group_sect_ptr == NULL)
+           return false;
+
+         num_group = 0;
+         for (i = 0; i < shnum; i++)
+           {
+             Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
+             if (shdr->sh_type == SHT_GROUP && shdr->sh_size >= 8)
+               {
+                 char *src;
+                 Elf_Internal_Group *dest;
+
+                 /* Add to list of sections.  */
+                 elf_tdata (abfd)->group_sect_ptr[num_group] = shdr;
+                 num_group += 1;
+
+                 /* Read the raw contents.  */
+                 BFD_ASSERT (sizeof (*dest) >= 4);
+                 amt = shdr->sh_size * sizeof (*dest) / 4;
+                 shdr->contents = bfd_alloc (abfd, amt);
+                 if (shdr->contents == NULL
+                     || bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
+                     || (bfd_bread (shdr->contents, shdr->sh_size, abfd)
+                         != shdr->sh_size))
+                   return false;
+
+                 /* Translate raw contents, a flag word followed by an
+                    array of elf section indices all in target byte order,
+                    to the flag word followed by an array of elf section
+                    pointers.  */
+                 src = shdr->contents + shdr->sh_size;
+                 dest = (Elf_Internal_Group *) (shdr->contents + amt);
+                 while (1)
+                   {
+                     unsigned int idx;
+
+                     src -= 4;
+                     --dest;
+                     idx = H_GET_32 (abfd, src);
+                     if (src == shdr->contents)
+                       {
+                         dest->flags = idx;
+                         break;
+                       }
+                     if (idx >= shnum)
+                       {
+                         ((*_bfd_error_handler)
+                          (_("%s: invalid SHT_GROUP entry"),
+                           bfd_archive_filename (abfd)));
+                         idx = 0;
+                       }
+                     dest->shdr = elf_elfsections (abfd)[idx];
+                   }
+               }
+           }
+       }
+    }
+
+  if (num_group != (unsigned) -1)
+    {
+      unsigned int i;
+
+      for (i = 0; i < num_group; i++)
+       {
+         Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
+         Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents;
+         unsigned int n_elt = shdr->sh_size / 4;
+
+         /* Look through this group's sections to see if current
+            section is a member.  */
+         while (--n_elt != 0)
+           if ((++idx)->shdr == hdr)
+             {
+               asection *s;
+
+               /* We are a member of this group.  Go looking through
+                  other members to see if any others are linked via
+                  next_in_group.  */
+               idx = (Elf_Internal_Group *) shdr->contents;
+               n_elt = shdr->sh_size / 4;
+               while (--n_elt != 0)
+                 if ((s = (++idx)->shdr->bfd_section) != NULL
+                     && elf_section_data (s)->next_in_group != NULL)
+                   break;
+               if (n_elt != 0)
+                 {
+                   const char *gname;
+                   asection *next;
+
+                   /* Snarf the group name from other member, and
+                      insert current section in circular list.  */
+                   gname = elf_section_data (s)->group;
+                   elf_section_data (newsect)->group = gname;
+                   next = elf_section_data (s)->next_in_group;
+                   elf_section_data (newsect)->next_in_group = next;
+                   elf_section_data (s)->next_in_group = newsect;
+                 }
+               else
+                 {
+                   struct elf_backend_data *bed;
+                   file_ptr pos;
+                   unsigned char ename[4];
+                   unsigned long iname;
+                   const char *gname;
+
+                   /* Humbug.  Get the name from the group signature
+                      symbol.  Why isn't the signature just a string?
+                      Fortunately, the name index is at the same
+                      place in the external symbol for both 32 and 64
+                      bit ELF.  */
+                   bed = get_elf_backend_data (abfd);
+                   pos = elf_tdata (abfd)->symtab_hdr.sh_offset;
+                   pos += shdr->sh_info * bed->s->sizeof_sym;
+                   if (bfd_seek (abfd, pos, SEEK_SET) != 0
+                       || bfd_bread (ename, 4, abfd) != 4)
+                     return false;
+                   iname = H_GET_32 (abfd, ename);
+                   gname = elf_string_from_elf_strtab (abfd, iname);
+                   elf_section_data (newsect)->group = gname;
+
+                   /* Start a circular list with one element.  */
+                   elf_section_data (newsect)->next_in_group = newsect;
+                 }
+               if (shdr->bfd_section != NULL)
+                 shdr->bfd_section->lineno = (alent *) newsect;
+               i = num_group - 1;
+               break;
+             }
+       }
+    }
+
+  if (elf_section_data (newsect)->group == NULL)
+    {
+      (*_bfd_error_handler) (_("%s: no group info for section %s"),
+                            bfd_archive_filename (abfd), newsect->name);
+    }
+  return true;
+}
+
 /* Make a BFD section from an ELF section.  We store a pointer to the
    BFD section in the bfd_section field of the header.  */
 
@@ -380,6 +567,8 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
   flags = SEC_NO_FLAGS;
   if (hdr->sh_type != SHT_NOBITS)
     flags |= SEC_HAS_CONTENTS;
+  if (hdr->sh_type == SHT_GROUP)
+    flags |= SEC_GROUP | SEC_EXCLUDE;
   if ((hdr->sh_flags & SHF_ALLOC) != 0)
     {
       flags |= SEC_ALLOC;
@@ -399,6 +588,9 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
       if ((hdr->sh_flags & SHF_STRINGS) != 0)
        flags |= SEC_STRINGS;
     }
+  if (hdr->sh_flags & SHF_GROUP)
+    if (!setup_group (abfd, hdr, newsect))
+      return false;
 
   /* The debugging sections appear to be recognized only by name, not
      any sort of flag.  */
@@ -841,6 +1033,7 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
        const char *name = NULL;
        struct elf_backend_data *bed;
        unsigned char st_other;
+       bfd_vma val;
 
        section_name = symbol->section ? symbol->section->name : "(*none*)";
 
@@ -859,10 +1052,11 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
           we've already printed the size; now print the alignment.
           For other symbols, we have no specified alignment, and
           we've printed the address; now print the size.  */
-       bfd_fprintf_vma (abfd, file,
-                        (bfd_is_com_section (symbol->section)
-                         ? ((elf_symbol_type *) symbol)->internal_elf_sym.st_value
-                         : ((elf_symbol_type *) symbol)->internal_elf_sym.st_size));
+       if (bfd_is_com_section (symbol->section))
+         val = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value;
+       else
+         val = ((elf_symbol_type *) symbol)->internal_elf_sym.st_size;
+       bfd_fprintf_vma (abfd, file, val);
 
        /* If we have version information, print it.  */
        if (elf_tdata (abfd)->dynversym_section != 0
@@ -1512,6 +1706,26 @@ bfd_section_from_shdr (abfd, shindex)
     case SHT_SHLIB:
       return true;
 
+    case SHT_GROUP:
+      /* Make a section for objcopy and relocatable links.  */
+      if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name))
+       return false;
+      if (hdr->contents != NULL)
+       {
+         Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
+         unsigned int n_elt = hdr->sh_size / 4;
+         asection *s;
+
+         while (--n_elt != 0)
+           if ((s = (++idx)->shdr->bfd_section) != NULL
+               && elf_section_data (s)->next_in_group != NULL)
+             {
+               hdr->bfd_section->lineno = (alent *) s;
+               break;
+             }
+       }
+      break;
+
     default:
       /* Check for any processor-specific section types.  */
       {
@@ -1847,6 +2061,11 @@ elf_fake_sections (abfd, asect, failedptrarg)
        BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0
                    || this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
     }
+  else if ((asect->flags & SEC_GROUP) != 0)
+    {
+      this_hdr->sh_type = SHT_GROUP;
+      this_hdr->sh_entsize = 4;
+    }
   else if ((asect->flags & SEC_ALLOC) != 0
           && ((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0))
     this_hdr->sh_type = SHT_NOBITS;
@@ -1866,6 +2085,8 @@ elf_fake_sections (abfd, asect, failedptrarg)
       if ((asect->flags & SEC_STRINGS) != 0)
        this_hdr->sh_flags |= SHF_STRINGS;
     }
+  if (elf_section_data (asect)->group != NULL)
+    this_hdr->sh_flags |= SHF_GROUP;
 
   /* Check for processor-specific section types.  */
   if (bed->elf_backend_fake_sections)
@@ -1883,6 +2104,82 @@ elf_fake_sections (abfd, asect, failedptrarg)
     *failedptr = true;
 }
 
+/* Fill in the contents of a SHT_GROUP section.  */
+
+static void
+set_group_contents (abfd, sec, failedptrarg)
+     bfd *abfd;
+     asection *sec;
+     PTR failedptrarg ATTRIBUTE_UNUSED;
+{
+  boolean *failedptr = (boolean *) failedptrarg;
+  unsigned long symindx;
+  asection *elt;
+  unsigned char *loc;
+  struct bfd_link_order *l;
+
+  if (elf_section_data (sec)->this_hdr.sh_type != SHT_GROUP
+      || *failedptr)
+    return;
+
+  /* If called from the assembler, swap_out_syms will have set up
+     udata.i;  If called for "ld -r", the symbols won't yet be mapped,
+     so emulate elf_bfd_final_link.  */
+  symindx = sec->symbol->udata.i;
+  if (symindx == 0)
+    symindx = elf_section_data (sec)->this_idx;
+  elf_section_data (sec)->this_hdr.sh_info = symindx;
+
+  /* Nor will the contents be allocated for "ld -r".  */
+  if (sec->contents == NULL)
+    {
+      sec->contents = bfd_alloc (abfd, sec->_raw_size);
+      if (sec->contents == NULL)
+       {
+         *failedptr = true;
+         return;
+       }
+    }
+
+  loc = sec->contents + sec->_raw_size;
+
+  /* Get the pointer to the first section in the group that we
+     squirreled away here.  */
+  elt = (asection *) sec->lineno;
+
+  /* First element is a flag word.  Rest of section is elf section
+     indices for all the sections of the group.  Write them backwards
+     just to keep the group in the same order as given in .section
+     directives, not that it matters.  */
+  while (elt != NULL)
+    {
+      loc -= 4;
+      H_PUT_32 (abfd, elf_section_data (elt)->this_idx, loc);
+      elt = elf_section_data (elt)->next_in_group;
+    }
+
+  /* If this is a relocatable link, then the above did nothing because
+     SEC is the output section.  Look through the input sections
+     instead.  */
+  for (l = sec->link_order_head; l != NULL; l = l->next)
+    if (l->type == bfd_indirect_link_order
+       && (elt = (asection *) l->u.indirect.section->lineno) != NULL)
+      do
+       {
+         loc -= 4;
+         H_PUT_32 (abfd,
+                   elf_section_data (elt->output_section)->this_idx, loc);
+         elt = elf_section_data (elt)->next_in_group;
+         /* During a relocatable link, the lists are circular.  */
+       }
+      while (elt != (asection *) l->u.indirect.section->lineno);
+
+  loc -= 4;
+  H_PUT_32 (abfd, 0, loc);
+
+  BFD_ASSERT (loc == sec->contents);
+}
+
 /* Assign all ELF section numbers.  The dummy first section is handled here
    too.  The link/info pointers for the standard section types are filled
    in here too, while we're at it.  */
@@ -2055,6 +2352,9 @@ assign_section_numbers (abfd)
          if (s != NULL)
            d->this_hdr.sh_link = elf_section_data (s)->this_idx;
          break;
+
+       case SHT_GROUP:
+         d->this_hdr.sh_link = t->symtab_section;
        }
     }
 
@@ -2331,6 +2631,13 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
        return false;
     }
 
+  if (link_info == NULL || link_info->relocateable)
+    {
+      bfd_map_over_sections (abfd, set_group_contents, &failed);
+      if (failed)
+       return false;
+    }
+
   shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr;
   /* sh_name was set in prep_headers.  */
   shstrtab_hdr->sh_type = SHT_STRTAB;
@@ -4569,11 +4876,9 @@ _bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols)
 {
   arelent *tblptr;
   unsigned int i;
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
-  if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd,
-                                                          section,
-                                                          symbols,
-                                                          false))
+  if (! bed->s->slurp_reloc_table (abfd, section, symbols, false))
     return -1;
 
   tblptr = section->relocation;
@@ -4590,8 +4895,8 @@ _bfd_elf_get_symtab (abfd, alocation)
      bfd *abfd;
      asymbol **alocation;
 {
-  long symcount = get_elf_backend_data (abfd)->s->slurp_symbol_table
-    (abfd, alocation, false);
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  long symcount = bed->s->slurp_symbol_table (abfd, alocation, false);
 
   if (symcount >= 0)
     bfd_get_symcount (abfd) = symcount;
@@ -4603,8 +4908,8 @@ _bfd_elf_canonicalize_dynamic_symtab (abfd, alocation)
      bfd *abfd;
      asymbol **alocation;
 {
-  return get_elf_backend_data (abfd)->s->slurp_symbol_table
-    (abfd, alocation, true);
+  struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  return bed->s->slurp_symbol_table (abfd, alocation, true);
 }
 
 /* Return the size required for the dynamic reloc entries.  Any
index 3a76f1a2678f08977418b295cb21705777695091..d6342195099bbafca7d5037822e1b26c4beadcd6 100644 (file)
@@ -1084,10 +1084,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
       if (x_symp == NULL && symcount != 0)
        goto error_return;
 
-      if (bfd_bread ((PTR) x_symp,
-                   (bfd_size_type) (symcount * sizeof (Elf_External_Sym)),
-                   abfd)
-         != symcount * sizeof (Elf_External_Sym))
+      if (bfd_bread ((PTR) x_symp, amt, abfd) != amt)
        goto error_return;
 
       /* Read the raw ELF version symbol information.  */
@@ -1115,7 +1112,7 @@ elf_slurp_symbol_table (abfd, symptrs, dynamic)
          if (x_versymp == NULL && verhdr->sh_size != 0)
            goto error_return;
 
-         if (bfd_bread ((PTR) x_versymp, (bfd_size_type) verhdr->sh_size, abfd)
+         if (bfd_bread ((PTR) x_versymp, verhdr->sh_size, abfd)
              != verhdr->sh_size)
            goto error_return;
        }
index a8ffb0b85d98f1392f97a778944018700a465650..19fcea7d2185b454cc3f27a7e6a3c97e35614dbe 100644 (file)
@@ -6878,7 +6878,8 @@ static boolean elf_gc_smash_unused_vtentry_relocs
   PARAMS ((struct elf_link_hash_entry *h, PTR dummy));
 
 /* The mark phase of garbage collection.  For a given section, mark
-   it, and all the sections which define symbols to which it refers.  */
+   it and any sections in this section's group, and all the sections
+   which define symbols to which it refers.  */
 
 static boolean
 elf_gc_mark (info, sec, gc_mark_hook)
@@ -6888,12 +6889,19 @@ elf_gc_mark (info, sec, gc_mark_hook)
        PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,
                struct elf_link_hash_entry *, Elf_Internal_Sym *));
 {
-  boolean ret = true;
+  boolean ret;
+  asection *group_sec;
 
   sec->gc_mark = 1;
 
-  /* Look through the section relocs.  */
+  /* Mark all the sections in the group.  */
+  group_sec = elf_section_data (sec)->next_in_group;
+  if (group_sec && !group_sec->gc_mark)
+    if (!elf_gc_mark (info, group_sec, gc_mark_hook))
+      return false;
 
+  /* Look through the section relocs.  */
+  ret = true;
   if ((sec->flags & SEC_RELOC) != 0 && sec->reloc_count > 0)
     {
       Elf_Internal_Rela *relstart, *rel, *relend;
index 59da0389172dc24a59bb188f2ea187c06ee0b237..758deb4c5cdc3912f825f2321a11fd36112d5cf4 100644 (file)
@@ -495,7 +495,7 @@ const bfd_target TARGET_BIG_SYM =
   /* section_flags: mask of all section flags */
   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
    | SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_EXCLUDE | SEC_SORT_ENTRIES
-   | SEC_ARCH_BIT_0 | SEC_SMALL_DATA | SEC_MERGE | SEC_STRINGS),
+   | SEC_ARCH_BIT_0 | SEC_SMALL_DATA | SEC_MERGE | SEC_STRINGS | SEC_GROUP),
 
    /* leading_symbol_char: is the first char of a user symbol
       predictable, and if so what is it */
@@ -591,7 +591,7 @@ const bfd_target TARGET_LITTLE_SYM =
   /* section_flags: mask of all section flags */
   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
    | SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_EXCLUDE | SEC_SORT_ENTRIES
-   | SEC_ARCH_BIT_0 | SEC_SMALL_DATA | SEC_MERGE | SEC_STRINGS),
+   | SEC_ARCH_BIT_0 | SEC_SMALL_DATA | SEC_MERGE | SEC_STRINGS | SEC_GROUP),
 
    /* leading_symbol_char: is the first char of a user symbol
       predictable, and if so what is it */
index f3bd381a4cca198fd4e277d2cf140ab0cd95f841..702f05a72a732c913503816d9fbea29af1893164 100644 (file)
@@ -177,7 +177,7 @@ CODE_FRAGMENT
 .
 .  int id;
 .
-.  {* Which section is it; 0..nth.  *}
+.  {* Which section in the bfd; 0..n-1 as sections are created in a bfd.  *}
 .
 .  int index;
 .
@@ -292,9 +292,10 @@ CODE_FRAGMENT
 .     objects are to be further relocated.  *}
 .#define SEC_EXCLUDE 0x40000
 .
-.  {* The contents of this section are to be sorted by the
-.     based on the address specified in the associated symbol
-.     table.  *}
+.  {* The contents of this section are to be sorted based on the sum of
+.     the symbol and addend values specified by the associated relocation
+.     entries.  Entries without associated relocation entries will be
+.     appended to the end of the section in an unspecified order.  *}
 .#define SEC_SORT_ENTRIES 0x80000
 .
 .  {* When linking, duplicate sections of the same name should be
@@ -361,6 +362,9 @@ CODE_FRAGMENT
 .     size entries.  *}
 .#define SEC_STRINGS 0x40000000
 .
+.  {* This section contains data about section groups.  *}
+.#define SEC_GROUP 0x80000000
+.
 .  {*  End of section flags.  *}
 .
 .  {* Some internal packed boolean fields.  *}
@@ -381,7 +385,8 @@ CODE_FRAGMENT
 .  {* A mark flag used by some linker backends for garbage collection.  *}
 .  unsigned int gc_mark : 1;
 .
-.  {* Used by the ELF code to mark sections which have been allocated to segments.  *}
+.  {* Used by the ELF code to mark sections which have been allocated
+.     to segments.  *}
 .  unsigned int segment_mark : 1;
 .
 .  {* End of internal packed boolean fields.  *}