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 992: regression: ld selective1 and selective2 fails, cris-elf


On Sat, Jun 04, 2005 at 12:58:30PM -0700, H. J. Lu wrote:
> We should set SEC_KEEP on current section only if the symbol will be
> defined.

I'm not really happy with the way HJ's lang_mark_used_section has panned
out.  It seems like we'll be forever chasing down corner cases.  When I
made the suggestion to write a special version of lang_do_assignments
that just marked sections, I was thinking that this might avoid lots of
special cases in lang_do_assignments and/or changes to expression
folding.  Of course, it turned out that a new ldexp.c function was
needed for expression folding.

Worse, I'm sure that many possible linker script constructs are not
handled currently by lang_mark_used_section, and others are handled
wrongly.  An obvious example of the latter is that SIZEOF marks the
referenced section as needed.  A little more complicated example is that
LOADADDR need not access the referenced section's lma if load_base for
the section is some expression that depends on other sections.  Even
if it does access the lma, then all that requires is that the lma be
set.  So I decided to rip out this code and rewrite, in the process
getting rid of all the needless passing of parameters and structure
copies in ldexp.c.  The majority of this patch is a result of
restructuring ldexp.c.  I suppose I should have separated that out into
a separate patch, and also the fixes for bugs I discovered along the
way..

As far as marking goes, there really is only one reason to keep an empty
output section, and that is if symbols are defined there.  Access to a
section vma, lma or size don't require that a section actually be
output, merely that those values be set.  A lang_size_sections_1 tweak
does this, and global symbols are marked in elf_mark_used_section.  Of
course, elf_mark_used_section only works for ELF and we need this for
other formats.  So move elf_mark_used_section into the generic linker
code.

That leaves no place in ldexp.c that needs to mark a section with
SEC_KEEP, and we just need to make sure that link script symbols are
put into the bfd hash table somehow.  I chose to use a
lang_size_sections run to do that rather than lang_do_assignments,
because sizing sections allowed me to easily handle data statements and
assignments to dot (*).  Also, we have the precedent of running
lang_size_sections multiple times.  Now, lang_size_sections is
unnecessarily heavyweight due to running through the sections multiple
times to support DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END, so to
mitigate this I defined one_lang_size_sections_pass.

*) I believe any assignment to "dot" that allocates space in a section
should result in the section being kept.  ld-scripts/empty-aligned thus
ought to keep .text2.

bfd/
	* elflink.c (elf_mark_used_section): Delete.
	(bfd_elf_gc_sections): Call bfd_generic_gc_sections.
	* reloc.c (bfd_mark_used_section): New function.
	(bfd_generic_gc_sections): Call bfd_mark_used_section.

ld/
	* ld.h (lang_phase_type): Move to..
	* ldexp.h: ..here.  Add lang_mark_phase_enum.
	(node_type): Remove etree_undef and etree_unspec.
	(exp_data_seg): Delete.
	(struct ldexp_control, expld): New.
	(invalid, exp_mark_used_section): Delete.
	(exp_fold_tree, exp_get_vma, exp_get_value_int, exp_get_fill,
	exp_get_abs_int): Update prototypes.
	* ldexp.c (assigning_to_dot): Delete.
	(expld): Define.
	(make_abs): Operate directly on expld.result.  Update all callers.
	(new_abs): Likewise.  Return void.
	(new_rel_from_abs): Rename from new_rel_from_section.
	(new_rel, new_rel_from_abs): Operate on expld.result and return void.
	Update all callers.
	(fold_unary): Operate on expld.result and return void.  Remove
	"current_section", "allocation_done", "dot", "dotp" and "mark_used"
	params.  Update all callers.
	(fold_binary, fold_trinary, fold_name, exp_fold_tree_1): Likewise.
	(fold_unary <ALIGN_K>): Ensure alignment is absolute.
	(fold_unary <ABSOLUTE>): Use make_abs.
	(fold_unary <DATA_SEGMENT_END>): Evaluate mark_phase as for
	allocating_phase.
	(fold_binary <DATA_SEGMENT_ALIGN, DATA_SEGMENT_RELRO_END, >): Ditto.
	(fold_binary <'%','/'>): Don't error if marking.
	(fold_name <SIZEOF_HEADERS>): Don't call bfd_sizeof_headers when
	marking.
	(fold_name <NAME>): Remove FIXME; -R is handled correctly.  Don't
	error when marking.
	(fold_name <ADDR, LOADADDR, SIZEOF>): Don't set SEC_KEEP.
	(exp_fold_tree_1): Don't error when marking.
	(exp_fold_tree_1 <etree_rel>): Evaluate in all phases except first.
	(exp_fold_tree_1 <etree_assign to dot>): Don't check for NULL
	current section, instead check for NULL dotp.
	(exp_fold_tree_1 <etree_provide>): Don't evaluate the assignment
	source unless the symbol is referenced and undefined.
	(exp_fold_tree): Remove "allocation_done" and "dot" params.  Save
	params to expld.
	(exp_fold_tree_no_dot): Remove "current_section", "allocation_done
	and "mark_used" params.  Save params to expld.  Update all callers.
	(exp_assop): Do without temp var.
	(exp_print_tree <etree_undef>): Delete code.
	(exp_get_vma): Remove "allocation_done" param.  Correct error return.
	(exp_get_fill, exp_get_abs_int): Likewise.
	(exp_get_value_int): Remove "allocation_done" param.
	(exp_mark_used_section): Delete.
	* ldgram.y (fill_exp): Update exp_get_fill call.
	(origin_spec, length_spec): Update exp_get_vma call.
	* ldlang.c (lang_init): Don't bother clearing lang_statement_iteration.
	(lang_mark_used_section_1, lang_mark_used_section): Delete.
	(strip_excluded_output_sections): Call one_lang_size_sections_pass in
	marking mode.  Merge old lang_mark_used_section code.  Correct handling
	of output sections with excluded input sections and data statements.
	Don't drop non-zero sized sections.  Don't zap os->bfd_section.
	Do set SEC_EXCLUDE when appropriate.
	(print_output_section_statement): Update for changed ldexp.c
	interface.
	(print_assignment, lang_size_sections_1): Likewise.
	(lang_do_assignments_1, lang_enter_output_section_statement): Likewise.
	(lang_new_phdr, lang_record_phdrs): Likewise.
	(lang_size_sections): Likewise.
	(insert_pad): Use following statement if it is a pad, rather than
	creating a new one.
	(lang_size_sections_1 <lang_output_section_statement_enum>): Do
	process ignored output section to set vma and lma, but don't
	update dot for these sections.  Don't error if marking.
	(lang_size_sections_1 <lang_assignment_statement_enum>): Don't
	update dot for ignored sections.
	(lang_size_sections_1 <lang_data_statement_enum>): Don't mark absolute
	section with SEC_ALLOC.
	(one_lang_size_sections_pass): New function.
	(lang_size_sections): Remove first five params.  Set expld.phase on
	entry and exit.   Use one_lang_size_sections_pass.
	(lang_do_assignments): Remove all params.  Update all callers.
	(lang_reset_memory_regions): Clear os->processed for all output
	section statements.
	* ldlang.h (lang_do_assignments): Update prototype.
	(lang_size_sections): Likewise.
	(one_lang_size_sections_pass): Declare.
	* pe-dll.c (pe_dll_fill_sections, pe_exe_fill_sections): Update
	lang_size_sections and lang_do_assignments calls.
	* emultempl/elf32.em (layout_sections_again): Likewise.
	* emultempl/ppc64elf.em (ppc_before_allocation): Use
	one_lang_size_sections_pass.

ld/testsuite/
	* ld-scripts/empty-aligned.d: Adjust.

Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.166
diff -u -p -r1.166 elflink.c
--- bfd/elflink.c	3 Jun 2005 09:52:49 -0000	1.166
+++ bfd/elflink.c	8 Jun 2005 13:44:04 -0000
@@ -9067,27 +9067,6 @@ elf_gc_mark_dynamic_ref_symbol (struct e
   return TRUE;
 }
 
-/* Mark sections containing global symbols.  This is called through
-   elf_link_hash_traverse.  */
-
-static bfd_boolean
-elf_mark_used_section (struct elf_link_hash_entry *h,
-		       void *data ATTRIBUTE_UNUSED)
-{
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-  if (h->root.type == bfd_link_hash_defined
-      || h->root.type == bfd_link_hash_defweak)
-    {
-      asection *s = h->root.u.def.section;
-      if (s != NULL && s->output_section != NULL)
-	s->output_section->flags |= SEC_KEEP;
-    }
-
-  return TRUE;
-}
-
 /* Do mark and sweep of unused sections.  */
 
 bfd_boolean
@@ -9100,15 +9079,7 @@ bfd_elf_gc_sections (bfd *abfd, struct b
      struct elf_link_hash_entry *h, Elf_Internal_Sym *);
 
   if (!info->gc_sections)
