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 index 0000000000..c006c94af6 --- /dev/null +++ b/toolchain/binutils/patches/2.31.1/100-delay_evaluation_of_alignment_expressions_in_output_sections.patch @@ -0,0 +1,276 @@ +From 3d9c8f6b3f033a6092425b7344647fb51dbed5c6 Mon Sep 17 00:00:00 2001 +From: Alan Modra +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/ : {*(*)} ++}