bfd/
authorAlan Modra <amodra@gmail.com>
Fri, 3 Oct 2008 09:40:49 +0000 (09:40 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 3 Oct 2008 09:40:49 +0000 (09:40 +0000)
* elf.c (bfd_elf_set_group_contents): Assign sh_info for ld -r when
the signature symbol is global.
* elflink.c (elf_link_input_bfd): Ensure group signature symbol
is output when ld -r.  Set group sh_info when local.
* linker.c (default_indirect_link_order): Handle group sections
specially.
ld/
* ldemul.c (ldemul_place_orphan): Add "name" param.
* ldemul.h (ldemul_place_orphan): Update prototype.
(struct ld_emulation_xfer_struct <place_orphan>): Likewise.
* ldlang.c (lang_place_orphans): Generate unique section names here..
* emultempl/elf32.em (place_orphan): ..rather than here.  Don't
directly use an existing output section statement that has no
bfd section.
* emultempl/pe.em (place_orphan): Likewise.
* emultempl/pep.em (place_orphan): Likewise.
* emultempl/beos.em (place_orphan): Adjust.
* emultempl/spuelf.em (spu_place_special_section): Adjust
place_orphan call.
* emultempl/genelf.em (gld${EMULATION_NAME}_after_open): New function.
(LDEMUL_AFTER_OPEN): Define.

14 files changed:
bfd/ChangeLog
bfd/elf.c
bfd/elflink.c
bfd/linker.c
ld/ChangeLog
ld/emultempl/beos.em
ld/emultempl/elf32.em
ld/emultempl/genelf.em
ld/emultempl/pe.em
ld/emultempl/pep.em
ld/emultempl/spuelf.em
ld/ldemul.c
ld/ldemul.h
ld/ldlang.c

index f77553615539606bf9d84b07c669f8e495db90d7..b95f32212ae74716dc203005b06a39a7d0a6cefa 100644 (file)
@@ -1,3 +1,12 @@
+2008-10-03  Alan Modra  <amodra@bigpond.net.au>
+
+       * elf.c (bfd_elf_set_group_contents): Assign sh_info for ld -r when
+       the signature symbol is global.
+       * elflink.c (elf_link_input_bfd): Ensure group signature symbol
+       is output when ld -r.  Set group sh_info when local.
+       * linker.c (default_indirect_link_order): Handle group sections
+       specially.
+
 2008-09-30  Wesley W. Terpstra  <wesley@terpstra.ca>
            Nick Clifton  <nickc@redhat.com>
 
index 763750b8827dfc6b8c36e47545b9353b2ee30933..e9d0af302a5ed6e100c65bfa1ac2c8c9c93f1932 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2681,13 +2681,15 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
     *failedptr = TRUE;
 }
 
-/* Fill in the contents of a SHT_GROUP section.  */
+/* Fill in the contents of a SHT_GROUP section.  Called from
+   _bfd_elf_compute_section_file_positions for gas, objcopy, and
+   when ELF targets use the generic linker, ld.  Called for ld -r
+   from bfd_elf_final_link.  */
 
 void
 bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
 {
   bfd_boolean *failedptr = failedptrarg;
-  unsigned long symindx;
   asection *elt, *first;
   unsigned char *loc;
   bfd_boolean gas;
@@ -2698,20 +2700,49 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
       || *failedptr)
     return;
 
