public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Support NEXT_SECTION in ALIGNOF and SIZEOF
@ 2023-07-12  3:54 Alan Modra
  2023-07-16 23:00 ` Alan Modra
  0 siblings, 1 reply; 2+ messages in thread
From: Alan Modra @ 2023-07-12  3:54 UTC (permalink / raw)
  To: binutils

This patch is aimed at making __bss_start properly aligned with the
first of any bss-style sections following.  Most of the work here
involves keeping track of the last output section seen when processing
the linker script.

You can almost align __bss_start properly by using
${RELOCATING+. = ALIGN(${DATA_SDATA-${NO_SMALL_DATA-ALIGNOF(.${SBSS_NAME}) != 0 ? ALIGNOF(.${SBSS_NAME}) : }}${BSS_PLT+ALIGNOF(.plt) != 0 ? ALIGNOF(.plt) : }ALIGNOF(.${BSS_NAME}));}
and changing every place that defines NO_SMALL_DATA to use " ", but
.plt being marked SPECIAL foils that idea.  The problem is that you
only want to pick up the following .plt, not the one preceeding this
in the data segment if the backend decides that is the proper .plt
section.

Perhaps that could be fixed too, but I decided instead to extend the
linker script a little.  THIS_SECTION and PREV_SECTION could easily be
added too.

Are there any objections to this script extension for mainline?

	* ld.texi (ALIGNOF, SIZEOF): Update and mention NEXT_SECTION.
	* ldexp.c (output_section_find): New function.
	(fold_name <ALIGNOF, SIZEOF>): Use output_section_find.
	(exp_fold_tree): Add os parameter.  Adjust all calls.
	(exp_fold_tree_no_dot, exp_get_vma, exp_get_power): Likewise.
	* ldexp.h (struct ldexp_control): Add last_os.
	(exp_fold_tree, exp_fold_tree_no_dot): Update prototypes.
	(exp_get_vma, exp_get_power): Likewise.
	* ldlang.c: Pass last output section to expression folder
	calls throughout file.
	(open_input_bfds): Add os parameter to track last os seen.
	(lang_size_sections_1): Rename output_section_statement param
	to current_os.  Track last os.
	(lang_do_assignments_1): Track last os.
	* scripttempl/arclinux.sc: Align to ALIGNOF NEXT_SECTION
	before defining __bss_start.
	* scripttempl/elf.sc: Likewise.
	* scripttempl/elf64bpf.sc: Likewise.
	* scripttempl/elf64hppa.sc: Likewise.
	* scripttempl/elf_chaos.sc: Likewise.
	* scripttempl/elfarc.sc: Likewise.
	* scripttempl/elfd10v.sc: Likewise.
	* scripttempl/elfxtensa.sc: Likewise.
	* scripttempl/epiphany_4x4.sc: Likewise.
	* scripttempl/iq2000.sc: Likewise.
	* scripttempl/mep.sc: Likewise.
	* scripttempl/nds32elf.sc: Likewise.
	* scripttempl/xstormy16.sc: Likewise.
	* testsuite/ld-x86-64/pe-x86-64-5.od: Update expected __bss_start.
	* testsuite/ld-x86-64/pe-x86-64-5.rd: Likewise.

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

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Support NEXT_SECTION in ALIGNOF and SIZEOF
  2023-07-12  3:54 Support NEXT_SECTION in ALIGNOF and SIZEOF Alan Modra
@ 2023-07-16 23:00 ` Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2023-07-16 23:00 UTC (permalink / raw)
  To: binutils

On Wed, Jul 12, 2023 at 01:24:33PM +0930, Alan Modra wrote:
> This patch is aimed at making __bss_start properly aligned with the
> first of any bss-style sections following.  Most of the work here
> involves keeping track of the last output section seen when processing
> the linker script.

Since no one commented on this, I've gone ahead and committed the
patch.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-07-16 23:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-12  3:54 Support NEXT_SECTION in ALIGNOF and SIZEOF Alan Modra
2023-07-16 23:00 ` Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).