Re: Orphan output section with multiple input sections
authorAlan Modra <amodra@gmail.com>
Thu, 29 Oct 2015 05:46:22 +0000 (16:16 +1030)
committerAlan Modra <amodra@gmail.com>
Thu, 29 Oct 2015 09:12:50 +0000 (19:42 +1030)
The last patch missed handling the case where the ideal place to put
an orphan was after a non-existent output section statement, as can
happen when not using the builtin linker scripts.  This patch uses the
updated flags for that case too, and extends the support to mmo and pe.

PR ld/19162
* emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Pass
updated flags to lang_output_section_find_by_flags.
* emultempl/mmo.em (mmo_place_orphan): Merge flags for any
other input sections that might match a new output section to
decide placement.
* emultempl/pe.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
* emultempl/pep.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
* ldlang.c (lang_output_section_find_by_flags): Add sec_flags param.
* ldlang.h (lang_output_section_find_by_flags): Update prototype.

ld/ChangeLog
ld/emultempl/elf32.em
ld/emultempl/mmo.em
ld/emultempl/pe.em
ld/emultempl/pep.em
ld/ldlang.c
ld/ldlang.h

index d187c0c448cad613c924dbb4ae719da92aabf879..69363e1af47dd2b395b7b4f5c51b3d171c64337b 100644 (file)
@@ -1,3 +1,16 @@
+2015-10-29  Alan Modra  <amodra@gmail.com>
+
+       PR ld/19162
+       * emultempl/elf32.em (gld${EMULATION_NAME}_place_orphan): Pass
+       updated flags to lang_output_section_find_by_flags.
+       * emultempl/mmo.em (mmo_place_orphan): Merge flags for any
+       other input sections that might match a new output section to
+       decide placement.
+       * emultempl/pe.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
+       * emultempl/pep.em (gld_${EMULATION_NAME}_place_orphan): Likewise.
+       * ldlang.c (lang_output_section_find_by_flags): Add sec_flags param.
+       * ldlang.h (lang_output_section_find_by_flags): Update prototype.
+
 2015-10-29  Matthias Klose  <doko@ubuntu.com>
 
        * ld.texinfo (Options <-rpath>): Fix typo.
index 629c414b483149936af682b9213d91f514450aa2..0405d4fa71554a672e6b3070f3f310fec2244760 100644 (file)
@@ -2003,8 +2003,9 @@ gld${EMULATION_NAME}_place_orphan (asection *s,
        }
       after = place->os;
       if (after == NULL)
-       after = lang_output_section_find_by_flags
-         (s, &place->os, _bfd_elf_match_sections_by_type);
+       after
+         = lang_output_section_find_by_flags (s, flags, &place->os,
+                                              _bfd_elf_match_sections_by_type);
       if (after == NULL)
        /* *ABS* is always the first output section statement.  */
        after = &lang_output_section_statement.head->output_section_statement;
index 47f77d850da3f8ffcd56c0c68c21634bc9d692cc..8949aed13fa22a88c6feacd95d063998db7ff677 100644 (file)
@@ -88,6 +88,8 @@ mmo_place_orphan (asection *s,
   lang_output_section_statement_type *after;
   lang_output_section_statement_type *os;
   size_t i;
+  flagword flags;
+  asection *nexts;
 
   /* We have nothing to say for anything other than a final link or
      for sections that are excluded.  */
@@ -109,9 +111,21 @@ mmo_place_orphan (asection *s,
      A section without contents can have SEC_LOAD == 0, but we still
      want it attached to a sane section so the symbols appear as
      expected.  */
-  if ((s->flags & (SEC_ALLOC | SEC_READONLY)) != SEC_READONLY)
+  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))
+      flags = (((flags ^ SEC_READONLY) | (nexts->flags ^ SEC_READONLY))
+              ^ SEC_READONLY);
+  if ((flags & (SEC_ALLOC | SEC_READONLY)) != SEC_READONLY)
     for (i = 0; i < sizeof (holds) / sizeof (holds[0]); i++)
-      if ((s->flags & holds[i].nonzero_flags) != 0)
+      if ((flags & holds[i].nonzero_flags) != 0)
        {
          place = &holds[i].orphansave;
          if (place->os == NULL)
index 04a7f5cd7f81b850404053a425beedc76ed4d0a7..0370c5a52637c4043e80963f4065ab13ee7f9a14 100644 (file)
@@ -2209,6 +2209,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
       struct orphan_save *place;
       lang_output_section_statement_type *after;
       etree_type *address;
+      flagword flags;
+      asection *nexts;
 
       if (!orphan_init_done)
        {
@@ -2226,14 +2228,26 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
       /* Try to put the new output section in a reasonable place based
         on the section name and section flags.  */
 
+      flags = s->flags;
+      nexts = s;
+      while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts)))
+       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))
+         flags = (((flags ^ SEC_READONLY) | (nexts->flags ^ SEC_READONLY))
+                  ^ SEC_READONLY);
       place = NULL;
