This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Re: Orphan output section with multiple input sections


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=936384714fa8b0f7ca8cc3b5637394461bc998c8

commit 936384714fa8b0f7ca8cc3b5637394461bc998c8
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Oct 29 16:16:22 2015 +1030

    Re: Orphan output section with multiple input sections
    
    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.

Diff:
---
 ld/ChangeLog          | 13 +++++++++++++
 ld/emultempl/elf32.em |  5 +++--
 ld/emultempl/mmo.em   | 18 ++++++++++++++++--
 ld/emultempl/pe.em    | 25 ++++++++++++++++++++-----
 ld/emultempl/pep.em   | 25 ++++++++++++++++++++-----
 ld/ldlang.c           |  6 +++---
 ld/ldlang.h           |  2 +-
 7 files changed, 76 insertions(+), 18 deletions(-)

diff --git a/ld/ChangeLog b/ld/ChangeLog
index d187c0c..69363e1 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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.
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 629c414..0405d4f 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -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;
diff --git a/ld/emultempl/mmo.em b/ld/emultempl/mmo.em
index 47f77d8..8949aed 100644
--- a/ld/emultempl/mmo.em
+++ b/ld/emultempl/mmo.em
@@ -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)
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 04a7f5c..0370c5a 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -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
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index 0b740c3..91de501 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -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
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 5c7ea9f..3841afc 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -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.
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 4b7e65d..32e5196 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -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 *,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]