Move support code for linker script DEFINED to ldexp.c

This moves support code for DEFINED to ldexp.c where it is used,
losing the lang_ prefix on identifiers.  Two new functions are needed
to initialize and clean up to hash table, but other than that there
are no functional changes here.

	* ldexp.c (struct definedness_hash_entry, definedness_table)
	(definedness_newfunc, symbol_defined, update_definedness): Move
	and rename from..
	* ldlang.h (struct lang_definedness_hash_entry): ..here,..
	* ldlang.c (lang_definedness_table, lang_definedness_newfunc)
	(lang_symbol_defined, lang_update_definedness): ..and here.
	* ldexp.c (ldexp_init, ldexp_finish): New functions, extracted from..
	* ldlang.c (lang_init, lang_finish): ..here.
	* ldexp.h (ldexp_init, ldexp_finish): Declare.
	* ldlang.h (lang_symbol_defined, lang_update_definedness): Delete.
	* ldmain.c (main): Call ldexp_init and ldexp_finish.
This commit is contained in:
Alan Modra
2014-12-22 10:45:13 +10:30
parent 175a3e5098
commit 18d6a79d35
6 changed files with 114 additions and 93 deletions

View File

@@ -48,6 +48,19 @@ segment_type *segments;
struct ldexp_control expld;
/* This structure records symbols for which we need to keep track of
definedness for use in the DEFINED () test. */
struct definedness_hash_entry
{
struct bfd_hash_entry root;
unsigned int by_object : 1;
unsigned int by_script : 1;
unsigned int iteration : 1;
};
static struct bfd_hash_table definedness_table;
/* Print the string representation of the given token. Surround it
with spaces if INFIX_P is TRUE. */
@@ -244,6 +257,64 @@ new_rel_from_abs (bfd_vma value)
expld.result.section = s;
}
/* New-function for the definedness hash table. */
static struct bfd_hash_entry *
definedness_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table ATTRIBUTE_UNUSED,
const char *name ATTRIBUTE_UNUSED)
{
struct definedness_hash_entry *ret = (struct definedness_hash_entry *) entry;
if (ret == NULL)
ret = (struct definedness_hash_entry *)
bfd_hash_allocate (table, sizeof (struct definedness_hash_entry));
if (ret == NULL)
einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name);
ret->by_object = 0;
ret->by_script = 0;
ret->iteration = 0;
return &ret->root;
}
/* Called during processing of linker script script expressions.
For symbols assigned in a linker script, return a struct describing
where the symbol is defined relative to the current expression,
otherwise return NULL. */
static struct definedness_hash_entry *
symbol_defined (const char *name)
{
return ((struct definedness_hash_entry *)
bfd_hash_lookup (&definedness_table, name, FALSE, FALSE));
}
/* Update the definedness state of NAME. */
static void
update_definedness (const char *name, struct bfd_link_hash_entry *h)
{
struct definedness_hash_entry *defentry
= (struct definedness_hash_entry *)
bfd_hash_lookup (&definedness_table, name, TRUE, FALSE);
if (defentry == NULL)
einfo (_("%P%F: bfd_hash_lookup failed creating symbol %s\n"), name);
/* If the symbol was already defined, and not by a script, then it
must be defined by an object file. */
if (!defentry->by_script
&& h->type != bfd_link_hash_undefined
&& h->type != bfd_link_hash_common
&& h->type != bfd_link_hash_new)
defentry->by_object = 1;
defentry->by_script = 1;
defentry->iteration = lang_statement_iteration;
}
static void
fold_unary (etree_type *tree)
{
@@ -578,7 +649,7 @@ fold_name (etree_type *tree)
if (expld.phase != lang_first_phase_enum)
{
struct bfd_link_hash_entry *h;
struct lang_definedness_hash_entry *def;
struct definedness_hash_entry *def;
h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
&link_info,
@@ -588,7 +659,7 @@ fold_name (etree_type *tree)
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak
|| h->type == bfd_link_hash_common)
&& ((def = lang_symbol_defined (tree->name.name)) == NULL
&& ((def = symbol_defined (tree->name.name)) == NULL
|| def->by_object
|| def->iteration == (lang_statement_iteration & 1)));
}
@@ -601,7 +672,7 @@ fold_name (etree_type *tree)
/* Self-assignment is only allowed for absolute symbols
defined in a linker script. */
struct bfd_link_hash_entry *h;
struct lang_definedness_hash_entry *def;
struct definedness_hash_entry *def;
h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
&link_info,
@@ -611,7 +682,7 @@ fold_name (etree_type *tree)
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak)
&& h->u.def.section == bfd_abs_section_ptr
&& (def = lang_symbol_defined (tree->name.name)) != NULL
&& (def = symbol_defined (tree->name.name)) != NULL
&& def->iteration == (lang_statement_iteration & 1)))
expld.assign_name = NULL;
}
@@ -817,11 +888,11 @@ static bfd_boolean
is_sym_value (const etree_type *tree, bfd_vma val)
{
struct bfd_link_hash_entry *h;
struct lang_definedness_hash_entry *def;
struct definedness_hash_entry *def;
return (tree->type.node_class == etree_name
&& tree->type.node_code == NAME
&& (def = lang_symbol_defined (tree->name.name)) != NULL
&& (def = symbol_defined (tree->name.name)) != NULL
&& def->by_script
&& def->iteration == (lang_statement_iteration & 1)
&& (h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
@@ -1041,7 +1112,7 @@ exp_fold_tree_1 (etree_type *tree)
/* FIXME: Should we worry if the symbol is already
defined? */
lang_update_definedness (tree->assign.dst, h);
update_definedness (tree->assign.dst, h);
h->type = bfd_link_hash_defined;
h->u.def.value = expld.result.value;
if (expld.result.section == NULL)
@@ -1470,3 +1541,21 @@ align_n (bfd_vma value, bfd_vma align)
value = (value + align - 1) / align;
return value * align;
}
void
ldexp_init (void)
{
/* The value "13" is ad-hoc, somewhat related to the expected number of
assignments in a linker script. */
if (!bfd_hash_table_init_n (&definedness_table,
definedness_newfunc,
sizeof (struct definedness_hash_entry),
13))
einfo (_("%P%F: can not create hash table: %E\n"));
}
void
ldexp_finish (void)
{
bfd_hash_table_free (&definedness_table);
}