Orphan output section with multiple input sections
authorAlan Modra <amodra@gmail.com>
Wed, 28 Oct 2015 06:48:13 +0000 (17:18 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 28 Oct 2015 07:21:10 +0000 (17:51 +1030)
If given input sections with differing flags, we'd like to place the
section according to the final output section flags.

bfd/
PR ld/19162
* elflink.c (_bfd_elf_gc_mark_reloc): Move code iterating over
linker input bfds..
* section.c (bfd_get_next_section_by_name): ..to here.  Add ibfd param.
(bfd_get_linker_section): Adjust bfd_get_next_section_by_name call.
* tekhex.c (first_phase): Likewise.
* elflink.c (bfd_elf_gc_sections): Likewise.
* bfd-in2.h: Regenerate.
ld/
PR ld/19162
* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Check flags
before calling _bfd_elf_match_sections_by_type.  Merge flags for
any other input sections that might match a new output section to
decide placement.

bfd/ChangeLog
bfd/bfd-in2.h
bfd/elflink.c
bfd/section.c
bfd/tekhex.c
ld/ChangeLog
ld/emultempl/elf32.em

index 1ef747e..3f9a3de 100644 (file)
@@ -1,3 +1,14 @@
+2015-10-28  Alan Modra  <amodra@gmail.com>
+
+       PR ld/19162
+       * elflink.c (_bfd_elf_gc_mark_reloc): Move code iterating over
+       linker input bfds..
+       * section.c (bfd_get_next_section_by_name): ..to here.  Add ibfd param.
+       (bfd_get_linker_section): Adjust bfd_get_next_section_by_name call.
+       * tekhex.c (first_phase): Likewise.
+       * elflink.c (bfd_elf_gc_sections): Likewise.
+       * bfd-in2.h: Regenerate.
+
 2015-10-27  Laurent Alfonsi <laurent.alfonsi@st.com>
             Christophe Monat <christophe.monat@st.com>
 
index f381f06..85fa3ab 100644 (file)
@@ -1810,7 +1810,7 @@ void bfd_section_list_clear (bfd *);
 
 asection *bfd_get_section_by_name (bfd *abfd, const char *name);
 
-asection *bfd_get_next_section_by_name (asection *sec);
+asection *bfd_get_next_section_by_name (bfd *ibfd, asection *sec);
 
 asection *bfd_get_linker_section (bfd *abfd, const char *name);
 
index 1cfdd31..1b41c79 100644 (file)
@@ -12179,8 +12179,6 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
   rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie, &start_stop);
   while (rsec != NULL)
     {
-      asection *s;
-
       if (!rsec->gc_mark)
        {
          if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour
@@ -12191,22 +12189,7 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
        }
       if (!start_stop)
        break;
-      s = bfd_get_next_section_by_name (rsec);
-      if (s == NULL)
-       {
-         bfd *i = rsec->owner;
-
-         if (i != NULL)
-           {
-             while ((i = i->link.next) != NULL)
-               {
-                 s = bfd_get_section_by_name (i, rsec->name);
-                 if (s != NULL)
-                   break;
-               }
-           }
-       }
-      rsec = s;
+      rsec = bfd_get_next_section_by_name (rsec->owner, rsec);
     }
   return TRUE;
 }
@@ -12757,7 +12740,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
              && (sec->flags & SEC_LINKER_CREATED) == 0)
            elf_eh_frame_section (sub) = sec;
          fini_reloc_cookie_for_section (&cookie, sec);
-         sec = bfd_get_next_section_by_name (sec);
+         sec = bfd_get_next_section_by_name (NULL, sec);
        }
     }
 
index 834a9ab..247d98a 100644 (file)
@@ -903,16 +903,18 @@ FUNCTION
        bfd_get_next_section_by_name
 
 SYNOPSIS
-       asection *bfd_get_next_section_by_name (asection *sec);
+       asection *bfd_get_next_section_by_name (bfd *ibfd, asection *sec);
 
 DESCRIPTION
        Given @var{sec} is a section returned by @code{bfd_get_section_by_name},
        return the next most recently created section attached to the same
-       BFD with the same name.  Return NULL if no such section exists.
+       BFD with the same name, or if no such section exists in the same BFD and
+       IBFD is non-NULL, the next section with the same name in any input
+       BFD following IBFD.  Return NULL on finding no section.
 */
 
 asection *
-bfd_get_next_section_by_name (asection *sec)
+bfd_get_next_section_by_name (bfd *ibfd, asection *sec)
 {
   struct section_hash_entry *sh;
   const char *name;
@@ -930,6 +932,16 @@ bfd_get_next_section_by_name (asection *sec)
        && strcmp (sh->root.string, name) == 0)
       return &sh->section;
 
+  if (ibfd != NULL)
+    {
+      while ((ibfd = ibfd->link.next) != NULL)
+       {
+         asection *s = bfd_get_section_by_name (ibfd, name);
+         if (s != NULL)
+           return s;
+       }
+    }
+
   return NULL;
 }
 
