diff -rup binutils.orig/ld/emultempl/pe.em binutils-2.31.1/ld/emultempl/pe.em --- binutils.orig/ld/emultempl/pe.em 2018-09-04 11:00:05.546667021 +0100 +++ binutils-2.31.1/ld/emultempl/pe.em 2018-09-04 11:00:58.427292612 +0100 @@ -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; } } diff -rup binutils.orig/ld/emultempl/pep.em binutils-2.31.1/ld/emultempl/pep.em --- binutils.orig/ld/emultempl/pep.em 2018-09-04 11:00:05.545667029 +0100 +++ binutils-2.31.1/ld/emultempl/pep.em 2018-09-04 11:01:29.340073740 +0100 @@ -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; } } diff -rup binutils.orig/ld/ldexp.c binutils-2.31.1/ld/ldexp.c --- binutils.orig/ld/ldexp.c 2018-09-04 11:00:05.535667100 +0100 +++ binutils-2.31.1/ld/ldexp.c 2018-09-04 11:03:29.179225246 +0100 @@ -1528,6 +1528,28 @@ exp_get_value_int (etree_type *tree, int return exp_get_vma (tree, def, name); } +/* 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. */ + +signed int +exp_get_power (etree_type *tree, char *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 * exp_get_fill (etree_type *tree, fill_type *def, char *name) { diff -rup binutils.orig/ld/ldexp.h binutils-2.31.1/ld/ldexp.h --- binutils.orig/ld/ldexp.h 2018-09-04 11:00:05.536667092 +0100 +++ binutils-2.31.1/ld/ldexp.h 2018-09-04 11:04:12.937915422 +0100 @@ -231,6 +231,8 @@ bfd_vma exp_get_vma (etree_type *, bfd_vma, char *); int exp_get_value_int (etree_type *, int, char *); +signed int exp_get_power + (etree_type *, char *); fill_type *exp_get_fill (etree_type *, fill_type *, char *); bfd_vma exp_get_abs_int diff -rup binutils.orig/ld/ldlang.c binutils-2.31.1/ld/ldlang.c --- binutils.orig/ld/ldlang.c 2018-09-04 11:00:05.536667092 +0100 +++ binutils-2.31.1/ld/ldlang.c 2018-09-04 11:07:42.249433438 +0100 @@ -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; diff -rup binutils.orig/ld/ldlang.h binutils-2.31.1/ld/ldlang.h --- binutils.orig/ld/ldlang.h 2018-09-04 11:00:05.533667114 +0100 +++ binutils-2.31.1/ld/ldlang.h 2018-09-04 11:08:29.224100845 +0100 @@ -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;