summaryrefslogtreecommitdiff
path: root/ld/ldexp.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2018-08-26 14:23:38 +0930
committerAlan Modra <amodra@gmail.com>2018-08-26 22:45:59 +0930
commit3d9c8f6b3f033a6092425b7344647fb51dbed5c6 (patch)
tree20093232792f1e8061ef1a406c15505571294198 /ld/ldexp.c
parented60adf0a31db8ebc95edd09088465470a296671 (diff)
downloadbinutils-gdb-3d9c8f6b3f033a6092425b7344647fb51dbed5c6.tar.gz
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.
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r--ld/ldexp.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 4ca812e9b20..e123f0e35fe 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -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 *