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

Re: PATCH: PR 797: Alignment in empty section changes the output layout


On Sat, May 07, 2005 at 10:34:32AM -0700, H. J. Lu wrote:
> On Fri, May 06, 2005 at 03:47:17PM +0930, Alan Modra wrote:
> > On Thu, May 05, 2005 at 09:02:23AM -0700, H. J. Lu wrote:
> > > With
> > > 
> > >   lang_size_sections (statement_list.head, abs_output_section,
> > >                       &statement_list.head, 0, 0, NULL,
> > >                       command_line.relax ? FALSE : TRUE);
> > >   lang_do_assignments (statement_list.head, abs_output_section, NULL,
> > > 0);
> > >   lang_reset_memory_regions ();
> > >   lang_mark_used_section ();
> > >   strip_unused_output_sections ();
> > > 
> > > at the end of strip_excluded_output_sections, I got
> > > failed: Bad value FAIL: PHDRS
> > > FAIL: PHDRS2
> > 
> > You need this from ppc64elf.em.
> > 
> > 	  /* We must not cache anything from the preliminary sizing.  */
> > 	  elf_tdata (output_bfd)->program_header_size = 0;
> > 
> > Perhaps a better approach would be to run a cut-down lang_do_assignments
> > that just keeps track of output section and symbol assignments other
> > than "." within output sections.  If it finds such an assignment, mark
> > the section as needed.
> > 
> 
> This patch implements it.
> 
> 

We should ignore assert failure if mark_used is TRUE, not skip it.


H.J.
---
bfd/

2005-05-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* elf32-i386.c (elf_i386_size_dynamic_sections): Also remove
	empty sdynbss section.
	* elf64-x86-64.c (elf64_x86_64_size_dynamic_sections): Likewise.

ld/

2005-05-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR 797
	* ldexp.c (exp_fold_tree_1): Renamed from exp_fold_tree and
	take take a bfd_boolean, mark_used. Ignore assert failure if
	mark_used is TRUE.
	(exp_fold_tree) Call exp_fold_tree_1 with mark_used == FALSE.
	(exp_fold_tree_no_dot): Updated to take a bfd_boolean,
	mark_used and pass down.
	(fold_unary): Likewise.
	(fold_binary): Likewise.
	(fold_trinary): Likewise.
	(exp_binop): Add FALSE to call to exp_fold_tree_no_dot.
	(exp_trinop): Likewise.
	(exp_unop): Likewise.
	(exp_nameop): Likewise.
	(exp_get_vma): Likewise.
	(exp_get_fill): Likewise.
	(exp_get_abs_int): Likewise.
	(fold_name): Likewise. Set SEC_KEEP in output section flags.
	(exp_mark_used_section): New.

	* ldexp.h (exp_mark_used_section): New.

	* ldlang.c (lang_output_section_statement_lookup_1): Set the
	ignored field to FALSE.
	(lang_mark_used_section_1): New.
	(lang_mark_used_section): Call lang_mark_used_section_1.
	(strip_excluded_output_sections): Call lang_mark_used_section
	and check for unused sections.
	(lang_size_sections_1): Skip an output section if it should
	be ignored.
	(lang_do_assignments_1): Likewise.
	(lang_process): Don't call lang_mark_used_section here.

	* ldlang.h (lang_output_section_statement_type): Change
	all_input_readonly to bitfield. Add ignored.

