diff --git a/ld/ld.texi b/ld/ld.texi
index aa8b1aa86eb..4f925f9d034 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -7110,10 +7110,13 @@ The builtin function @code{NEXT} is closely related to @code{ALIGN}.
 @kindex ALIGNOF(@var{section})
 @cindex section alignment
 Return the alignment in bytes of the named @var{section}, if that section has
-been allocated.  If the section has not been allocated when this is
-evaluated, the linker will report an error. In the following example,
-the alignment of the @code{.output} section is stored as the first
-value in that section.
+been allocated, or zero if the section has not been allocated.  If the
+section does not exist in the linker script the linker will report an
+error.  If @var{section} is @code{NEXT_SECTION} then @code{ALIGNOF} will
+return the alignment of the next allocated section specified in the
+linker script, or zero if there is no such section.  In the following
+example, the alignment of the @code{.output} section is stored as the
+first value in that section.
 @smallexample
 @group
 SECTIONS@{ @dots{}
@@ -7262,9 +7265,13 @@ name.
 @kindex SIZEOF(@var{section})
 @cindex section size
 Return the size in bytes of the named @var{section}, if that section has
-been allocated.  If the section has not been allocated when this is
-evaluated, the linker will report an error.  In the following example,
-@code{symbol_1} and @code{symbol_2} are assigned identical values:
+been allocated, or zero if the section has not been allocated.  If the
+section does not exist in the linker script the linker will report an
+error.  If @var{section} is @code{NEXT_SECTION} then @code{SIZEOF} will
+return the alignment of the next allocated section specified in the
+linker script, or zero if there is no such section.  In the following
+example, @code{symbol_1} and @code{symbol_2} are assigned identical
+values:
 @smallexample
 @group
 SECTIONS@{ @dots{}
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 170e1ed7f56..8b9d6dcce0b 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -691,6 +691,24 @@ fold_trinary (etree_type *tree)
 		     : tree->trinary.rhs);
 }
 