-  symindx = 0;
-  if (elf_group_id (sec) != NULL)
-    symindx = elf_group_id (sec)->udata.i;
+  if (elf_section_data (sec)->this_hdr.sh_info == 0)
+    {
+      unsigned long symindx = 0;
+
+      /* elf_group_id will have been set up by objcopy and the
+        generic linker.  */
+      if (elf_group_id (sec) != NULL)
+       symindx = elf_group_id (sec)->udata.i;
 
-  if (symindx == 0)
+      if (symindx == 0)
+       {
+         /* If called from the assembler, swap_out_syms will have set up
+            elf_section_syms.  */
+         BFD_ASSERT (elf_section_syms (abfd) != NULL);
+         symindx = elf_section_syms (abfd)[sec->index]->udata.i;
+       }
+      elf_section_data (sec)->this_hdr.sh_info = symindx;
+    }
+  else if (elf_section_data (sec)->this_hdr.sh_info == (unsigned int) -2)
     {
-      /* If called from the assembler, swap_out_syms will have set up
-        elf_section_syms;  If called for "ld -r", use target_index.  */
-      if (elf_section_syms (abfd) != NULL)
-       symindx = elf_section_syms (abfd)[sec->index]->udata.i;
-      else
-       symindx = sec->target_index;
+      /* The ELF backend linker sets sh_info to -2 when the group
+        signature symbol is global, and thus the index can't be
+        set until all local symbols are output.  */
+      asection *igroup = elf_sec_group (elf_next_in_group (sec));
+      struct bfd_elf_section_data *sec_data = elf_section_data (igroup);
+      unsigned long symndx = sec_data->this_hdr.sh_info;
+      unsigned long extsymoff = 0;
+      struct elf_link_hash_entry *h;
+
+      if (!elf_bad_symtab (igroup->owner))
+       {
+         Elf_Internal_Shdr *symtab_hdr;
+
+         symtab_hdr = &elf_tdata (igroup->owner)->symtab_hdr;
+         extsymoff = symtab_hdr->sh_info;
+       }
+      h = elf_sym_hashes (igroup->owner)[symndx - extsymoff];
+      while (h->root.type == bfd_link_hash_indirect
+            || h->root.type == bfd_link_hash_warning)
+       h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+      elf_section_data (sec)->this_hdr.sh_info = h->indx;
     }
-  elf_section_data (sec)->this_hdr.sh_info = symindx;
 
   /* The contents won't be allocated for "ld -r" or objcopy.  */
   gas = TRUE;
index 8e59383aae60c3b0446031af6a5b7bc7a7ce6152..d2dc17d37477332c5e34d34a38f64fcbac2adfff 100644 (file)
@@ -9062,6 +9062,63 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
          continue;
        }
 
+      if (finfo->info->relocatable
+         && (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP)
+       {
+         /* Deal with the group signature symbol.  */
+         struct bfd_elf_section_data *sec_data = elf_section_data (o);
+         unsigned long symndx = sec_data->this_hdr.sh_info;
+         asection *osec = o->output_section;
+
+         if (symndx >= locsymcount
+             || (elf_bad_symtab (input_bfd)
+                 && finfo->sections[symndx] == NULL))
+           {
+             struct elf_link_hash_entry *h = sym_hashes[symndx - extsymoff];
+             while (h->root.type == bfd_link_hash_indirect
+                    || h->root.type == bfd_link_hash_warning)
+               h = (struct elf_link_hash_entry *) h->root.u.i.link;
+             /* Arrange for symbol to be output.  */
+             h->indx = -2;
+             elf_section_data (osec)->this_hdr.sh_info = -2;
+           }
+         else if (ELF_ST_TYPE (isymbuf[symndx].st_info) == STT_SECTION)
+           {
+             /* We'll use the output section target_index.  */
+             asection *sec = finfo->sections[symndx]->output_section;
+             elf_section_data (osec)->this_hdr.sh_info = sec->target_index;
+           }
+         else
+           {
+             if (finfo->indices[symndx] == -1)
+               {
+                 /* Otherwise output the local symbol now.  */
+                 Elf_Internal_Sym sym = isymbuf[symndx];
+                 asection *sec = finfo->sections[symndx]->output_section;
+                 const char *name;
+
+                 name = bfd_elf_string_from_elf_section (input_bfd,
+                                                         symtab_hdr->sh_link,
+                                                         sym.st_name);
+                 if (name == NULL)
+                   return FALSE;
+
+                 sym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
+                                                                   sec);
+                 if (sym.st_shndx == SHN_BAD)
+                   return FALSE;
+
+                 sym.st_value += o->output_offset;
+
+                 finfo->indices[symndx] = bfd_get_symcount (output_bfd);
+                 if (! elf_link_output_sym (finfo, name, &sym, o, NULL))
+                   return FALSE;
+               }
+             elf_section_data (osec)->this_hdr.sh_info
+               = finfo->indices[symndx];
+           }
+       }
+
       if ((o->flags & SEC_HAS_CONTENTS) == 0
          || (o->size == 0 && (o->flags & SEC_RELOC) == 0))
        continue;