--- binutils/bfd/elf32-i386.c.empty	2005-05-05 07:44:37.000000000 -0700
+++ binutils/bfd/elf32-i386.c	2005-05-07 06:58:49.000000000 -0700
@@ -1914,7 +1914,8 @@ elf_i386_size_dynamic_sections (bfd *out
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/bfd/elf64-x86-64.c.empty	2005-05-05 07:44:41.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c	2005-05-07 06:58:49.000000000 -0700
@@ -1624,7 +1624,8 @@ elf64_x86_64_size_dynamic_sections (bfd 
 
       if (s == htab->splt
 	  || s == htab->sgot
-	  || s == htab->sgotplt)
+	  || s == htab->sgotplt
+	  || s == htab->sdynbss)
 	{
 	  /* Strip this section if we don't need it; see the
 	     comment below.  */
--- binutils/ld/ldexp.c.empty	2005-03-15 09:35:19.000000000 -0800
+++ binutils/ld/ldexp.c	2005-05-07 12:11:09.000000000 -0700
@@ -41,8 +41,12 @@
 #include "libiberty.h"
 #include "safe-ctype.h"
 
+static etree_value_type exp_fold_tree_1
+  (etree_type *, lang_output_section_statement_type *,
+   lang_phase_type, bfd_vma, bfd_vma *, bfd_boolean);
 static etree_value_type exp_fold_tree_no_dot
-  (etree_type *, lang_output_section_statement_type *, lang_phase_type);
+  (etree_type *, lang_output_section_statement_type *, lang_phase_type,
+   bfd_boolean);
 static bfd_vma align_n
   (bfd_vma, bfd_vma);
 
@@ -219,13 +223,14 @@ fold_unary (etree_type *tree,
 	    lang_output_section_statement_type *current_section,
 	    lang_phase_type allocation_done,
 	    bfd_vma dot,
-	    bfd_vma *dotp)
+	    bfd_vma *dotp,
+	    bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->unary.child,
-			  current_section,
-			  allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->unary.child,
+			    current_section,
+			    allocation_done, dot, dotp, mark_used);
   if (result.valid_p)
     {
       switch (tree->type.node_code)
@@ -308,12 +313,13 @@ fold_binary (etree_type *tree,
 	     lang_output_section_statement_type *current_section,
 	     lang_phase_type allocation_done,
 	     bfd_vma dot,
-	     bfd_vma *dotp)
+	     bfd_vma *dotp,
+	     bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->binary.lhs, current_section,
-			  allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->binary.lhs, current_section,
+			    allocation_done, dot, dotp, mark_used);
 
   /* The SEGMENT_START operator is special because its first
      operand is a string, not the name of a symbol.  */
@@ -338,9 +344,10 @@ fold_binary (etree_type *tree,
     {
       etree_value_type other;
 
-      other = exp_fold_tree (tree->binary.rhs,
-			     current_section,
-			     allocation_done, dot, dotp);
+      other = exp_fold_tree_1 (tree->binary.rhs,
+			       current_section,
+			       allocation_done,
+			       dot, dotp, mark_used);
       if (other.valid_p)
 	{
 	  /* If the values are from different sections, or this is an
@@ -498,18 +505,20 @@ fold_trinary (etree_type *tree,
 	      lang_output_section_statement_type *current_section,
 	      lang_phase_type allocation_done,
 	      bfd_vma dot,
-	      bfd_vma *dotp)
+	      bfd_vma *dotp,
+	      bfd_boolean mark_used)
 {
   etree_value_type result;
 
-  result = exp_fold_tree (tree->trinary.cond, current_section,
-			  allocation_done, dot, dotp);
+  result = exp_fold_tree_1 (tree->trinary.cond, current_section,
+			    allocation_done, dot, dotp, mark_used);
   if (result.valid_p)
-    result = exp_fold_tree ((result.value
-			     ? tree->trinary.lhs
-			     : tree->trinary.rhs),
-			    current_section,
-			    allocation_done, dot, dotp);
+    result = exp_fold_tree_1 ((result.value
+			       ? tree->trinary.lhs
+			       : tree->trinary.rhs),
+			      current_section,
+			      allocation_done,
+			      dot, dotp, mark_used);
 
   return result;
 }
@@ -518,7 +527,8 @@ static etree_value_type
 fold_name (etree_type *tree,
 	   lang_output_section_statement_type *current_section,
 	   lang_phase_type allocation_done,
-	   bfd_vma dot)
+	   bfd_vma dot,
+	   bfd_boolean mark_used)
 {
   etree_value_type result;
 
@@ -596,6 +606,7 @@ fold_name (etree_type *tree,
 					 + h->u.def.section->output_offset),
 					NULL,
 					os);
+		      os->bfd_section->flags |= SEC_KEEP;
 		    }
 		}
 	    }
@@ -619,8 +630,12 @@ fold_name (etree_type *tree,
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os && os->processed > 0)
-	    result = new_rel (0, NULL, os);
+	  if (os)
+	    {
+	      os->bfd_section->flags |= SEC_KEEP;
+	      if (os->processed > 0)
+		result = new_rel (0, NULL, os);
+	    }
 	}
       break;
 
@@ -630,14 +645,19 @@ fold_name (etree_type *tree,
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os && os->processed != 0)
+	  if (os)
 	    {
-	      if (os->load_base == NULL)
-		result = new_rel (0, NULL, os);
-	      else
-		result = exp_fold_tree_no_dot (os->load_base,
-					       abs_output_section,
-					       allocation_done);
+	      os->bfd_section->flags |= SEC_KEEP;
+	      if (os->processed != 0)
+		{
+		  if (os->load_base == NULL)
+		    result = new_rel (0, NULL, os);
+		  else
+		    result = exp_fold_tree_no_dot (os->load_base,
+						   abs_output_section,
+						   allocation_done,
+						   mark_used);
+		}
 	    }
 	}
       break;
@@ -649,8 +669,12 @@ fold_name (etree_type *tree,
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os && os->processed > 0)
-	    result = new_abs (os->bfd_section->size / opb);
+	  if (os)
+	    {
+	      os->bfd_section->flags |= SEC_KEEP;
+	      if (os->processed > 0)
+		result = new_abs (os->bfd_section->size / opb);
+	    }
 	}
       break;
 
@@ -688,12 +712,13 @@ fold_name (etree_type *tree,
   return result;
 }
 
-etree_value_type
-exp_fold_tree (etree_type *tree,
-	       lang_output_section_statement_type *current_section,
-	       lang_phase_type allocation_done,
-	       bfd_vma dot,
-	       bfd_vma *dotp)
+static etree_value_type
+exp_fold_tree_1 (etree_type *tree,
+		 lang_output_section_statement_type *current_section,
+		 lang_phase_type allocation_done,
+		 bfd_vma dot,
+		 bfd_vma *dotp,
+		 bfd_boolean mark_used)
 {
   etree_value_type result;
 
@@ -721,26 +746,34 @@ exp_fold_tree (etree_type *tree,
       break;
 
     case etree_assert:
-      result = exp_fold_tree (tree->assert_s.child,
-			      current_section,
-			      allocation_done, dot, dotp);
-      if (result.valid_p && !result.value)
-	einfo ("%X%P: %s\n", tree->assert_s.message);
+      result = exp_fold_tree_1 (tree->assert_s.child,
+				current_section,
+				allocation_done, dot, dotp,
+				mark_used);
+      if (result.valid_p)
+	{
+	  if (mark_used)
+	    /* We don't care if assert fails or not when we are just
+	       marking if a section is used or not.  */
+	    result.value = 1;
+	  else if (!result.value)
+	    einfo ("%X%P: %s\n", tree->assert_s.message);
+	}
       break;
 
     case etree_unary:
       result = fold_unary (tree, current_section, allocation_done,
-			   dot, dotp);
+			   dot, dotp, mark_used);
       break;
 
     case etree_binary:
       result = fold_binary (tree, current_section, allocation_done,
-			    dot, dotp);
+			    dot, dotp, mark_used);
       break;
 
     case etree_trinary:
       result = fold_trinary (tree, current_section, allocation_done,
-			     dot, dotp);
+			     dot, dotp, mark_used);
       break;
 
     case etree_assign:
@@ -757,9 +790,10 @@ exp_fold_tree (etree_type *tree,
 	    {
 	      /* Notify the folder that this is an assignment to dot.  */
 	      assigning_to_dot = TRUE;
-	      result = exp_fold_tree (tree->assign.src,
-				      current_section,
-				      allocation_done, dot, dotp);
+	      result = exp_fold_tree_1 (tree->assign.src,
+					current_section,
+					allocation_done,
+					dot, dotp, mark_used);
 	      assigning_to_dot = FALSE;
 
 	      if (! result.valid_p)
@@ -788,9 +822,9 @@ exp_fold_tree (etree_type *tree,
 	}
       else
 	{
-	  result = exp_fold_tree (tree->assign.src,
-				  current_section, allocation_done,
-				  dot, dotp);
+	  result = exp_fold_tree_1 (tree->assign.src,
+				    current_section, allocation_done,
+				    dot, dotp, mark_used);
 	  if (result.valid_p)
 	    {
 	      bfd_boolean create;
@@ -832,7 +866,8 @@ exp_fold_tree (etree_type *tree,
       break;
 
     case etree_name:
-      result = fold_name (tree, current_section, allocation_done, dot);
+      result = fold_name (tree, current_section, allocation_done, dot,
+			  mark_used);
       break;
 
     default:
@@ -844,12 +879,25 @@ exp_fold_tree (etree_type *tree,
   return result;
 }
 
+etree_value_type
+exp_fold_tree (etree_type *tree,
+	       lang_output_section_statement_type *current_section,
+	       lang_phase_type allocation_done,
+	       bfd_vma dot,
+	       bfd_vma *dotp)
+{
+  return exp_fold_tree_1 (tree, current_section, allocation_done,
+			  dot, dotp, FALSE);
+}
+
 static etree_value_type
 exp_fold_tree_no_dot (etree_type *tree,
 		      lang_output_section_statement_type *current_section,
-		      lang_phase_type allocation_done)
+		      lang_phase_type allocation_done,
+		      bfd_boolean mark_used)
 {
-  return exp_fold_tree (tree, current_section, allocation_done, 0, NULL);
+  return exp_fold_tree_1 (tree, current_section, allocation_done, 0,
+			  NULL, mark_used);
 }
 
 etree_type *
@@ -864,7 +912,7 @@ exp_binop (int code, etree_type *lhs, et
   value.type.node_class = etree_binary;
   r = exp_fold_tree_no_dot (&value,
 			    abs_output_section,
-			    lang_first_phase_enum);
+			    lang_first_phase_enum, FALSE);
   if (r.valid_p)
     {
       return exp_intop (r.value);
@@ -884,7 +932,7 @@ exp_trinop (int code, etree_type *cond, 
   value.trinary.cond = cond;
   value.trinary.rhs = rhs;
   value.type.node_class = etree_trinary;
-  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
+  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -903,7 +951,7 @@ exp_unop (int code, etree_type *child)
   value.unary.child = child;
   value.unary.type.node_class = etree_unary;
   r = exp_fold_tree_no_dot (&value, abs_output_section,
-			    lang_first_phase_enum);
+			    lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -921,7 +969,7 @@ exp_nameop (int code, const char *name)
   value.name.name = name;
   value.name.type.node_class = etree_name;
 
-  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
+  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum, FALSE);
   if (r.valid_p)
     return exp_intop (r.value);
 
@@ -1071,7 +1119,8 @@ exp_get_vma (etree_type *tree,
 
   if (tree != NULL)
     {
-      r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+      r = exp_fold_tree_no_dot (tree, abs_output_section,
+				allocation_done, FALSE);
       if (! r.valid_p && name != NULL)
 	einfo (_("%F%S nonconstant expression for %s\n"), name);
       return r.value;
@@ -1103,7 +1152,8 @@ exp_get_fill (etree_type *tree,
   if (tree == NULL)
     return def;
 
-  r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+  r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done,
+			    FALSE);
   if (! r.valid_p && name != NULL)
     einfo (_("%F%S nonconstant expression for %s\n"), name);
 
@@ -1154,7 +1204,8 @@ exp_get_abs_int (etree_type *tree,
 		 lang_phase_type allocation_done)
 {
   etree_value_type res;
-  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+  res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done,
+			      FALSE);
 
   if (res.valid_p)
     res.value += res.section->bfd_section->vma;
@@ -1173,3 +1224,91 @@ align_n (bfd_vma value, bfd_vma align)
   value = (value + align - 1) / align;
   return value * align;
 }
+
+void
+exp_mark_used_section
+  (etree_type *tree,
+   lang_output_section_statement_type *current_section)
+{
+  switch (tree->type.node_class)
+    {
+    case etree_value:
+      break;
+
+    case etree_rel:
+      break;
+
+    case etree_assert:
+      break;
+
+    case etree_unary:
+      break;
+
+    case etree_binary:
+      break;
+
+    case etree_trinary:
+      break;
+
+    case etree_assign:
+    case etree_provide:
+    case etree_provided:
+      if (tree->assign.dst[0] != '.' || tree->assign.dst[1] != 0)
+	{
+	  etree_value_type result;
+	  bfd_vma dot = 0;
+
+	  result = exp_fold_tree_1 (tree->assign.src,
+				    current_section,
+				    lang_allocating_phase_enum,
+				    dot, &dot, TRUE);
+	  if (result.valid_p)
+	    {
+	      bfd_boolean create;
+	      struct bfd_link_hash_entry *h;
+
+	      if (tree->type.node_class == etree_assign)
+		create = TRUE;
+	      else
+		create = FALSE;
+	      h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
+					create, FALSE, TRUE);
+	      if (h == NULL)
+		{
+		  if (create)
+		    einfo (_("%P%F:%s: hash creation failed\n"),
+			   tree->assign.dst);
+		}
+	      else if (tree->type.node_class == etree_provide
+		       && h->type != bfd_link_hash_new
+		       && h->type != bfd_link_hash_undefined
+		       && h->type != bfd_link_hash_common)
+		{
+		  /* Do nothing.  The symbol was defined by some
+		     object.  */
+		}
+	      else
+		{
+		  /* FIXME: Should we worry if the symbol is already
+		     defined?  */
+		  lang_update_definedness (tree->assign.dst, h);
+		  h->type = bfd_link_hash_defined;
+		  h->u.def.value = result.value;
+		  h->u.def.section = result.section->bfd_section;
+		  if (tree->type.node_class == etree_provide)
+		    tree->type.node_class = etree_provided;
+		}
+	    }
+	}
+      break;
+
+    case etree_name:
+      fold_name (tree, current_section, lang_allocating_phase_enum, 0,
+		 TRUE);
+      break;
+
+    default:
+      abort ();
+      break;
+    }
+}
--- binutils/ld/ldexp.h.empty	2004-12-22 09:30:57.000000000 -0800
+++ binutils/ld/ldexp.h	2005-05-07 09:34:05.000000000 -0700
@@ -156,5 +156,7 @@ fill_type *exp_get_fill
   (etree_type *, fill_type *, char *, lang_phase_type);
 bfd_vma exp_get_abs_int
   (etree_type *, int, char *, lang_phase_type);
+void exp_mark_used_section
+  (etree_type *, struct lang_output_section_statement_struct *);
 
 #endif
--- binutils/ld/ldlang.c.empty	2005-05-07 06:58:49.000000000 -0700
+++ binutils/ld/ldlang.c	2005-05-07 10:13:04.000000000 -0700
@@ -1083,6 +1083,7 @@ lang_output_section_statement_lookup_1 (
       lookup->bfd_section = NULL;
       lookup->processed = 0;
       lookup->constraint = constraint;
+      lookup->ignored = FALSE;
       lookup->sectype = normal_section;
       lookup->addr_tree = NULL;
       lang_list_init (&lookup->children);
@@ -3109,6 +3110,90 @@ map_input_to_output_sections
     }
 }
 
+/* Worker function for lang_mark_used_section.  Recursiveness goes
+   here.  */
+
+static void
+lang_mark_used_section_1
+  (lang_statement_union_type *s,
+   lang_output_section_statement_type *output_section_statement)
+{
+  for (; s != NULL; s = s->header.next)
+    {
+      switch (s->header.type)
+	{
+	case lang_constructors_statement_enum:
+	  break;
+
+	case lang_output_section_statement_enum:
+	  {
+	    lang_output_section_statement_type *os;
+
+	    os = &(s->output_section_statement);
+	    if (os->bfd_section != NULL)
+	      lang_mark_used_section_1 (os->children.head, os);
+	  }
+	  break;
+	case lang_wild_statement_enum:
+	  lang_mark_used_section_1 (s->wild_statement.children.head,
+				    output_section_statement);
+
+	  break;
+
+	case lang_object_symbols_statement_enum:
+	case lang_output_statement_enum:
+	case lang_target_statement_enum:
+	  break;
+	case lang_data_statement_enum:
+	  exp_mark_used_section (s->data_statement.exp,
+				 abs_output_section);
+	  break;
+
+	case lang_reloc_statement_enum:
+	  break;
+
+	case lang_input_section_enum:
+	  break;
+
+	case lang_input_statement_enum:
+	  break;
+	case lang_fill_statement_enum:
+	  break;
+	case lang_assignment_statement_enum:
+	  exp_mark_used_section (s->assignment_statement.exp,
+				 output_section_statement);
+	  break;
+	case lang_padding_statement_enum:
+	  break;
+
+	case lang_group_statement_enum:
+	  lang_mark_used_section_1 (s->group_statement.children.head,
+				    output_section_statement);
+	  break;
+
+	default:
+	  FAIL ();
+	  break;
+	case lang_address_statement_enum:
+	  break;
+	}
+    }
+}
+
+static void
+lang_mark_used_section (void)
+{
+  unsigned int gc_sections = link_info.gc_sections;
+
+  /* Callers of exp_fold_tree need to increment this.  */
+  lang_statement_iteration++;
+  lang_mark_used_section_1 (statement_list.head, abs_output_section);
+
+  link_info.gc_sections = 0;
+  bfd_gc_sections (output_bfd, &link_info);
+  link_info.gc_sections = gc_sections;
+}
+
 /* An output section might have been removed after its statement was
    added.  For example, ldemul_before_allocation can remove dynamic
    sections if they turn out to be not needed.  Clean them up here.  */
@@ -3118,32 +3203,54 @@ strip_excluded_output_sections (void)
 {
   lang_output_section_statement_type *os;
 
+  lang_mark_used_section ();
+
   for (os = &lang_output_section_statement.head->output_section_statement;
        os != NULL;
        os = os->next)
     {
-      asection *s;
+      asection *output_section;
+      bfd_boolean exclude;
 
       if (os->constraint == -1)
 	continue;
 
-      if (os->bfd_section == NULL || os->bfd_section->map_head.s == NULL)
+      output_section = os->bfd_section;
+      if (output_section == NULL)
 	continue;
 
-      for (s = os->bfd_section->map_head.s; s != NULL; s = s->map_head.s)
-	if ((s->flags & SEC_EXCLUDE) == 0)
-	  break;
+      exclude = FALSE;
+      if (output_section->map_head.s != NULL)
+	{
+	  asection *s;
 
-      os->bfd_section->map_head.link_order = NULL;
-      os->bfd_section->map_tail.link_order = NULL;
+	  for (s = output_section->map_head.s; s != NULL;
+	       s = s->map_head.s)
+	    if ((s->flags & SEC_EXCLUDE) == 0)
+	      break;
+
+	  output_section->map_head.link_order = NULL;
+	  output_section->map_tail.link_order = NULL;
+
+	  if (s == NULL)
+	    exclude = TRUE;
+	}
 
-      if (s == NULL)
+      if (exclude
+	  || (output_section->linker_has_input == 0
+	      && ((output_section->flags
+		   & (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)))
 	{
-	  s = os->bfd_section;
-	  os->bfd_section = NULL;
-	  if (!bfd_section_removed_from_list (output_bfd, s))
+	  if (exclude)
+	    os->bfd_section = NULL;
+	  else
+	    /* We don't set bfd_section to NULL since bfd_section of the
+	     * removed output section statement may still be used.  */
+	    os->ignored = TRUE;
+	  if (!bfd_section_removed_from_list (output_bfd,
+					      output_section))
 	    {
-	      bfd_section_list_remove (output_bfd, s);
+	      bfd_section_list_remove (output_bfd, output_section);
 	      output_bfd->section_count--;
 	    }
 	}
@@ -3925,8 +4032,8 @@ lang_size_sections_1
 	    lang_output_section_statement_type *os;
 
 	    os = &s->output_section_statement;
-	    if (os->bfd_section == NULL)
-	      /* This section was never actually created.  */
+	    if (os->bfd_section == NULL || os->ignored)
+	      /* This section was removed or never actually created.  */
 	      break;
 
 	    /* If this is a COFF shared library section, use the size and
@@ -4421,7 +4528,7 @@ lang_do_assignments_1
 	    lang_output_section_statement_type *os;
 
 	    os = &(s->output_section_statement);
-	    if (os->bfd_section != NULL)
+	    if (os->bfd_section != NULL && !os->ignored)
 	      {
 		dot = os->bfd_section->vma;
 		lang_do_assignments_1 (os->children.head, os, os->fill, dot);
@@ -4435,7 +4542,7 @@ lang_do_assignments_1
 	      {
 		/* If nothing has been placed into the output section then
 		   it won't have a bfd_section.  */
-		if (os->bfd_section)
+		if (os->bfd_section && !os->ignored)
 		  {
 		    os->bfd_section->lma
 		      = exp_get_abs_int (os->load_base, 0, "load base",
@@ -5240,16 +5347,6 @@ lang_gc_sections (void)
     bfd_gc_sections (output_bfd, &link_info);
 }
 
-static void
-lang_mark_used_section (void)
-{
-  unsigned int gc_sections = link_info.gc_sections;
-
-  link_info.gc_sections = 0;
-  bfd_gc_sections (output_bfd, &link_info);
-  link_info.gc_sections = gc_sections;
-}
-
 void
 lang_process (void)
 {
@@ -5408,7 +5505,6 @@ lang_process (void)
     lang_check_section_addresses ();
 
   /* Final stuffs.  */
-  lang_mark_used_section ();
   ldemul_finish ();
   lang_end ();
 }
--- binutils/ld/ldlang.h.empty	2005-05-07 06:58:49.000000000 -0700
+++ binutils/ld/ldlang.h	2005-05-07 08:59:05.000000000 -0700
@@ -147,7 +147,8 @@ typedef struct lang_output_section_state
   int subsection_alignment;	/* Alignment of components.  */
   int section_alignment;	/* Alignment of start of section.  */
   int constraint;
-  bfd_boolean all_input_readonly;
+  unsigned int all_input_readonly : 1;
+  unsigned int ignored : 1; 
 
   union etree_union *load_base;
 


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