-    {
-      /* If we are called when info->gc_sections is 0, we will mark
-	 all sections containing global symbols for non-relocatable
-	 link.  */
-      if (!info->relocatable)
-	elf_link_hash_traverse (elf_hash_table (info),
-				elf_mark_used_section, NULL);
-      return TRUE;
-    }
+    return bfd_generic_gc_sections (abfd, info);
 
   if (!get_elf_backend_data (abfd)->can_gc_sections
       || info->relocatable
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.128
diff -u -p -r1.128 reloc.c
--- bfd/reloc.c	18 May 2005 05:40:06 -0000	1.128
+++ bfd/reloc.c	8 Jun 2005 13:44:08 -0000
@@ -4516,6 +4516,27 @@ bfd_generic_relax_section (bfd *abfd ATT
   return TRUE;
 }
 
+/* Mark sections containing global symbols.  This is called through
+   bfd_link_hash_traverse.  */
+
+static bfd_boolean
+bfd_mark_used_section (struct bfd_link_hash_entry *h,
+		       void *data ATTRIBUTE_UNUSED)
+{
+  if (h->type == bfd_link_hash_warning)
+    h = h->u.i.link;
+
+  if (h->type == bfd_link_hash_defined
+      || h->type == bfd_link_hash_defweak)
+    {
+      asection *s = h->u.def.section;
+      if (s != NULL && s->output_section != NULL)
+	s->output_section->flags |= SEC_KEEP;
+    }
+
+  return TRUE;
+}
+
 /*
 INTERNAL_FUNCTION
 	bfd_generic_gc_sections
@@ -4526,13 +4547,18 @@ SYNOPSIS
 
 DESCRIPTION
 	Provides default handling for relaxing for back ends which
-	don't do section gc -- i.e., does nothing.
+	don't do section gc -- i.e., does nothing besides the special
+	case for marking sections having global symbols.
 */
 
 bfd_boolean
 bfd_generic_gc_sections (bfd *abfd ATTRIBUTE_UNUSED,
-			 struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
+			 struct bfd_link_info *info)
 {
+  /* If called when info->gc_sections is 0, then mark all sections
+     containing global symbols with SEC_KEEP.  */
+  if (!info->gc_sections && !info->relocatable)
+    bfd_link_hash_traverse (info->hash, bfd_mark_used_section, NULL);
   return TRUE;
 }
 
Index: ld/ld.h
===================================================================
RCS file: /cvs/src/src/ld/ld.h,v
retrieving revision 1.28
diff -u -p -r1.28 ld.h
--- ld/ld.h	12 May 2005 07:32:02 -0000	1.28
+++ ld/ld.h	8 Jun 2005 23:58:35 -0000
@@ -238,12 +238,6 @@ typedef struct {
 
 extern ld_config_type config;
 
-typedef enum {
-  lang_first_phase_enum,
-  lang_allocating_phase_enum,
-  lang_final_phase_enum
-} lang_phase_type;
-
 extern FILE * saved_script_handle;
 extern bfd_boolean force_make_executable;
 
Index: ld/ldexp.h
===================================================================
RCS file: /cvs/src/src/ld/ldexp.h,v
retrieving revision 1.17
diff -u -p -r1.17 ldexp.h
--- ld/ldexp.h	2 Jun 2005 03:08:41 -0000	1.17
+++ ld/ldexp.h	8 Jun 2005 23:58:35 -0000
@@ -40,8 +40,6 @@ typedef struct {
     etree_assign,
     etree_provide,
     etree_provided,
-    etree_undef,
-    etree_unspec,
     etree_value,
     etree_assert,
     etree_rel
@@ -91,17 +89,44 @@ typedef union etree_union {
   } assert_s;
 } etree_type;
 
-extern struct exp_data_seg {
-  enum {
-    exp_dataseg_none,
-    exp_dataseg_align_seen,
-    exp_dataseg_relro_seen,
-    exp_dataseg_end_seen,
-    exp_dataseg_relro_adjust,
-    exp_dataseg_adjust
-  } phase;
-  bfd_vma base, min_base, relro_end, end, pagesize, maxpagesize;
-} exp_data_seg;
+typedef enum {
+  lang_first_phase_enum,
+  lang_mark_phase_enum,
+  lang_allocating_phase_enum,
+  lang_final_phase_enum
+} lang_phase_type;
+
+struct ldexp_control {
+  /* Modify expression evaluation depending on this.  */
+  lang_phase_type phase;
+
+  /* Principally used for diagnostics.  */
+  bfd_boolean assigning_to_dot;
+
+  /* Working results.  */
+  etree_value_type result;
+  bfd_vma dot;
+
+  /* Current dot and section passed to ldexp folder.  */
+  bfd_vma *dotp;
+  asection *section;
+
+  /* State machine and results for DATASEG.  */
+  struct {
+    enum {
+      exp_dataseg_none,
+      exp_dataseg_align_seen,
+      exp_dataseg_relro_seen,
+      exp_dataseg_end_seen,
+      exp_dataseg_relro_adjust,
+      exp_dataseg_adjust
+    } phase;
+
+    bfd_vma base, min_base, relro_end, end, pagesize, maxpagesize;
+  } dataseg;
+};
+
+extern struct ldexp_control expld;
 
 /* A maps from a segment name to a base address.  */
 typedef struct segment_struct {
@@ -127,10 +152,8 @@ etree_type *exp_bigintop
   (bfd_vma, char *);
 etree_type *exp_relop
   (asection *, bfd_vma);
-etree_value_type invalid
-  (void);
-etree_value_type exp_fold_tree
-  (etree_type *, asection *, lang_phase_type, bfd_vma, bfd_vma *);
+void exp_fold_tree
+  (etree_type *, asection *, bfd_vma *);
 etree_type *exp_binop
   (int, etree_type *, etree_type *);
 etree_type *exp_trinop
@@ -148,14 +171,12 @@ etree_type *exp_assert
 void exp_print_tree
   (etree_type *);
 bfd_vma exp_get_vma
-  (etree_type *, bfd_vma, char *, lang_phase_type);
+  (etree_type *, bfd_vma, char *);
 int exp_get_value_int
-  (etree_type *, int, char *, lang_phase_type);
+  (etree_type *, int, char *);
 fill_type *exp_get_fill
-  (etree_type *, fill_type *, char *, lang_phase_type);
+  (etree_type *, fill_type *, char *);
 bfd_vma exp_get_abs_int
-  (etree_type *, int, char *, lang_phase_type);
-void exp_mark_used_section
-  (etree_type *, asection *);
+  (etree_type *, int, char *);
 
 #endif
Index: ld/ldexp.c
===================================================================
RCS file: /cvs/src/src/ld/ldexp.c,v
retrieving revision 1.51
diff -u -p -r1.51 ldexp.c
--- ld/ldexp.c	5 Jun 2005 15:28:35 -0000	1.51
+++ ld/ldexp.c	8 Jun 2005 23:58:35 -0000
@@ -41,19 +41,13 @@
 #include "libiberty.h"
 #include "safe-ctype.h"
 
-static etree_value_type exp_fold_tree_1
-  (etree_type *, asection *, lang_phase_type, bfd_vma, bfd_vma *, bfd_boolean);
-static etree_value_type exp_fold_tree_no_dot
-  (etree_type *, asection *, lang_phase_type, bfd_boolean);
-static bfd_vma align_n
-  (bfd_vma, bfd_vma);
-
-struct exp_data_seg exp_data_seg;
+static void exp_fold_tree_1 (etree_type *);
+static void exp_fold_tree_no_dot (etree_type *);
+static bfd_vma align_n (bfd_vma, bfd_vma);
 
 segment_type *segments;
 
-/* Principally used for diagnostics.  */
-static bfd_boolean assigning_to_dot = FALSE;
+struct ldexp_control expld;
 
 /* Print the string representation of the given token.  Surround it
    with spaces if INFIX_P is TRUE.  */
@@ -135,21 +129,19 @@ exp_print_token (token_code_type code, i
 }
 
 static void
-make_abs (etree_value_type *ptr)
+make_abs (void)
 {
-  ptr->value += ptr->section->vma;
-  ptr->section = bfd_abs_section_ptr;
+  expld.result.value += expld.result.section->vma;
+  expld.result.section = bfd_abs_section_ptr;
 }
 
-static etree_value_type
+static void
 new_abs (bfd_vma value)
 {
-  etree_value_type new;
-  new.valid_p = TRUE;
-  new.section = bfd_abs_section_ptr;
-  new.value = value;
-  new.str = NULL;
-  return new;
+  expld.result.valid_p = TRUE;
+  expld.result.section = bfd_abs_section_ptr;
+  expld.result.value = value;
+  expld.result.str = NULL;
 }
 
 etree_type *
@@ -187,112 +179,90 @@ exp_relop (asection *section, bfd_vma va
   return new;
 }
 
-static etree_value_type
-new_rel (bfd_vma value,
-	 char *str,
-	 asection *section)
-{
-  etree_value_type new;
-  new.valid_p = TRUE;
-  new.value = value;
-  new.str = str;
-  new.section = section;
-  return new;
+static void
+new_rel (bfd_vma value, char *str, asection *section)
+{
+  expld.result.valid_p = TRUE;
+  expld.result.value = value;
+  expld.result.str = str;
+  expld.result.section = section;
 }
 
-static etree_value_type
-new_rel_from_section (bfd_vma value, asection *section)
+static void
+new_rel_from_abs (bfd_vma value)
 {
-  etree_value_type new;
-  new.valid_p = TRUE;
-  new.value = value;
-  new.str = NULL;
-  new.section = section;
-
-  new.value -= section->vma;
-
-  return new;
+  expld.result.valid_p = TRUE;
+  expld.result.value = value - expld.section->vma;
+  expld.result.str = NULL;
+  expld.result.section = expld.section;
 }
 
-static etree_value_type
-fold_unary (etree_type *tree,
-	    asection *current_section,
-	    lang_phase_type allocation_done,
-	    bfd_vma dot,
-	    bfd_vma *dotp,
-	    bfd_boolean mark_used)
-{
-  etree_value_type result;
-
-  result = exp_fold_tree_1 (tree->unary.child,
-			    current_section,
-			    allocation_done, dot, dotp, mark_used);
-  if (result.valid_p)
+static void
+fold_unary (etree_type *tree)
+{
+  exp_fold_tree_1 (tree->unary.child);
+  if (expld.result.valid_p)
     {
       switch (tree->type.node_code)
 	{
 	case ALIGN_K:
-	  if (allocation_done != lang_first_phase_enum)
-	    result = new_rel_from_section (align_n (dot, result.value),
-					   current_section);
+	  if (expld.phase != lang_first_phase_enum)
+	    {
+	      make_abs ();
+	      new_rel_from_abs (align_n (expld.dot, expld.result.value));
+	    }
 	  else
-	    result.valid_p = FALSE;
+	    expld.result.valid_p = FALSE;
 	  break;
 
 	case ABSOLUTE:
-	  if (allocation_done != lang_first_phase_enum)
-	    {
-	      result.value += result.section->vma;
-	      result.section = bfd_abs_section_ptr;
-	    }
-	  else
-	    result.valid_p = FALSE;
+	  make_abs ();
 	  break;
 
 	case '~':
-	  make_abs (&result);
-	  result.value = ~result.value;
+	  make_abs ();
+	  expld.result.value = ~expld.result.value;
 	  break;
 
 	case '!':
-	  make_abs (&result);
-	  result.value = !result.value;
+	  make_abs ();
+	  expld.result.value = !expld.result.value;
 	  break;
 
 	case '-':
-	  make_abs (&result);
-	  result.value = -result.value;
+	  make_abs ();
+	  expld.result.value = -expld.result.value;
 	  break;
 
 	case NEXT:
 	  /* Return next place aligned to value.  */
-	  if (allocation_done == lang_allocating_phase_enum)
+	  if (expld.phase != lang_first_phase_enum)
 	    {
-	      make_abs (&result);
-	      result.value = align_n (dot, result.value);
+	      make_abs ();
+	      expld.result.value = align_n (expld.dot, expld.result.value);
 	    }
 	  else
-	    result.valid_p = FALSE;
+	    expld.result.valid_p = FALSE;
 	  break;
 
 	case DATA_SEGMENT_END:
-	  if (allocation_done != lang_first_phase_enum
-	      && current_section == bfd_abs_section_ptr
-	      && (exp_data_seg.phase == exp_dataseg_align_seen
-		  || exp_data_seg.phase == exp_dataseg_relro_seen
-		  || exp_data_seg.phase == exp_dataseg_adjust
-		  || exp_data_seg.phase == exp_dataseg_relro_adjust
-		  || allocation_done != lang_allocating_phase_enum))
+	  if (expld.phase != lang_first_phase_enum
+	      && expld.section == bfd_abs_section_ptr
+	      && (expld.dataseg.phase == exp_dataseg_align_seen
+		  || expld.dataseg.phase == exp_dataseg_relro_seen
+		  || expld.dataseg.phase == exp_dataseg_adjust
+		  || expld.dataseg.phase == exp_dataseg_relro_adjust
+		  || expld.phase == lang_final_phase_enum))
 	    {
-	      if (exp_data_seg.phase == exp_dataseg_align_seen
-		  || exp_data_seg.phase == exp_dataseg_relro_seen)
+	      if (expld.dataseg.phase == exp_dataseg_align_seen
+		  || expld.dataseg.phase == exp_dataseg_relro_seen)
 		{
-		  exp_data_seg.phase = exp_dataseg_end_seen;
-		  exp_data_seg.end = result.value;
+		  expld.dataseg.phase = exp_dataseg_end_seen;
+		  expld.dataseg.end = expld.result.value;
 		}
 	    }
 	  else
-	    result.valid_p = FALSE;
+	    expld.result.valid_p = FALSE;
 	  break;
 
 	default:
@@ -300,26 +270,16 @@ fold_unary (etree_type *tree,
 	  break;
 	}
     }
-
-  return result;
 }
 
-static etree_value_type
-fold_binary (etree_type *tree,
-	     asection *current_section,
-	     lang_phase_type allocation_done,
-	     bfd_vma dot,
-	     bfd_vma *dotp,
-	     bfd_boolean mark_used)
+static void
+fold_binary (etree_type *tree)
 {
-  etree_value_type result;
-
-  result = exp_fold_tree_1 (tree->binary.lhs, current_section,
-			    allocation_done, dot, dotp, mark_used);
+  exp_fold_tree_1 (tree->binary.lhs);
 
   /* The SEGMENT_START operator is special because its first
      operand is a string, not the name of a symbol.  */
-  if (result.valid_p && tree->type.node_code == SEGMENT_START)
+  if (expld.result.valid_p && tree->type.node_code == SEGMENT_START)
     {
       const char *segment_name;
       segment_type *seg;
@@ -330,68 +290,70 @@ fold_binary (etree_type *tree,
 	if (strcmp (seg->name, segment_name) == 0)
 	  {
 	    seg->used = TRUE;
-	    result.value = seg->value;
-	    result.str = NULL;
-	    result.section = NULL;
+	    expld.result.value = seg->value;
+	    expld.result.str = NULL;
+	    expld.result.section = NULL;
 	    break;
 	  }
     }
-  else if (result.valid_p)
+  else if (expld.result.valid_p)
     {
-      etree_value_type other;
+      etree_value_type lhs = expld.result;
 
-      other = exp_fold_tree_1 (tree->binary.rhs,
-			       current_section,
-			       allocation_done,
-			       dot, dotp, mark_used);
-      if (other.valid_p)
+      exp_fold_tree_1 (tree->binary.rhs);
+      if (expld.result.valid_p)
 	{
 	  /* If the values are from different sections, or this is an
 	     absolute expression, make both the source arguments
 	     absolute.  However, adding or subtracting an absolute
 	     value from a relative value is meaningful, and is an
 	     exception.  */
-	  if (current_section != bfd_abs_section_ptr
-	      && (other.section == bfd_abs_section_ptr
-		  || (result.section == bfd_abs_section_ptr
-		      && tree->type.node_code == '+'))
+	  if (expld.section != bfd_abs_section_ptr
+	      && lhs.section == bfd_abs_section_ptr
+	      && tree->type.node_code == '+')
+	    {
+	      /* Keep the section of the rhs term.  */
+	      expld.result.value = lhs.value + expld.result.value;
+	      return;
+	    }
+	  else if (expld.section != bfd_abs_section_ptr
+	      && expld.result.section == bfd_abs_section_ptr
 	      && (tree->type.node_code == '+'
 		  || tree->type.node_code == '-'))
 	    {
-	      if (other.section != bfd_abs_section_ptr)
-		{
-		  /* Keep the section of the other term.  */
-		  if (tree->type.node_code == '+')
-		    other.value = result.value + other.value;
-		  else
-		    other.value = result.value - other.value;
-		  return other;
-		}
+	      /* Keep the section of the lhs term.  */
+	      expld.result.section = lhs.section;
 	    }
-	  else if (result.section != other.section
-		   || current_section == bfd_abs_section_ptr)
+	  else if (expld.result.section != lhs.section
+		   || expld.section == bfd_abs_section_ptr)
 	    {
-	      make_abs (&result);
-	      make_abs (&other);
+	      make_abs ();
+	      lhs.value += lhs.section->vma;
 	    }
 
 	  switch (tree->type.node_code)
 	    {
 	    case '%':
-	      if (other.value == 0)
+	      if (expld.result.value != 0)
+		expld.result.value = ((bfd_signed_vma) lhs.value
+				      % (bfd_signed_vma) expld.result.value);
+	      else if (expld.phase != lang_mark_phase_enum)
 		einfo (_("%F%S %% by zero\n"));
-	      result.value = ((bfd_signed_vma) result.value
-			      % (bfd_signed_vma) other.value);
 	      break;
 
 	    case '/':
-	      if (other.value == 0)
+	      if (expld.result.value != 0)
+		expld.result.value = ((bfd_signed_vma) lhs.value
+				      / (bfd_signed_vma) expld.result.value);
+	      else if (expld.phase != lang_mark_phase_enum)
 		einfo (_("%F%S / by zero\n"));
-	      result.value = ((bfd_signed_vma) result.value
-			      / (bfd_signed_vma) other.value);
 	      break;
 
-#define BOP(x,y) case x : result.value = result.value y other.value; break;
+#define BOP(x, y) \
+	    case x:							\
+	      expld.result.value = lhs.value y expld.result.value;	\
+	      break;
+
 	      BOP ('+', +);
 	      BOP ('*', *);
 	      BOP ('-', -);
@@ -410,77 +372,82 @@ fold_binary (etree_type *tree,
 	      BOP (OROR, ||);
 
 	    case MAX_K:
-	      if (result.value < other.value)
-		result = other;
+	      if (lhs.value > expld.result.value)
+		expld.result.value = lhs.value;
 	      break;
 
 	    case MIN_K:
-	      if (result.value > other.value)
-		result = other;
+	      if (lhs.value < expld.result.value)
+		expld.result.value = lhs.value;
 	      break;
 
 	    case ALIGN_K:
-	      result.value = align_n (result.value, other.value);
+	      expld.result.value = align_n (lhs.value, expld.result.value);
 	      break;
 
 	    case DATA_SEGMENT_ALIGN:
-	      if (allocation_done != lang_first_phase_enum
-		  && current_section == bfd_abs_section_ptr
-		  && (exp_data_seg.phase == exp_dataseg_none
-		      || exp_data_seg.phase == exp_dataseg_adjust
-		      || exp_data_seg.phase == exp_dataseg_relro_adjust
-		      || allocation_done != lang_allocating_phase_enum))
+	      if (expld.phase != lang_first_phase_enum
+		  && expld.section == bfd_abs_section_ptr
+		  && (expld.dataseg.phase == exp_dataseg_none
+		      || expld.dataseg.phase == exp_dataseg_adjust
+		      || expld.dataseg.phase == exp_dataseg_relro_adjust
+		      || expld.phase == lang_final_phase_enum))
 		{
-		  bfd_vma maxpage = result.value;
+		  bfd_vma maxpage = lhs.value;
+		  bfd_vma commonpage = expld.result.value;
 
-		  result.value = align_n (dot, maxpage);
-		  if (exp_data_seg.phase == exp_dataseg_relro_adjust)
-		    result.value = exp_data_seg.base;
-		  else if (exp_data_seg.phase != exp_dataseg_adjust)
+		  expld.result.value = align_n (expld.dot, maxpage);
+		  if (expld.dataseg.phase == exp_dataseg_relro_adjust)
+		    expld.result.value = expld.dataseg.base;
+		  else if (expld.dataseg.phase != exp_dataseg_adjust)
 		    {
-		      result.value += dot & (maxpage - 1);
-		      if (allocation_done == lang_allocating_phase_enum)
+		      expld.result.value += expld.dot & (maxpage - 1);
+		      if (expld.phase == lang_allocating_phase_enum)
 			{
-			  exp_data_seg.phase = exp_dataseg_align_seen;
-			  exp_data_seg.min_base = align_n (dot, maxpage);
-			  exp_data_seg.base = result.value;
-			  exp_data_seg.pagesize = other.value;
-			  exp_data_seg.maxpagesize = maxpage;
-			  exp_data_seg.relro_end = 0;
+			  expld.dataseg.phase = exp_dataseg_align_seen;
+			  expld.dataseg.min_base = align_n (expld.dot, maxpage);
+			  expld.dataseg.base = expld.result.value;
+			  expld.dataseg.pagesize = commonpage;
+			  expld.dataseg.maxpagesize = maxpage;
+			  expld.dataseg.relro_end = 0;
 			}
 		    }
-		  else if (other.value < maxpage)
-		    result.value += (dot + other.value - 1)
-				    & (maxpage - other.value);
+		  else if (commonpage < maxpage)
+		    expld.result.value += ((expld.dot + commonpage - 1)
+					   & (maxpage - commonpage));
 		}
 	      else
-		result.valid_p = FALSE;
+		expld.result.valid_p = FALSE;
 	      break;
 
 	    case DATA_SEGMENT_RELRO_END:
-	      if (allocation_done != lang_first_phase_enum
-		  && (exp_data_seg.phase == exp_dataseg_align_seen
-		      || exp_data_seg.phase == exp_dataseg_adjust
-		      || exp_data_seg.phase == exp_dataseg_relro_adjust
-		      || allocation_done != lang_allocating_phase_enum))
+	      if (expld.phase != lang_first_phase_enum
+		  && (expld.dataseg.phase == exp_dataseg_align_seen
+		      || expld.dataseg.phase == exp_dataseg_adjust
+		      || expld.dataseg.phase == exp_dataseg_relro_adjust
+		      || expld.phase == lang_final_phase_enum))
 		{
-		  if (exp_data_seg.phase == exp_dataseg_align_seen
-		      || exp_data_seg.phase == exp_dataseg_relro_adjust)
-		    exp_data_seg.relro_end
-		      = result.value + other.value;
-		  if (exp_data_seg.phase == exp_dataseg_relro_adjust
-		      && (exp_data_seg.relro_end
-			  & (exp_data_seg.pagesize - 1)))
+		  if (expld.dataseg.phase == exp_dataseg_align_seen
+		      || expld.dataseg.phase == exp_dataseg_relro_adjust)
+		    expld.dataseg.relro_end = lhs.value + expld.result.value;
+
+		  if (expld.dataseg.phase == exp_dataseg_relro_adjust
+		      && (expld.dataseg.relro_end
+			  & (expld.dataseg.pagesize - 1)))
 		    {
-		      exp_data_seg.relro_end += exp_data_seg.pagesize - 1;
-		      exp_data_seg.relro_end &= ~(exp_data_seg.pagesize - 1);
-		      result.value = exp_data_seg.relro_end - other.value;
+		      expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
+		      expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
+		      expld.result.value = (expld.dataseg.relro_end
+					    - expld.result.value);
 		    }
-		  if (exp_data_seg.phase == exp_dataseg_align_seen)
-		    exp_data_seg.phase = exp_dataseg_relro_seen;
+		  else
+		    expld.result.value = lhs.value;
+
+		  if (expld.dataseg.phase == exp_dataseg_align_seen)
+		    expld.dataseg.phase = exp_dataseg_relro_seen;
 		}
 	      else
-		result.valid_p = FALSE;
+		expld.result.valid_p = FALSE;
 	      break;
 
 	    default:
@@ -488,57 +455,40 @@ fold_binary (etree_type *tree,
 	    }
 	}
       else
-	{
-	  result.valid_p = FALSE;
-	}
+	expld.result.valid_p = FALSE;
     }
-
-  return result;
 }
 
-static etree_value_type
-fold_trinary (etree_type *tree,
-	      asection *current_section,
-	      lang_phase_type allocation_done,
-	      bfd_vma dot,
-	      bfd_vma *dotp,
-	      bfd_boolean mark_used)
-{
-  etree_value_type result;
-
-  result = exp_fold_tree_1 (tree->trinary.cond, current_section,
-			    allocation_done, dot, dotp, mark_used);
-  if (result.valid_p)
-    result = exp_fold_tree_1 ((result.value
-			       ? tree->trinary.lhs
-			       : tree->trinary.rhs),
-			      current_section,
-			      allocation_done,
-			      dot, dotp, mark_used);
-
-  return result;
-}
-
-static etree_value_type
-fold_name (etree_type *tree,
-	   asection *current_section,
-	   lang_phase_type allocation_done,
-	   bfd_vma dot,
-	   bfd_boolean mark_used)
+static void
+fold_trinary (etree_type *tree)
 {
-  etree_value_type result;
+  exp_fold_tree_1 (tree->trinary.cond);
+  if (expld.result.valid_p)
+    exp_fold_tree_1 (expld.result.value
+		     ? tree->trinary.lhs
+		     : tree->trinary.rhs);
+}
 
-  memset (&result, 0, sizeof (result));
+static void
+fold_name (etree_type *tree)
+{
+  memset (&expld.result, 0, sizeof (expld.result));
 
   switch (tree->type.node_code)
     {
     case SIZEOF_HEADERS:
-      if (allocation_done != lang_first_phase_enum)
-	result = new_abs (bfd_sizeof_headers (output_bfd,
-					      link_info.relocatable));
+      if (expld.phase != lang_first_phase_enum)
+	{
+	  bfd_vma hdr_size = 0;
+	  /* Don't find the real header size if only marking sections;
+	     The bfd function may cache incorrect data.  */
+	  if (expld.phase != lang_mark_phase_enum)
+	    hdr_size = bfd_sizeof_headers (output_bfd, link_info.relocatable);
+	  new_abs (hdr_size);
+	}
       break;
     case DEFINED:
-      if (allocation_done == lang_first_phase_enum)
+      if (expld.phase == lang_first_phase_enum)
 	lang_track_definedness (tree->name.name);
       else
 	{
@@ -549,23 +499,22 @@ fold_name (etree_type *tree,
 	  h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
 					    tree->name.name,
 					    FALSE, FALSE, TRUE);
-	  result.value = (h != NULL
-			  && (h->type == bfd_link_hash_defined
-			      || h->type == bfd_link_hash_defweak
-			      || h->type == bfd_link_hash_common)
-			  && (def_iteration == lang_statement_iteration
-			      || def_iteration == -1));
-	  result.section = bfd_abs_section_ptr;
-	  result.valid_p = TRUE;
+	  expld.result.value = (h != NULL
+				&& (h->type == bfd_link_hash_defined
+				    || h->type == bfd_link_hash_defweak
+				    || h->type == bfd_link_hash_common)
+				&& (def_iteration == lang_statement_iteration
+				    || def_iteration == -1));
+	  expld.result.section = bfd_abs_section_ptr;
+	  expld.result.valid_p = TRUE;
 	}
       break;
     case NAME:
-      if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
-	{
-	  if (allocation_done != lang_first_phase_enum)
-	    result = new_rel_from_section (dot, current_section);
-	}
-      else if (allocation_done != lang_first_phase_enum)
+      if (expld.phase == lang_first_phase_enum)
+	;
+      else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
+	new_rel_from_abs (expld.dot);
+      else
 	{
 	  struct bfd_link_hash_entry *h;
 
@@ -578,30 +527,26 @@ fold_name (etree_type *tree,
 		   || h->type == bfd_link_hash_defweak)
 	    {
 	      if (bfd_is_abs_section (h->u.def.section))
-		result = new_abs (h->u.def.value);
-	      else if (allocation_done == lang_final_phase_enum
-		       || allocation_done == lang_allocating_phase_enum)
+		new_abs (h->u.def.value);
+	      else
 		{
 		  asection *output_section;
 
 		  output_section = h->u.def.section->output_section;
 		  if (output_section == NULL)
-		    einfo (_("%X%S: unresolvable symbol `%s' referenced in expression\n"),
-			   tree->name.name);
-		  else
 		    {
-		      /* FIXME: Is this correct if this section is
-			 being linked with -R?  */
-		      result = new_rel ((h->u.def.value
-					 + h->u.def.section->output_offset),
-					NULL,
-					output_section);
-		      output_section->flags |= SEC_KEEP;
+		      if (expld.phase != lang_mark_phase_enum)
+			einfo (_("%X%S: unresolvable symbol `%s'"
+				 " referenced in expression\n"),
+			       tree->name.name);
 		    }
+		  else
+		    new_rel (h->u.def.value + h->u.def.section->output_offset,
+			     NULL, output_section);
 		}
 	    }
-	  else if (allocation_done == lang_final_phase_enum
-		   || assigning_to_dot)
+	  else if (expld.phase == lang_final_phase_enum
+		   || expld.assigning_to_dot)
 	    einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
 		   tree->name.name);
 	  else if (h->type == bfd_link_hash_new)
@@ -615,56 +560,41 @@ fold_name (etree_type *tree,
       break;
 
     case ADDR:
-      if (allocation_done != lang_first_phase_enum)
+      if (expld.phase != lang_first_phase_enum)
 	{
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os)
-	    {
-	      os->bfd_section->flags |= SEC_KEEP;
-	      if (os->processed > 0)
-		result = new_rel (0, NULL, os->bfd_section);
-	    }
+	  if (os != NULL && os->processed > 0)
+	    new_rel (0, NULL, os->bfd_section);
 	}
       break;
 
     case LOADADDR:
-      if (allocation_done != lang_first_phase_enum)
+      if (expld.phase != lang_first_phase_enum)
 	{
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os)
+	  if (os != NULL && os->processed > 0)
 	    {
-	      os->bfd_section->flags |= SEC_KEEP;
-	      if (os->processed != 0)
-		{
-		  if (os->load_base == NULL)
-		    result = new_rel (0, NULL, os->bfd_section);
-		  else
-		    result = exp_fold_tree_no_dot (os->load_base,
-						   bfd_abs_section_ptr,
-						   allocation_done,
-						   mark_used);
-		}
+	      if (os->load_base == NULL)
+		new_rel (0, NULL, os->bfd_section);
+	      else
+		exp_fold_tree_1 (os->load_base);
 	    }
 	}
       break;
 
     case SIZEOF:
-      if (allocation_done != lang_first_phase_enum)
+      if (expld.phase != lang_first_phase_enum)
 	{
 	  int opb = bfd_octets_per_byte (output_bfd);
 	  lang_output_section_statement_type *os;
 
 	  os = lang_output_section_find (tree->name.name);
-	  if (os)
-	    {
-	      os->bfd_section->flags |= SEC_KEEP;
-	      if (os->processed > 0)
-		result = new_abs (os->bfd_section->size / opb);
-	    }
+	  if (os != NULL && os->processed > 0)
+	    new_abs (os->bfd_section->size / opb);
 	}
       break;
 
@@ -674,10 +604,10 @@ fold_name (etree_type *tree,
         
         mem = lang_memory_region_lookup (tree->name.name, FALSE);  
         if (mem != NULL) 
-          result = new_abs (mem->length);
+          new_abs (mem->length);
         else          
-          einfo (_("%F%S: undefined MEMORY region `%s' referenced in expression\n"),
-		   tree->name.name);
+          einfo (_("%F%S: undefined MEMORY region `%s'"
+		   " referenced in expression\n"), tree->name.name);
       }
       break;
 
@@ -687,10 +617,10 @@ fold_name (etree_type *tree,
         
         mem = lang_memory_region_lookup (tree->name.name, FALSE);  
         if (mem != NULL) 
-          result = new_abs (mem->origin);
+          new_abs (mem->origin);
         else          
-          einfo (_("%F%S: undefined MEMORY region `%s' referenced in expression\n"),
-		   tree->name.name);
+          einfo (_("%F%S: undefined MEMORY region `%s'"
+		   " referenced in expression\n"), tree->name.name);
       }
       break;
 
@@ -698,72 +628,57 @@ fold_name (etree_type *tree,
       FAIL ();
       break;
     }
-
-  return result;
 }
 
-static etree_value_type
-exp_fold_tree_1 (etree_type *tree,
-		 asection *current_section,
-		 lang_phase_type allocation_done,
-		 bfd_vma dot,
-		 bfd_vma *dotp,
-		 bfd_boolean mark_used)
+static void
+exp_fold_tree_1 (etree_type *tree)
 {
-  etree_value_type result;
-
   if (tree == NULL)
     {
-      memset (&result, 0, sizeof (result));
-      return result;
+      memset (&expld.result, 0, sizeof (expld.result));
+      return;
     }
 
   switch (tree->type.node_class)
     {
     case etree_value:
-      result = new_rel (tree->value.value, tree->value.str, current_section);
+      new_rel (tree->value.value, tree->value.str, expld.section);
       break;
 
     case etree_rel:
-      if (allocation_done != lang_final_phase_enum)
-	memset (&result, 0, sizeof (result));
+      if (expld.phase != lang_first_phase_enum)
+	{
+	  asection *output_section = tree->rel.section->output_section;
+	  new_rel (tree->rel.value + tree->rel.section->output_offset,
+		   NULL, output_section);
+	}
       else
-	result = new_rel ((tree->rel.value
-			   + tree->rel.section->output_section->vma
-			   + tree->rel.section->output_offset),
-			  NULL,
-			  current_section);
+	memset (&expld.result, 0, sizeof (expld.result));
       break;
 
     case etree_assert:
-      result = exp_fold_tree_1 (tree->assert_s.child,
-				current_section,
-				allocation_done, dot, dotp,
-				mark_used);
-      if (result.valid_p)
+      exp_fold_tree_1 (tree->assert_s.child);
+      if (expld.result.valid_p)
 	{
-	  if (mark_used)
+	  if (expld.phase == lang_mark_phase_enum)
 	    /* 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)
+	    expld.result.value = 1;
+	  else if (!expld.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, mark_used);
+      fold_unary (tree);
       break;
 
     case etree_binary:
-      result = fold_binary (tree, current_section, allocation_done,
-			    dot, dotp, mark_used);
+      fold_binary (tree);
       break;
 
     case etree_trinary:
-      result = fold_trinary (tree, current_section, allocation_done,
-			     dot, dotp, mark_used);
+      fold_trinary (tree);
       break;
 
     case etree_assign:
@@ -774,138 +689,128 @@ exp_fold_tree_1 (etree_type *tree,
 	  /* Assignment to dot can only be done during allocation.  */
 	  if (tree->type.node_class != etree_assign)
 	    einfo (_("%F%S can not PROVIDE assignment to location counter\n"));
-	  if (allocation_done == lang_allocating_phase_enum
-	      || (allocation_done == lang_final_phase_enum
-		  && current_section == bfd_abs_section_ptr))
+	  if (expld.phase == lang_mark_phase_enum
+	      || expld.phase == lang_allocating_phase_enum
+	      || (expld.phase == lang_final_phase_enum
+		  && expld.section == bfd_abs_section_ptr))
 	    {
 	      /* Notify the folder that this is an assignment to dot.  */
-	      assigning_to_dot = TRUE;
-	      result = exp_fold_tree_1 (tree->assign.src,
-					current_section,
-					allocation_done,
-					dot, dotp, mark_used);
-	      assigning_to_dot = FALSE;
+	      expld.assigning_to_dot = TRUE;
+	      exp_fold_tree_1 (tree->assign.src);
+	      expld.assigning_to_dot = FALSE;
 
-	      if (! result.valid_p)
-		einfo (_("%F%S invalid assignment to location counter\n"));
+	      if (!expld.result.valid_p)
+		{
+		  if (expld.phase != lang_mark_phase_enum)
+		    einfo (_("%F%S invalid assignment to location counter\n"));
+		}
+	      else if (expld.dotp == NULL)
+		einfo (_("%F%S assignment to location counter"
+			 " invalid outside of SECTION\n"));
 	      else
 		{
-		  if (current_section == NULL)
-		    einfo (_("%F%S assignment to location counter invalid outside of SECTION\n"));
+		  bfd_vma nextdot;
+
+		  nextdot = expld.result.value + expld.section->vma;
+		  if (nextdot < expld.dot
+		      && expld.section != bfd_abs_section_ptr)
+		    einfo (_("%F%S cannot move location counter backwards"
+			     " (from %V to %V)\n"), expld.dot, nextdot);
 		  else
 		    {
-		      bfd_vma nextdot;
-
-		      nextdot = result.value + current_section->vma;
-		      if (nextdot < dot
-			  && current_section != bfd_abs_section_ptr)
-			einfo (_("%F%S cannot move location counter backwards (from %V to %V)\n"),
-			       dot, nextdot);
-		      else
-			*dotp = nextdot;
+		      expld.dot = nextdot;
+		      *expld.dotp = nextdot;
 		    }
 		}
 	    }
 	  else
-	    memset (&result, 0, sizeof (result));
+	    memset (&expld.result, 0, sizeof (expld.result));
 	}
       else
 	{
-	  result = exp_fold_tree_1 (tree->assign.src,
-				    current_section, allocation_done,
-				    dot, dotp, mark_used);
-	  if (result.valid_p)
-	    {
-	      bfd_boolean create;
-	      struct bfd_link_hash_entry *h;
+	  struct bfd_link_hash_entry *h = NULL;
 
-	      if (tree->type.node_class == etree_assign)
-		create = TRUE;
-	      else
-		create = FALSE;
+	  if (tree->type.node_class == etree_provide)
+	    {
 	      h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
-					create, FALSE, TRUE);
+					FALSE, FALSE, TRUE);
+	      if (h == NULL
+		  || (h->type != bfd_link_hash_new
+		      && h->type != bfd_link_hash_undefined
+		      && h->type != bfd_link_hash_common))
+		{
+		  /* Do nothing.  The symbol was never referenced, or was
+		     defined by some object.  */
+		  break;
+		}
+	    }
+
+	  exp_fold_tree_1 (tree->assign.src);
+	  if (expld.result.valid_p)
+	    {
 	      if (h == NULL)
 		{
-		  if (create)
+		  h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
+					    TRUE, FALSE, TRUE);
+		  if (h == NULL)
 		    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;
-		  if (tree->type.node_class == etree_provide)
-		    tree->type.node_class = etree_provided;
-		}
+
+	      /* 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 = expld.result.value;
+	      h->u.def.section = expld.result.section;
+	      if (tree->type.node_class == etree_provide)
+		tree->type.node_class = etree_provided;
 	    }
 	}
       break;
 
     case etree_name:
-      result = fold_name (tree, current_section, allocation_done, dot,
-			  mark_used);
+      fold_name (tree);
       break;
 
     default:
       FAIL ();
-      memset (&result, 0, sizeof (result));
+      memset (&expld.result, 0, sizeof (expld.result));
       break;
     }
-
-  return result;
 }
 
-etree_value_type
-exp_fold_tree (etree_type *tree,
-	       asection *current_section,
-	       lang_phase_type allocation_done,
-	       bfd_vma dot,
-	       bfd_vma *dotp)
+void
+exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp)
 {
-  return exp_fold_tree_1 (tree, current_section, allocation_done,
-			  dot, dotp, FALSE);
+  expld.dot = *dotp;
+  expld.dotp = dotp;
+  expld.section = current_section;
+  exp_fold_tree_1 (tree);
 }
 
-static etree_value_type
-exp_fold_tree_no_dot (etree_type *tree,
-		      asection *current_section,
-		      lang_phase_type allocation_done,
-		      bfd_boolean mark_used)
+static void
+exp_fold_tree_no_dot (etree_type *tree)
 {
-  return exp_fold_tree_1 (tree, current_section, allocation_done, 0,
-			  NULL, mark_used);
+  expld.dot = 0;
+  expld.dotp = NULL;
+  expld.section = bfd_abs_section_ptr;
+  exp_fold_tree_1 (tree);
 }
 
 etree_type *
 exp_binop (int code, etree_type *lhs, etree_type *rhs)
 {
   etree_type value, *new;
-  etree_value_type r;
 
   value.type.node_code = code;
   value.binary.lhs = lhs;
   value.binary.rhs = rhs;
   value.type.node_class = etree_binary;
-  r = exp_fold_tree_no_dot (&value,
-			    bfd_abs_section_ptr,
-			    lang_first_phase_enum, FALSE);
-  if (r.valid_p)
-    {
-      return exp_intop (r.value);
-    }
+  exp_fold_tree_no_dot (&value);
+  if (expld.result.valid_p)
+    return exp_intop (expld.result.value);
+
   new = stat_alloc (sizeof (new->binary));
   memcpy (new, &value, sizeof (new->binary));
   return new;
@@ -915,15 +820,15 @@ etree_type *
 exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
 {
   etree_type value, *new;
-  etree_value_type r;
+
   value.type.node_code = code;
   value.trinary.lhs = lhs;
   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, FALSE);
-  if (r.valid_p)
-    return exp_intop (r.value);
+  exp_fold_tree_no_dot (&value);
+  if (expld.result.valid_p)
+    return exp_intop (expld.result.value);
 
   new = stat_alloc (sizeof (new->trinary));
   memcpy (new, &value, sizeof (new->trinary));
@@ -935,14 +840,12 @@ exp_unop (int code, etree_type *child)
 {
   etree_type value, *new;
 
-  etree_value_type r;
   value.unary.type.node_code = code;
   value.unary.child = child;
   value.unary.type.node_class = etree_unary;
-  r = exp_fold_tree_no_dot (&value, bfd_abs_section_ptr,
-			    lang_first_phase_enum, FALSE);
-  if (r.valid_p)
-    return exp_intop (r.value);
+  exp_fold_tree_no_dot (&value);
+  if (expld.result.valid_p)
+    return exp_intop (expld.result.value);
 
   new = stat_alloc (sizeof (new->unary));
   memcpy (new, &value, sizeof (new->unary));
@@ -953,14 +856,14 @@ etree_type *
 exp_nameop (int code, const char *name)
 {
   etree_type value, *new;
-  etree_value_type r;
+
   value.name.type.node_code = code;
   value.name.name = name;
   value.name.type.node_class = etree_name;
 
-  r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum, FALSE);
-  if (r.valid_p)
-    return exp_intop (r.value);
+  exp_fold_tree_no_dot (&value);
+  if (expld.result.valid_p)
+    return exp_intop (expld.result.value);
 
   new = stat_alloc (sizeof (new->name));
   memcpy (new, &value, sizeof (new->name));
@@ -971,16 +874,13 @@ exp_nameop (int code, const char *name)
 etree_type *
 exp_assop (int code, const char *dst, etree_type *src)
 {
-  etree_type value, *new;
-
-  value.assign.type.node_code = code;
-
-  value.assign.src = src;
-  value.assign.dst = dst;
-  value.assign.type.node_class = etree_assign;
+  etree_type *new;
 
   new = stat_alloc (sizeof (new->assign));
-  memcpy (new, &value, sizeof (new->assign));
+  new->type.node_code = code;
+  new->type.node_class = etree_assign;
+  new->assign.src = src;
+  new->assign.dst = dst;
   return new;
 }
 
@@ -1077,9 +977,6 @@ exp_print_tree (etree_type *tree)
       fprintf (config.map_file, ", %s)", tree->assert_s.message);
       break;
 
-    case etree_undef:
-      fprintf (config.map_file, "????????");
-      break;
     case etree_name:
       if (tree->type.node_code == NAME)
 	{
@@ -1099,61 +996,51 @@ exp_print_tree (etree_type *tree)
 }
 
 bfd_vma
-exp_get_vma (etree_type *tree,
-	     bfd_vma def,
-	     char *name,
-	     lang_phase_type allocation_done)
+exp_get_vma (etree_type *tree, bfd_vma def, char *name)
 {
-  etree_value_type r;
-
   if (tree != NULL)
     {
-      r = exp_fold_tree_no_dot (tree, bfd_abs_section_ptr,
-				allocation_done, FALSE);
-      if (! r.valid_p && name != NULL)
+      exp_fold_tree_no_dot (tree);
+      if (expld.result.valid_p)
+	return expld.result.value;
+      else if (name != NULL && expld.phase != lang_mark_phase_enum)
 	einfo (_("%F%S nonconstant expression for %s\n"), name);
-      return r.value;
     }
-  else
-    return def;
+  return def;
 }
 
 int
-exp_get_value_int (etree_type *tree,
-		   int def,
-		   char *name,
-		   lang_phase_type allocation_done)
+exp_get_value_int (etree_type *tree, int def, char *name)
 {
-  return exp_get_vma (tree, def, name, allocation_done);
+  return exp_get_vma (tree, def, name);
 }
 
 fill_type *
-exp_get_fill (etree_type *tree,
-	      fill_type *def,
-	      char *name,
-	      lang_phase_type allocation_done)
+exp_get_fill (etree_type *tree, fill_type *def, char *name)
 {
   fill_type *fill;
-  etree_value_type r;
   size_t len;
   unsigned int val;
 
   if (tree == NULL)
     return def;
 
-  r = exp_fold_tree_no_dot (tree, bfd_abs_section_ptr, allocation_done,
-			    FALSE);
-  if (! r.valid_p && name != NULL)
-    einfo (_("%F%S nonconstant expression for %s\n"), name);
+  exp_fold_tree_no_dot (tree);
+  if (!expld.result.valid_p)
+    {
+      if (name != NULL && expld.phase != lang_mark_phase_enum)
+	einfo (_("%F%S nonconstant expression for %s\n"), name);
+      return def;
+    }
 
-  if (r.str != NULL && (len = strlen (r.str)) != 0)
+  if (expld.result.str != NULL && (len = strlen (expld.result.str)) != 0)
     {
       unsigned char *dst;
       unsigned char *s;
       fill = xmalloc ((len + 1) / 2 + sizeof (*fill) - 1);
       fill->size = (len + 1) / 2;
       dst = fill->data;
-      s = (unsigned char *) r.str;
+      s = (unsigned char *) expld.result.str;
       val = 0;
       do
 	{
@@ -1176,7 +1063,7 @@ exp_get_fill (etree_type *tree,
   else
     {
       fill = xmalloc (4 + sizeof (*fill) - 1);
-      val = r.value;
+      val = expld.result.value;
       fill->data[0] = (val >> 24) & 0xff;
       fill->data[1] = (val >> 16) & 0xff;
       fill->data[2] = (val >>  8) & 0xff;
@@ -1187,21 +1074,21 @@ exp_get_fill (etree_type *tree,
 }
 
 bfd_vma
-exp_get_abs_int (etree_type *tree,
-		 int def ATTRIBUTE_UNUSED,
-		 char *name,
-		 lang_phase_type allocation_done)
-{
-  etree_value_type res;
-  res = exp_fold_tree_no_dot (tree, bfd_abs_section_ptr, allocation_done,
-			      FALSE);
-
-  if (res.valid_p)
-    res.value += res.section->vma;
-  else
-    einfo (_("%F%S non constant expression for %s\n"), name);
+exp_get_abs_int (etree_type *tree, int def, char *name)
+{
+  if (tree != NULL)
+    {
+      exp_fold_tree_no_dot (tree);
 
-  return res.value;
+      if (expld.result.valid_p)
+	{
+	  expld.result.value += expld.result.section->vma;
+	  return expld.result.value;
+	}
+      else if (name != NULL && expld.phase != lang_mark_phase_enum)
+	einfo (_("%F%S non constant expression for %s\n"), name);
+    }
+  return def;
 }
 
 static bfd_vma
@@ -1213,103 +1100,3 @@ align_n (bfd_vma value, bfd_vma align)
   value = (value + align - 1) / align;
   return value * align;
 }
-
-void
-exp_mark_used_section (etree_type *tree, asection *current_section)
-{
-  bfd_vma dot = 0;
-
-  switch (tree->type.node_class)
-    {
-    case etree_value:
-      break;
-
-    case etree_rel:
-      break;
-
-    case etree_assert:
-      break;
-
-    case etree_unary:
-      break;
-
-    case etree_binary:
-      fold_binary (tree, current_section, lang_allocating_phase_enum,
-		   dot, &dot, TRUE);
-      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_boolean create = tree->type.node_class == etree_assign;
-	  struct bfd_link_hash_entry *h;
-
-	  result = exp_fold_tree_1 (tree->assign.src,
-				    current_section,
-				    lang_allocating_phase_enum,
-				    dot, &dot, TRUE);
-
-	  /* We mark the current section SEC_KEEP only if the symbol
-	     will be defined.  */
-	  if (!create)
-	    h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
-				      create, FALSE, TRUE);
-	  else
-	    h = NULL;
-
-	  if ((create || h)
-	      && current_section != bfd_abs_section_ptr)
-	    current_section->flags |= SEC_KEEP;
-
-	  if (result.valid_p)
-	    {
-
-	      if (create)
-		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;
-		  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;
-    }
-}
Index: ld/ldgram.y
===================================================================
RCS file: /cvs/src/src/ld/ldgram.y,v
retrieving revision 1.42
diff -u -p -r1.42 ldgram.y
--- ld/ldgram.y	12 May 2005 07:32:02 -0000	1.42
+++ ld/ldgram.y	8 Jun 2005 23:58:35 -0000
@@ -600,10 +600,7 @@ length:
 fill_exp:
 	mustbe_exp
 		{
-		  $$ = exp_get_fill ($1,
-				     0,
-				     "fill value",
-				     lang_first_phase_enum);
+		  $$ = exp_get_fill ($1, 0, "fill value");
 		}
 	;
 
@@ -681,18 +678,16 @@ memory_spec: 	NAME
 
 origin_spec:
 	ORIGIN '=' mustbe_exp
-		{ region->current =
-		 region->origin =
-		 exp_get_vma($3, 0L,"origin", lang_first_phase_enum);
-}
+		{
+		  region->origin = exp_get_vma ($3, 0, "origin");
+		  region->current = region->origin;
+		}
 	;
 
 length_spec:
              LENGTH '=' mustbe_exp
-               { region->length = exp_get_vma($3,
-					       ~((bfd_vma)0),
-					       "length",
-					       lang_first_phase_enum);
+		{
+		  region->length = exp_get_vma ($3, -1, "length");
 		}
 	;
 
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.188
diff -u -p -r1.188 ldlang.c
--- ld/ldlang.c	4 Jun 2005 14:40:21 -0000	1.188
+++ ld/ldlang.c	8 Jun 2005 23:58:37 -0000
@@ -101,6 +101,9 @@ bfd_boolean delete_output_file_on_failur
 struct lang_nocrossrefs *nocrossref_list;
 static struct unique_sections *unique_section_list;
 static bfd_boolean ldlang_sysrooted_script = FALSE;
+
+ /* Functions that traverse the linker script and might evaluate
+    DEFINED() need to increment this.  */
 int lang_statement_iteration = 0;
 
 etree_type *base; /* Relocation base - or null */
@@ -895,9 +898,6 @@ lang_init (void)
   if (!bfd_hash_table_init_n (&lang_definedness_table,
 			      lang_definedness_newfunc, 3))
     einfo (_("%P%F: out of memory during initialization"));
-
-  /* Callers of exp_fold_tree need to increment this.  */
-  lang_statement_iteration = 0;
 }
 
 /*----------------------------------------------------------------------
@@ -3044,95 +3044,6 @@ 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);
-		if (os->load_base)
-		  exp_mark_used_section (os->load_base,
-					 bfd_abs_section_ptr);
-	      }
-	  }
-	  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,
-				 bfd_abs_section_ptr);
-	  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->bfd_section);
-	  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.  */
@@ -3141,8 +3052,25 @@ void
 strip_excluded_output_sections (void)
 {
   lang_output_section_statement_type *os;
+  unsigned int gc_sections;
 
-  lang_mark_used_section ();
+  /* Run lang_size_sections (if not already done) to ensure that all
+     symbols defined in the linker script are put in the bfd hash
+     table.  */
+  if (expld.phase != lang_mark_phase_enum)
+    {
+      expld.phase = lang_mark_phase_enum;
+      expld.dataseg.phase = exp_dataseg_none;
+      one_lang_size_sections_pass (NULL, FALSE);
+      lang_reset_memory_regions ();
+    }
+
+  /* Now call into bfd_gc_sections to mark all sections defining global
+     symbols with SEC_KEEP.  */
+  gc_sections = link_info.gc_sections;
+  link_info.gc_sections = 0;
+  bfd_gc_sections (output_bfd, &link_info);
+  link_info.gc_sections = gc_sections;
 
   for (os = &lang_output_section_statement.head->output_section_statement;
        os != NULL;
@@ -3158,7 +3086,7 @@ strip_excluded_output_sections (void)
       if (output_section == NULL)
 	continue;
 
-      exclude = FALSE;
+      exclude = TRUE;
       if (output_section->map_head.s != NULL)
 	{
 	  asection *s;
@@ -3166,26 +3094,25 @@ strip_excluded_output_sections (void)
 	  for (s = output_section->map_head.s; s != NULL;
 	       s = s->map_head.s)
 	    if ((s->flags & SEC_EXCLUDE) == 0)
-	      break;
+	      {
+		exclude = FALSE;
+		break;
+	      }
 
 	  output_section->map_head.link_order = NULL;
 	  output_section->map_tail.link_order = NULL;
-
-	  if (s == NULL)
-	    exclude = TRUE;
 	}
 
       if (exclude
-	  || (output_section->linker_has_input == 0
-	      && ((output_section->flags
-		   & (SEC_KEEP | SEC_HAS_CONTENTS)) == 0)))
-	{
-	  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;
+	  && (output_section->flags & SEC_KEEP) == 0
+	  && output_section->rawsize == 0
+	  && !bfd_is_abs_section (output_section))
+	{
+	  /* We don't set bfd_section to NULL since bfd_section of the
+	     removed output section statement may still be used.  */
+	  os->ignored = TRUE;
+	  output_section->flags |= SEC_EXCLUDE;
+
 	  if (!bfd_section_removed_from_list (output_bfd,
 					      output_section))
 	    {
@@ -3234,7 +3161,7 @@ print_output_section_statement
 	      bfd_vma addr;
 
 	      addr = exp_get_abs_int (output_section_statement->load_base, 0,
-				      "load base", lang_final_phase_enum);
+				      "load base");
 	      minfo (_(" load address 0x%V"), addr);
 	    }
 	}
@@ -3304,7 +3231,6 @@ print_assignment (lang_assignment_statem
   bfd_boolean is_dot;
   bfd_boolean computation_is_valid = TRUE;
   etree_type *tree;
-  etree_value_type result;
 
   for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
     print_space ();
@@ -3324,18 +3250,17 @@ print_assignment (lang_assignment_statem
       computation_is_valid = is_dot || (scan_for_self_assignment (dst, tree) == FALSE);
     }
 
-  result = exp_fold_tree (tree, output_section->bfd_section,
-			  lang_final_phase_enum, print_dot, &print_dot);
-  if (result.valid_p)
+  exp_fold_tree (tree, output_section->bfd_section, &print_dot);
+  if (expld.result.valid_p)
     {
       bfd_vma value;
 
       if (computation_is_valid)
 	{
-	  value = result.value;
+	  value = expld.result.value;
 
-	  if (result.section)
-	    value += result.section->vma;
+	  if (expld.result.section)
+	    value += expld.result.section->vma;
 
 	  minfo ("0x%V", value);
 	  if (is_dot)
@@ -3351,8 +3276,8 @@ print_assignment (lang_assignment_statem
 	    {
 	      value = h->u.def.value;
 
-	      if (result.section)
-	      value += result.section->vma;
+	      if (expld.result.section)
+	      value += expld.result.section->vma;
 
 	      minfo ("[0x%V]", value);
 	    }
@@ -3821,16 +3746,22 @@ insert_pad (lang_statement_union_type **
 	    bfd_vma dot)
 {
   static fill_type zero_fill = { 1, { 0 } };
-  lang_statement_union_type *pad;
+  lang_statement_union_type *pad = NULL;
 
-  pad = ((lang_statement_union_type *)
-	 ((char *) ptr - offsetof (lang_statement_union_type, header.next)));
-  if (ptr != &statement_list.head
+  if (ptr != &statement_list.head)
+    pad = ((lang_statement_union_type *)
+	   ((char *) ptr - offsetof (lang_statement_union_type, header.next)));
+  if (pad != NULL
       && pad->header.type == lang_padding_statement_enum
       && pad->padding_statement.output_section == output_section)
     {
-      /* Use the existing pad statement.  The above test on output
-	 section is probably redundant, but it doesn't hurt to check.  */
+      /* Use the existing pad statement.  */
+    }
+  else if ((pad = *ptr) != NULL
+      && pad->header.type == lang_padding_statement_enum
+      && pad->padding_statement.output_section == output_section)
+    {
+      /* Use the existing pad statement.  */
     }
   else
     {
@@ -4045,11 +3976,11 @@ lang_size_sections_1
 	{
 	case lang_output_section_statement_enum:
 	  {
-	    bfd_vma after;
+	    bfd_vma newdot, after;
 	    lang_output_section_statement_type *os;
 
 	    os = &s->output_section_statement;
-	    if (os->bfd_section == NULL || os->ignored)
+	    if (os->bfd_section == NULL)
 	      /* This section was removed or never actually created.  */
 	      break;
 
@@ -4109,7 +4040,8 @@ lang_size_sections_1
 			&& lang_memory_region_list != NULL
 			&& (strcmp (lang_memory_region_list->name,
 				    DEFAULT_MEMORY_REGION) != 0
-			    || lang_memory_region_list->next != NULL))
+			    || lang_memory_region_list->next != NULL)
+			&& expld.phase != lang_mark_phase_enum)
 		      {
 			/* By default this is an error rather than just a
 			   warning because if we allocate the section to the
@@ -4132,80 +4064,80 @@ lang_size_sections_1
 						       os->bfd_section));
 		      }
 
-		    dot = os->region->current;
+		    newdot = os->region->current;
 
 		    if (os->section_alignment == -1)
 		      {
-			bfd_vma olddot;
-
-			olddot = dot;
-			dot = align_power (dot,
-					   os->bfd_section->alignment_power);
-
-			if (dot != olddot && config.warn_section_align)
+			bfd_vma savedot = newdot;
+			newdot = align_power (newdot,
+					      os->bfd_section->alignment_power);
+
+			if (newdot != savedot
+			    && config.warn_section_align
+			    && expld.phase != lang_mark_phase_enum)
 			  einfo (_("%P: warning: changing start of section"
-				   " %s by %u bytes\n"),
-				 os->name, (unsigned int) (dot - olddot));
+				   " %s by %lu bytes\n"),
+				 os->name, (unsigned long) (newdot - savedot));
 		      }
 		  }
 		else
 		  {
-		    etree_value_type r;
-
+		    newdot = dot;
 		    os->processed = -1;
-		    r = exp_fold_tree (os->addr_tree,
-				       bfd_abs_section_ptr,
-				       lang_allocating_phase_enum,
-				       dot, &dot);
+		    exp_fold_tree (os->addr_tree, bfd_abs_section_ptr,
+				   &newdot);
 		    os->processed = 0;
 
-		    if (!r.valid_p)
+		    if (!expld.result.valid_p
+			&& expld.phase != lang_mark_phase_enum)
 		      einfo (_("%F%S: non constant or forward reference"
 			       " address expression for section %s\n"),
 			     os->name);
 
-		    dot = r.value + r.section->vma;
+		    newdot = expld.result.value + expld.result.section->vma;
 		  }
 
 		/* The section starts here.
 		   First, align to what the section needs.  */
 
 		if (os->section_alignment != -1)
-		  dot = align_power (dot, os->section_alignment);
+		  newdot = align_power (newdot, os->section_alignment);
 
-		bfd_set_section_vma (0, os->bfd_section, dot);
+		bfd_set_section_vma (0, os->bfd_section, newdot);
 
 		os->bfd_section->output_offset = 0;
 	      }
 
 	    lang_size_sections_1 (os->children.head, os, &os->children.head,
-				  os->fill, dot, relax, check_regions);
+				  os->fill, newdot, relax, check_regions);
+
+	    os->processed = 1;
+
+	    if (bfd_is_abs_section (os->bfd_section) || os->ignored)
+	      {
+		ASSERT (os->bfd_section->size == 0);
+		break;
+	      }
+
+	    dot = os->bfd_section->vma;
 
 	    /* Put the section within the requested block size, or
 	       align at the block boundary.  */
-	    after = ((os->bfd_section->vma
+	    after = ((dot
 		      + TO_ADDR (os->bfd_section->size)
 		      + os->block_value - 1)
 		     & - (bfd_vma) os->block_value);
 
-	    if (bfd_is_abs_section (os->bfd_section))
-	      ASSERT (after == os->bfd_section->vma);
-	    else
-	      os->bfd_section->size
-		= TO_SIZE (after - os->bfd_section->vma);
+	    os->bfd_section->size = TO_SIZE (after - os->bfd_section->vma);
 
-	    dot = os->bfd_section->vma;
 	    /* .tbss sections effectively have zero size.  */
 	    if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
 		|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
 		|| link_info.relocatable)
 	      dot += TO_ADDR (os->bfd_section->size);
 
-	    os->processed = 1;
-
 	    if (os->update_dot_tree != 0)
-	      exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr,
-			     lang_allocating_phase_enum, dot, &dot);
+	      exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
 
 	    /* Update dot in the region ?
 	       We only do this if the section is going to be allocated,
@@ -4263,8 +4195,7 @@ lang_size_sections_1
 
 	    /* We might refer to provided symbols in the expression, and
 	       need to mark them as needed.  */
-	    exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr,
-			   lang_allocating_phase_enum, dot, &dot);
+	    exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
 
 	    switch (s->data_statement.type)
 	      {
@@ -4306,21 +4237,21 @@ lang_size_sections_1
 	  break;
 
 	case lang_wild_statement_enum:
-
 	  dot = lang_size_sections_1 (s->wild_statement.children.head,
 				      output_section_statement,
 				      &s->wild_statement.children.head,
 				      fill, dot, relax, check_regions);
-
 	  break;
 
 	case lang_object_symbols_statement_enum:
 	  link_info.create_object_symbols_section =
 	    output_section_statement->bfd_section;
 	  break;
+
 	case lang_output_statement_enum:
 	case lang_target_statement_enum:
 	  break;
+
 	case lang_input_section_enum:
 	  {
 	    asection *i;
@@ -4339,25 +4270,26 @@ lang_size_sections_1
 				      output_section_statement->fill, dot);
 	  }
 	  break;
+
 	case lang_input_statement_enum:
 	  break;
+
 	case lang_fill_statement_enum:
 	  s->fill_statement.output_section =
 	    output_section_statement->bfd_section;
 
 	  fill = s->fill_statement.fill;
 	  break;
+
 	case lang_assignment_statement_enum:
 	  {
 	    bfd_vma newdot = dot;
 
 	    exp_fold_tree (s->assignment_statement.exp,
 			   output_section_statement->bfd_section,
-			   lang_allocating_phase_enum,
-			   dot,
 			   &newdot);
 
-	    if (newdot != dot)
+	    if (newdot != dot && !output_section_statement->ignored)
 	      {
 		if (output_section_statement == abs_output_section)
 		  {
@@ -4376,15 +4308,15 @@ lang_size_sections_1
 
 		    /* Don't neuter the pad below when relaxing.  */
 		    s = s->header.next;
-		  }
-
-		/* If dot is advanced, this implies that the section should
-		   have space allocated to it, unless the user has explicitly
-		   stated that the section should never be loaded.  */
-		if (!(output_section_statement->flags
-		      & (SEC_NEVER_LOAD | SEC_ALLOC)))
-		  output_section_statement->bfd_section->flags |= SEC_ALLOC;
 
+		    /* If dot is advanced, this implies that the section
+		       should have space allocated to it, unless the
+		       user has explicitly stated that the section
+		       should never be loaded.  */
+		    if (!(output_section_statement->flags
+			  & (SEC_NEVER_LOAD | SEC_ALLOC)))
+		      output_section_statement->bfd_section->flags |= SEC_ALLOC;
+		  }
 		dot = newdot;
 	      }
 	  }
@@ -4427,47 +4359,43 @@ lang_size_sections_1
   return dot;
 }
 
-bfd_vma
-lang_size_sections
-  (lang_statement_union_type *s,
-   lang_output_section_statement_type *output_section_statement,
-   lang_statement_union_type **prev,
-   fill_type *fill,
-   bfd_vma dot,
-   bfd_boolean *relax,
-   bfd_boolean check_regions)
+void
+one_lang_size_sections_pass (bfd_boolean *relax, bfd_boolean check_regions)
 {
-  bfd_vma result;
-
-  /* Callers of exp_fold_tree need to increment this.  */
   lang_statement_iteration++;
+  lang_size_sections_1 (statement_list.head, abs_output_section,
+			&statement_list.head, 0, 0, relax, check_regions);
+}
+
+void
+lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
+{
+  expld.phase = lang_allocating_phase_enum;
+  expld.dataseg.phase = exp_dataseg_none;
 
-  exp_data_seg.phase = exp_dataseg_none;
-  result = lang_size_sections_1 (s, output_section_statement, prev, fill,
-				 dot, relax, check_regions);
-  if (exp_data_seg.phase == exp_dataseg_end_seen
-      && link_info.relro && exp_data_seg.relro_end)
+  one_lang_size_sections_pass (relax, check_regions);
+  if (expld.dataseg.phase == exp_dataseg_end_seen
+      && link_info.relro && expld.dataseg.relro_end)
     {
       /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
-	 to put exp_data_seg.relro on a (common) page boundary.  */
+	 to put expld.dataseg.relro on a (common) page boundary.  */
       bfd_vma old_min_base, relro_end, maxpage;
 
-      exp_data_seg.phase = exp_dataseg_relro_adjust;
-      old_min_base = exp_data_seg.min_base;
-      maxpage = exp_data_seg.maxpagesize;
-      exp_data_seg.base += (-exp_data_seg.relro_end
-			    & (exp_data_seg.pagesize - 1));
+      expld.dataseg.phase = exp_dataseg_relro_adjust;
+      old_min_base = expld.dataseg.min_base;
+      maxpage = expld.dataseg.maxpagesize;
+      expld.dataseg.base += (-expld.dataseg.relro_end
+			     & (expld.dataseg.pagesize - 1));
       /* Compute the expected PT_GNU_RELRO segment end.  */
-      relro_end = (exp_data_seg.relro_end + exp_data_seg.pagesize - 1)
-		  & ~(exp_data_seg.pagesize - 1);
-      if (old_min_base + maxpage < exp_data_seg.base)
+      relro_end = (expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
+		  & ~(expld.dataseg.pagesize - 1);
+      if (old_min_base + maxpage < expld.dataseg.base)
 	{
-	  exp_data_seg.base -= maxpage;
+	  expld.dataseg.base -= maxpage;
 	  relro_end -= maxpage;
 	}
-      result = lang_size_sections_1 (s, output_section_statement, prev, fill,
-				     dot, relax, check_regions);
-      if (exp_data_seg.relro_end > relro_end)
+      one_lang_size_sections_pass (relax, check_regions);
+      if (expld.dataseg.relro_end > relro_end)
 	{
 	  /* The alignment of sections between DATA_SEGMENT_ALIGN
 	     and DATA_SEGMENT_RELRO_END caused huge padding to be
@@ -4478,46 +4406,42 @@ lang_size_sections
 	  /* Find maximum alignment power of sections between
 	     DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END.  */
 	  for (sec = output_bfd->sections; sec; sec = sec->next)
-	    if (sec->vma >= exp_data_seg.base
-		&& sec->vma < exp_data_seg.relro_end
+	    if (sec->vma >= expld.dataseg.base
+		&& sec->vma < expld.dataseg.relro_end
 		&& sec->alignment_power > max_alignment_power)
 	      max_alignment_power = sec->alignment_power;
 
-	  if (((bfd_vma) 1 << max_alignment_power) < exp_data_seg.pagesize)
+	  if (((bfd_vma) 1 << max_alignment_power) < expld.dataseg.pagesize)
 	    {
-	      if (exp_data_seg.base - (1 << max_alignment_power)
+	      if (expld.dataseg.base - (1 << max_alignment_power)
 		  < old_min_base)
-		exp_data_seg.base += exp_data_seg.pagesize;
-	      exp_data_seg.base -= (1 << max_alignment_power);
-	      result = lang_size_sections_1 (s, output_section_statement,
-					     prev, fill, dot, relax,
-					     check_regions);
+		expld.dataseg.base += expld.dataseg.pagesize;
+	      expld.dataseg.base -= (1 << max_alignment_power);
+	      one_lang_size_sections_pass (relax, check_regions);
 	    }
 	}
-      link_info.relro_start = exp_data_seg.base;
-      link_info.relro_end = exp_data_seg.relro_end;
+      link_info.relro_start = expld.dataseg.base;
+      link_info.relro_end = expld.dataseg.relro_end;
     }
-  else if (exp_data_seg.phase == exp_dataseg_end_seen)
+  else if (expld.dataseg.phase == exp_dataseg_end_seen)
     {
       /* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
 	 a page could be saved in the data segment.  */
       bfd_vma first, last;
 
-      first = -exp_data_seg.base & (exp_data_seg.pagesize - 1);
-      last = exp_data_seg.end & (exp_data_seg.pagesize - 1);
+      first = -expld.dataseg.base & (expld.dataseg.pagesize - 1);
+      last = expld.dataseg.end & (expld.dataseg.pagesize - 1);
       if (first && last
-	  && ((exp_data_seg.base & ~(exp_data_seg.pagesize - 1))
-	      != (exp_data_seg.end & ~(exp_data_seg.pagesize - 1)))
-	  && first + last <= exp_data_seg.pagesize)
-	{
-	  exp_data_seg.phase = exp_dataseg_adjust;
-	  lang_statement_iteration++;
-	  result = lang_size_sections_1 (s, output_section_statement, prev,
-					 fill, dot, relax, check_regions);
+	  && ((expld.dataseg.base & ~(expld.dataseg.pagesize - 1))
+	      != (expld.dataseg.end & ~(expld.dataseg.pagesize - 1)))
+	  && first + last <= expld.dataseg.pagesize)
+	{
+	  expld.dataseg.phase = exp_dataseg_adjust;
+	  one_lang_size_sections_pass (relax, check_regions);
 	}
     }
 
-  return result;
+  expld.phase = lang_final_phase_enum;
 }
 
 /* Worker function for lang_do_assignments.  Recursiveness goes here.  */
@@ -4562,36 +4486,31 @@ lang_do_assignments_1
 		if (os->bfd_section && !os->ignored)
 		  {
 		    os->bfd_section->lma
-		      = exp_get_abs_int (os->load_base, 0, "load base",
-					 lang_final_phase_enum);
+		      = exp_get_abs_int (os->load_base, 0, "load base");
 		  }
 	      }
 	  }
 	  break;
+
 	case lang_wild_statement_enum:
 
 	  dot = lang_do_assignments_1 (s->wild_statement.children.head,
 				       output_section_statement,
 				       fill, dot);
-
 	  break;
 
 	case lang_object_symbols_statement_enum:
 	case lang_output_statement_enum:
 	case lang_target_statement_enum:
 	  break;
-	case lang_data_statement_enum:
-	  {
-	    etree_value_type value;
 
-	    value = exp_fold_tree (s->data_statement.exp,
-				   bfd_abs_section_ptr,
-				   lang_final_phase_enum, dot, &dot);
-	    if (!value.valid_p)
-	      einfo (_("%F%P: invalid data statement\n"));
-	    s->data_statement.value
-	      = value.value + value.section->vma;
-	  }
+	case lang_data_statement_enum:
+	  exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
+	  if (expld.result.valid_p)
+	    s->data_statement.value = (expld.result.value
+				       + expld.result.section->vma);
+	  else
+	    einfo (_("%F%P: invalid data statement\n"));
 	  {
 	    unsigned int size;
 	    switch (s->data_statement.type)
@@ -4619,16 +4538,12 @@ lang_do_assignments_1
 	  break;
 
 	case lang_reloc_statement_enum:
-	  {
-	    etree_value_type value;
-
-	    value = exp_fold_tree (s->reloc_statement.addend_exp,
-				   bfd_abs_section_ptr,
-				   lang_final_phase_enum, dot, &dot);
-	    s->reloc_statement.addend_value = value.value;
-	    if (!value.valid_p)
-	      einfo (_("%F%P: invalid reloc statement\n"));
-	  }
+	  exp_fold_tree (s->reloc_statement.addend_exp,
+			 bfd_abs_section_ptr, &dot);
+	  if (expld.result.valid_p)
+	    s->reloc_statement.addend_value = expld.result.value;
+	  else
+	    einfo (_("%F%P: invalid reloc statement\n"));
 	  dot += TO_ADDR (bfd_get_reloc_size (s->reloc_statement.howto));
 	  break;
 
@@ -4643,19 +4558,17 @@ lang_do_assignments_1
 
 	case lang_input_statement_enum:
 	  break;
+
 	case lang_fill_statement_enum:
 	  fill = s->fill_statement.fill;
 	  break;
-	case lang_assignment_statement_enum:
-	  {
-	    exp_fold_tree (s->assignment_statement.exp,
-			   output_section_statement->bfd_section,
-			   lang_final_phase_enum,
-			   dot,
-			   &dot);
-	  }
 
+	case lang_assignment_statement_enum:
+	  exp_fold_tree (s->assignment_statement.exp,
+			 output_section_statement->bfd_section,
+			 &dot);
 	  break;
+
 	case lang_padding_statement_enum:
 	  dot += TO_ADDR (s->padding_statement.size);
 	  break;
@@ -4664,30 +4577,24 @@ lang_do_assignments_1
 	  dot = lang_do_assignments_1 (s->group_statement.children.head,
 				       output_section_statement,
 				       fill, dot);
-
 	  break;
 
 	default:
 	  FAIL ();
 	  break;
+
 	case lang_address_statement_enum:
 	  break;
 	}
-
     }
   return dot;
 }
 
 void
-lang_do_assignments
-  (lang_statement_union_type *s,
-   lang_output_section_statement_type *output_section_statement,
-   fill_type *fill,
-   bfd_vma dot)
+lang_do_assignments (void)
 {
-  /* Callers of exp_fold_tree need to increment this.  */
   lang_statement_iteration++;
-  lang_do_assignments_1 (s, output_section_statement, fill, dot);
+  lang_do_assignments_1 (statement_list.head, abs_output_section, NULL, 0);
 }
 
 /* Fix any .startof. or .sizeof. symbols.  When the assemblers see the
@@ -5227,9 +5134,9 @@ lang_enter_output_section_statement (con
   stat_ptr = &os->children;
 
   os->subsection_alignment =
-    topower (exp_get_value_int (subalign, -1, "subsection alignment", 0));
+    topower (exp_get_value_int (subalign, -1, "subsection alignment"));
   os->section_alignment =
-    topower (exp_get_value_int (align, -1, "section alignment", 0));
+    topower (exp_get_value_int (align, -1, "section alignment"));
 
   os->load_base = ebase;
   return os;
@@ -5251,6 +5158,7 @@ lang_reset_memory_regions (void)
 {
   lang_memory_region_type *p = lang_memory_region_list;
   asection *o;
+  lang_output_section_statement_type *os;
 
   for (p = lang_memory_region_list; p != NULL; p = p->next)
     {
@@ -5258,6 +5166,11 @@ lang_reset_memory_regions (void)
       p->current = p->origin;
     }
 
+  for (os = &lang_output_section_statement.head->output_section_statement;
+       os != NULL;
+       os = os->next)
+    os->processed = 0;
+
   for (o = output_bfd->sections; o != NULL; o = o->next)
     {
       /* Save the last size for possible use by bfd_relax_section.  */
@@ -5444,9 +5357,7 @@ lang_process (void)
   lang_record_phdrs ();
 
   /* Size up the sections.  */
-  lang_size_sections (statement_list.head, abs_output_section,
-		      &statement_list.head, 0, 0, NULL,
-		      command_line.relax ? FALSE : TRUE);
+  lang_size_sections (NULL, !command_line.relax);
 
   /* Now run around and relax if we can.  */
   if (command_line.relax)
@@ -5464,8 +5375,7 @@ lang_process (void)
 
 	  /* Do all the assignments with our current guesses as to
 	     section sizes.  */
-	  lang_do_assignments (statement_list.head, abs_output_section,
-			       NULL, 0);
+	  lang_do_assignments ();
 
 	  /* We must do this after lang_do_assignments, because it uses
 	     size.  */
@@ -5473,8 +5383,7 @@ lang_process (void)
 
 	  /* Perform another relax pass - this time we know where the
 	     globals are, so can make a better guess.  */
-	  lang_size_sections (statement_list.head, abs_output_section,
-			      &statement_list.head, 0, 0, &relax_again, FALSE);
+	  lang_size_sections (&relax_again, FALSE);
 
 	  /* If the normal relax is done and the relax finalize pass
 	     is not performed yet, we perform another relax pass.  */
@@ -5487,10 +5396,9 @@ lang_process (void)
       while (relax_again);
 
       /* Final extra sizing to report errors.  */
-      lang_do_assignments (statement_list.head, abs_output_section, NULL, 0);
+      lang_do_assignments ();
       lang_reset_memory_regions ();
-      lang_size_sections (statement_list.head, abs_output_section,
-			  &statement_list.head, 0, 0, NULL, TRUE);
+      lang_size_sections (NULL, TRUE);
     }
 
   /* See if anything special should be done now we know how big
@@ -5503,7 +5411,7 @@ lang_process (void)
   /* Do all the assignments, now that we know the final resting places
      of all the symbols.  */
 
-  lang_do_assignments (statement_list.head, abs_output_section, NULL, 0);
+  lang_do_assignments ();
 
   /* Make sure that the section addresses make sense.  */
   if (! link_info.relocatable
@@ -5891,8 +5799,7 @@ lang_new_phdr (const char *name,
   n = stat_alloc (sizeof (struct lang_phdr));
   n->next = NULL;
   n->name = name;
-  n->type = exp_get_value_int (type, 0, "program header type",
-			       lang_final_phase_enum);
+  n->type = exp_get_value_int (type, 0, "program header type");
   n->filehdr = filehdr;
   n->phdrs = phdrs;
   n->at = at;
@@ -5968,14 +5875,12 @@ lang_record_phdrs (void)
       if (l->flags == NULL)
 	flags = 0;
       else
-	flags = exp_get_vma (l->flags, 0, "phdr flags",
-			     lang_final_phase_enum);
+	flags = exp_get_vma (l->flags, 0, "phdr flags");
 
       if (l->at == NULL)
 	at = 0;
       else
-	at = exp_get_vma (l->at, 0, "phdr load address",
-			  lang_final_phase_enum);
+	at = exp_get_vma (l->at, 0, "phdr load address");
 
       if (! bfd_record_phdr (output_bfd, l->type,
 			     l->flags != NULL, flags, l->at != NULL,
Index: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.50
diff -u -p -r1.50 ldlang.h
--- ld/ldlang.h	1 Jun 2005 04:04:18 -0000	1.50
+++ ld/ldlang.h	8 Jun 2005 23:58:37 -0000
@@ -509,8 +509,7 @@ extern void lang_for_each_file
 extern void lang_reset_memory_regions
   (void);
 extern void lang_do_assignments
-  (lang_statement_union_type *, lang_output_section_statement_type *,
-   fill_type *, bfd_vma);
+  (void);
 
 #define LANG_FOR_EACH_INPUT_STATEMENT(statement)			\
   lang_input_statement_type *statement;					\
@@ -556,10 +555,10 @@ extern void strip_excluded_output_sectio
   (void);
 extern void dprint_statement
   (lang_statement_union_type *, int);
-extern bfd_vma lang_size_sections
-  (lang_statement_union_type *, lang_output_section_statement_type *,
-   lang_statement_union_type **, fill_type *, bfd_vma, bfd_boolean *,
-   bfd_boolean);
+extern void lang_size_sections
+  (bfd_boolean *, bfd_boolean);
+extern void one_lang_size_sections_pass
+  (bfd_boolean *, bfd_boolean);
 extern void lang_enter_group
   (void);
 extern void lang_leave_group
Index: ld/pe-dll.c
===================================================================
RCS file: /cvs/src/src/ld/pe-dll.c,v
retrieving revision 1.78
diff -u -p -r1.78 pe-dll.c
--- ld/pe-dll.c	12 May 2005 07:32:03 -0000	1.78
+++ ld/pe-dll.c	8 Jun 2005 23:58:38 -0000
@@ -2636,14 +2636,13 @@ pe_dll_fill_sections (bfd *abfd, struct 
       bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
 
       /* Resize the sections.  */
-      lang_size_sections (stat_ptr->head, abs_output_section,
-			  &stat_ptr->head, 0, 0, NULL, TRUE);
+      lang_size_sections (NULL, TRUE);
 
       /* Redo special stuff.  */
       ldemul_after_allocation ();
 
       /* Do the assignments again.  */
-      lang_do_assignments (stat_ptr->head, abs_output_section, NULL, 0);
+      lang_do_assignments ();
     }
 
   fill_edata (abfd, info);
@@ -2667,14 +2666,13 @@ pe_exe_fill_sections (bfd *abfd, struct 
       bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
 
       /* Resize the sections.  */
-      lang_size_sections (stat_ptr->head, abs_output_section,
-			  &stat_ptr->head, 0, 0, NULL, TRUE);
+      lang_size_sections (NULL, TRUE);
 
       /* Redo special stuff.  */
       ldemul_after_allocation ();
 
       /* Do the assignments again.  */
-      lang_do_assignments (stat_ptr->head, abs_output_section, NULL, 0);
+      lang_do_assignments ();
     }
   reloc_s->contents = reloc_d;
 }
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.147
diff -u -p -r1.147 elf32.em
--- ld/emultempl/elf32.em	12 May 2005 07:32:03 -0000	1.147
+++ ld/emultempl/elf32.em	8 Jun 2005 23:58:40 -0000
@@ -1497,15 +1497,13 @@ gld${EMULATION_NAME}_layout_sections_aga
   lang_reset_memory_regions ();
 
   /* Resize the sections.  */
-  lang_size_sections (stat_ptr->head, abs_output_section,
-		      &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
+  lang_size_sections (NULL, TRUE);
 
   /* Redo special stuff.  */
   ldemul_after_allocation ();
 
   /* Do the assignments again.  */
-  lang_do_assignments (stat_ptr->head, abs_output_section,
-		       (fill_type *) 0, (bfd_vma) 0);
+  lang_do_assignments ();
 }
 
 static void
Index: ld/emultempl/ppc64elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc64elf.em,v
retrieving revision 1.44
diff -u -p -r1.44 ppc64elf.em
--- ld/emultempl/ppc64elf.em	6 Jun 2005 12:59:59 -0000	1.44
+++ ld/emultempl/ppc64elf.em	8 Jun 2005 23:58:40 -0000
@@ -110,14 +110,14 @@ ppc_before_allocation (void)
 	{
 	  /* Size the sections.  This is premature, but we want to know the
 	     TLS segment layout so that certain optimizations can be done.  */
-	  lang_size_sections (stat_ptr->head, abs_output_section,
-			      &stat_ptr->head, 0, 0, NULL, TRUE);
+	  expld.phase = lang_mark_phase_enum;
+	  expld.dataseg.phase = exp_dataseg_none;
+	  one_lang_size_sections_pass (NULL, TRUE);
 
 	  if (!ppc64_elf_tls_optimize (output_bfd, &link_info))
 	    einfo ("%X%P: TLS problem %E\n");
 
 	  /* We must not cache anything from the preliminary sizing.  */
-	  elf_tdata (output_bfd)->program_header_size = 0;
 	  lang_reset_memory_regions ();
 	}
 
Index: ld/testsuite/ld-scripts/empty-aligned.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-scripts/empty-aligned.d,v
retrieving revision 1.1
diff -u -p -r1.1 empty-aligned.d
--- ld/testsuite/ld-scripts/empty-aligned.d	17 May 2005 16:42:53 -0000	1.1
+++ ld/testsuite/ld-scripts/empty-aligned.d	8 Jun 2005 23:58:41 -0000
@@ -6,7 +6,9 @@
 Program Headers:
  +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg +Align
  +LOAD +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ [RWE ]+ +0x[0-9a-f]+
+ +LOAD +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ [RWE ]+ +0x[0-9a-f]+
 
  Section to Segment mapping:
  +Segment Sections\.\.\.
- +00.*\.text.*\.data.*
+ +00.*\.text.*\.text2.*
+ +01.*.data.*

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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