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.
This commit is contained in:
Alan Modra 2018-08-26 14:23:38 +09:30
parent ed60adf0a3
commit 3d9c8f6b3f
10 changed files with 88 additions and 40 deletions

View File

@ -1,3 +1,26 @@
2018-08-26 Alan Modra <amodra@gmail.com>
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.
2018-08-24 Chenghua Xu <paul.hua.gm@gmail.com>
* testsuite/ld-mips-elf/mips-elf-flags.exp

View File

@ -2165,7 +2165,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
&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;
}
}

View File

@ -1962,7 +1962,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s,
&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;
}
}

View File

@ -1523,10 +1523,26 @@ exp_get_vma (etree_type *tree, bfd_vma def, char *name)
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 *

View File

@ -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

View File

@ -1199,8 +1199,8 @@ output_section_statement_newfunc (struct bfd_hash_entry *entry,
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_type *s, flagword flags)
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 from_script)
}
}
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 (const char *output_section_statement_name,
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;

View File

@ -143,6 +143,8 @@ typedef struct lang_output_section_statement_struct
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_statement_struct
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;

View File

@ -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
}

View File

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

View File

@ -0,0 +1,11 @@
SECTIONS
{
.text CONSTANT(COMMONPAGESIZE) : {
*(.text)
}
.data : ALIGN(CONSTANT(COMMONPAGESIZE)) {
*(.data)
}
/DISCARD/ : {*(*)}
}