-      if ((s->flags & SEC_ALLOC) == 0)
+      if ((flags & SEC_ALLOC) == 0)
        ;
-      else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+      else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
        place = &hold[orphan_bss];
-      else if ((s->flags & SEC_READONLY) == 0)
+      else if ((flags & SEC_READONLY) == 0)
        place = &hold[orphan_data];
-      else if ((s->flags & SEC_CODE) == 0)
+      else if ((flags & SEC_CODE) == 0)
        {
          place = (!strncmp (secname, ".idata\$", 7) ? &hold[orphan_idata]
                                                     : &hold[orphan_rodata]);
@@ -2248,7 +2262,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
            place->os = lang_output_section_find (place->name);
          after = place->os;
          if (after == NULL)
-           after = lang_output_section_find_by_flags (s, &place->os, NULL);
+           after = lang_output_section_find_by_flags (s, flags, &place->os,
+                                                      NULL);
          if (after == NULL)
            /* *ABS* is always the first output section statement.  */
            after = (&lang_output_section_statement.head
index 0b740c3ccd0b1acaa9aa30d0558d932a29fa6373..91de50165d71765ee61179dbd4e1f6b3f6ebe486 100644 (file)
@@ -1980,6 +1980,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
       struct orphan_save *place;
       lang_output_section_statement_type *after;
       etree_type *address;
+      flagword flags;
+      asection *nexts;
 
       if (!orphan_init_done)
        {
@@ -1997,14 +1999,26 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
       /* Try to put the new output section in a reasonable place based
         on the section name and section flags.  */
 
+      flags = s->flags;
+      nexts = s;
+      while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts)))
+       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))
+         flags = (((flags ^ SEC_READONLY) | (nexts->flags ^ SEC_READONLY))
+                  ^ SEC_READONLY);
       place = NULL;
-      if ((s->flags & SEC_ALLOC) == 0)
+      if ((flags & SEC_ALLOC) == 0)
        ;
-      else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+      else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
        place = &hold[orphan_bss];
-      else if ((s->flags & SEC_READONLY) == 0)
+      else if ((flags & SEC_READONLY) == 0)
        place = &hold[orphan_data];
-      else if ((s->flags & SEC_CODE) == 0)
+      else if ((flags & SEC_CODE) == 0)
        {
          place = (!strncmp (secname, ".idata\$", 7) ? &hold[orphan_idata]
                                                     : &hold[orphan_rodata]);
@@ -2019,7 +2033,8 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
            place->os = lang_output_section_find (place->name);
          after = place->os;
          if (after == NULL)
-           after = lang_output_section_find_by_flags (s, &place->os, NULL);
+           after = lang_output_section_find_by_flags (s, flags, &place->os,
+                                                      NULL);
          if (after == NULL)
            /* *ABS* is always the first output section statement.  */
            after = (&lang_output_section_statement.head
index 5c7ea9fcd1d30c0e26afb7efe28c1d8bc0ab09ca..3841afc75f8400912cbe5d05b1894d4abcf25d93 100644 (file)
@@ -1499,11 +1499,12 @@ next_matching_output_section_statement (lang_output_section_statement_type *os,
 
 lang_output_section_statement_type *
 lang_output_section_find_by_flags (const asection *sec,
+                                  flagword sec_flags,
                                   lang_output_section_statement_type **exact,
                                   lang_match_sec_type_func match_type)
 {
   lang_output_section_statement_type *first, *look, *found;
-  flagword look_flags, sec_flags, differ;
+  flagword look_flags, differ;
 
   /* We know the first statement on this list is *ABS*.  May as well
      skip it.  */
@@ -1511,7 +1512,6 @@ lang_output_section_find_by_flags (const asection *sec,
   first = first->next;
 
   /* First try for an exact match.  */
-  sec_flags = sec->flags;
   found = NULL;
   for (look = first; look; look = look->next)
     {
@@ -1695,7 +1695,7 @@ lang_output_section_find_by_flags (const asection *sec,
   if (found || !match_type)
     return found;
 
-  return lang_output_section_find_by_flags (sec, NULL, NULL);
+  return lang_output_section_find_by_flags (sec, sec_flags, NULL, NULL);
 }
 
 /* Find the last output section before given output statement.
index 4b7e65df541fff6aab09eff63f2856c4a91410bf..32e519623e599d2ffc08a6f4a878d007d8a85e58 100644 (file)
@@ -592,7 +592,7 @@ extern void lang_process
 extern void ldlang_add_file
   (lang_input_statement_type *);
 extern lang_output_section_statement_type *lang_output_section_find_by_flags
-  (const asection *, lang_output_section_statement_type **,
+  (const asection *, flagword, lang_output_section_statement_type **,
    lang_match_sec_type_func);
 extern lang_output_section_statement_type *lang_insert_orphan
   (asection *, const char *, int, lang_output_section_statement_type *,