diff options
author | Alan Modra <amodra@gmail.com> | 2014-01-20 21:28:42 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2014-01-20 21:28:42 +1030 |
commit | fa72205cb90527fd34753203993859907a53ead2 (patch) | |
tree | 287b960405c90fec23679e85d9a8688e8d5dec17 /ld/ldlang.c | |
parent | 24ef1aa73ed312282bd1a755b3ac94681c9f1544 (diff) | |
download | gdb-fa72205cb90527fd34753203993859907a53ead2.zip gdb-fa72205cb90527fd34753203993859907a53ead2.tar.gz gdb-fa72205cb90527fd34753203993859907a53ead2.tar.bz2 |
Allow self-assignment for absolute symbols defined in a linker script
Modifies ld machinery tracking linker script assignments to notice all
assignments, not just those symbols mentioned in DEFINED().
ld/
PR ld/14962
* ldlang.h (struct lang_definedness_hash_entry): Add by_object and
by_script. Make iteration a single bit field.
(lang_track_definedness, lang_symbol_definition_iteration): Delete.
(lang_symbol_defined): Declare.
* ldlang.c (lang_statement_iteration): Expand comment a little.
(lang_init <lang_definedness_table>): Make it bigger.
(lang_track_definedness, lang_symbol_definition): Delete.
(lang_definedness_newfunc): Update.
(lang_symbol_defined): New function.
(lang_update_definedness): Create entries here. Do track whether
script definition of symbol is valid, even when also defined in
an object file.
* ldexp.c (fold_name <DEFINED>): Update.
(fold_name <NAME>): Allow self-assignment for absolute symbols
defined in a linker script.
ld/testsuite/
* ld-scripts/pr14962-2.d,
* ld-scripts/pr14962-2.t: New test.
* ld-scripts/expr.exp: Run it.
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 74 |
1 files changed, 25 insertions, 49 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c index f6d713c..9e35527 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -107,7 +107,7 @@ struct lang_phdr *lang_phdr_list; struct lang_nocrossrefs *nocrossref_list; /* Functions that traverse the linker script and might evaluate - DEFINED() need to increment this. */ + DEFINED() need to increment this at the start of the traversal. */ int lang_statement_iteration = 0; etree_type *base; /* Relocation base - or null */ @@ -1221,16 +1221,12 @@ lang_init (void) abs_output_section->bfd_section = bfd_abs_section_ptr; - /* The value "3" is ad-hoc, somewhat related to the expected number of - DEFINED expressions in a linker script. For most default linker - scripts, there are none. Why a hash table then? Well, it's somewhat - simpler to re-use working machinery than using a linked list in terms - of code-complexity here in ld, besides the initialization which just - looks like other code here. */ + /* 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), - 3)) + 13)) einfo (_("%P%F: can not create hash table: %E\n")); } @@ -2054,7 +2050,7 @@ lang_map (void) obstack_begin (&map_obstack, 1000); bfd_link_hash_traverse (link_info.hash, sort_def_symbol, 0); } - lang_statement_iteration ++; + lang_statement_iteration++; print_statements (); } @@ -3286,15 +3282,6 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode) einfo ("%F"); } -/* Add a symbol to a hash of symbols used in DEFINED (NAME) expressions. */ - -void -lang_track_definedness (const char *name) -{ - if (bfd_hash_lookup (&lang_definedness_table, name, TRUE, FALSE) == NULL) - einfo (_("%P%F: bfd_hash_lookup failed creating symbol %s\n"), name); -} - /* New-function for the definedness hash table. */ static struct bfd_hash_entry * @@ -3312,28 +3299,22 @@ lang_definedness_newfunc (struct bfd_hash_entry *entry, if (ret == NULL) einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name); - ret->iteration = -1; + ret->by_object = 0; + ret->by_script = 0; + ret->iteration = 0; return &ret->root; } -/* Return the iteration when the definition of NAME was last updated. A - value of -1 means that the symbol is not defined in the linker script - or the command line, but may be defined in the linker symbol table. */ +/* 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. */ -int -lang_symbol_definition_iteration (const char *name) +struct lang_definedness_hash_entry * +lang_symbol_defined (const char *name) { - struct lang_definedness_hash_entry *defentry - = (struct lang_definedness_hash_entry *) - bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE); - - /* We've already created this one on the presence of DEFINED in the - script, so it can't be NULL unless something is borked elsewhere in - the code. */ - if (defentry == NULL) - FAIL (); - - return defentry->iteration; + return ((struct lang_definedness_hash_entry *) + bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE)); } /* Update the definedness state of NAME. */ @@ -3343,25 +3324,20 @@ 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, FALSE, FALSE); + bfd_hash_lookup (&lang_definedness_table, name, TRUE, FALSE); - /* We don't keep track of symbols not tested with DEFINED. */ if (defentry == NULL) - return; + einfo (_("%P%F: bfd_hash_lookup failed creating symbol %s\n"), name); - /* If the symbol was already defined, and not from an earlier statement - iteration, don't update the definedness iteration, because that'd - make the symbol seem defined in the linker script at this point, and - it wasn't; it was defined in some object. If we do anyway, DEFINED - would start to yield false before this point and the construct "sym = - DEFINED (sym) ? sym : X;" would change sym to X despite being defined - in an object. */ - if (h->type != bfd_link_hash_undefined + /* 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->iteration == -1) - return; + && h->type != bfd_link_hash_new) + defentry->by_object = 1; + defentry->by_script = 1; defentry->iteration = lang_statement_iteration; } |