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:
parent
175a3e5098
commit
18d6a79d35
6 changed files with 114 additions and 93 deletions
14
ld/ChangeLog
14
ld/ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2014-12-23 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2014-12-10 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ldmisc.c: #include "coff-bfd.h"
|
||||
|
|
103
ld/ldexp.c
103
ld/ldexp.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -221,5 +221,7 @@ fill_type *exp_get_fill
|
|||
(etree_type *, fill_type *, char *);
|
||||
bfd_vma exp_get_abs_int
|
||||
(etree_type *, int, char *);
|
||||
void ldexp_init (void);
|
||||
void ldexp_finish (void);
|
||||
|
||||
#endif
|
||||
|
|
71
ld/ldlang.c
71
ld/ldlang.c
|
@ -64,7 +64,6 @@ static bfd_vma print_dot;
|
|||
static lang_input_statement_type *first_file;
|
||||
static const char *current_target;
|
||||
static lang_statement_list_type statement_list;
|
||||
static struct bfd_hash_table lang_definedness_table;
|
||||
static lang_statement_list_type *stat_save[10];
|
||||
static lang_statement_list_type **stat_save_ptr = &stat_save[0];
|
||||
static struct unique_sections *unique_section_list;
|
||||
|
@ -73,8 +72,6 @@ static struct asneeded_minfo *asneeded_list_head;
|
|||
/* Forward declarations. */
|
||||
static void exp_init_os (etree_type *);
|
||||
static lang_input_statement_type *lookup_name (const char *);
|
||||
static struct bfd_hash_entry *lang_definedness_newfunc
|
||||
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
|
||||
static void insert_undefined (const char *);
|
||||
static bfd_boolean sort_def_symbol (struct bfd_link_hash_entry *, void *);
|
||||
static void print_statement (lang_statement_union_type *,
|
||||
|
@ -1241,14 +1238,6 @@ lang_init (void)
|
|||
|
||||
abs_output_section->bfd_section = bfd_abs_section_ptr;
|
||||
|
||||
/* The value "13" is ad-hoc, somewhat related to the expected number of
|
||||
assignments in a linker script. */
|
||||
if (!bfd_hash_table_init_n (&lang_definedness_table,
|
||||
lang_definedness_newfunc,
|
||||
sizeof (struct lang_definedness_hash_entry),
|
||||
13))
|
||||
einfo (_("%P%F: can not create hash table: %E\n"));
|
||||
|
||||
asneeded_list_head = NULL;
|
||||
asneeded_list_tail = &asneeded_list_head;
|
||||
}
|
||||
|
@ -1256,7 +1245,6 @@ lang_init (void)
|
|||
void
|
||||
lang_finish (void)
|
||||
{
|
||||
bfd_hash_table_free (&lang_definedness_table);
|
||||
output_section_statement_table_free ();
|
||||
}
|
||||
|
||||
|
@ -3365,65 +3353,6 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
|
|||
einfo ("%F");
|
||||
}
|
||||
|
||||
/* New-function for the definedness hash table. */
|
||||
|
||||
static struct bfd_hash_entry *
|
||||
lang_definedness_newfunc (struct bfd_hash_entry *entry,
|
||||
struct bfd_hash_table *table ATTRIBUTE_UNUSED,
|
||||
const char *name ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct lang_definedness_hash_entry *ret
|
||||
= (struct lang_definedness_hash_entry *) entry;
|
||||
|
||||
if (ret == NULL)
|
||||
ret = (struct lang_definedness_hash_entry *)
|
||||
bfd_hash_allocate (table, sizeof (struct lang_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. */
|
||||
|
||||
struct lang_definedness_hash_entry *
|
||||
lang_symbol_defined (const char *name)
|
||||
{
|
||||
return ((struct lang_definedness_hash_entry *)
|
||||
bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE));
|
||||
}
|
||||
|
||||
/* Update the definedness state of NAME. */
|
||||
|
||||
void
|
||||
lang_update_definedness (const char *name, struct bfd_link_hash_entry *h)
|
||||
{
|
||||
struct lang_definedness_hash_entry *defentry
|
||||
= (struct lang_definedness_hash_entry *)
|
||||
bfd_hash_lookup (&lang_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;
|
||||
}
|
||||
|
||||
/* Add the supplied name to the symbol table as an undefined reference.
|
||||
This is a two step process as the symbol table doesn't even exist at
|
||||
the time the ld command line is processed. First we put the name
|
||||
|
|
15
ld/ldlang.h
15
ld/ldlang.h
|
@ -470,17 +470,6 @@ struct unique_sections
|
|||
const char *name;
|
||||
};
|
||||
|
||||
/* This structure records symbols for which we need to keep track of
|
||||
definedness for use in the DEFINED () test. */
|
||||
|
||||
struct lang_definedness_hash_entry
|
||||
{
|
||||
struct bfd_hash_entry root;
|
||||
unsigned int by_object : 1;
|
||||
unsigned int by_script : 1;
|
||||
unsigned int iteration : 1;
|
||||
};
|
||||
|
||||
/* Used by place_orphan to keep track of orphan sections and statements. */
|
||||
|
||||
struct orphan_save
|
||||
|
@ -683,10 +672,6 @@ extern void lang_add_unique
|
|||
(const char *);
|
||||
extern const char *lang_get_output_target
|
||||
(void);
|
||||
extern struct lang_definedness_hash_entry *lang_symbol_defined (const char *);
|
||||
extern void lang_update_definedness
|
||||
(const char *, struct bfd_link_hash_entry *);
|
||||
|
||||
extern void add_excluded_libs (const char *);
|
||||
extern bfd_boolean load_symbols
|
||||
(lang_input_statement_type *, lang_statement_list_type *);
|
||||
|
|
|
@ -297,6 +297,7 @@ main (int argc, char **argv)
|
|||
config.maxpagesize = bfd_emul_get_maxpagesize (default_target);
|
||||
config.commonpagesize = bfd_emul_get_commonpagesize (default_target);
|
||||
lang_init ();
|
||||
ldexp_init ();
|
||||
ldemul_before_parse ();
|
||||
lang_has_input_file = FALSE;
|
||||
parse_args (argc, argv);
|
||||
|
@ -440,6 +441,7 @@ main (int argc, char **argv)
|
|||
fprintf (stderr, "lookup = %p val %lx\n", h, h ? h->u.def.value : 1);
|
||||
}
|
||||
#endif
|
||||
ldexp_finish ();
|
||||
lang_finish ();
|
||||
|
||||
/* Even if we're producing relocatable output, some non-fatal errors should
|
||||
|
|
Loading…
Reference in a new issue