This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Relative expressions and ASSERT
I started down the path to treating all constants as absolute, and
fairly rapidly found that was unworkable, as we need to distinguish
between a plain numerical value and an absolute address. So I made
constants have a NULL section. This allows some nice simplification
when setting up result section in fold_binary; No special case for
'+' or '-' is needed, I think.
Most of the patch is fairly obvious, but I had to make a few hacks for
ORIGIN, to get ld-scripts/memaddr.t to pass. ORIGIN was returning an
absolute value (correctly, it really is an address) but this was being
turned into a plain constant by exp_nameop. exp_nameop can be made to
behave by simply saying the result is invalid during the initial pass
through script expressions. Then it's possible to return a relative
value for ORIGIN, like the test suite expects. I originally just
fixed the test suite but I'll leave that to a followup patch.
I don't intend to commit this patch immediately. I'm sure it will
break some scripts, but if breakage is not too common then this chance
to improve ld sanity may be worthwhile.
* ldexp.c (make_non_rel, new_number): New functions.
(make_abs, exp_get_abs_int): Cope with NULL expld.result.section.
(fold_unary <'~', '!', '-'>): make_non_rel instead of make_abs.
(fold_binary): Simplify result section logic. Return NULL section
for logical ops.
(fold_name <SIZEOF_HEADERS>): Return new_number, not new_abs.
(fold_name <DEFINED, SIZEOF, ALIGNOF, LENGTH, CONSTANT>): Likewise.
(fold_name <ORIGIN>): Don't return valid result when
lang_first_phase_enum. Return new_rel, not new_abs.
(exp_fold_tree_1 <etree_value>): Return new_number, not new_rel.
(exp_fold_tree_1): Ajust for NULL expld.result.section. When assigning
a plain number to dot, assume the value is relative to expld.section.
Make numbers not in an output section, absolute.
* ldlang.c (print_assignment): Fix style nit.
(lang_size_sections_1): Cope with NULL expld.result.section.
(lang_do_assignments_1): Likewise.
Index: ld/ldexp.c
===================================================================
RCS file: /cvs/src/src/ld/ldexp.c,v
retrieving revision 1.85
diff -u -p -r1.85 ldexp.c
--- ld/ldexp.c 12 Aug 2010 13:36:50 -0000 1.85
+++ ld/ldexp.c 12 Aug 2010 13:45:27 -0000
@@ -138,11 +138,22 @@ exp_print_token (token_code_type code, i
static void
make_abs (void)
{
- expld.result.value += expld.result.section->vma;
+ if (expld.result.section != NULL)
+ expld.result.value += expld.result.section->vma;
expld.result.section = bfd_abs_section_ptr;
}
static void
+make_non_rel (void)
+{
+ if (expld.result.section != NULL)
+ {
+ expld.result.value += expld.result.section->vma;
+ expld.result.section = bfd_abs_section_ptr;
+ }
+}
+
+static void
new_abs (bfd_vma value)
{
expld.result.valid_p = TRUE;
@@ -190,6 +201,15 @@ exp_relop (asection *section, bfd_vma va
}
static void
+new_number (bfd_vma value)
+{
+ expld.result.valid_p = TRUE;
+ expld.result.value = value;
+ expld.result.str = NULL;
+ expld.result.section = NULL;
+}
+
+static void
new_rel (bfd_vma value, asection *section)
{
expld.result.valid_p = TRUE;
@@ -227,17 +247,17 @@ fold_unary (etree_type *tree)
break;
case '~':
- make_abs ();
+ make_non_rel ();
expld.result.value = ~expld.result.value;
break;
case '!':
- make_abs ();
+ make_non_rel ();
expld.result.value = !expld.result.value;
break;
case '-':
- make_abs ();
+ make_non_rel ();
expld.result.value = -expld.result.value;
break;
@@ -319,32 +339,20 @@ fold_binary (etree_type *tree)
if (expld.result.valid_p)
{
- /* If the values are from different sections, or this is an
- absolute expression, make both the source arguments
- absolute. However, adding or subtracting an absolute
- value from a relative value is meaningful, and is an
- exception. */
- if (expld.section != bfd_abs_section_ptr
- && lhs.section == bfd_abs_section_ptr
- && tree->type.node_code == '+')
+ if (lhs.section != expld.result.section)
{
- /* Keep the section of the rhs term. */
- expld.result.value = lhs.value + expld.result.value;
- return;
- }
- else if (expld.section != bfd_abs_section_ptr
- && expld.result.section == bfd_abs_section_ptr
- && (tree->type.node_code == '+'
- || tree->type.node_code == '-'))
- {
- /* Keep the section of the lhs term. */
- expld.result.section = lhs.section;
- }
- else if (expld.result.section != lhs.section
- || expld.section == bfd_abs_section_ptr)
- {
- make_abs ();
- lhs.value += lhs.section->vma;
+ /* If the values are from different sections, and neither is
+ just a number, make both the source arguments absolute. */
+ if (expld.result.section != NULL
+ && lhs.section != NULL)
+ {
+ make_abs ();
+ lhs.value += lhs.section->vma;
+ }
+
+ /* If the rhs is just a number, keep the lhs section. */
+ else if (expld.result.section == NULL)
+ expld.result.section = lhs.section;
}
switch (tree->type.node_code)
@@ -366,26 +374,32 @@ fold_binary (etree_type *tree)
break;
#define BOP(x, y) \
- case x: \
- expld.result.value = lhs.value y expld.result.value; \
- break;
+ case x: \
+ expld.result.value = lhs.value y expld.result.value; \
+ break;
+
+#define BOPN(x, y) \
+ case x: \
+ expld.result.value = lhs.value y expld.result.value; \
+ expld.result.section = NULL; \
+ break;
BOP ('+', +);
BOP ('*', *);
BOP ('-', -);
BOP (LSHIFT, <<);
BOP (RSHIFT, >>);
- BOP (EQ, ==);
- BOP (NE, !=);
- BOP ('<', <);
- BOP ('>', >);
- BOP (LE, <=);
- BOP (GE, >=);
+ BOPN (EQ, ==);
+ BOPN (NE, !=);
+ BOPN ('<', <);
+ BOPN ('>', >);
+ BOPN (LE, <=);
+ BOPN (GE, >=);
BOP ('&', &);
BOP ('^', ^);
BOP ('|', |);
- BOP (ANDAND, &&);
- BOP (OROR, ||);
+ BOPN (ANDAND, &&);
+ BOPN (OROR, ||);
case MAX_K:
if (lhs.value > expld.result.value)
@@ -499,7 +513,7 @@ fold_name (etree_type *tree)
The bfd function may cache incorrect data. */
if (expld.phase != lang_mark_phase_enum)
hdr_size = bfd_sizeof_headers (link_info.output_bfd, &link_info);
- new_abs (hdr_size);
+ new_number (hdr_size);
}
break;
@@ -516,14 +530,12 @@ fold_name (etree_type *tree)
&link_info,
tree->name.name,
FALSE, FALSE, TRUE);
- expld.result.value = (h != NULL
- && (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_defweak
- || h->type == bfd_link_hash_common)
- && (def_iteration == lang_statement_iteration
- || def_iteration == -1));
- expld.result.section = expld.section;
- expld.result.valid_p = TRUE;
+ new_number (h != NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak
+ || h->type == bfd_link_hash_common)
+ && (def_iteration == lang_statement_iteration
+ || def_iteration == -1));
}
break;
@@ -633,7 +645,7 @@ fold_name (etree_type *tree)
if (expld.phase == lang_final_phase_enum)
einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
tree->name.name);
- new_abs (0);
+ new_number (0);
}
else if (os->processed_vma)
{
@@ -645,7 +657,7 @@ fold_name (etree_type *tree)
else
val = (bfd_vma)1 << os->bfd_section->alignment_power;
- new_abs (val);
+ new_number (val);
}
}
break;
@@ -656,7 +668,7 @@ fold_name (etree_type *tree)
mem = lang_memory_region_lookup (tree->name.name, FALSE);
if (mem != NULL)
- new_abs (mem->length);
+ new_number (mem->length);
else
einfo (_("%F%S: undefined MEMORY region `%s'"
" referenced in expression\n"), tree->name.name);
@@ -664,23 +676,24 @@ fold_name (etree_type *tree)
break;
case ORIGIN:
- {
- lang_memory_region_type *mem;
+ if (expld.phase != lang_first_phase_enum)
+ {
+ lang_memory_region_type *mem;
- mem = lang_memory_region_lookup (tree->name.name, FALSE);
- if (mem != NULL)
- new_abs (mem->origin);
- else
- einfo (_("%F%S: undefined MEMORY region `%s'"
- " referenced in expression\n"), tree->name.name);
- }
+ mem = lang_memory_region_lookup (tree->name.name, FALSE);
+ if (mem != NULL)
+ new_rel (mem->origin, expld.section);
+ else
+ einfo (_("%F%S: undefined MEMORY region `%s'"
+ " referenced in expression\n"), tree->name.name);
+ }
break;
case CONSTANT:
if (strcmp (tree->name.name, "MAXPAGESIZE") == 0)
- new_abs (config.maxpagesize);
+ new_number (config.maxpagesize);
else if (strcmp (tree->name.name, "COMMONPAGESIZE") == 0)
- new_abs (config.commonpagesize);
+ new_number (config.commonpagesize);
else
einfo (_("%F%S: unknown constant `%s' referenced in expression\n"),
tree->name.name);
@@ -704,7 +717,7 @@ exp_fold_tree_1 (etree_type *tree)
switch (tree->type.node_class)
{
case etree_value:
- new_rel (tree->value.value, expld.section);
+ new_number (tree->value.value);
expld.result.str = tree->value.str;
break;
@@ -767,7 +780,11 @@ exp_fold_tree_1 (etree_type *tree)
{
bfd_vma nextdot;
- nextdot = expld.result.value + expld.result.section->vma;
+ nextdot = expld.result.value;
+ if (expld.result.section != NULL)
+ nextdot += expld.result.section->vma;
+ else
+ nextdot += expld.section->vma;
if (nextdot < expld.dot
&& expld.section != bfd_abs_section_ptr)
einfo (_("%F%S cannot move location counter backwards"
@@ -818,6 +835,8 @@ exp_fold_tree_1 (etree_type *tree)
lang_update_definedness (tree->assign.dst, h);
h->type = bfd_link_hash_defined;
h->u.def.value = expld.result.value;
+ if (expld.result.section == NULL)
+ expld.result.section = expld.section;
h->u.def.section = expld.result.section;
if (tree->type.node_class == etree_provide)
tree->type.node_class = etree_provided;
@@ -856,6 +875,13 @@ exp_fold_tree_1 (etree_type *tree)
memset (&expld.result, 0, sizeof (expld.result));
break;
}
+
+ /* Any number not inside an output section statement is an
+ absolute value. */
+ if (expld.result.valid_p
+ && expld.result.section == NULL
+ && expld.section == bfd_abs_section_ptr)
+ expld.result.section = bfd_abs_section_ptr;
}
void
@@ -1186,7 +1212,8 @@ exp_get_abs_int (etree_type *tree, int d
if (expld.result.valid_p)
{
- expld.result.value += expld.result.section->vma;
+ if (expld.result.section != NULL)
+ expld.result.value += expld.result.section->vma;
return expld.result.value;
}
else if (name != NULL && expld.phase != lang_mark_phase_enum)
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.337
diff -u -p -r1.337 ldlang.c
--- ld/ldlang.c 6 Aug 2010 01:51:17 -0000 1.337
+++ ld/ldlang.c 12 Aug 2010 13:45:30 -0000
@@ -3916,7 +3916,7 @@ print_assignment (lang_assignment_statem
{
value = expld.result.value;
- if (expld.result.section)
+ if (expld.result.section != NULL)
value += expld.result.section->vma;
minfo ("0x%V", value);
@@ -3933,7 +3933,7 @@ print_assignment (lang_assignment_statem
{
value = h->u.def.value;
- if (expld.result.section)
+ if (expld.result.section != NULL)
value += expld.result.section->vma;
minfo ("[0x%V]", value);
@@ -4718,7 +4718,11 @@ lang_size_sections_1
exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot);
if (expld.result.valid_p)
- dot = expld.result.value + expld.result.section->vma;
+ {
+ dot = expld.result.value;
+ if (expld.result.section != NULL)
+ dot += expld.result.section->vma;
+ }
else if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S: non constant or forward reference"
" address expression for section %s\n"),
@@ -5397,8 +5401,11 @@ lang_do_assignments_1 (lang_statement_un
case lang_data_statement_enum:
exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
if (expld.result.valid_p)
- s->data_statement.value = (expld.result.value
- + expld.result.section->vma);
+ {
+ s->data_statement.value = expld.result.value;
+ if (expld.result.section != NULL)
+ s->data_statement.value += expld.result.section->vma;
+ }
else
einfo (_("%F%P: invalid data statement\n"));
{
--
Alan Modra
Australia Development Lab, IBM