summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2010-11-03 17:18:23 +0000
committerNick Clifton <nickc@redhat.com>2010-11-03 17:18:23 +0000
commite597fa086665187c4d0dea1c45d5c044e297af66 (patch)
tree425160e0e61155ace9a561b8166d4f3fc29c067c
parent74cea91bbb82d5e4afa212b67eaf53710fd99dcd (diff)
downloadbinutils-gdb-e597fa086665187c4d0dea1c45d5c044e297af66.tar.gz
PR ld/12001
* ldlang.c (ldlang_def_chain_list): New variable. Contains a list of symbols defined via the --defsym command line option and currently waiting assignment. (insert_defined): Add a defined symbol to the symbol table. (ldlang_add_def): Add a entry to the ldlang_def_chain_list. (lang_place_defineds): Walk ldlang_def_chain_list defining the symbols. (lang_process): Call lang_place_defineds. (lang_add_assignment): If the assignment has come from a --defsym command line option then call lang_add_def. * ld-script/default-script2.d: Fix expected address for text section. PR gold/12001 * script.h (class Symbol_assignment: name): New member. Returns the name of the symbol. * scrfipt.cc (Script_options::is_pending_assignment): New member. Returns true if the given symbol name is on the list of assignments wating to be processed. * archive.cc (should_incldue_member): If the symbol is undefined, check to see if it is on the list of symbols pending assignment.
-rw-r--r--gold/ChangeLog11
-rw-r--r--gold/archive.cc4
-rw-r--r--gold/script.cc14
-rw-r--r--gold/script.h8
-rw-r--r--ld/ChangeLog14
-rw-r--r--ld/ldlang.c64
-rw-r--r--ld/testsuite/ChangeLog6
-rw-r--r--ld/testsuite/ld-scripts/default-script2.d2
8 files changed, 122 insertions, 1 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index caae10c3e20..53bc3639d27 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,14 @@
+2010-11-03 Nick Clifton <nickc@redhat.com>
+
+ PR gold/12001
+ * script.h (class Symbol_assignment: name): New member. Returns
+ the name of the symbol.
+ * scrfipt.cc (Script_options::is_pending_assignment): New member.
+ Returns true if the given symbol name is on the list of
+ assignments wating to be processed.
+ * archive.cc (should_incldue_member): If the symbol is undefined,
+ check to see if it is on the list of symbols pending assignment.
+
2010-11-03 Ryan Mansfield <rmansfield@qnx.com>
* script-sections.cc (Script_sections::find_memory_region): Check
diff --git a/gold/archive.cc b/gold/archive.cc
index 541a49456a5..a289e5eaeff 100644
--- a/gold/archive.cc
+++ b/gold/archive.cc
@@ -671,6 +671,10 @@ Archive::should_include_member(Symbol_table* symtab, Layout* layout,
}
else if (!sym->is_undefined())
return Archive::SHOULD_INCLUDE_NO;
+ // PR 12001: Do not include an archive when the undefined
+ // symbol has actually been defined on the command line.
+ else if (layout->script_options()->is_pending_assignment(sym_name))
+ return Archive::SHOULD_INCLUDE_NO;
else if (sym->binding() == elfcpp::STB_WEAK)
return Archive::SHOULD_INCLUDE_UNKNOWN;
diff --git a/gold/script.cc b/gold/script.cc
index b92f85cb923..ada9abccc69 100644
--- a/gold/script.cc
+++ b/gold/script.cc
@@ -1050,6 +1050,20 @@ Script_options::Script_options()
{
}
+// Returns true if NAME is on the list of symbol assignments waiting
+// to be processed.
+
+bool
+Script_options::is_pending_assignment(const char* name)
+{
+ for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
+ p != this->symbol_assignments_.end();
+ ++p)
+ if ((*p)->name() == name)
+ return true;
+ return false;
+}
+
// Add a symbol to be defined.
void
diff --git a/gold/script.h b/gold/script.h
index 70e3a59e7b4..e1134ca2861 100644
--- a/gold/script.h
+++ b/gold/script.h
@@ -345,6 +345,10 @@ class Symbol_assignment
set_if_absolute(Symbol_table*, const Layout*, bool is_dot_available,
uint64_t dot_value);
+ const std::string&
+ name() const
+ { return this->name_; }
+
// Print the assignment to the FILE. This is for debugging.
void
print(FILE*) const;
@@ -423,6 +427,10 @@ class Script_options
add_symbol_assignment(const char* name, size_t length, bool is_defsym,
Expression* value, bool provide, bool hidden);
+ // Look for an assigned symbol.
+ bool
+ is_pending_assignment(const char* name);
+
// Add a reference to a symbol.
void
add_symbol_reference(const char* name, size_t length);
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 538f32de3fa..b6cada28aad 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,17 @@
+2010-11-03 Nick Clifton <nickc@redhat.com>
+
+ PR ld/12001
+ * ldlang.c (ldlang_def_chain_list): New variable. Contains a list
+ of symbols defined via the --defsym command line option and
+ currently waiting assignment.
+ (insert_defined): Add a defined symbol to the symbol table.
+ (ldlang_add_def): Add a entry to the ldlang_def_chain_list.
+ (lang_place_defineds): Walk ldlang_def_chain_list defining the
+ symbols.
+ (lang_process): Call lang_place_defineds.
+ (lang_add_assignment): If the assignment has come from a --defsym
+ command line option then call lang_add_def.
+
2010-11-03 Alan Modra <amodra@gmail.com>
* Makefile.am (eelf64hppa.c): Correct dependencies.
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 95ef5f5d960..798d7a11097 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -3344,6 +3344,65 @@ lang_place_undefineds (void)
insert_undefined (ptr->name);
}
+typedef struct bfd_sym_chain ldlang_def_chain_list_type;
+
+static ldlang_def_chain_list_type ldlang_def_chain_list_head;
+
+/* Insert NAME as defined in the symbol table. */
+
+static void
+insert_defined (const char *name)
+{
+ struct bfd_link_hash_entry *h;
+
+ h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE);
+ if (h == NULL)
+ einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
+ if (h->type == bfd_link_hash_new
+ || h->type == bfd_link_hash_undefined
+ || h->type == bfd_link_hash_undefweak)
+ {
+ h->type = bfd_link_hash_defined;
+ h->u.def.section = bfd_abs_section_ptr;
+ h->u.def.value = 0;
+ }
+}
+
+/* Like lang_add_undef, but this time for symbols defined on the
+ command line. */
+
+static void
+ldlang_add_def (const char *const name)
+{
+ if (link_info.output_bfd != NULL)
+ insert_defined (xstrdup (name));
+ else
+ {
+ ldlang_def_chain_list_type *new_def;
+
+ new_def = (ldlang_def_chain_list_type *) stat_alloc (sizeof (*new_def));
+ new_def->next = ldlang_def_chain_list_head.next;
+ ldlang_def_chain_list_head.next = new_def;
+
+ new_def->name = xstrdup (name);
+ }
+}
+
+/* Run through the list of defineds created above and place them
+ into the linker hash table as defined symbols belonging to the
+ script file. */
+
+static void
+lang_place_defineds (void)
+{
+ ldlang_def_chain_list_type *ptr;
+
+ for (ptr = ldlang_def_chain_list_head.next;
+ ptr != NULL;
+ ptr = ptr->next)
+ insert_defined (ptr->name);
+}
+
/* Check for all readonly or some readwrite sections. */
static void
@@ -6350,6 +6409,7 @@ lang_process (void)
/* Add to the hash table all undefineds on the command line. */
lang_place_undefineds ();
+ lang_place_defineds ();
if (!bfd_section_already_linked_table_init ())
einfo (_("%P%F: Failed to create hash table\n"));
@@ -6634,6 +6694,10 @@ lang_add_assignment (etree_type *exp)
{
lang_assignment_statement_type *new_stmt;
+ extern int parsing_defsym;
+ if (parsing_defsym)
+ ldlang_add_def (exp->assign.dst);
+
new_stmt = new_stat (lang_assignment_statement, stat_ptr);
new_stmt->exp = exp;
return new_stmt;
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 8d49e4ab8a7..1bbde6202c8 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2010-11-03 Nick Clifton <nickc@redhat.com>
+
+ PR ld/12001
+ * ld-script/default-script2.d: Fix expected address for text
+ section.
+
2010-11-02 Joseph Myers <joseph@codesourcery.com>
* ld-tic6x/attr-array-16-16.d, ld-tic6x/attr-array-16-4.d,
diff --git a/ld/testsuite/ld-scripts/default-script2.d b/ld/testsuite/ld-scripts/default-script2.d
index 68ce2aa9fe2..829718d8a97 100644
--- a/ld/testsuite/ld-scripts/default-script2.d
+++ b/ld/testsuite/ld-scripts/default-script2.d
@@ -5,5 +5,5 @@
#...
0*8000000 . _START
#...
-0*9000000 T text
+0*8000000 T text
#pass