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]

PR 11304, --section-start and orphans


This PR is due to init_os being called too soon.  Ever since HJ Lu
added the bfd_init_private_section_data call to copy over elf section
type from an input section, it isn't appropriate to call init_os with
a NULL input section argument until all input sections have been
attached to output sections.  Otherwise we create an output section
with a zero elf section type, and _bfd_elf_match_sections_by_type in
the elf orphan handling code won't match.  There is a hack in that
code that allows us to match one section regardless, but as this PR
demonstrates, that doesn't work with two orphans.

	PR ld/11304
	* ldlang.c (exp_init_os): Delete forward declaration.
	(init_os): Don't check for bfd_section already created and don't
	init addr_tree and load_base expressions here.
	(map_input_to_output_sections): Only map input to output sections
	and set constraints here, and as an exception, create output
	sections which have their address set.  Move all the other code to..
	(create_other_output_sections): ..here.  New function.  Handle init
	of addr_tree and load_base here too.
	(lang_process): Call create_other_output_sections.

Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.329
diff -u -p -r1.329 ldlang.c
--- ld/ldlang.c	19 Feb 2010 01:47:13 -0000	1.329
+++ ld/ldlang.c	22 Feb 2010 11:04:40 -0000
@@ -68,7 +68,6 @@ static struct unique_sections *unique_se
 static bfd_boolean ldlang_sysrooted_script = FALSE;
 
 /* Forward declarations.  */
-static void exp_init_os (etree_type *);
 static void init_map_userdata (bfd *, asection *, void *);
 static lang_input_statement_type *lookup_name (const char *);
 static struct bfd_hash_entry *lang_definedness_newfunc