index baf280c7a24bf60ea1734af344e865fdea6d230b..5080d7d44cb6eb9a41710a4333ce65c2a7c563a6 100644 (file)
@@ -2796,18 +2796,36 @@ default_indirect_link_order (bfd *output_bfd,
        }
     }
 
-  /* Get and relocate the section contents.  */
-  sec_size = (input_section->rawsize > input_section->size
-             ? input_section->rawsize
-             : input_section->size);
-  contents = bfd_malloc (sec_size);
-  if (contents == NULL && sec_size != 0)
-    goto error_return;
-  new_contents = (bfd_get_relocated_section_contents
-                 (output_bfd, info, link_order, contents, info->relocatable,
-                  _bfd_generic_link_get_symbols (input_bfd)));
-  if (!new_contents)
-    goto error_return;
+  if ((output_section->flags & (SEC_GROUP | SEC_LINKER_CREATED)) == SEC_GROUP
+      && input_section->size != 0)
+    {
+      /* Group section contents are set by bfd_elf_set_group_contents.  */
+      if (!output_bfd->output_has_begun)
+       {
+         /* FIXME: This hack ensures bfd_elf_set_group_contents is called.  */
+         if (!bfd_set_section_contents (output_bfd, output_section, "", 0, 1))
+           goto error_return;
+       }
+      new_contents = output_section->contents;
+      BFD_ASSERT (new_contents != NULL);
+      BFD_ASSERT (input_section->output_offset == 0);
+    }
+  else
+    {
+      /* Get and relocate the section contents.  */
+      sec_size = (input_section->rawsize > input_section->size
+                 ? input_section->rawsize
+                 : input_section->size);
+      contents = bfd_malloc (sec_size);
+      if (contents == NULL && sec_size != 0)
+       goto error_return;
+      new_contents = (bfd_get_relocated_section_contents
+                     (output_bfd, info, link_order, contents,
+                      info->relocatable,
+                      _bfd_generic_link_get_symbols (input_bfd)));
+      if (!new_contents)
+       goto error_return;
+    }
 
   /* Output the section contents.  */
   loc = input_section->output_offset * bfd_octets_per_byte (output_bfd);
index 25debe5ef6c8bbf266036d411626d9fe46d74edf..f957395ed092d9d45f87b3b6ac061439f1818709 100644 (file)
@@ -1,3 +1,20 @@
+2008-10-03  Alan Modra  <amodra@bigpond.net.au>
+
+       * ldemul.c (ldemul_place_orphan): Add "name" param.
+       * ldemul.h (ldemul_place_orphan): Update prototype.
+       (struct ld_emulation_xfer_struct <place_orphan>): Likewise.
+       * ldlang.c (lang_place_orphans): Generate unique section names here..
+       * emultempl/elf32.em (place_orphan): ..rather than here.  Don't
+       directly use an existing output section statement that has no
+       bfd section.
+       * emultempl/pe.em (place_orphan): Likewise.
+       * emultempl/pep.em (place_orphan): Likewise.
+       * emultempl/beos.em (place_orphan): Adjust.
+       * emultempl/spuelf.em (spu_place_special_section): Adjust
+       place_orphan call.
+       * emultempl/genelf.em (gld${EMULATION_NAME}_after_open): New function.
+       (LDEMUL_AFTER_OPEN): Define.
+
 2008-09-30  Joseph Myers  <joseph@codesourcery.com>
 
        * emulparams/elf64ppc.sh (OTHER_GOT_RELOC_SECTIONS): Add .rela.opd