+static lang_output_section_statement_type *
+output_section_find (const char *name)
+{
+  lang_output_section_statement_type *os = lang_output_section_find (name);
+
+  if (os == NULL && strcmp (name, "NEXT_SECTION") == 0)
+    {
+      os = expld.last_os;
+      if (os != NULL)
+	while ((os = os->next) != NULL)
+	  if (os->constraint >= 0 && os->bfd_section != NULL)
+	    break;
+      if (os == NULL)
+	os = abs_output_section;
+    }
+  return os;
+}
+
 static void
 fold_name (etree_type *tree)
 {
@@ -850,7 +868,7 @@ fold_name (etree_type *tree)
 	{
 	  lang_output_section_statement_type *os;
 
-	  os = lang_output_section_find (tree->name.name);
+	  os = output_section_find (tree->name.name);
 	  if (os == NULL)
 	    {
 	      if (expld.phase == lang_final_phase_enum)
@@ -1270,29 +1288,32 @@ exp_fold_tree_1 (etree_type *tree)
 }
 
 void
-exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp)
+exp_fold_tree (etree_type *tree, lang_output_section_statement_type *os,
+	       asection *current_section, bfd_vma *dotp)
 {
   expld.rel_from_abs = false;
   expld.dot = *dotp;
   expld.dotp = dotp;
   expld.section = current_section;
+  expld.last_os = os;
   exp_fold_tree_1 (tree);
 }
 
 void
-exp_fold_tree_no_dot (etree_type *tree)
+exp_fold_tree_no_dot (etree_type *tree, lang_output_section_statement_type *os)
 {
   expld.rel_from_abs = false;
   expld.dot = 0;
   expld.dotp = NULL;
   expld.section = bfd_abs_section_ptr;
+  expld.last_os = os;
   exp_fold_tree_1 (tree);
 }
 
 static void
 exp_value_fold (etree_type *tree)
 {
-  exp_fold_tree_no_dot (tree);
+  exp_fold_tree_no_dot (tree, NULL);
   if (expld.result.valid_p)
     {
       tree->type.node_code = INT;
@@ -1547,11 +1568,12 @@ exp_print_tree (etree_type *tree)
 }
 
 bfd_vma
-exp_get_vma (etree_type *tree, bfd_vma def, char *name)
+exp_get_vma (etree_type *tree, lang_output_section_statement_type *os,
+	     bfd_vma def, char *name)
 {
   if (tree != NULL)
     {
-      exp_fold_tree_no_dot (tree);
+      exp_fold_tree_no_dot (tree, os);
       if (expld.result.valid_p)
 	return expld.result.value;
       else if (name != NULL && expld.phase != lang_mark_phase_enum)
@@ -1567,9 +1589,10 @@ exp_get_vma (etree_type *tree, bfd_vma def, char *name)
    NULL or cannot be resolved, return -1.  */
 
 int
-exp_get_power (etree_type *tree, char *name)
+exp_get_power (etree_type *tree, lang_output_section_statement_type *os,
+	       char *name)
 {
-  bfd_vma x = exp_get_vma (tree, -1, name);
+  bfd_vma x = exp_get_vma (tree, os, -1, name);
   bfd_vma p2;
   int n;
 
@@ -1593,7 +1616,7 @@ exp_get_fill (etree_type *tree, fill_type *def, char *name)
   if (tree == NULL)
     return def;
 
-  exp_fold_tree_no_dot (tree);
+  exp_fold_tree_no_dot (tree, NULL);
   if (!expld.result.valid_p)
     {
       if (name != NULL && expld.phase != lang_mark_phase_enum)
@@ -1647,7 +1670,7 @@ exp_get_abs_int (etree_type *tree, int def, char *name)
 {
   if (tree != NULL)
     {
-      exp_fold_tree_no_dot (tree);
+      exp_fold_tree_no_dot (tree, NULL);
 
       if (expld.result.valid_p)
 	{
diff --git a/ld/ldexp.h b/ld/ldexp.h
index 70908c17eb5..7c302753192 100644
--- a/ld/ldexp.h
+++ b/ld/ldexp.h
@@ -133,6 +133,8 @@ enum relro_enum {
   exp_seg_relro_end,
 };
 
+struct lang_output_section_statement_struct;
+
 typedef struct {
   enum phase_enum phase;
 
@@ -176,10 +178,17 @@ struct ldexp_control {
   etree_value_type result;
   bfd_vma dot;
 
-  /* Current dot and section passed to ldexp folder.  */
+  /* Current dot and section passed to ldexp folder.  SECTION will be
+     bfd_abs_section for expressions outside of an output section
+     statement.  */
   bfd_vma *dotp;
   asection *section;
 
+  /* Last output section statement.  For expressions within an output
+     section statement, this will be the current output section
+     statement being processed.  */
+  struct lang_output_section_statement_struct *last_os;
+
   /* State machine and results for DATASEG.  */
   seg_align_type dataseg;
 };
@@ -211,9 +220,10 @@ etree_type *exp_bigintop
 etree_type *exp_relop
   (asection *, bfd_vma);
 void exp_fold_tree
-  (etree_type *, asection *, bfd_vma *);
+  (etree_type *, struct lang_output_section_statement_struct *,
+   asection *, bfd_vma *);
 void exp_fold_tree_no_dot
-  (etree_type *);
+  (etree_type *, struct lang_output_section_statement_struct *);
 etree_type *exp_binop
   (int, etree_type *, etree_type *);
 etree_type *exp_trinop
@@ -233,9 +243,9 @@ etree_type *exp_assert
 void exp_print_tree
   (etree_type *);
 bfd_vma exp_get_vma
-  (etree_type *, bfd_vma, char *);
+  (etree_type *, struct lang_output_section_statement_struct *, bfd_vma, char *);
 int exp_get_power
-  (etree_type *, char *);
+  (etree_type *, struct lang_output_section_statement_struct *, char *);
 fill_type *exp_get_fill
   (etree_type *, fill_type *, char *);
 bfd_vma exp_get_abs_int
diff --git a/ld/ldlang.c b/ld/ldlang.c
index b3a89bf041b..4b86c164843 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2433,7 +2433,7 @@ init_os (lang_output_section_statement_type *s, flagword flags)
 
   /* If supplied an alignment, set it.  */
   if (s->section_alignment != NULL)
-    s->bfd_section->alignment_power = exp_get_power (s->section_alignment,
+    s->bfd_section->alignment_power = exp_get_power (s->section_alignment, s,
 						     "section alignment");
 }
 
@@ -3488,17 +3488,20 @@ static struct bfd_link_hash_entry *plugin_undefs = NULL;
 #endif
 
 static void
-open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
+open_input_bfds (lang_statement_union_type *s,
+		 lang_output_section_statement_type *os,
+		 enum open_bfd_mode mode)
 {
   for (; s != NULL; s = s->header.next)
     {
       switch (s->header.type)
 	{
 	case lang_constructors_statement_enum:
-	  open_input_bfds (constructor_list.head, mode);
+	  open_input_bfds (constructor_list.head, os, mode);
 	  break;
 	case lang_output_section_statement_enum:
-	  open_input_bfds (s->output_section_statement.children.head, mode);
+	  os = &s->output_section_statement;
+	  open_input_bfds (os->children.head, os, mode);
 	  break;
 	case lang_wild_statement_enum:
 	  /* Maybe we should load the file's symbols.  */
@@ -3507,7 +3510,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
 	      && !wildcardp (s->wild_statement.filename)
 	      && !archive_path (s->wild_statement.filename))
 	    lookup_name (s->wild_statement.filename);
-	  open_input_bfds (s->wild_statement.children.head, mode);
+	  open_input_bfds (s->wild_statement.children.head, os, mode);
 	  break;
 	case lang_group_statement_enum:
 	  {
@@ -3526,7 +3529,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
 		plugin_insert_save = plugin_insert;
 #endif
 		undefs = link_info.hash->undefs_tail;
-		open_input_bfds (s->group_statement.children.head,
+		open_input_bfds (s->group_statement.children.head, os,
 				 mode | OPEN_BFD_FORCE);
 	      }
 	    while (undefs != link_info.hash->undefs_tail
@@ -3613,7 +3616,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
 	  break;
 	case lang_assignment_statement_enum:
 	  if (s->assignment_statement.exp->type.node_class != etree_assert)
-	    exp_fold_tree_no_dot (s->assignment_statement.exp);
+	    exp_fold_tree_no_dot (s->assignment_statement.exp, os);
 	  break;
 	default:
 	  break;
@@ -4221,7 +4224,7 @@ map_input_to_output_sections
 		}
 	     else
 	       {
-		 exp_fold_tree_no_dot (os->sectype_value);
+		 exp_fold_tree_no_dot (os->sectype_value, os);
 		 if (expld.result.valid_p)
 		   type = expld.result.value;
 		 else
@@ -4648,6 +4651,7 @@ print_output_section_statement
 
 	  if (output_section_statement->update_dot_tree != NULL)
 	    exp_fold_tree (output_section_statement->update_dot_tree,
+			   output_section_statement,
 			   bfd_abs_section_ptr, &print_dot);
 	}
 
@@ -4686,7 +4690,7 @@ print_assignment (lang_assignment_statement_type *assignment,
     osec = bfd_abs_section_ptr;
 
   if (assignment->exp->type.node_class != etree_provide)
-    exp_fold_tree (tree, osec, &print_dot);
+    exp_fold_tree (tree, output_section, osec, &print_dot);
   else
     expld.result.valid_p = false;
 
@@ -5417,6 +5421,7 @@ size_input_section
       if (output_section_statement->subsection_alignment != NULL)
 	i->alignment_power
 	  = exp_get_power (output_section_statement->subsection_alignment,
+			   output_section_statement,
 			   "subsection alignment");
 
       if (o->alignment_power < i->alignment_power)
@@ -5755,7 +5760,7 @@ ldlang_check_relro_region (lang_statement_union_type *s)
 static bfd_vma
 lang_size_sections_1
   (lang_statement_union_type **prev,
-   lang_output_section_statement_type *output_section_statement,
+   lang_output_section_statement_type *current_os,
    fill_type *fill,
    bfd_vma dot,
    bool *relax,
@@ -5764,6 +5769,7 @@ lang_size_sections_1
   lang_statement_union_type *s;
   lang_statement_union_type *prev_s = NULL;
   bool removed_prev_s = false;
+  lang_output_section_statement_type *os = current_os;
 
   /* Size up the sections from their constituent parts.  */
   for (s = *prev; s != NULL; prev_s = s, s = s->header.next)
@@ -5775,7 +5781,6 @@ lang_size_sections_1
 	case lang_output_section_statement_enum:
 	  {
 	    bfd_vma newdot, after, dotdelta;
-	    lang_output_section_statement_type *os;
 	    lang_memory_region_type *r;
 	    int section_alignment = 0;
 
@@ -5794,7 +5799,7 @@ lang_size_sections_1
 	      os->addr_tree = exp_intop (0);
 	    if (os->addr_tree != NULL)
 	      {
-		exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot);
+		exp_fold_tree (os->addr_tree, os, bfd_abs_section_ptr, &dot);
 
 		if (expld.result.valid_p)
 		  {
@@ -5899,7 +5904,7 @@ lang_size_sections_1
 		    section_alignment = os->bfd_section->alignment_power;
 		  }
 		else
-		  section_alignment = exp_get_power (os->section_alignment,
+		  section_alignment = exp_get_power (os->section_alignment, os,
 						     "section alignment");
 
 		/* Align to what the section needs.  */
@@ -5987,6 +5992,7 @@ lang_size_sections_1
 		       statement.  */
 		    if (os->lma_region != os->region)
 		      section_alignment = exp_get_power (os->section_alignment,
+							 os,
 							 "section alignment");
 		    if (section_alignment > 0)
 		      lma = align_power (lma, section_alignment);
@@ -6076,7 +6082,7 @@ lang_size_sections_1
 	    dot += dotdelta;
 
 	    if (os->update_dot_tree != 0)
-	      exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
+	      exp_fold_tree (os->update_dot_tree, os, bfd_abs_section_ptr, &dot);
 
 	    /* Update dot in the region ?
 	       We only do this if the section is going to be allocated,
@@ -6107,8 +6113,7 @@ lang_size_sections_1
 	  break;
 
 	case lang_constructors_statement_enum:
-	  dot = lang_size_sections_1 (&constructor_list.head,
-				      output_section_statement,
+	  dot = lang_size_sections_1 (&constructor_list.head, current_os,
 				      fill, dot, relax, check_regions);
 	  break;
 
@@ -6116,14 +6121,13 @@ lang_size_sections_1
 	  {
 	    unsigned int size = 0;
 
-	    s->data_statement.output_offset =
-	      dot - output_section_statement->bfd_section->vma;
-	    s->data_statement.output_section =
-	      output_section_statement->bfd_section;
+	    s->data_statement.output_offset = dot - current_os->bfd_section->vma;
+	    s->data_statement.output_section = current_os->bfd_section;
 
 	    /* 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, &dot);
+	    exp_fold_tree (s->data_statement.exp, os,
+			   bfd_abs_section_ptr, &dot);
 
 	    switch (s->data_statement.type)
 	      {
@@ -6146,10 +6150,9 @@ lang_size_sections_1
 	    if (size < TO_SIZE ((unsigned) 1))
 	      size = TO_SIZE ((unsigned) 1);
 	    dot += TO_ADDR (size);
-	    if (!(output_section_statement->bfd_section->flags
-		  & SEC_FIXED_SIZE))
-	      output_section_statement->bfd_section->size
-		= TO_SIZE (dot - output_section_statement->bfd_section->vma);
+	    if (!(current_os->bfd_section->flags & SEC_FIXED_SIZE))
+	      current_os->bfd_section->size
+		= TO_SIZE (dot - current_os->bfd_section->vma);
 
 	  }
 	  break;
@@ -6158,29 +6161,27 @@ lang_size_sections_1
 	  {
 	    int size;
 
-	    s->reloc_statement.output_offset =
-	      dot - output_section_statement->bfd_section->vma;
-	    s->reloc_statement.output_section =
-	      output_section_statement->bfd_section;
+	    s->reloc_statement.output_offset
+	      = dot - current_os->bfd_section->vma;
+	    s->reloc_statement.output_section
+	      = current_os->bfd_section;
 	    size = bfd_get_reloc_size (s->reloc_statement.howto);
 	    dot += TO_ADDR (size);
-	    if (!(output_section_statement->bfd_section->flags
-		  & SEC_FIXED_SIZE))
-	      output_section_statement->bfd_section->size
-		= TO_SIZE (dot - output_section_statement->bfd_section->vma);
+	    if (!(current_os->bfd_section->flags & SEC_FIXED_SIZE))
+	      current_os->bfd_section->size
+		= TO_SIZE (dot - current_os->bfd_section->vma);
 	  }
 	  break;
 
 	case lang_wild_statement_enum:
 	  dot = lang_size_sections_1 (&s->wild_statement.children.head,
-				      output_section_statement,
-				      fill, dot, relax, check_regions);
+				      current_os, fill, dot, relax,
+				      check_regions);
 	  break;
 
 	case lang_object_symbols_statement_enum:
-	  link_info.create_object_symbols_section
-	    = output_section_statement->bfd_section;
-	  output_section_statement->bfd_section->flags |= SEC_KEEP;
+	  link_info.create_object_symbols_section = current_os->bfd_section;
+	  current_os->bfd_section->flags |= SEC_KEEP;
 	  break;
 
 	case lang_output_statement_enum:
@@ -6201,8 +6202,7 @@ lang_size_sections_1
 		if (again)
 		  *relax = true;
 	      }
-	    dot = size_input_section (prev, output_section_statement,
-				      fill, &removed, dot);
+	    dot = size_input_section (prev, current_os, fill, &removed, dot);
 	  }
 	  break;
 
@@ -6210,8 +6210,7 @@ lang_size_sections_1
 	  break;
 
 	case lang_fill_statement_enum:
-	  s->fill_statement.output_section =
-	    output_section_statement->bfd_section;
+	  s->fill_statement.output_section = current_os->bfd_section;
 
 	  fill = s->fill_statement.fill;
 	  break;
@@ -6223,9 +6222,7 @@ lang_size_sections_1
 
 	    expld.dataseg.relro = exp_seg_relro_none;
 
-	    exp_fold_tree (tree,
-			   output_section_statement->bfd_section,
-			   &newdot);
+	    exp_fold_tree (tree, os, current_os->bfd_section, &newdot);
 
 	    ldlang_check_relro_region (s);
 
@@ -6236,11 +6233,11 @@ lang_size_sections_1
 		 || tree->type.node_class == etree_assign)
 		&& (tree->assign.dst [0] != '.'
 		    || tree->assign.dst [1] != '\0'))
-	      output_section_statement->update_dot = 1;
+	      current_os->update_dot = 1;
 
-	    if (!output_section_statement->ignored)
+	    if (!current_os->ignored)
 	      {
-		if (output_section_statement == abs_output_section)
+		if (current_os == abs_output_section)
 		  {
 		    /* If we don't have an output section, then just adjust
 		       the default memory address.  */
@@ -6253,7 +6250,7 @@ lang_size_sections_1
 		       put the pad before when relaxing, in case the
 		       assignment references dot.  */
 		    insert_pad (&s->header.next, fill, TO_SIZE (newdot - dot),
-				output_section_statement->bfd_section, dot);
+				current_os->bfd_section, dot);
 
 		    /* Don't neuter the pad below when relaxing.  */
 		    s = s->header.next;
@@ -6262,11 +6259,11 @@ lang_size_sections_1
 		       should have space allocated to it, unless the
 		       user has explicitly stated that the section
 		       should not be allocated.  */
-		    if (output_section_statement->sectype != noalloc_section
-			&& (output_section_statement->sectype != noload_section
+		    if (current_os->sectype != noalloc_section
+			&& (current_os->sectype != noload_section
 			    || (bfd_get_flavour (link_info.output_bfd)
 				== bfd_target_elf_flavour)))
-		      output_section_statement->bfd_section->flags |= SEC_ALLOC;
+		      current_os->bfd_section->flags |= SEC_ALLOC;
 		  }
 		dot = newdot;
 	      }
@@ -6287,13 +6284,13 @@ lang_size_sections_1
 	     section.  bfd_set_section_contents will complain even for
 	     a pad size of zero.  */
 	  s->padding_statement.output_offset
-	    = dot - output_section_statement->bfd_section->vma;
+	    = dot - current_os->bfd_section->vma;
 	  break;
 
 	case lang_group_statement_enum:
 	  dot = lang_size_sections_1 (&s->group_statement.children.head,
-				      output_section_statement,
-				      fill, dot, relax, check_regions);
+				      current_os, fill, dot, relax,
+				      check_regions);
 	  break;
 
 	case lang_insert_statement_enum:
@@ -6540,6 +6537,8 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 		       bfd_vma dot,
 		       bool *found_end)
 {
+  lang_output_section_statement_type *os = current_os;
+
   for (; s != NULL; s = s->header.next)
     {
       switch (s->header.type)
@@ -6551,10 +6550,9 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 
 	case lang_output_section_statement_enum:
 	  {
-	    lang_output_section_statement_type *os;
 	    bfd_vma newdot;
 
-	    os = &(s->output_section_statement);
+	    os = &s->output_section_statement;
 	    os->after_end = *found_end;
 	    init_opb (os->bfd_section);
 	    newdot = dot;
@@ -6581,7 +6579,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 		      newdot += TO_ADDR (os->bfd_section->size);
 
 		    if (os->update_dot_tree != NULL)
-		      exp_fold_tree (os->update_dot_tree,
+		      exp_fold_tree (os->update_dot_tree, os,
 				     bfd_abs_section_ptr, &newdot);
 		  }
 		dot = newdot;
@@ -6601,7 +6599,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 	  break;
 
 	case lang_data_statement_enum:
-	  exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
+	  exp_fold_tree (s->data_statement.exp, os, bfd_abs_section_ptr, &dot);
 	  if (expld.result.valid_p)
 	    {
 	      s->data_statement.value = expld.result.value;
@@ -6637,7 +6635,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 	  break;
 
 	case lang_reloc_statement_enum:
-	  exp_fold_tree (s->reloc_statement.addend_exp,
+	  exp_fold_tree (s->reloc_statement.addend_exp, os,
 			 bfd_abs_section_ptr, &dot);
 	  if (expld.result.valid_p)
 	    s->reloc_statement.addend_value = expld.result.value;
@@ -6676,7 +6674,7 @@ lang_do_assignments_1 (lang_statement_union_type *s,
 	      if (strcmp (p, "end") == 0)
 		*found_end = true;
 	    }
-	  exp_fold_tree (s->assignment_statement.exp,
+	  exp_fold_tree (s->assignment_statement.exp, os,
 			 (current_os->bfd_section != NULL
 			  ? current_os->bfd_section : bfd_und_section_ptr),
 			 &dot);
@@ -8106,7 +8104,7 @@ lang_process (void)
   /* Create a bfd for each input file.  */
   current_target = default_target;
   lang_statement_iteration++;
-  open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
+  open_input_bfds (statement_list.head, NULL, OPEN_BFD_NORMAL);
 
   /* Now that open_input_bfds has processed assignments and provide
      statements we can give values to symbolic origin/length now.  */
@@ -8136,7 +8134,12 @@ lang_process (void)
       link_info.lto_all_symbols_read = true;
       /* Open any newly added files, updating the file chains.  */
       plugin_undefs = link_info.hash->undefs_tail;
-      open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
+      lang_output_section_statement_type *last_os = NULL;
+      if (lang_os_list.head != NULL)
+	last_os = ((lang_output_section_statement_type *)
+		   ((char *) lang_os_list.tail
+		    - offsetof (lang_output_section_statement_type, next)));
+      open_input_bfds (*added.tail, last_os, OPEN_BFD_NORMAL);
       if (plugin_undefs == link_info.hash->undefs_tail)
 	plugin_undefs = NULL;
       /* Restore the global list pointer now they have all been added.  */
@@ -8187,7 +8190,7 @@ lang_process (void)
 	  /* Rescan archives in case new undefined symbols have appeared.  */
 	  files = file_chain;
 	  lang_statement_iteration++;
-	  open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
+	  open_input_bfds (statement_list.head, NULL, OPEN_BFD_RESCAN);
 	  lang_list_remove_tail (&file_chain, &files);
 	  while (files.head != NULL)
 	    {
@@ -8842,7 +8845,7 @@ lang_new_phdr (const char *name,
   n = stat_alloc (sizeof (struct lang_phdr));
   n->next = NULL;
   n->name = name;
-  n->type = exp_get_vma (type, 0, "program header type");
+  n->type = exp_get_vma (type, NULL, 0, "program header type");
   n->filehdr = filehdr;
   n->phdrs = phdrs;
   n->at = at;
@@ -8956,12 +8959,12 @@ lang_record_phdrs (void)
       if (l->flags == NULL)
 	flags = 0;
       else
-	flags = exp_get_vma (l->flags, 0, "phdr flags");
+	flags = exp_get_vma (l->flags, NULL, 0, "phdr flags");
 
       if (l->at == NULL)
 	at = 0;
       else
-	at = exp_get_vma (l->at, 0, "phdr load address");
+	at = exp_get_vma (l->at, NULL, 0, "phdr load address");
 
       if (!bfd_record_phdr (link_info.output_bfd, l->type,
 			    l->flags != NULL, flags, l->at != NULL,
@@ -9721,7 +9724,7 @@ lang_do_memory_regions (bool update_regions_p)
     {
       if (r->origin_exp)
 	{
-	  exp_fold_tree_no_dot (r->origin_exp);
+	  exp_fold_tree_no_dot (r->origin_exp, NULL);
           if (update_regions_p)
             {
               if (expld.result.valid_p)
@@ -9736,7 +9739,7 @@ lang_do_memory_regions (bool update_regions_p)
 	}
       if (r->length_exp)
 	{
-	  exp_fold_tree_no_dot (r->length_exp);
+	  exp_fold_tree_no_dot (r->length_exp, NULL);
           if (update_regions_p)
             {
               if (expld.result.valid_p)
diff --git a/ld/scripttempl/arclinux.sc b/ld/scripttempl/arclinux.sc
index 20429df45a8..3c27625fedb 100644
--- a/ld/scripttempl/arclinux.sc
+++ b/ld/scripttempl/arclinux.sc
@@ -613,7 +613,7 @@ cat <<EOF
   ${DATA_SDATA-${SDATA}}
   ${DATA_SDATA-${OTHER_SDATA_SECTIONS}}
   ${RELOCATING+${DATA_END_SYMBOLS-${USER_LABEL_PREFIX}_edata = .; PROVIDE (${USER_LABEL_PREFIX}edata = .);}}
-  ${RELOCATING+. = .;}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+${USER_LABEL_PREFIX}__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${DATA_SDATA-${SBSS}}
diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc
index 82de4ed9f88..fe921cd587a 100644
--- a/ld/scripttempl/elf.sc
+++ b/ld/scripttempl/elf.sc
@@ -689,7 +689,7 @@ cat <<EOF
   ${RELOCATING+${SYMBOL_ABI_ALIGNMENT+. = ALIGN(${SYMBOL_ABI_ALIGNMENT});}}
   ${RELOCATING+${DATA_END_SYMBOLS-${CREATE_SHLIB+PROVIDE (}$(def_symbol "_edata")${CREATE_SHLIB+)}; PROVIDE ($(def_symbol "edata"));}}
   ${PERSISTENT}
-  ${RELOCATING+. = .;}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+${CREATE_SHLIB+PROVIDE (}$(def_symbol "__bss_start")${CREATE_SHLIB+)};}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${DATA_SDATA-${SBSS}}
diff --git a/ld/scripttempl/elf64bpf.sc b/ld/scripttempl/elf64bpf.sc
index 74154585125..07a0726384c 100644
--- a/ld/scripttempl/elf64bpf.sc
+++ b/ld/scripttempl/elf64bpf.sc
@@ -636,7 +636,7 @@ cat <<EOF
   ${DATA_SDATA-${SDATA}}
   ${DATA_SDATA-${OTHER_SDATA_SECTIONS}}
   ${RELOCATING+${DATA_END_SYMBOLS-${CREATE_SHLIB+PROVIDE (}${USER_LABEL_PREFIX}_edata = .${CREATE_SHLIB+)}; PROVIDE (${USER_LABEL_PREFIX}edata = .);}}
-  ${RELOCATING+. = .;}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+${CREATE_SHLIB+PROVIDE (}${USER_LABEL_PREFIX}__bss_start = .${CREATE_SHLIB+)};}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${DATA_SDATA-${SBSS}}
diff --git a/ld/scripttempl/elf64hppa.sc b/ld/scripttempl/elf64hppa.sc
index e85dd397993..b3be5a22dac 100644
--- a/ld/scripttempl/elf64hppa.sc
+++ b/ld/scripttempl/elf64hppa.sc
@@ -490,6 +490,7 @@ cat <<EOF
   ${SDATA}
   ${OTHER_SDATA_SECTIONS}
   ${RELOCATING+${DATA_END_SYMBOLS-${USER_LABEL_PREFIX}_edata = .; PROVIDE (${USER_LABEL_PREFIX}edata = .);}}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${SBSS}
diff --git a/ld/scripttempl/elf_chaos.sc b/ld/scripttempl/elf_chaos.sc
index 72f91c9c9fc..88b573c131f 100644
--- a/ld/scripttempl/elf_chaos.sc
+++ b/ld/scripttempl/elf_chaos.sc
@@ -303,6 +303,7 @@ cat <<EOF
   ${OTHER_SDATA_SECTIONS}
   ${RELOCATING+_edata = .;}
   ${RELOCATING+PROVIDE (edata = .);}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${SBSS}
diff --git a/ld/scripttempl/elfarc.sc b/ld/scripttempl/elfarc.sc
index 57cd0a561a0..1ae0248a900 100644
--- a/ld/scripttempl/elfarc.sc
+++ b/ld/scripttempl/elfarc.sc
@@ -365,6 +365,7 @@ cat <<EOF
   ${OTHER_SDATA_SECTIONS}
   ${RELOCATING+_edata = .;}
   ${RELOCATING+PROVIDE (edata = .);}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${SBSS}
diff --git a/ld/scripttempl/elfd10v.sc b/ld/scripttempl/elfd10v.sc
index e52aaedeac0..316fa896329 100644
--- a/ld/scripttempl/elfd10v.sc
+++ b/ld/scripttempl/elfd10v.sc
@@ -156,6 +156,7 @@ SECTIONS
 
   ${RELOCATING+_edata = .;}
   ${RELOCATING+PROVIDE (edata = .);}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+__bss_start = .;}
   .sbss    ${RELOCATING-0} : { *(.sbss)${RELOCATING+ *(.scommon)} } ${RELOCATING+ >DATA}
   .bss     ${RELOCATING-0} :
diff --git a/ld/scripttempl/elfxtensa.sc b/ld/scripttempl/elfxtensa.sc
index 7c71525cbeb..9c85d157881 100644
--- a/ld/scripttempl/elfxtensa.sc
+++ b/ld/scripttempl/elfxtensa.sc
@@ -500,6 +500,7 @@ cat <<EOF
   ${SDATA}
   ${OTHER_SDATA_SECTIONS}
   ${RELOCATING+${DATA_END_SYMBOLS-${USER_LABEL_PREFIX}_edata = .; PROVIDE (${USER_LABEL_PREFIX}edata = .);}}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${SBSS}
diff --git a/ld/scripttempl/epiphany_4x4.sc b/ld/scripttempl/epiphany_4x4.sc
index 0f4e74f9e06..ee253af256e 100644
--- a/ld/scripttempl/epiphany_4x4.sc
+++ b/ld/scripttempl/epiphany_4x4.sc
@@ -578,7 +578,7 @@ cat <<EOF
   /* Align ___bss_start and _end to a multiple of 8 so that we can use strd
      to clear bss.  N.B., without adding any extra alignment, we would have
      to clear the bss byte by byte.  */
-  ${RELOCATING+. = ALIGN(8);}
+  ${RELOCATING+. = ALIGN(MAX(8,ALIGNOF(NEXT_SECTION)));}
   ${RELOCATING+___bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${SBSS}
diff --git a/ld/scripttempl/iq2000.sc b/ld/scripttempl/iq2000.sc
index 47bd777327e..c3d3620bc78 100644
--- a/ld/scripttempl/iq2000.sc
+++ b/ld/scripttempl/iq2000.sc
@@ -373,6 +373,7 @@ cat <<EOF
   ${RELOCATING+${OTHER_SDATA_SECTIONS}}
   ${RELOCATING+_edata = .;}
   ${RELOCATING+PROVIDE (edata = .);}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   .sbss    ${RELOCATING-0} :
diff --git a/ld/scripttempl/mep.sc b/ld/scripttempl/mep.sc
index 6b80c36066b..d49f848bf69 100644
--- a/ld/scripttempl/mep.sc
+++ b/ld/scripttempl/mep.sc
@@ -385,6 +385,7 @@ cat <<EOF
   ${OTHER_SDATA_SECTIONS}
   ${RELOCATING+_edata = .;}
   ${RELOCATING+PROVIDE (edata = .);}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${SBSS}
diff --git a/ld/scripttempl/nds32elf.sc b/ld/scripttempl/nds32elf.sc
index 9645e80c567..36d04cd1ca4 100644
--- a/ld/scripttempl/nds32elf.sc
+++ b/ld/scripttempl/nds32elf.sc
@@ -557,7 +557,7 @@ cat <<EOF
   ${OTHER_SDATA_SECTIONS}
   ${RELOCATING+. = ALIGN(4);}
   ${RELOCATING+${DATA_END_SYMBOLS-${USER_LABEL_PREFIX}_edata = .; PROVIDE (${USER_LABEL_PREFIX}edata = .);}}
-  ${RELOCATING+. = .;}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+${USER_LABEL_PREFIX}__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   ${SBSS}
diff --git a/ld/scripttempl/xstormy16.sc b/ld/scripttempl/xstormy16.sc
index ccae0a2e04f..b29f7201cb1 100644
--- a/ld/scripttempl/xstormy16.sc
+++ b/ld/scripttempl/xstormy16.sc
@@ -143,6 +143,7 @@ SECTIONS
   ${RELOCATING+${OTHER_GOT_SECTIONS}}
   ${RELOCATING+_edata = .;}
   ${RELOCATING+PROVIDE (edata = .);}
+  ${RELOCATING+. = ALIGN(ALIGNOF(NEXT_SECTION));}
   ${RELOCATING+__bss_start = .;}
   ${RELOCATING+${OTHER_BSS_SYMBOLS}}
   .bss     ${RELOCATING-0} :
diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.od b/ld/testsuite/ld-x86-64/pe-x86-64-5.od
index ffd6622dc0d..2a1b69b7857 100644
--- a/ld/testsuite/ld-x86-64/pe-x86-64-5.od
+++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.od
@@ -6,7 +6,7 @@ SYMBOL TABLE:
 0+402010 g       .data	0000000000000000 initdummy
 0+400000 g       .text\$mn	0000000000000000 __executable_start
 0+401000 g       .text\$mn	0000000000000000 begin
-0+402012 g       .bss	0000000000000000 __bss_start
+0+402014 g       .bss	0000000000000000 __bss_start
 0+402000 g       .data	0000000000000000 Struct
 0+402011 g       .data	0000000000000000 initializedVar
 0+402012 g       .data	0000000000000000 _edata
diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd
index 237052805e9..060233ea4d7 100644
--- a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd
+++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd
@@ -6,7 +6,7 @@ Symbol table '.symtab' contains 11 entries:
  +[a-f0-9]+: 0000000000402010     0 NOTYPE  GLOBAL DEFAULT    2 initdummy
  +[a-f0-9]+: 0000000000400000     0 NOTYPE  GLOBAL DEFAULT    1 __executable_start
  +[a-f0-9]+: 0000000000401000     0 NOTYPE  GLOBAL DEFAULT    1 begin
- +[a-f0-9]+: 0000000000402012     0 NOTYPE  GLOBAL DEFAULT    3 __bss_start
+ +[a-f0-9]+: 0000000000402014     0 NOTYPE  GLOBAL DEFAULT    3 __bss_start
  +[a-f0-9]+: 0000000000402000     0 NOTYPE  GLOBAL DEFAULT    2 Struct
  +[a-f0-9]+: 0000000000402011     0 NOTYPE  GLOBAL DEFAULT    2 initializedVar
  +[a-f0-9]+: 0000000000402012     0 NOTYPE  GLOBAL DEFAULT    2 _edata
