aboutsummaryrefslogtreecommitdiff
path: root/ld/ldlang.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-01-20 21:28:42 +1030
committerAlan Modra <amodra@gmail.com>2014-01-20 21:28:42 +1030
commitfa72205cb90527fd34753203993859907a53ead2 (patch)
tree287b960405c90fec23679e85d9a8688e8d5dec17 /ld/ldlang.c
parent24ef1aa73ed312282bd1a755b3ac94681c9f1544 (diff)
downloadgdb-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.c74
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;
}