index fac0c893c6793108fbe2944d4ca934f05859c8e4..997f3a63cec719157cd0bf10fec086fe438b1897 100644 (file)
@@ -665,9 +665,8 @@ gld_${EMULATION_NAME}_before_allocation (void)
    which are not mentioned in the linker script.  */
 
 static bfd_boolean
-gld${EMULATION_NAME}_place_orphan (asection *s)
+gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
 {
-  const char *secname;
   char *output_secname, *ps;
   lang_output_section_statement_type *os;
   lang_statement_union_type *l;
@@ -682,8 +681,6 @@ gld${EMULATION_NAME}_place_orphan (asection *s)
   if (link_info.relocatable)
     return FALSE;
 
-  secname = bfd_get_section_name (s->owner, s);
-
   /* Everything from the '\$' on gets deleted so don't allow '\$' as the
      first character.  */
   if (*secname == '\$')
index be9d78d2eff54859a07caf01535777bc59663d64..65ad4f134616b798143244ce579d82200ab04f61 100644 (file)
@@ -62,7 +62,7 @@ fragment <<EOF
 static void gld${EMULATION_NAME}_before_parse (void);
 static void gld${EMULATION_NAME}_after_open (void);
 static void gld${EMULATION_NAME}_before_allocation (void);
-static bfd_boolean gld${EMULATION_NAME}_place_orphan (asection *s);
+static bfd_boolean gld${EMULATION_NAME}_place_orphan (asection *, const char *);
 static void gld${EMULATION_NAME}_finish (void);
 
 EOF
@@ -1635,7 +1635,7 @@ output_rel_find (asection *sec, int isdyn)
    sections in the right segment.  */
 
 static bfd_boolean
-gld${EMULATION_NAME}_place_orphan (asection *s)
+gld${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
 {
   static struct orphan_save hold[] =
     {
@@ -1673,15 +1673,12 @@ gld${EMULATION_NAME}_place_orphan (asection *s)
     };
   static int orphan_init_done = 0;
   struct orphan_save *place;
-  const char *secname;
   lang_output_section_statement_type *after;
   lang_output_section_statement_type *os;
   int isdyn = 0;
   int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
   unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
 
-  secname = bfd_get_section_name (s->owner, s);
-
   if (! link_info.relocatable
       && link_info.combreloc
       && (s->flags & SEC_ALLOC))
@@ -1707,28 +1704,24 @@ gld${EMULATION_NAME}_place_orphan (asection *s)
        }
     }
 
-  if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s)))
+  /* Look through the script to see where to place this section.  */
+  os = lang_output_section_find (secname);
+
+  if (os != NULL
+      && os->bfd_section != NULL
+      && (os->bfd_section->flags == 0
+         || (_bfd_elf_match_sections_by_type (link_info.output_bfd,
+                                              os->bfd_section, s->owner, s)
+             && ((s->flags ^ os->bfd_section->flags)
+                 & (SEC_LOAD | SEC_ALLOC)) == 0)))
     {
-      /* Look through the script to see where to place this section.  */
-      os = lang_output_section_find (secname);
-
-      if (os != NULL
-         && (os->bfd_section == NULL
-             || os->bfd_section->flags == 0
-             || (_bfd_elf_match_sections_by_type (link_info.output_bfd,
-                                                  os->bfd_section,
-                                                  s->owner, s)
-                 && ((s->flags ^ os->bfd_section->flags)
-                     & (SEC_LOAD | SEC_ALLOC)) == 0)))
-       {
-         /* We already have an output section statement with this
-            name, and its bfd section, if any, has compatible flags.
-            If the section already exists but does not have any flags
-            set, then it has been created by the linker, probably as a
-            result of a --section-start command line switch.  */
-         lang_add_section (&os->children, s, os);
-         return TRUE;
-       }
+      /* We already have an output section statement with this
+        name, and its bfd section has compatible flags.
+        If the section already exists but does not have any flags
+        set, then it has been created by the linker, probably as a
+        result of a --section-start command line switch.  */
+      lang_add_section (&os->children, s, os);
+      return TRUE;
     }
 
   if (!orphan_init_done)
