aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog17
-rw-r--r--ld/ldexp.c89
-rw-r--r--ld/ldlang.c15
-rw-r--r--ld/ldlang.h2
-rw-r--r--ld/testsuite/ChangeLog5
-rw-r--r--ld/testsuite/ld-scripts/provide-1.d8
-rw-r--r--ld/testsuite/ld-scripts/provide-1.s3
-rw-r--r--ld/testsuite/ld-scripts/provide-1.t11
-rw-r--r--ld/testsuite/ld-scripts/provide-2.d6
-rw-r--r--ld/testsuite/ld-scripts/provide-2.s6
-rw-r--r--ld/testsuite/ld-scripts/provide-2.t10
-rw-r--r--ld/testsuite/ld-scripts/provide-3.d3
-rw-r--r--ld/testsuite/ld-scripts/provide-3.s3
-rw-r--r--ld/testsuite/ld-scripts/provide-3.t11
-rw-r--r--ld/testsuite/ld-scripts/provide.exp25
15 files changed, 153 insertions, 61 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 12716fb..391292e 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,20 @@
+2004-02-23 Nathan Sidwell <nathan@codesourcery.com>
+
+ * ldlang.h (struct lang_output_section_state): Change processed
+ field's type.
+ * ldexp.c (check, invalid): Remove.
+ (fold_name): Move valid_p assignments. Create undefined symbol
+ when needed. Directly exampine section's processd flag.
+ * ldlang.c (lang_output_section_statement_lookup): Adjust
+ processed field init.
+ (lang_size_sections_1): Allow LOADADDR when determining section's
+ VMA. Adjust error message. Fold data statement's expr.
+ (lang_size_sections): Correctly increment lang_statement_iteration.
+
+2004-02-23 Alan Modra <amodra@bigpond.net.au>
+
+ * ldexp.c (fold_tree): Follow indirect symbols.
+
2004-02-20 Nathan Sidwell <nathan@codesourcery.com>
* ldgram.y (exp): Add two operand ALIGN.
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 23a2392..4d9a857 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -141,17 +141,6 @@ new_abs (bfd_vma value)
return new;
}
-static void
-check (lang_output_section_statement_type *os,
- const char *name,
- const char *op)
-{
- if (os == NULL)
- einfo (_("%F%P: %s uses undefined section %s\n"), op, name);
- if (! os->processed)
- einfo (_("%F%P: %s forward reference of section %s\n"), op, name);
-}
-
etree_type *
exp_intop (bfd_vma value)
{
@@ -460,14 +449,6 @@ fold_trinary (etree_type *tree,
return result;
}
-etree_value_type
-invalid (void)
-{
- etree_value_type new;
- new.valid_p = FALSE;
- return new;
-}
-
static etree_value_type
fold_name (etree_type *tree,
lang_output_section_statement_type *current_section,
@@ -476,25 +457,18 @@ fold_name (etree_type *tree,
{
etree_value_type result;
+ result.valid_p = FALSE;
+
switch (tree->type.node_code)
{
case SIZEOF_HEADERS:
if (allocation_done != lang_first_phase_enum)
- {
- result = new_abs (bfd_sizeof_headers (output_bfd,
- link_info.relocatable));
- }
- else
- {
- result.valid_p = FALSE;
- }
+ result = new_abs (bfd_sizeof_headers (output_bfd,
+ link_info.relocatable));
break;
case DEFINED:
if (allocation_done == lang_first_phase_enum)
- {
- lang_track_definedness (tree->name.name);
- result.valid_p = FALSE;
- }
+ lang_track_definedness (tree->name.name);
else
{
struct bfd_link_hash_entry *h;
@@ -515,13 +489,10 @@ fold_name (etree_type *tree,
}
break;
case NAME:
- result.valid_p = FALSE;
if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
{
if (allocation_done != lang_first_phase_enum)
result = new_rel_from_section (dot, current_section);
- else
- result = invalid ();
}
else if (allocation_done != lang_first_phase_enum)
{
@@ -529,10 +500,11 @@ fold_name (etree_type *tree,
h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
tree->name.name,
- FALSE, FALSE, TRUE);
- if (h != NULL
- && (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_defweak))
+ TRUE, FALSE, TRUE);
+ if (!h)
+ einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+ else if (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
{
if (bfd_is_abs_section (h->u.def.section))
result = new_abs (h->u.def.value);
@@ -565,6 +537,12 @@ fold_name (etree_type *tree,
else if (allocation_done == lang_final_phase_enum)
einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
tree->name.name);
+ else if (h->type == bfd_link_hash_new)
+ {
+ h->type = bfd_link_hash_undefined;
+ h->u.undef.abfd = NULL;
+ bfd_link_add_undef (link_info.hash, h);
+ }
}
break;
@@ -574,11 +552,9 @@ fold_name (etree_type *tree,
lang_output_section_statement_type *os;
os = lang_output_section_find (tree->name.name);
- check (os, tree->name.name, "ADDR");
- result = new_rel (0, NULL, os);
+ if (os && os->processed > 0)
+ result = new_rel (0, NULL, os);
}
- else
- result = invalid ();
break;
case LOADADDR:
@@ -587,16 +563,16 @@ fold_name (etree_type *tree,
lang_output_section_statement_type *os;
os = lang_output_section_find (tree->name.name);
- check (os, tree->name.name, "LOADADDR");
- if (os->load_base == NULL)
- result = new_rel (0, NULL, os);
- else
- result = exp_fold_tree_no_dot (os->load_base,
- abs_output_section,
- allocation_done);
+ if (os && os->processed != 0)
+ {
+ if (os->load_base == NULL)
+ result = new_rel (0, NULL, os);
+ else
+ result = exp_fold_tree_no_dot (os->load_base,
+ abs_output_section,
+ allocation_done);
+ }
}
- else
- result = invalid ();
break;
case SIZEOF:
@@ -606,11 +582,9 @@ fold_name (etree_type *tree,
lang_output_section_statement_type *os;
os = lang_output_section_find (tree->name.name);
- check (os, tree->name.name, "SIZEOF");
- result = new_abs (os->bfd_section->_raw_size / opb);
+ if (os && os->processed > 0)
+ result = new_abs (os->bfd_section->_raw_size / opb);
}
- else
- result = invalid ();
break;
default:
@@ -733,14 +707,15 @@ exp_fold_tree (etree_type *tree,
else
create = FALSE;
h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
- create, FALSE, FALSE);
+ create, FALSE, TRUE);
if (h == NULL)
{
- if (tree->type.node_class == etree_assign)
+ if (create)
einfo (_("%P%F:%s: hash creation failed\n"),
tree->assign.dst);
}
else if (tree->type.node_class == etree_provide
+ && h->type != bfd_link_hash_new
&& h->type != bfd_link_hash_undefined
&& h->type != bfd_link_hash_common)
{
diff --git a/ld/ldlang.c b/ld/ldlang.c
index a25f5f3..0f5c630 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -622,7 +622,7 @@ lang_output_section_statement_lookup (const char *const name)
lookup->next = NULL;
lookup->bfd_section = NULL;
- lookup->processed = FALSE;
+ lookup->processed = 0;
lookup->sectype = normal_section;
lookup->addr_tree = NULL;
lang_list_init (&lookup->children);
@@ -2984,12 +2984,15 @@ lang_size_sections_1
{
etree_value_type r;
+ os->processed = -1;
r = exp_fold_tree (os->addr_tree,
abs_output_section,
lang_allocating_phase_enum,
dot, &dot);
+ os->processed = 0;
+
if (!r.valid_p)
- einfo (_("%F%S: non constant address expression for section %s\n"),
+ einfo (_("%F%S: non constant or forward reference address expression for section %s\n"),
os->name);
dot = r.value + r.section->bfd_section->vma;
@@ -3027,7 +3030,7 @@ lang_size_sections_1
= TO_SIZE (after - os->bfd_section->vma);
dot = os->bfd_section->vma + TO_ADDR (os->bfd_section->_raw_size);
- os->processed = TRUE;
+ os->processed = 1;
if (os->update_dot_tree != 0)
exp_fold_tree (os->update_dot_tree, abs_output_section,
@@ -3089,6 +3092,11 @@ lang_size_sections_1
s->data_statement.output_section =
output_section_statement->bfd_section;
+ /* We might refer to provided symbols in the expression, and
+ need to mark them as needed. */
+ exp_fold_tree (s->data_statement.exp, abs_output_section,
+ lang_allocating_phase_enum, dot, &dot);
+
switch (s->data_statement.type)
{
default:
@@ -3294,6 +3302,7 @@ lang_size_sections
&& first + last <= exp_data_seg.pagesize)
{
exp_data_seg.phase = exp_dataseg_adjust;
+ lang_statement_iteration++;
result = lang_size_sections_1 (s, output_section_statement, prev,
fill, dot, relax, check_regions);
}
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 867eb14..d518398 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -134,7 +134,7 @@ typedef struct lang_output_section_statement_struct
union lang_statement_union *next;
const char *name;
- bfd_boolean processed;
+ int processed;
asection *bfd_section;
flagword flags; /* Or together of all input sections. */
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 2bb7510..9622064 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2004-02-23 Nathan Sidwell <nathan@codesourcery.com>
+
+ * ld-scripts/provide.exp: New.
+ * ld-scripts/provide-{1,2,3}.{s,t,d}.exp: New.
+
2004-02-23 Alan Modra <amodra@bigpond.net.au>
* ld-scripts/data.t: Set ".other" address so location doesn't
diff --git a/ld/testsuite/ld-scripts/provide-1.d b/ld/testsuite/ld-scripts/provide-1.d
new file mode 100644
index 0000000..bec3982
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide-1.d
@@ -0,0 +1,8 @@
+#source: provide-1.s
+#ld: -T provide-1.t
+#objdump: -s -j .data
+
+.*: file format .*
+
+Contents of section .data:
+ 0000 (08)?000000(08)? (0c)?000000(0c)? 00000000 ............
diff --git a/ld/testsuite/ld-scripts/provide-1.s b/ld/testsuite/ld-scripts/provide-1.s
new file mode 100644
index 0000000..6395f3a
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide-1.s
@@ -0,0 +1,3 @@
+ .data
+ .globl foo
+foo: .long 0
diff --git a/ld/testsuite/ld-scripts/provide-1.t b/ld/testsuite/ld-scripts/provide-1.t
new file mode 100644
index 0000000..dd30956
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide-1.t
@@ -0,0 +1,11 @@
+SECTIONS
+{
+ .data :
+ {
+ LONG (foo)
+ LONG (bar)
+ *(.data)
+ }
+ PROVIDE (foo = .);
+ PROVIDE (bar = .);
+}
diff --git a/ld/testsuite/ld-scripts/provide-2.d b/ld/testsuite/ld-scripts/provide-2.d
new file mode 100644
index 0000000..3b59e32
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide-2.d
@@ -0,0 +1,6 @@
+#source: provide-2.s
+#ld: -T provide-2.t
+#nm: -B
+0+3 A baz
+0+0 D foo
+
diff --git a/ld/testsuite/ld-scripts/provide-2.s b/ld/testsuite/ld-scripts/provide-2.s
new file mode 100644
index 0000000..6fa93e4
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide-2.s
@@ -0,0 +1,6 @@
+ .data
+ .globl foo
+foo: .long 0
+
+ .globl baz
+ .long baz
diff --git a/ld/testsuite/ld-scripts/provide-2.t b/ld/testsuite/ld-scripts/provide-2.t
new file mode 100644
index 0000000..f128d5e1
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide-2.t
@@ -0,0 +1,10 @@
+SECTIONS
+{
+ PROVIDE (foo = 1);
+ PROVIDE (bar = 2);
+ PROVIDE (baz = 3);
+ .data :
+ {
+ *(.data)
+ }
+}
diff --git a/ld/testsuite/ld-scripts/provide-3.d b/ld/testsuite/ld-scripts/provide-3.d
new file mode 100644
index 0000000..1ee38e3
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide-3.d
@@ -0,0 +1,3 @@
+#source: provide-2.s
+#ld: -T provide-2.t
+#error: symbol defined in linker script and object file
diff --git a/ld/testsuite/ld-scripts/provide-3.s b/ld/testsuite/ld-scripts/provide-3.s
new file mode 100644
index 0000000..6395f3a
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide-3.s
@@ -0,0 +1,3 @@
+ .data
+ .globl foo
+foo: .long 0
diff --git a/ld/testsuite/ld-scripts/provide-3.t b/ld/testsuite/ld-scripts/provide-3.t
new file mode 100644
index 0000000..f6229d4
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide-3.t
@@ -0,0 +1,11 @@
+SECTIONS
+{
+ .data :
+ {
+ LONG (foo)
+ LONG (bar)
+ *(.data)
+ }
+ foo = .;
+ bar = .;
+}
diff --git a/ld/testsuite/ld-scripts/provide.exp b/ld/testsuite/ld-scripts/provide.exp
new file mode 100644
index 0000000..0092674
--- /dev/null
+++ b/ld/testsuite/ld-scripts/provide.exp
@@ -0,0 +1,25 @@
+# Test PROVIDE in a linker script.
+# By Nathan Sidwell, CodeSourcery LLC
+# Copyright 2004
+# Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+set testname "provide"
+
+run_dump_test provide-1
+run_dump_test provide-2
+setup_xfail *-*-*
+run_dump_test provide-3