Support NEXT_SECTION in ALIGNOF and SIZEOF
authorAlan Modra <amodra@gmail.com>
Fri, 14 Jul 2023 23:16:35 +0000 (08:46 +0930)
committerAlan Modra <amodra@gmail.com>
Sun, 16 Jul 2023 22:47:44 +0000 (08:17 +0930)
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
having two .plt sections (marked SPECIAL) on some backends foils that
idea.  The problem is that you only want to pick up the following
.plt, not the one preceeding __bss_start 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.

* 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.

19 files changed:
ld/ld.texi
ld/ldexp.c
ld/ldexp.h
ld/ldlang.c
ld/scripttempl/arclinux.sc
ld/scripttempl/elf.sc
ld/scripttempl/elf64bpf.sc
ld/scripttempl/elf64hppa.sc
ld/scripttempl/elf_chaos.sc
ld/scripttempl/elfarc.sc
ld/scripttempl/elfd10v.sc
ld/scripttempl/elfxtensa.sc
ld/scripttempl/epiphany_4x4.sc
ld/scripttempl/iq2000.sc
ld/scripttempl/mep.sc
ld/scripttempl/nds32elf.sc
ld/scripttempl/xstormy16.sc
ld/testsuite/ld-x86-64/pe-x86-64-5.od
ld/testsuite/ld-x86-64/pe-x86-64-5.rd

index 40d388ae84b743a7d86907e15497b444408d51cd..406e87ecad730972f1393dd04a3affad3b4118f7 100644 (file)
@@ -7114,10 +7114,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{}
@@ -7266,9 +7269,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{}
index 170e1ed7f565c6b97604f1bc3f3d33ded89291c0..8b9d6dcce0b0c3f9ef5656a43255f9b3442925a9 100644 (file)
@@ -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)
        {
index 70908c17eb5c75d96f41cea7c6a0d864f7c5fda2..7c302753192fdce24ec72d660909e24fe4f15fa1 100644 (file)
@@ -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
index b3a89bf041b651bf335ee34e9b782f92fabf27f0..4b86c1648433e92a7c977b7d8984b0f32511b0ea 100644 (file)
@@ -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)
index 20429df45a82d45ad68e7fcf45e9ad577501b72a..3c27625fedb9a4b0aadfc88c785ca2ce29129a80 100644 (file)
@@ -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}}
index 82de4ed9f88ca4a023abfe290c0e51a59c712ffa..fe921cd587a326c5df82e06966fe33a4028a4b02 100644 (file)
@@ -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}}
index 74154585125106cf6dc26d11a7542b9474ed3a1b..07a0726384c363026037bd429c460134565fa506 100644 (file)
@@ -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}}
index e85dd397993cca6430a5e93aae8982fc722b237f..b3be5a22dacff4b711d3a4b64d563e633f35228a 100644 (file)
@@ -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}
index 72f91c9c9fcd93bede04cd51845a25e87fe68103..88b573c131f045a3dcd35e90a37044351d51fed9 100644 (file)
@@ -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}
index 57cd0a561a0c386c14499725b0ec9c01cfc286c4..1ae0248a90044ee9d82e9a701cc63f53e69e2431 100644 (file)
@@ -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}
index e52aaedeac008e67e04437c7886d48ad479881f0..316fa89632939e2022522d173749c1231881e68d 100644 (file)
@@ -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} :
index 7c71525cbebea8e57e03d33697db08e3541c6652..9c85d1578815fcc13c5be4e64539d87bf58285fa 100644 (file)
@@ -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}
index 0f4e74f9e06101354a869fe14be176208c707dc0..ee253af256ea7af1b1bbf96b0ce247812b589697 100644 (file)
@@ -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}
index 47bd777327e276659fe8d18edebc4b52e6cbd7f2..c3d3620bc78156a32a94d69c7d04d15fe7786619 100644 (file)
@@ -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} :
index 6b80c36066b5604b5b9b7eb0420e77f9dc1d78af..d49f848bf69e76903962a12c6c57651d67d4dbcd 100644 (file)
@@ -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}
index 9645e80c56770444c2a2af9120f499fd007c9de4..36d04cd1ca4e83c98479deee3135035a32168e53 100644 (file)
@@ -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}
index ccae0a2e04f7a742edd058f84b336bd3412e0940..b29f7201cb16f7b04399663b479db56f78f4e2b0 100644 (file)
@@ -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} :
index ffd6622dc0d410aca12cd126ae4a9dc3660137cf..2a1b69b785785b888342f75d4c8871715f242ea9 100644 (file)
@@ -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
index 237052805e96e601615c95abbd0e3f3da0bb1ea1..060233ea4d74d8449fbf6ae62416e6b9db1003bc 100644 (file)
@@ -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