@@ -1748,7 +1741,7 @@ gld${EMULATION_NAME}_place_orphan (asection *s)
      sections into the .text section to get them out of the way.  */
   if (link_info.executable
       && ! link_info.relocatable
-      && CONST_STRNEQ (secname, ".gnu.warning.")
+      && CONST_STRNEQ (s->name, ".gnu.warning.")
       && hold[orphan_text].os != NULL)
     {
       lang_add_section (&hold[orphan_text].os->children, s,
@@ -1803,18 +1796,6 @@ gld${EMULATION_NAME}_place_orphan (asection *s)
        after = &lang_output_section_statement.head->output_section_statement;
     }
 
-  /* Choose a unique name for the section.  This will be needed if the
-     same section name appears in the input file with different
-     loadable or allocatable characteristics.  */
-  if (bfd_get_section_by_name (link_info.output_bfd, secname) != NULL)
-    {
-      static int count = 1;
-      secname = bfd_get_unique_section_name (link_info.output_bfd,
-                                            secname, &count);
-      if (secname == NULL)
-       einfo ("%F%P: place_orphan failed: %E\n");
-    }
-
   lang_insert_orphan (s, secname, after, place, NULL, NULL);
 
   return TRUE;
index e44bb9b9e107f053a8db58bea7ed8735a8f2b124..e6e8841f0d3ae0c0f01df2e145e9ae4a99f1f5fb 100644 (file)
@@ -34,7 +34,27 @@ gld${EMULATION_NAME}_finish (void)
   gld${EMULATION_NAME}_map_segments (FALSE);
   finish_default ();
 }
