aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog7
-rw-r--r--ld/ld.texinfo4
-rw-r--r--ld/ldexp.c50
3 files changed, 39 insertions, 22 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 8b22c50..dd20229 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,12 @@
2016-10-04 Alan Modra <amodra@gmail.com>
+ * ld.texinfo (Expression Section): Update result of arithmetic
+ expressions.
+ * ldexp.c (arith_result_section): New function.
+ (fold_binary): Use it.
+
+2016-10-04 Alan Modra <amodra@gmail.com>
+
* ldexp.c (exp_value_fold): New function.
(exp_unop, exp_binop, exp_trinop): Use it.
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index 1303a0e..6528b6a 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -6032,7 +6032,9 @@ The result of comparisons, @samp{&&} and @samp{||} is also a number.
@item
The result of other binary arithmetic and logical operations on two
relative addresses in the same section or two absolute addresses
-(after above conversions) is also a number.
+(after above conversions) is also a number when
+@code{LD_FEATURE ("SANE_EXPR")} or inside an output section definition
+but an absolute address otherwise.
@item
The result of other operations on relative addresses or one
relative address and a number, is a relative address in the same
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 9f88144..a5931fd 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -417,6 +417,32 @@ fold_unary (etree_type *tree)
}
}
+/* Arithmetic operators, bitwise AND, bitwise OR and XOR keep the
+ section of one of their operands only when the other operand is a
+ plain number. Losing the section when operating on two symbols,
+ ie. a result of a plain number, is required for subtraction and
+ XOR. It's justifiable for the other operations on the grounds that
+ adding, multiplying etc. two section relative values does not
+ really make sense unless they are just treated as numbers.
+ The same argument could be made for many expressions involving one
+ symbol and a number. For example, "1 << x" and "100 / x" probably
+ should not be given the section of x. The trouble is that if we
+ fuss about such things the rules become complex and it is onerous
+ to document ld expression evaluation. */
+static void
+arith_result_section (const etree_value_type *lhs)
+{
+ if (expld.result.section == lhs->section)
+ {
+ if (expld.section == bfd_abs_section_ptr
+ && !config.sane_expr)
+ /* Duplicate the insanity in exp_fold_tree_1 case etree_value. */
+ expld.result.section = bfd_abs_section_ptr;
+ else
+ expld.result.section = NULL;
+ }
+}
+
static void
fold_binary (etree_type *tree)
{
@@ -483,26 +509,10 @@ fold_binary (etree_type *tree)
switch (tree->type.node_code)
{
- /* Arithmetic operators, bitwise AND, bitwise OR and XOR
- keep the section of one of their operands only when the
- other operand is a plain number. Losing the section when
- operating on two symbols, ie. a result of a plain number,
- is required for subtraction and XOR. It's justifiable
- for the other operations on the grounds that adding,
- multiplying etc. two section relative values does not
- really make sense unless they are just treated as
- numbers.
- The same argument could be made for many expressions
- involving one symbol and a number. For example,
- "1 << x" and "100 / x" probably should not be given the
- section of x. The trouble is that if we fuss about such
- things the rules become complex and it is onerous to
- document ld expression evaluation. */
#define BOP(x, y) \
case x: \
expld.result.value = lhs.value y expld.result.value; \
- if (expld.result.section == lhs.section) \
- expld.result.section = NULL; \
+ arith_result_section (&lhs); \
break;
/* Comparison operators, logical AND, and logical OR always
@@ -536,8 +546,7 @@ fold_binary (etree_type *tree)
% (bfd_signed_vma) expld.result.value);
else if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S %% by zero\n"), tree->binary.rhs);
- if (expld.result.section == lhs.section)
- expld.result.section = NULL;
+ arith_result_section (&lhs);
break;
case '/':
@@ -546,8 +555,7 @@ fold_binary (etree_type *tree)
/ (bfd_signed_vma) expld.result.value);
else if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S / by zero\n"), tree->binary.rhs);
- if (expld.result.section == lhs.section)
- expld.result.section = NULL;
+ arith_result_section (&lhs);
break;
case MAX_K: