This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] ld: fix ABSOLUTE for general expressions
- From: Tristan Gingold <gingold at adacore dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Mon, 18 Jul 2016 17:34:06 +0200
- Subject: [PATCH] ld: fix ABSOLUTE for general expressions
- Authentication-results: sourceware.org; auth=none
Hello,
it appears that ABSOLUTE(x) doesn't generate an absolute value when X is not a symbol, it looks like it works only for symbols.
See the testcase for an example.
I fixed that issue by defining a new node ABSINT, which is like INT except it is an absolute value.
No regression on powerpc-elf.
A very different way to fix this issue: allow only ABSOLUTE on symbols. Might even make the definition of ABSOLUTE clearer. What is the meaning of ABSOLUTE (a + b) ?
Tristan.
ld/
* ldgram.y (ABSINT): Declare.
Adjust calls to exp_intop.
* ldexp.h (exp_intop): Add IS_ABS argument.
* ldexp.c (exp_intop): Likewise.
(make_int): New function to factorize code.
(exp_fold_tree_1): Handle ABSINT node.
(exp_trinop, exp_unop, exp_nameop, exp_binop): Call make_int.
* ldlang.c (lang_insert_orphan, lang_size_sections_1)
(ldlang_place_orphan): Adjust calls to exp_intop.
* lexsup.c (set_section_start, set_segment_start): Ditto.
* ldctor.c (ldctor_build_sets): Ditto.
* testsuite/ld-scripts/absolute1.s: New test.
* testsuite/ld-scripts/absolute1.d: New test.
* testsuite/ld-scripts/absolute1.t: New test.
* testsuite/ld-scripts/expr.exp: Run new test.
diff --git a/ld/ldctor.c b/ld/ldctor.c
index 2075ad3..3aff582 100644
--- a/ld/ldctor.c
+++ b/ld/ldctor.c
@@ -319,12 +319,12 @@ ldctor_build_sets (void)
lang_add_assignment (exp_assign (".",
exp_unop (ALIGN_K,
- exp_intop (reloc_size)),
+ exp_intop (reloc_size, FALSE)),
FALSE));
lang_add_assignment (exp_assign (p->h->root.string,
exp_nameop (NAME, "."),
FALSE));
- lang_add_data (size, exp_intop (p->count));
+ lang_add_data (size, exp_intop (p->count, FALSE));
for (e = p->elements; e != NULL; e = e->next)
{
@@ -364,12 +364,12 @@ ldctor_build_sets (void)
if (bfd_link_relocatable (&link_info))
lang_add_reloc (p->reloc, howto, e->section, e->name,
- exp_intop (e->value));
+ exp_intop (e->value, FALSE));
else
lang_add_data (size, exp_relop (e->section, e->value));
}
- lang_add_data (size, exp_intop (0));
+ lang_add_data (size, exp_intop (0, FALSE));
}
pop_stat_ptr ();
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 68c4bc5..5913dc5 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -199,10 +199,10 @@ new_abs (bfd_vma value)
}
etree_type *
-exp_intop (bfd_vma value)
+exp_intop (bfd_vma value, bfd_boolean is_abs)
{
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
- new_e->type.node_code = INT;
+ new_e->type.node_code = is_abs ? ABSINT : INT;
new_e->type.filename = ldlex_filename ();
new_e->type.lineno = lineno;
new_e->value.value = value;
@@ -211,6 +211,13 @@ exp_intop (bfd_vma value)
return new_e;
}
+static etree_type *
+make_int (void)
+{
+ return exp_intop (expld.result.value,
+ expld.result.section == bfd_abs_section_ptr);
+}
+
etree_type *
exp_bigintop (bfd_vma value, char *str)
{
@@ -1006,8 +1013,8 @@ exp_fold_tree_1 (etree_type *tree)
switch (tree->type.node_class)
{
case etree_value:
- if (expld.section == bfd_abs_section_ptr
- && !config.sane_expr)
+ if (tree->type.node_code == ABSINT
+ || (expld.section == bfd_abs_section_ptr && !config.sane_expr))
new_abs (tree->value.value);
else
new_number (tree->value.value);
@@ -1265,7 +1272,7 @@ exp_binop (int code, etree_type *lhs, etree_type *rhs)
value.type.node_class = etree_binary;
exp_fold_tree_no_dot (&value);
if (expld.result.valid_p)
- return exp_intop (expld.result.value);
+ return make_int ();
new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
memcpy (new_e, &value, sizeof (new_e->binary));
@@ -1286,7 +1293,7 @@ exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
value.type.node_class = etree_trinary;
exp_fold_tree_no_dot (&value);
if (expld.result.valid_p)
- return exp_intop (expld.result.value);
+ return make_int ();
new_e = (etree_type *) stat_alloc (sizeof (new_e->trinary));
memcpy (new_e, &value, sizeof (new_e->trinary));
@@ -1305,7 +1312,7 @@ exp_unop (int code, etree_type *child)
value.unary.type.node_class = etree_unary;
exp_fold_tree_no_dot (&value);
if (expld.result.valid_p)
- return exp_intop (expld.result.value);
+ return make_int ();
new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
memcpy (new_e, &value, sizeof (new_e->unary));
@@ -1325,7 +1332,7 @@ exp_nameop (int code, const char *name)
exp_fold_tree_no_dot (&value);
if (expld.result.valid_p)
- return exp_intop (expld.result.value);
+ return make_int ();
new_e = (etree_type *) stat_alloc (sizeof (new_e->name));
memcpy (new_e, &value, sizeof (new_e->name));
diff --git a/ld/ldexp.h b/ld/ldexp.h
index 0da3981..2093e3f 100644
--- a/ld/ldexp.h
+++ b/ld/ldexp.h
@@ -194,7 +194,7 @@ extern segment_type *segments;
typedef struct _fill_type fill_type;
etree_type *exp_intop
- (bfd_vma);
+ (bfd_vma, bfd_boolean);
etree_type *exp_bigintop
(bfd_vma, char *);
etree_type *exp_relop
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 9973b07..31c2941 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -99,7 +99,7 @@ static int error_index;
%type <name> memspec_at_opt
%type <cname> wildcard_name
%type <wildcard> wildcard_spec
-%token <bigint> INT
+%token <bigint> INT ABSINT
%token <name> NAME LNAME
%type <integer> length
%type <phdr> phdr_qualifiers
@@ -1235,21 +1235,21 @@ phdr_type:
i++)
if (strcmp (s, phdr_types[i]) == 0)
{
- $$ = exp_intop (i);
+ $$ = exp_intop (i, TRUE);
break;
}
if (i == sizeof phdr_types / sizeof phdr_types[0])
{
if (strcmp (s, "PT_GNU_EH_FRAME") == 0)
- $$ = exp_intop (0x6474e550);
+ $$ = exp_intop (0x6474e550, TRUE);
else if (strcmp (s, "PT_GNU_STACK") == 0)
- $$ = exp_intop (0x6474e551);
+ $$ = exp_intop (0x6474e551, TRUE);
else
{
einfo (_("\
%X%P:%S: unknown phdr type `%s' (try integer literal)\n"),
NULL, s);
- $$ = exp_intop (0);
+ $$ = exp_intop (0, TRUE);
}
}
}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index aee8720..0833ab5 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1826,7 +1826,7 @@ lang_insert_orphan (asection *s,
if (bfd_link_relocatable (&link_info)
|| (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
- address = exp_intop (0);
+ address = exp_intop (0, FALSE);
os_tail = ((lang_output_section_statement_type **)
lang_output_section_statement.tail);
@@ -4932,7 +4932,7 @@ lang_size_sections_1
&& bfd_link_relocatable (&link_info)
&& (bfd_get_flavour (link_info.output_bfd)
== bfd_target_coff_flavour))
- os->addr_tree = exp_intop (0);
+ os->addr_tree = exp_intop (0, FALSE);
if (os->addr_tree != NULL)
{
os->processed_vma = FALSE;
@@ -6199,7 +6199,7 @@ ldlang_place_orphan (asection *s)
if (os->addr_tree == NULL
&& (bfd_link_relocatable (&link_info)
|| (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
- os->addr_tree = exp_intop (0);
+ os->addr_tree = exp_intop (0, FALSE);
lang_add_section (&os->children, s, NULL, os);
}
else
@@ -6222,7 +6222,7 @@ ldlang_place_orphan (asection *s)
if (os->addr_tree == NULL
&& (bfd_link_relocatable (&link_info)
|| (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
- os->addr_tree = exp_intop (0);
+ os->addr_tree = exp_intop (0, FALSE);
lang_add_section (&os->children, s, NULL, os);
}
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 6e279ae..0ab0a21 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -1671,7 +1671,7 @@ set_section_start (char *sect, char *valstr)
bfd_vma val = bfd_scan_vma (valstr, &end, 16);
if (*end)
einfo (_("%P%F: invalid hex number `%s'\n"), valstr);
- lang_section_start (sect, exp_intop (val), NULL);
+ lang_section_start (sect, exp_intop (val, TRUE), NULL);
}
static void
@@ -1691,7 +1691,7 @@ set_segment_start (const char *section, char *valstr)
if (strcmp (seg->name, name) == 0)
{
seg->value = val;
- lang_section_start (section, exp_intop (val), seg);
+ lang_section_start (section, exp_intop (val, TRUE), seg);
return;
}
/* There was no existing value so we must create a new segment
@@ -1707,7 +1707,7 @@ set_segment_start (const char *section, char *valstr)
particular section. For backwards compatibility, we still do
that. If a SEGMENT_START directive is seen, the section address
assignment will be disabled. */
- lang_section_start (section, exp_intop (val), seg);
+ lang_section_start (section, exp_intop (val, TRUE), seg);
}
static void
diff --git a/ld/testsuite/ld-scripts/absolute1.d b/ld/testsuite/ld-scripts/absolute1.d
new file mode 100644
index 0000000..a09c318
--- /dev/null
+++ b/ld/testsuite/ld-scripts/absolute1.d
@@ -0,0 +1,9 @@
+# source: absolute1.s
+# ld: -T absolute1.t
+# nm: -B -n
+# notarget: mmix-*
+# mmix symbol sections are wrong
+
+0+0100 t _start
+0+0800 A _stack_start
+#....
\ No newline at end of file
diff --git a/ld/testsuite/ld-scripts/absolute1.s b/ld/testsuite/ld-scripts/absolute1.s
new file mode 100644
index 0000000..44d2748
--- /dev/null
+++ b/ld/testsuite/ld-scripts/absolute1.s
@@ -0,0 +1,4 @@
+ .text
+_start:
+ nop
+ .long _stack_start
diff --git a/ld/testsuite/ld-scripts/absolute1.t b/ld/testsuite/ld-scripts/absolute1.t
new file mode 100644
index 0000000..060e90a
--- /dev/null
+++ b/ld/testsuite/ld-scripts/absolute1.t
@@ -0,0 +1,8 @@
+SECTIONS
+{
+ .text 0x100 :
+ {
+ *(.text)
+ _stack_start = ABSOLUTE(0x0800);
+ }
+}
diff --git a/ld/testsuite/ld-scripts/expr.exp b/ld/testsuite/ld-scripts/expr.exp
index 7c9b2c4..5f65125 100644
--- a/ld/testsuite/ld-scripts/expr.exp
+++ b/ld/testsuite/ld-scripts/expr.exp
@@ -25,6 +25,7 @@ run_dump_test sane1
run_dump_test assign-loc
run_dump_test pr14962
run_dump_test pr14962-2
+run_dump_test absolute1
set old_ldflags $LDFLAGS
if { [istarget spu*-*-*] } {