This is the mail archive of the binutils@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]

PATCH: ld/1467: Orphaned section is put in the odd place


The ELF linker doesn't check section type and checks section name when
placing orphan. Both may lead to odd orphaned section placement. This
patch adds section type check and removes the section name check.


H.J.
---
2005-10-11  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/1467
	* emultempl/elf32.em: Include "elf-bfd.h".
	(gld${EMULATION_NAME}_output_section_find): New.
	(gld${EMULATION_NAME}_place_orphan): Use it. Don't use section
	name. Check section type.

--- ld/emultempl/elf32.em.orphan	2005-09-07 11:42:00.000000000 -0700
+++ ld/emultempl/elf32.em	2005-10-11 22:40:13.000000000 -0700
@@ -53,6 +53,7 @@ Foundation, Inc., 51 Franklin Street - F
 #include "ldemul.h"
 #include <ldgram.h>
 #include "elf/common.h"
+#include "elf-bfd.h"
 
 /* Declare functions used by various EXTRA_EM_FILEs.  */
 static void gld${EMULATION_NAME}_before_parse (void);
@@ -1278,6 +1279,148 @@ output_rel_find (asection *sec, int isdy
   return last;
 }
 
+/* A variant of lang_output_section_find used by place_orphan.
+   Returns the output statement that should precede a new output
+   statement for SEC.  If an exact match is found on certain flags,
+   sets *EXACT too.  */
+
+static lang_output_section_statement_type *
+gld${EMULATION_NAME}_output_section_find
+  (const asection *sec, lang_output_section_statement_type **exact)
+{
+  lang_output_section_statement_type *first, *look, *found;
+  flagword flags;
+  unsigned int sh_type = elf_section_type (sec);
+
+  /* We know the first statement on this list is *ABS*.  May as well
+     skip it.  */
+  first = &lang_output_section_statement.head->output_section_statement;
+  first = first->next;
+
+  /* First try for an exact match.  */
+  found = NULL;
+  for (look = first; look; look = look->next)
+    {
+      flags = look->flags;
+      if (look->bfd_section != NULL)
+	{
+	  flags = look->bfd_section->flags;
+	  if (sh_type != elf_section_type (look->bfd_section))
+	    continue;
+	}
+      flags ^= sec->flags;
+      if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+		     | SEC_READONLY | SEC_CODE | SEC_SMALL_DATA
+		     | SEC_THREAD_LOCAL)))
+	found = look;
+    }
+  if (found != NULL)
+    {
+      *exact = found;
+      return found;
+    }
+
+  if (sec->flags & SEC_CODE)
+    {
+      /* Try for a rw code section.  */
+      for (look = first; look; look = look->next)
+	{
+	  flags = look->flags;
+	  if (look->bfd_section != NULL)
+	    {
+	      flags = look->bfd_section->flags;
+	      if (sh_type != elf_section_type (look->bfd_section))
+		continue;
+	    }
+	  flags ^= sec->flags;
+	  if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+			 | SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
+	    found = look;
+	}
+      return found;
+    }
+
+  if (sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL))
+    {
+      /* .rodata can go after .text, .sdata2 after .rodata.  */
+      for (look = first; look; look = look->next)
+	{
+	  flags = look->flags;
+	  if (look->bfd_section != NULL)
+	    {
+	      flags = look->bfd_section->flags;
+	      if (sh_type != elf_section_type (look->bfd_section))
+		continue;
+	    }
+	  flags ^= sec->flags;
+	  if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+			 | SEC_READONLY))
+	      && !(look->flags & (SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
+	    found = look;
+	}
+      return found;
+    }
+
+  if (sec->flags & SEC_SMALL_DATA)
+    {
+      /* .sdata goes after .data, .sbss after .sdata.  */
+      for (look = first; look; look = look->next)
+	{
+	  flags = look->flags;
+	  if (look->bfd_section != NULL)
+	    {
+	      flags = look->bfd_section->flags;
+	      if (sh_type != elf_section_type (look->bfd_section))
+		continue;
+	    }
+	  flags ^= sec->flags;
+	  if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+			 | SEC_THREAD_LOCAL))
+	      || ((look->flags & SEC_SMALL_DATA)
+		  && !(sec->flags & SEC_HAS_CONTENTS)))
+	    found = look;
+	}
+      return found;
+    }
+
+  if (sec->flags & SEC_HAS_CONTENTS)
+    {
+      /* .data goes after .rodata.  */
+      for (look = first; look; look = look->next)
+	{
+	  flags = look->flags;
+	  if (look->bfd_section != NULL)
+	    {
+	      flags = look->bfd_section->flags;
+	      if (sh_type != elf_section_type (look->bfd_section))
+		continue;
+	    }
+	  flags ^= sec->flags;
+	  if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
+			 | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
+	    found = look;
+	}
+      return found;
+    }
+
+  /* .bss goes last.  */
+  for (look = first; look; look = look->next)
+    {
+      flags = look->flags;
+      if (look->bfd_section != NULL)
+	{
+	  flags = look->bfd_section->flags;
+	  if (sh_type != elf_section_type (look->bfd_section))
+	    continue;
+	}
+      flags ^= sec->flags;
+      if (!(flags & SEC_ALLOC))
+	found = look;
+    }
+
+  return found;
+}
+
 /* Place an orphan section.  We use this to put random SHF_ALLOC
    sections in the right segment.  */
 
@@ -1324,20 +1467,26 @@ gld${EMULATION_NAME}_place_orphan (lang_
   lang_output_section_statement_type *after;
   lang_output_section_statement_type *os;
   int isdyn = 0;
+  unsigned int sh_type = elf_section_type (s);
 
   secname = bfd_get_section_name (s->owner, s);
 
   if (! link_info.relocatable
       && link_info.combreloc
-      && (s->flags & SEC_ALLOC)
-      && strncmp (secname, ".rel", 4) == 0)
-    {
-      if (secname[4] == 'a')
+      && (s->flags & SEC_ALLOC))
+    switch (sh_type)
+      {
+      case SHT_RELA:
 	secname = ".rela.dyn";
-      else
+	isdyn = 1;
+	break;
+      case SHT_REL:
 	secname = ".rel.dyn";
-      isdyn = 1;
-    }
+	isdyn = 1;
+	break;
+      default:
+	break;
+      }
 
   if (isdyn || (!config.unique_orphan_sections && !unique_section_p (s)))
     {
@@ -1347,8 +1496,9 @@ gld${EMULATION_NAME}_place_orphan (lang_
       if (os != NULL
 	  && (os->bfd_section == NULL
 	      || os->bfd_section->flags == 0
-	      || ((s->flags ^ os->bfd_section->flags)
-		  & (SEC_LOAD | SEC_ALLOC)) == 0))
+	      || (sh_type == elf_section_type (os->bfd_section)
+		  && ((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.
@@ -1394,8 +1544,7 @@ gld${EMULATION_NAME}_place_orphan (lang_
   place = NULL;
   if ((s->flags & SEC_ALLOC) == 0)
     ;
-  else if ((s->flags & SEC_LOAD) != 0
-	   && strncmp (secname, ".note", 5) == 0)
+  else if ((s->flags & SEC_LOAD) != 0 && sh_type == SHT_NOTE)
     place = &hold[orphan_interp];
   else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
     place = &hold[orphan_bss];
@@ -1403,7 +1552,7 @@ gld${EMULATION_NAME}_place_orphan (lang_
     place = &hold[orphan_sdata];
   else if ((s->flags & SEC_READONLY) == 0)
     place = &hold[orphan_data];
-  else if (strncmp (secname, ".rel", 4) == 0
+  else if ((sh_type == SHT_RELA || sh_type == SHT_REL)
 	   && (s->flags & SEC_LOAD) != 0)
     place = &hold[orphan_rel];
   else if ((s->flags & SEC_CODE) == 0)
@@ -1423,7 +1572,7 @@ gld${EMULATION_NAME}_place_orphan (lang_
 	}
       after = place->os;
       if (after == NULL)
-	after = lang_output_section_find_by_flags (s, &place->os);
+	after = gld${EMULATION_NAME}_output_section_find (s, &place->os);
       if (after == NULL)
 	/* *ABS* is always the first output section statement.  */
 	after = &lang_output_section_statement.head->output_section_statement;


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