toolchain/binutils: Fix u-boot on some armhf platforms
[openwrt/staging/chunkeey.git] / toolchain / binutils / patches / 2.31.1 / 100-delay_evaluation_of_alignment_expressions_in_output_sections.patch
diff --git a/toolchain/binutils/patches/2.31.1/100-delay_evaluation_of_alignment_expressions_in_output_sections.patch b/toolchain/binutils/patches/2.31.1/100-delay_evaluation_of_alignment_expressions_in_output_sections.patch
new file mode 100644 (file)
index 0000000..c006c94
--- /dev/null
@@ -0,0 +1,276 @@
+From 3d9c8f6b3f033a6092425b7344647fb51dbed5c6 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra@gmail.com>
+Date: Sun, 26 Aug 2018 14:23:38 +0930
+Subject: [PATCH] Delay evaluation of alignment expressions in output sections
+
+git commit 702d16713 broke expressions using CONSTANT(COMMONPAGESIZE)
+in ALIGN or SUBALIGN of output section statements, because these
+optional fields were evaluated at script parse time and the patch in
+question delayed setting of config.commonpagesize.  The right thing to
+do is keep the tree representation of those fields for later
+evaluation.
+
+       PR 23571
+       * ldlang.h (section_alignment): Make it an expression tree.
+       (subsection_alignment): Likewise.
+       * ldlang.c (topower): Delete.
+       (output_section_statement_newfunc): Adjust initialization.
+       (init_os): Evaluate section_alignment.
+       (lang_size_sections_1): Likewise.
+       (size_input_section): Evaluate subsection_alignment.
+       (lang_enter_output_section_statement): Don't evaluate here.
+       (lang_new_phdr): Use exp_get_vma rather than exp_get_value_int.
+       * ldexp.h (exp_get_value_int): Delete.
+       (exp_get_power): Declare.
+       * ldexp.c (exp_get_value_int): Delete.
+       (exp_get_power): New function.
+       * emultempl/pe.em (place_orphan): Build expression for section
+       alignment.
+       * emultempl/pep.em (place_orphan): Likewise.
+       * testsuite/ld-scripts/pr23571.d,
+       * testsuite/ld-scripts/pr23571.t: New test.
+       * testsuite/ld-scripts/align.exp: Run it.
+---
+ ld/ChangeLog                      | 23 +++++++++++++++++++
+ ld/emultempl/pe.em                |  2 +-
+ ld/emultempl/pep.em               |  2 +-
+ ld/ldexp.c                        | 20 ++++++++++++++--
+ ld/ldexp.h                        |  4 ++--
+ ld/ldlang.c                       | 48 +++++++++++++--------------------------
+ ld/ldlang.h                       |  4 ++--
+ ld/testsuite/ld-scripts/align.exp |  4 ++++
+ ld/testsuite/ld-scripts/pr23571.d | 10 ++++++++
+ ld/testsuite/ld-scripts/pr23571.t | 11 +++++++++
+ 10 files changed, 88 insertions(+), 40 deletions(-)
+ create mode 100644 ld/testsuite/ld-scripts/pr23571.d
+ create mode 100644 ld/testsuite/ld-scripts/pr23571.t
+
+--- a/ld/emultempl/pe.em
++++ b/ld/emultempl/pe.em
+@@ -2165,7 +2165,7 @@ gld_${EMULATION_NAME}_place_orphan (asec
+                              &add_child);
+       if (bfd_link_relocatable (&link_info))
+       {
+-        os->section_alignment = s->alignment_power;
++        os->section_alignment = exp_intop (1U << s->alignment_power);
+         os->bfd_section->alignment_power = s->alignment_power;
+       }
+     }
+--- a/ld/emultempl/pep.em
++++ b/ld/emultempl/pep.em
+@@ -1962,7 +1962,7 @@ gld_${EMULATION_NAME}_place_orphan (asec
+                              &add_child);
+       if (bfd_link_relocatable (&link_info))
+       {
+-        os->section_alignment = s->alignment_power;
++        os->section_alignment = exp_intop (1U << s->alignment_power);
+         os->bfd_section->alignment_power = s->alignment_power;
+       }
+     }
+--- a/ld/ldexp.c
++++ b/ld/ldexp.c
+@@ -1522,10 +1522,26 @@ exp_get_vma (etree_type *tree, bfd_vma d
+   return def;
+ }
++/* Return the smallest non-negative integer such that two raised to
++   that power is at least as large as the vma evaluated at TREE, if
++   TREE is a non-NULL expression that can be resolved.  If TREE is
++   NULL or cannot be resolved, return -1.  */
++
+ int
+-exp_get_value_int (etree_type *tree, int def, char *name)
++exp_get_power (etree_type *tree, char *name)
+ {
+-  return exp_get_vma (tree, def, name);
++  bfd_vma x = exp_get_vma (tree, -1, name);
++  bfd_vma p2;
++  int n;
++
++  if (x == (bfd_vma) -1)
++    return -1;
++
++  for (n = 0, p2 = 1; p2 < x; ++n, p2 <<= 1)
++    if (p2 == 0)
++      break;
++
++  return n;
+ }
+ fill_type *
+--- a/ld/ldexp.h
++++ b/ld/ldexp.h
+@@ -229,8 +229,8 @@ void exp_print_tree
+   (etree_type *);
+ bfd_vma exp_get_vma
+   (etree_type *, bfd_vma, char *);
+-int exp_get_value_int
+-  (etree_type *, int, char *);
++int exp_get_power
++  (etree_type *, char *);
+ fill_type *exp_get_fill
+   (etree_type *, fill_type *, char *);
+ bfd_vma exp_get_abs_int
+--- a/ld/ldlang.c
++++ b/ld/ldlang.c
+@@ -1199,8 +1199,8 @@ output_section_statement_newfunc (struct
+   ret = (struct out_section_hash_entry *) entry;
+   memset (&ret->s, 0, sizeof (ret->s));
+   ret->s.header.type = lang_output_section_statement_enum;
+-  ret->s.output_section_statement.subsection_alignment = -1;
+-  ret->s.output_section_statement.section_alignment = -1;
++  ret->s.output_section_statement.subsection_alignment = NULL;
++  ret->s.output_section_statement.section_alignment = NULL;
+   ret->s.output_section_statement.block_value = 1;
+   lang_list_init (&ret->s.output_section_statement.children);
+   lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
+@@ -2193,8 +2193,9 @@ init_os (lang_output_section_statement_t
+     exp_init_os (s->load_base);
+   /* If supplied an alignment, set it.  */
+-  if (s->section_alignment != -1)
+-    s->bfd_section->alignment_power = s->section_alignment;
++  if (s->section_alignment != NULL)
++    s->bfd_section->alignment_power = exp_get_power (s->section_alignment,
++                                                   "section alignment");
+ }
+ /* Make sure that all output sections mentioned in an expression are
+@@ -4706,8 +4707,10 @@ size_input_section
+        is greater than any seen before, then record it too.  Perform
+        the alignment by inserting a magic 'padding' statement.  */
+-      if (output_section_statement->subsection_alignment != -1)
+-      i->alignment_power = output_section_statement->subsection_alignment;
++      if (output_section_statement->subsection_alignment != NULL)
++      i->alignment_power
++        = exp_get_power (output_section_statement->subsection_alignment,
++                         "subsection alignment");
+       if (o->alignment_power < i->alignment_power)
+       o->alignment_power = i->alignment_power;
+@@ -5147,7 +5150,8 @@ lang_size_sections_1
+                   section_alignment = os->bfd_section->alignment_power;
+                 }
+               else
+-                section_alignment = os->section_alignment;
++                section_alignment = exp_get_power (os->section_alignment,
++                                                   "section alignment");
+               /* Align to what the section needs.  */
+               if (section_alignment > 0)
+@@ -5225,7 +5229,8 @@ lang_size_sections_1
+                      only align according to the value in the output
+                      statement.  */
+                   if (os->lma_region != os->region)
+-                    section_alignment = os->section_alignment;
++                    section_alignment = exp_get_power (os->section_alignment,
++                                                       "section alignment");
+                   if (section_alignment > 0)
+                     lma = align_power (lma, section_alignment);
+                 }
+@@ -6673,25 +6678,6 @@ lang_add_output (const char *name, int f
+     }
+ }
+-static int
+-topower (int x)
+-{
+-  unsigned int i = 1;
+-  int l;
+-
+-  if (x < 0)
+-    return -1;
+-
+-  for (l = 0; l < 32; l++)
+-    {
+-      if (i >= (unsigned int) x)
+-      return l;
+-      i <<= 1;
+-    }
+-
+-  return 0;
+-}
+-
+ lang_output_section_statement_type *
+ lang_enter_output_section_statement (const char *output_section_statement_name,
+                                    etree_type *address_exp,
+@@ -6727,10 +6713,8 @@ lang_enter_output_section_statement (con
+     einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"),
+          NULL);
+-  os->subsection_alignment =
+-    topower (exp_get_value_int (subalign, -1, "subsection alignment"));
+-  os->section_alignment =
+-    topower (exp_get_value_int (align, -1, "section alignment"));
++  os->subsection_alignment = subalign;
++  os->section_alignment = align;
+   os->load_base = ebase;
+   return os;
+@@ -7748,7 +7732,7 @@ lang_new_phdr (const char *name,
+   n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr));
+   n->next = NULL;
+   n->name = name;
+-  n->type = exp_get_value_int (type, 0, "program header type");
++  n->type = exp_get_vma (type, 0, "program header type");
+   n->filehdr = filehdr;
+   n->phdrs = phdrs;
+   n->at = at;
+--- a/ld/ldlang.h
++++ b/ld/ldlang.h
+@@ -143,6 +143,8 @@ typedef struct lang_output_section_state
+   fill_type *fill;
+   union etree_union *addr_tree;
+   union etree_union *load_base;
++  union etree_union *section_alignment;
++  union etree_union *subsection_alignment;
+   /* If non-null, an expression to evaluate after setting the section's
+      size.  The expression is evaluated inside REGION (above) with '.'
+@@ -153,8 +155,6 @@ typedef struct lang_output_section_state
+   lang_output_section_phdr_list *phdrs;
+   unsigned int block_value;
+-  int subsection_alignment;   /* Alignment of components.  */
+-  int section_alignment;      /* Alignment of start of section.  */
+   int constraint;
+   flagword flags;
+   enum section_type sectype;
+--- a/ld/testsuite/ld-scripts/align.exp
++++ b/ld/testsuite/ld-scripts/align.exp
+@@ -53,3 +53,7 @@ if ![is_aout_format] {
+ }
+ run_dump_test align2c
+ set LDFLAGS "$saved_LDFLAGS"
++
++if { [is_elf_format] && ![is_generic_elf] } {
++    run_dump_test pr23571
++}
+--- /dev/null
++++ b/ld/testsuite/ld-scripts/pr23571.d
+@@ -0,0 +1,10 @@
++#source: align2a.s
++#ld: -T pr23571.t -z common-page-size=0x1000
++#objdump: -h -w
++
++.*: +file format .*
++
++Sections:
++Idx Name +Size +VMA +LMA +File off +Algn +Flags
++ +0 \.text +[0-9a-f]* +0+1000 +0+1000 .*
++ +1 \.data +[0-9a-f]* +0+2000 +0+2000 +[0-9a-f]* +2\*\*12 .*
+--- /dev/null
++++ b/ld/testsuite/ld-scripts/pr23571.t
+@@ -0,0 +1,11 @@
++SECTIONS
++{
++  .text CONSTANT(COMMONPAGESIZE) : {
++    *(.text)
++  }
++
++  .data : ALIGN(CONSTANT(COMMONPAGESIZE)) {
++    *(.data)
++  }
++  /DISCARD/ : {*(*)}
++}