+
+static void
+gld${EMULATION_NAME}_after_open (void)
+{
+  bfd *ibfd;
+  asection *sec;
+  asymbol **syms;
+
+  if (link_info.relocatable)
+    for (ibfd = link_info.input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+      if ((syms = bfd_get_outsymbols (ibfd)) != NULL
+         && bfd_get_flavour (ibfd) == bfd_target_elf_flavour)
+       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+         if ((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) == SEC_GROUP)
+           {
+             struct bfd_elf_section_data *sec_data = elf_section_data (sec);
+             elf_group_id (sec) = syms[sec_data->this_hdr.sh_info - 1];
+           }
+}
 EOF
 # Put these extra routines in ld_${EMULATION_NAME}_emulation
 #
 LDEMUL_FINISH=gld${EMULATION_NAME}_finish
+LDEMUL_AFTER_OPEN=gld${EMULATION_NAME}_after_open
index cec399a052b9c9d0ec87e4abd319b1ff559ded82..89c521d9e9e5a73a1959ebc0f5869ce38f6a9ef5 100644 (file)
@@ -1613,24 +1613,20 @@ gld_${EMULATION_NAME}_finish (void)
    sort_sections.  */
 
 static bfd_boolean
-gld_${EMULATION_NAME}_place_orphan (asection *s)
+gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
 {
-  const char *secname;
-  const char *orig_secname;
+  const char *orig_secname = secname;
   char *dollar = NULL;
   lang_output_section_statement_type *os;
   lang_statement_list_type add_child;
 
-  secname = bfd_get_section_name (s->owner, s);
-
   /* Look through the script to see where to place this section.  */
-  orig_secname = secname;
   if (!link_info.relocatable
       && (dollar = strchr (secname, '$')) != NULL)
     {
-      size_t len = dollar - orig_secname;
+      size_t len = dollar - secname;
       char *newname = xmalloc (len + 1);
-      memcpy (newname, orig_secname, len);
+      memcpy (newname, secname, len);
       newname[len] = '\0';
       secname = newname;
     }
@@ -1640,13 +1636,13 @@ gld_${EMULATION_NAME}_place_orphan (asection *s)
   lang_list_init (&add_child);
 
   if (os != NULL
-      && (os->bfd_section == NULL
-         || os->bfd_section->flags == 0
+      && os->bfd_section != NULL
+      && (os->bfd_section->flags == 0
          || ((s->flags ^ os->bfd_section->flags)
              & (SEC_LOAD | SEC_ALLOC)) == 0))
     {
       /* We already have an output section statement with this
-        name, and its bfd section, if any, has compatible flags.
+        name, and its bfd section has compatible flags.
         If the section already exists but does not have any flags set,
         then it has been created by the linker, probably as a result of
         a --section-start command line switch.  */
@@ -1723,18 +1719,6 @@ gld_${EMULATION_NAME}_place_orphan (asection *s)
                     ->output_section_statement);
        }
 
-      /* Choose a unique name for the section.  This will be needed if the
-        same section name appears in the input file with different
-        loadable or allocatable characteristics.  */
-      if (bfd_get_section_by_name (link_info.output_bfd, secname) != NULL)
-       {
-         static int count = 1;
-         secname = bfd_get_unique_section_name (link_info.output_bfd,
-                                                secname, &count);
-         if (secname == NULL)
-           einfo ("%F%P: place_orphan failed: %E\n");
-       }
-
       /* All sections in an executable must be aligned to a page boundary.  */
       address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
       os = lang_insert_orphan (s, secname, after, place, address, &add_child);
index 0b9bf402b5f372904993f94b8d620786b3a86bc0..4afac022b6dd58b47b35678e4556fb5f947945f8 100644 (file)
@@ -1372,24 +1372,20 @@ gld_${EMULATION_NAME}_finish (void)
    sort_sections.  */
 
 static bfd_boolean
-gld_${EMULATION_NAME}_place_orphan (asection *s)
+gld_${EMULATION_NAME}_place_orphan (asection *s, const char *secname)
 {
-  const char *secname;
-  const char *orig_secname;
+  const char *orig_secname = secname;
   char *dollar = NULL;
   lang_output_section_statement_type *os;
   lang_statement_list_type add_child;
 
-  secname = bfd_get_section_name (s->owner, s);
-
   /* Look through the script to see where to place this section.  */
-  orig_secname = secname;
   if (!link_info.relocatable
       && (dollar = strchr (secname, '$')) != NULL)
     {
-      size_t len = dollar - orig_secname;
+      size_t len = dollar - secname;
       char *newname = xmalloc (len + 1);
-      memcpy (newname, orig_secname, len);
+      memcpy (newname, secname, len);
       newname[len] = '\0';
       secname = newname;
     }
@@ -1399,13 +1395,13 @@ gld_${EMULATION_NAME}_place_orphan (asection *s)
   lang_list_init (&add_child);
 
   if (os != NULL
-      && (os->bfd_section == NULL
-         || os->bfd_section->flags == 0
+      && os->bfd_section != NULL
+      && (os->bfd_section->flags == 0
          || ((s->flags ^ os->bfd_section->flags)
              & (SEC_LOAD | SEC_ALLOC)) == 0))
     {
       /* We already have an output section statement with this
-        name, and its bfd section, if any, has compatible flags.
+        name, and its bfd section has compatible flags.
         If the section already exists but does not have any flags set,
         then it has been created by the linker, probably as a result of
         a --section-start command line switch.  */
@@ -1482,18 +1478,6 @@ gld_${EMULATION_NAME}_place_orphan (asection *s)
                     ->output_section_statement);
        }
 
-      /* Choose a unique name for the section.  This will be needed if the
-        same section name appears in the input file with different
-        loadable or allocatable characteristics.  */
-      if (bfd_get_section_by_name (link_info.output_bfd, secname) != NULL)
-       {
-         static int count = 1;
-         secname = bfd_get_unique_section_name (link_info.output_bfd,
-                                                secname, &count);
-         if (secname == NULL)
-           einfo ("%F%P: place_orphan failed: %E\n");
-       }
-
       /* All sections in an executable must be aligned to a page boundary.  */
       address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
       os = lang_insert_orphan (s, secname, after, place, address, &add_child);
index 116a0cc9851e76902b78e03631bac7d4176bb7ce..bc2f6b548fc1efbf23892e1f42c8c337a16e2341 100644 (file)
@@ -114,12 +114,7 @@ spu_place_special_section (asection *s, asection *o, const char *output_name)
 
   os = lang_output_section_find (o != NULL ? o->name : output_name);
   if (os == NULL)
-    {
-      const char *save = s->name;
-      s->name = output_name;
-      gld${EMULATION_NAME}_place_orphan (s);
-      s->name = save;
-    }
+    gld${EMULATION_NAME}_place_orphan (s, output_name);
   else if (o != NULL && os->children.head != NULL)
     {
       lang_statement_list_type add;
index 6b86ddfce489543548876272953050bc084c3572..68e1de26210a1e76ec9014e4bdef69f345fe799e 100644 (file)
@@ -120,10 +120,10 @@ ldemul_open_dynamic_archive (const char *arch, search_dirs_type *search,
 }
 
 bfd_boolean
-ldemul_place_orphan (asection *s)
+ldemul_place_orphan (asection *s, const char *name)
 {
   if (ld_emulation->place_orphan)
-    return (*ld_emulation->place_orphan) (s);
+    return (*ld_emulation->place_orphan) (s, name);
   return FALSE;
 }
 
index cc81728609423f8e8958789177e1b8b757fbbdf1..6c95a9d9a16b644030fd51e513b7c04ef47703bf 100644 (file)
@@ -59,7 +59,7 @@ extern void ldemul_set_symbols
 extern void ldemul_create_output_section_statements
   (void);
 extern bfd_boolean ldemul_place_orphan
-  (asection *);
+  (asection *, const char *);
 extern bfd_boolean ldemul_parse_args
   (int, char **);
 extern void ldemul_add_options
@@ -152,7 +152,7 @@ typedef struct ld_emulation_xfer_struct {
      the default action should be taken.  This field may be NULL, in
      which case the default action will always be taken.  */
   bfd_boolean (*place_orphan)
-    (asection *);
+    (asection *, const char *);
 
   /* Run after assigning parsing with the args, but before
      reading the script.  Used to initialize symbols used in the script.  */
index b1b88062b02bc4cdc77ab93b15c5a2e99d1600a0..44fb136d84b3b51bdd9fc134be7b6ac8c01663de 100644 (file)
@@ -5652,14 +5652,29 @@ lang_place_orphans (void)
                                        default_common_section);
                    }
                }
-             else if (ldemul_place_orphan (s))
-               ;
              else
                {
-                 lang_output_section_statement_type *os;
+                 const char *name = s->name;
 
-                 os = lang_output_section_statement_lookup (s->name, 0, TRUE);
-                 lang_add_section (&os->children, s, os);
+                 if ((config.unique_orphan_sections
+                      || unique_section_p (s))
+                     && bfd_get_section_by_name (link_info.output_bfd,
+                                                 name) != NULL)
+                   {
+                     static int count = 1;
+                     name = bfd_get_unique_section_name (link_info.output_bfd,
+                                                         name, &count);
+                     if (name == NULL)
+                       einfo ("%F%P: place_orphan failed: %E\n");
+                   }
+
+                 if (!ldemul_place_orphan (s, name))
+                   {
+                     lang_output_section_statement_type *os;
+                     os = lang_output_section_statement_lookup (name, 0,
+                                                                TRUE);
+                     lang_add_section (&os->children, s, os);
+                   }
                }
            }
        }