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)
{
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,
{
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;
}
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)
{
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);
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;
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:
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:
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:
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)
{
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);
{
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;
= 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,
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:
&& 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);
}
--- /dev/null
+# 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