@@ -951,7 +963,7 @@ bfd_get_linker_section (bfd *abfd, const char *name)
   asection *sec = bfd_get_section_by_name (abfd, name);
 
   while (sec != NULL && (sec->flags & SEC_LINKER_CREATED) == 0)
-    sec = bfd_get_next_section_by_name (sec);
+    sec = bfd_get_next_section_by_name (NULL, sec);
   return sec;
 }
 
index ccc68f9..951c327 100644 (file)
@@ -459,7 +459,8 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
                    else
                      {
                        if (alt_section == NULL)
-                         alt_section = bfd_get_next_section_by_name (section);
+                         alt_section
+                           = bfd_get_next_section_by_name (NULL, section);
                        if (alt_section == NULL)
                          alt_section = bfd_make_section_anyway_with_flags
                            (abfd, section->name,
@@ -476,7 +477,8 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
                    else
                      {
                        if (alt_section == NULL)
-                         alt_section = bfd_get_next_section_by_name (section);
+                         alt_section
+                           = bfd_get_next_section_by_name (NULL, section);
                        if (alt_section == NULL)
                          alt_section = bfd_make_section_anyway_with_flags
                            (abfd, section->name,
index 359fc19..5b9ac97 100644 (file)
@@ -1,3 +1,11 @@
+2015-10-28  Alan Modra  <amodra@gmail.com>
+
+       PR ld/19162
+       * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Check flags
+       before calling _bfd_elf_match_sections_by_type.  Merge flags for
+       any other input sections that might match a new output section to
+       decide placement.
+
 2015-10-27  Laurent Alfonsi <laurent.alfonsi@st.com>
             Christophe Monat <christophe.monat@st.com>
 
index 1dc215f..629c414 100644 (file)
@@ -1852,6 +1852,8 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
   int isdyn = 0;
   int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
   unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
+  flagword flags;
+  asection *nexts;
 
   if (!bfd_link_relocatable (&link_info)
       && link_info.combreloc
@@ -1890,11 +1892,11 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
 
        if (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)))
+               || (((s->flags ^ os->bfd_section->flags)
+                    & (SEC_LOAD | SEC_ALLOC)) == 0
+                   && _bfd_elf_match_sections_by_type (link_info.output_bfd,
+                                                       os->bfd_section,
+                                                       s->owner, s))))
          {
            /* We already have an output section statement with this
               name, and its bfd section has compatible flags.
@@ -1950,28 +1952,41 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
      stored right after the program headers where the OS can read it
      in the first page.  */
 
+  flags = s->flags;
+  nexts = s;
+  while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts)) != NULL)
+    if (nexts->output_section == NULL
+       && (nexts->flags & SEC_EXCLUDE) == 0
+       && ((nexts->flags ^ flags) & (SEC_LOAD | SEC_ALLOC)) == 0
+       && (nexts->owner->flags & DYNAMIC) == 0
+       && nexts->owner->usrdata != NULL
+       && !(((lang_input_statement_type *) nexts->owner->usrdata)
+            ->flags.just_syms)
+       && _bfd_elf_match_sections_by_type (nexts->owner, nexts, s->owner, s))
+      flags = (((flags ^ SEC_READONLY) | (nexts->flags ^ SEC_READONLY))
+              ^ SEC_READONLY);
   place = NULL;
-  if ((s->flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
+  if ((flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
     place = &hold[orphan_nonalloc];
-  else if ((s->flags & SEC_ALLOC) == 0)
+  else if ((flags & SEC_ALLOC) == 0)
     ;
-  else if ((s->flags & SEC_LOAD) != 0
+  else if ((flags & SEC_LOAD) != 0
           && ((iself && sh_type == SHT_NOTE)
               || (!iself && CONST_STRNEQ (secname, ".note"))))
     place = &hold[orphan_interp];
-  else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0)
+  else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0)
     place = &hold[orphan_bss];
-  else if ((s->flags & SEC_SMALL_DATA) != 0)
+  else if ((flags & SEC_SMALL_DATA) != 0)
     place = &hold[orphan_sdata];
-  else if ((s->flags & SEC_THREAD_LOCAL) != 0)
+  else if ((flags & SEC_THREAD_LOCAL) != 0)
     place = &hold[orphan_tdata];
-  else if ((s->flags & SEC_READONLY) == 0)
+  else if ((flags & SEC_READONLY) == 0)
     place = &hold[orphan_data];
   else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
            || (!iself && CONST_STRNEQ (secname, ".rel")))
-          && (s->flags & SEC_LOAD) != 0)
+          && (flags & SEC_LOAD) != 0)
     place = &hold[orphan_rel];
-  else if ((s->flags & SEC_CODE) == 0)
+  else if ((flags & SEC_CODE) == 0)
     place = &hold[orphan_rodata];
   else
     place = &hold[orphan_text];