@@ -2048,12 +2047,8 @@ sort_def_symbol (struct bfd_link_hash_en
 /* Initialize an output section.  */
 
 static void
-init_os (lang_output_section_statement_type *s, asection *isec,
-	 flagword flags)
+init_os (lang_output_section_statement_type *s, asection *isec, flagword flags)
 {
-  if (s->bfd_section != NULL)
-    return;
-
   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
     einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
 
@@ -2078,14 +2073,6 @@ init_os (lang_output_section_statement_t
       get_userdata (s->bfd_section) = new_userdata;
     }
 
-  /* If there is a base address, make sure that any sections it might
-     mention are initialized.  */
-  if (s->addr_tree != NULL)
-    exp_init_os (s->addr_tree);
-
-  if (s->load_base != NULL)
-    exp_init_os (s->load_base);
-
   /* If supplied an alignment, set it.  */
   if (s->section_alignment != -1)
     s->bfd_section->alignment_power = s->section_alignment;
@@ -3430,10 +3417,10 @@ map_input_to_output_sections
   (lang_statement_union_type *s, const char *target,
    lang_output_section_statement_type *os)
 {
-  flagword flags;
-
   for (; s != NULL; s = s->header.next)
     {
+      lang_output_section_statement_type *tos;
+
       switch (s->header.type)
 	{
 	case lang_wild_statement_enum:
@@ -3445,29 +3432,23 @@ map_input_to_output_sections
 					os);
 	  break;
 	case lang_output_section_statement_enum:
-	  if (s->output_section_statement.constraint)
+	  tos = &s->output_section_statement;
+	  if (tos->constraint != 0)
 	    {
-	      if (s->output_section_statement.constraint != ONLY_IF_RW
-		  && s->output_section_statement.constraint != ONLY_IF_RO)
+	      if (tos->constraint != ONLY_IF_RW
+		  && tos->constraint != ONLY_IF_RO)
 		break;
-	      s->output_section_statement.all_input_readonly = TRUE;
-	      check_input_sections (s->output_section_statement.children.head,
-				    &s->output_section_statement);
-	      if ((s->output_section_statement.all_input_readonly
-		   && s->output_section_statement.constraint == ONLY_IF_RW)
-		  || (!s->output_section_statement.all_input_readonly
-		      && s->output_section_statement.constraint == ONLY_IF_RO))
+	      tos->all_input_readonly = TRUE;
+	      check_input_sections (tos->children.head, tos);
+	      if (tos->all_input_readonly != (tos->constraint == ONLY_IF_RO))
 		{
-		  s->output_section_statement.constraint = -1;
+		  tos->constraint = -1;
 		  break;
 		}
 	    }
-
-	  map_input_to_output_sections (s->output_section_statement.children.head,
+	  map_input_to_output_sections (tos->children.head,
 					target,
-					&s->output_section_statement);
-	  break;
-	case lang_output_statement_enum:
+					tos);
 	  break;
 	case lang_target_statement_enum:
 	  target = s->target_statement.target;
@@ -3477,19 +3458,102 @@ map_input_to_output_sections
 					target,
 					os);
 	  break;
+	case lang_address_statement_enum:
+	  /* Mark the specified section with the supplied address.
+	     If this section was actually a segment marker, then the
+	     directive is ignored if the linker script explicitly
+	     processed the segment marker.  Originally, the linker
+	     treated segment directives (like -Ttext on the
+	     command-line) as section directives.  We honor the
+	     section directive semantics for backwards compatibilty;
+	     linker scripts that do not specifically check for
+	     SEGMENT_START automatically get the old semantics.  */
+	  if (!s->address_statement.segment
+	      || !s->address_statement.segment->used)
+	    {
+	      const char *name = s->address_statement.section_name;
+
+	      /* Create the output section statment here rather than
+		 in create_other_output_sections so that orphans with
+		 a set address will be placed after other script
+		 sections.  If we let the orphan placement code place
+		 them in amongst other sections then the address will
+		 affect following script sections, which is likely to
+		 surprise naive users.  */
+	      tos = lang_output_section_statement_lookup (name, 0, TRUE);
+	      tos->addr_tree = s->address_statement.address;
+	    }
+	  break;
+	case lang_output_statement_enum:
+	case lang_data_statement_enum:
+	case lang_input_section_enum:
+	case lang_fill_statement_enum:
+	case lang_object_symbols_statement_enum:
+	case lang_reloc_statement_enum:
+	case lang_padding_statement_enum:
+	case lang_input_statement_enum:
+	case lang_assignment_statement_enum:
+	case lang_insert_statement_enum:
+	  break;
+	}
+    }
+}
+
+/* Create any other output sections, such as needed for data statements
+   or those referenced in expressions.  */
+
+static void
+create_other_output_sections
+  (lang_statement_union_type *s,
+   lang_output_section_statement_type *os)
+{
+  lang_output_section_statement_type *tos;
+  flagword flags;
+
+  for (; s != NULL; s = s->header.next)
+    {
+      switch (s->header.type)
+	{
+	case lang_wild_statement_enum:
+	  break;
+	case lang_constructors_statement_enum:
+	  create_other_output_sections (constructor_list.head, os);
+	  break;
+	case lang_output_section_statement_enum:
+	  tos = &s->output_section_statement;
+	  if (tos->constraint != 0
+	      && tos->constraint != ONLY_IF_RW
+	      && tos->constraint != ONLY_IF_RO)
+	    break;
+	  create_other_output_sections (tos->children.head, tos);
+	  if (tos->bfd_section != NULL)
+	    {
+	      /* If there is a base address, make sure that any sections
+		 it might mention are initialized.  */
+	      if (tos->addr_tree != NULL)
+		exp_init_os (tos->addr_tree);
+	      if (tos->load_base != NULL)
+		exp_init_os (tos->load_base);
+	    }
+	  break;
+	case lang_output_statement_enum:
+	case lang_target_statement_enum:
+	  break;
+	case lang_group_statement_enum:
+	  create_other_output_sections (s->group_statement.children.head, os);
+	  break;
 	case lang_data_statement_enum:
 	  /* Make sure that any sections mentioned in the expression
 	     are initialized.  */
 	  exp_init_os (s->data_statement.exp);
+	  if (os->bfd_section == NULL)
+	    init_os (os, NULL, 0);
 	  flags = SEC_HAS_CONTENTS;
 	  /* The output section gets contents, and then we inspect for
 	     any flags set in the input script which override any ALLOC.  */
 	  if (!(os->flags & SEC_NEVER_LOAD))
 	    flags |= SEC_ALLOC | SEC_LOAD;
-	  if (os->bfd_section == NULL)
-	    init_os (os, NULL, flags);
-	  else
-	    os->bfd_section->flags |= flags;
+	  os->bfd_section->flags |= flags;
 	  break;
 	case lang_input_section_enum:
 	  break;
@@ -3510,25 +3574,14 @@ map_input_to_output_sections
 	  exp_init_os (s->assignment_statement.exp);
 	  break;
 	case lang_address_statement_enum:
-	  /* Mark the specified section with the supplied address.
-	     If this section was actually a segment marker, then the
-	     directive is ignored if the linker script explicitly
-	     processed the segment marker.  Originally, the linker
-	     treated segment directives (like -Ttext on the
-	     command-line) as section directives.  We honor the
-	     section directive semantics for backwards compatibilty;
-	     linker scripts that do not specifically check for
-	     SEGMENT_START automatically get the old semantics.  */
 	  if (!s->address_statement.segment
 	      || !s->address_statement.segment->used)
 	    {
-	      lang_output_section_statement_type *aos
-		= (lang_output_section_statement_lookup
-		   (s->address_statement.section_name, 0, TRUE));
-
-	      if (aos->bfd_section == NULL)
-		init_os (aos, NULL, 0);
-	      aos->addr_tree = s->address_statement.address;
+	      const char *name = s->address_statement.section_name;
+
+	      tos = lang_output_section_find (name);
+	      if (tos->bfd_section == NULL)
+		init_os (tos, NULL, 0);
 	    }
 	  break;
 	case lang_insert_statement_enum:
@@ -6347,6 +6400,10 @@ lang_process (void)
   /* Find any sections not attached explicitly and handle them.  */
   lang_place_orphans ();
 
+  /* Create sections for data statements and those referenced in
+     expressions but otherwise empty.  */
+  create_other_output_sections (statement_list.head, NULL);
+
   if (! link_info.relocatable)
     {
       asection *found;

-- 
Alan Modra
Australia Development Lab, IBM


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