+2010-08-02 Ian Lance Taylor <iant@google.com>
+
+ PR 11855
+ * script.cc (Script_options::Script_options): Initialize
+ symbol_definitions_ and symbol_references_.
+ (Script_options::add_symbol_assignment): Update
+ symbol_definitions_ and symbol_references_.
+ (Script_options::add_symbol_reference): New function.
+ (script_symbol): New function.
+ * script.h (class Script_options): Add symbol_definitions_ and
+ symbol_references_ fields.
+ (Script_options::referenced_const_iterator): New type.
+ (Script_options::referenced_begin): New function.
+ (Script_options::referenced_end): New function.
+ (Script_options::is_referenced): New function.
+ (Script_options::any_unreferenced): New function.
+ * script-c.h (script_symbol): Declare.
+ * yyscript.y (exp): Call script_symbol.
+ * symtab.cc: Include "script.h".
+ (Symbol_table::gc_mark_undef_symbols): Add layout parameter.
+ Change all callers. Check symbols referenced by scripts.
+ (Symbol_table::add_undefined_symbols_from_command_line): Add
+ layout parameter. Change all callers.
+ (Symbol_table::do_add_undefined_symbols_from_command_line):
+ Likewise. Break out loop body. Check symbols referenced by
+ scripts.
+ (Symbol_table::add_undefined_symbol_from_command_line): New
+ function broken out of
+ do_add_undefined_symbols_from_command_line.
+ * symtab.h (class Symbol_table): Update declarations.
+ * archive.cc: Include "layout.h".
+ (Archive::should_include_member): Add layout parameter. Change
+ all callers. Check for symbol mentioned in expression.
+ * archive.h (class Archive): Update declaration.
+ * object.cc (Sized_relobj::do_should_include_member): Add layout
+ parameter.
+ * object.h (Object::should_include_member): Add layout parameter.
+ Change all callers.
+ (Object::do_should_include_member): Add layout parameter.
+ (class Sized_relobj): Update declaration.
+ * dynobj.cc (Sized_dynobj::do_should_include_member): Add layout
+ parameter.
+ * dynobj.h (class Sized_dynobj): Update declaration.
+ * plugin.cc (Sized_pluginobj::do_should_include_member): Add
+ layout parameter.
+ * plugin.h (class Sized_pluginobj): Update declaration.
+
2010-08-02 Ian Lance Taylor <iant@google.com>
PR 11866
#include "readsyms.h"
#include "symtab.h"
#include "object.h"
+#include "layout.h"
#include "archive.h"
#include "plugin.h"
}
Archive::Should_include
-Archive::should_include_member(Symbol_table* symtab, const char* sym_name,
- Symbol** symp, std::string* why, char** tmpbufp,
+Archive::should_include_member(Symbol_table* symtab, Layout* layout,
+ const char* sym_name, Symbol** symp,
+ std::string* why, char** tmpbufp,
size_t* tmpbuflen)
{
// In an object file, and therefore in an archive map, an
if (sym == NULL)
{
// Check whether the symbol was named in a -u option.
- if (!parameters->options().is_undefined(sym_name))
- return Archive::SHOULD_INCLUDE_UNKNOWN;
- else
+ if (parameters->options().is_undefined(sym_name))
{
*why = "-u ";
*why += sym_name;
}
+ else if (layout->script_options()->is_referenced(sym_name))
+ {
+ size_t alc = 100 + strlen(sym_name);
+ char* buf = new char[alc];
+ snprintf(buf, alc, _("script or expression reference to %s"),
+ sym_name);
+ *why = buf;
+ delete[] buf;
+ }
+ else
+ return Archive::SHOULD_INCLUDE_UNKNOWN;
}
else if (!sym->is_undefined())
return Archive::SHOULD_INCLUDE_NO;
Symbol* sym;
std::string why;
Archive::Should_include t =
- Archive::should_include_member(symtab, sym_name, &sym, &why,
- &tmpbuf, &tmpbuflen);
+ Archive::should_include_member(symtab, layout, sym_name, &sym,
+ &why, &tmpbuf, &tmpbuflen);
if (t == Archive::SHOULD_INCLUDE_NO
|| t == Archive::SHOULD_INCLUDE_YES)
&& (member.sd_ == NULL || member.sd_->symbol_names != NULL))
{
Archive::Should_include t = obj->should_include_member(symtab,
+ layout,
member.sd_,
&why);
};
static Should_include
- should_include_member(Symbol_table* symtab, const char* sym_name,
+ should_include_member(Symbol_table* symtab, Layout*, const char* sym_name,
Symbol** symp, std::string* why, char** tmpbufp,
size_t* tmpbuflen);
template<int size, bool big_endian>
Archive::Should_include
-Sized_dynobj<size, big_endian>::do_should_include_member(
- Symbol_table*, Read_symbols_data*, std::string*)
+Sized_dynobj<size, big_endian>::do_should_include_member(Symbol_table*,
+ Layout*,
+ Read_symbols_data*,
+ std::string*)
{
return Archive::SHOULD_INCLUDE_YES;
}
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
Archive::Should_include
- do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
+ do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why);
// Get the size of a section.
Mapfile* mapfile)
{
// Add any symbols named with -u options to the symbol table.
- symtab->add_undefined_symbols_from_command_line();
+ symtab->add_undefined_symbols_from_command_line(layout);
// If garbage collection was chosen, relocs have been read and processed
// at this point by pre_middle_tasks. Layout can then be done for all
}
}
// Symbols named with -u should not be considered garbage.
- symtab->gc_mark_undef_symbols();
+ symtab->gc_mark_undef_symbols(layout);
gold_assert(symtab->gc() != NULL);
// Do a transitive closure on all references to determine the worklist.
symtab->gc()->do_transitive_closure();
template<int size, bool big_endian>
Archive::Should_include
Sized_relobj<size, big_endian>::do_should_include_member(Symbol_table* symtab,
+ Layout* layout,
Read_symbols_data* sd,
std::string* why)
{
unsigned int st_name = sym.get_st_name();
const char* name = sym_names + st_name;
Symbol* symbol;
- Archive::Should_include t = Archive::should_include_member(symtab, name,
+ Archive::Should_include t = Archive::should_include_member(symtab,
+ layout,
+ name,
&symbol, why,
&tmpbuf,
&tmpbuflen);
// Add symbol information to the global symbol table.
Archive::Should_include
- should_include_member(Symbol_table* symtab, Read_symbols_data* sd,
- std::string* why)
- { return this->do_should_include_member(symtab, sd, why); }
+ should_include_member(Symbol_table* symtab, Layout* layout,
+ Read_symbols_data* sd, std::string* why)
+ { return this->do_should_include_member(symtab, layout, sd, why); }
// Functions and types for the elfcpp::Elf_file interface. This
// permit us to use Object as the File template parameter for
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*) = 0;
virtual Archive::Should_include
- do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
+ do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why) = 0;
// Return the location of the contents of a section. Implemented by
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
Archive::Should_include
- do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
+ do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why);
// Read the relocs.
template<int size, bool big_endian>
Archive::Should_include
Sized_pluginobj<size, big_endian>::do_should_include_member(
- Symbol_table* symtab, Read_symbols_data*, std::string* why)
+ Symbol_table* symtab,
+ Layout* layout,
+ Read_symbols_data*,
+ std::string* why)
{
char* tmpbuf = NULL;
size_t tmpbuflen = 0;
- for (int i = 0; i < this->nsyms_; ++i) {
- const struct ld_plugin_symbol& sym = this->syms_[i];
- const char* name = sym.name;
- Symbol* symbol;
- Archive::Should_include t = Archive::should_include_member(symtab, name,
- &symbol, why,
- &tmpbuf,
- &tmpbuflen);
+ for (int i = 0; i < this->nsyms_; ++i)
+ {
+ const struct ld_plugin_symbol& sym = this->syms_[i];
+ const char* name = sym.name;
+ Symbol* symbol;
+ Archive::Should_include t = Archive::should_include_member(symtab,
+ layout,
+ name,
+ &symbol, why,
+ &tmpbuf,
+ &tmpbuflen);
if (t == Archive::SHOULD_INCLUDE_YES)
{
if (tmpbuf != NULL)
free(tmpbuf);
return t;
}
- }
+ }
if (tmpbuf != NULL)
free(tmpbuf);
return Archive::SHOULD_INCLUDE_UNKNOWN;
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
Archive::Should_include
- do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
+ do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why);
// Get the size of a section.
extern void
script_pop_lex_mode(void* closure);
+/* Called by the bison parser to get the value of a symbol. This is
+ called for a reference to a symbol, but is not called for something
+ like "sym += 10". Uses of the special symbol "." can just call
+ script_exp_string. */
+
+extern Expression_ptr
+script_symbol(void* closure, const char*, size_t);
+
/* Called by the bison parser to set a symbol to a value. PROVIDE is
non-zero if the symbol should be provided--only defined if there is
an undefined reference. HIDDEN is non-zero if the symbol should be
// Class Script_options.
Script_options::Script_options()
- : entry_(), symbol_assignments_(), version_script_info_(),
- script_sections_()
+ : entry_(), symbol_assignments_(), symbol_definitions_(),
+ symbol_references_(), version_script_info_(), script_sections_()
{
}
value, provide, hidden);
this->symbol_assignments_.push_back(p);
}
+
+ if (!provide)
+ {
+ std::string n(name, length);
+ this->symbol_definitions_.insert(n);
+ this->symbol_references_.erase(n);
+ }
}
else
{
}
}
+// Add a reference to a symbol.
+
+void
+Script_options::add_symbol_reference(const char* name, size_t length)
+{
+ if (length != 1 || name[0] != '.')
+ {
+ std::string n(name, length);
+ if (this->symbol_definitions_.find(n) == this->symbol_definitions_.end())
+ this->symbol_references_.insert(n);
+ }
+}
+
// Add an assertion.
void
script_parse_option(closurev, arg, strlen(arg));
}
+// Called by the bison parser to refer to a symbol.
+
+extern "C" Expression*
+script_symbol(void *closurev, const char* name, size_t length)
+{
+ Parser_closure* closure = static_cast<Parser_closure*>(closurev);
+ if (length != 1 || name[0] != '.')
+ closure->script_options()->add_symbol_reference(name, length);
+ return script_exp_string(name, length);
+}
+
// Called by the bison parser to define a symbol.
extern "C" void
add_symbol_assignment(const char* name, size_t length, bool is_defsym,
Expression* value, bool provide, bool hidden);
+ // Add a reference to a symbol.
+ void
+ add_symbol_reference(const char* name, size_t length);
+
// Add an assertion.
void
add_assertion(Expression* check, const char* message, size_t messagelen);
void
add_symbols_to_table(Symbol_table*);
+ // Used to iterate over symbols which are referenced in expressions
+ // but not defined.
+ typedef Unordered_set<std::string>::const_iterator referenced_const_iterator;
+
+ referenced_const_iterator
+ referenced_begin() const
+ { return this->symbol_references_.begin(); }
+
+ referenced_const_iterator
+ referenced_end() const
+ { return this->symbol_references_.end(); }
+
+ // Return whether a symbol is referenced but not defined.
+ bool
+ is_referenced(const std::string& name) const
+ {
+ return (this->symbol_references_.find(name)
+ != this->symbol_references_.end());
+ }
+
+ // Return whether there are any symbols which were referenced but
+ // not defined.
+ bool
+ any_unreferenced() const
+ { return !this->symbol_references_.empty(); }
+
// Finalize the symbol values. Also check assertions.
void
finalize_symbols(Symbol_table*, const Layout*);
std::string entry_;
// Symbols to set.
Symbol_assignments symbol_assignments_;
+ // Symbols defined in an expression, for faster lookup.
+ Unordered_set<std::string> symbol_definitions_;
+ // Symbols referenced in an expression.
+ Unordered_set<std::string> symbol_references_;
// Assertions to check.
Assertions assertions_;
// Version information parsed from a version script.
#include "target.h"
#include "workqueue.h"
#include "symtab.h"
-#include "demangle.h" // needed for --dynamic-list-cpp-new
+#include "script.h"
#include "plugin.h"
namespace gold
// work list to avoid gc'ing them.
void
-Symbol_table::gc_mark_undef_symbols()
+Symbol_table::gc_mark_undef_symbols(Layout* layout)
{
for (options::String_set::const_iterator p =
parameters->options().undefined_begin();
}
}
}
+
+ for (Script_options::referenced_const_iterator p =
+ layout->script_options()->referenced_begin();
+ p != layout->script_options()->referenced_end();
+ ++p)
+ {
+ Symbol* sym = this->lookup(p->c_str());
+ gold_assert(sym != NULL);
+ if (sym->source() == Symbol::FROM_OBJECT
+ && !sym->object()->is_dynamic())
+ {
+ Relobj* obj = static_cast<Relobj*>(sym->object());
+ bool is_ordinary;
+ unsigned int shndx = sym->shndx(&is_ordinary);
+ if (is_ordinary)
+ {
+ gold_assert(this->gc_ != NULL);
+ this->gc_->worklist().push(Section_id(obj, shndx));
+ }
+ }
+ }
}
void
// Add any undefined symbols named on the command line.
void
-Symbol_table::add_undefined_symbols_from_command_line()
+Symbol_table::add_undefined_symbols_from_command_line(Layout* layout)
{
- if (parameters->options().any_undefined())
+ if (parameters->options().any_undefined()
+ || layout->script_options()->any_unreferenced())
{
if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
- this->do_add_undefined_symbols_from_command_line<32>();
+ this->do_add_undefined_symbols_from_command_line<32>(layout);
#else
gold_unreachable();
#endif
else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
- this->do_add_undefined_symbols_from_command_line<64>();
+ this->do_add_undefined_symbols_from_command_line<64>(layout);
#else
gold_unreachable();
#endif
template<int size>
void
-Symbol_table::do_add_undefined_symbols_from_command_line()
+Symbol_table::do_add_undefined_symbols_from_command_line(Layout* layout)
{
for (options::String_set::const_iterator p =
parameters->options().undefined_begin();
p != parameters->options().undefined_end();
++p)
- {
- const char* name = p->c_str();
+ this->add_undefined_symbol_from_command_line<size>(p->c_str());
- if (this->lookup(name) != NULL)
- continue;
+ for (Script_options::referenced_const_iterator p =
+ layout->script_options()->referenced_begin();
+ p != layout->script_options()->referenced_end();
+ ++p)
+ this->add_undefined_symbol_from_command_line<size>(p->c_str());
+}
+
+template<int size>
+void
+Symbol_table::add_undefined_symbol_from_command_line(const char* name)
+{
+ if (this->lookup(name) != NULL)
+ return;
- const char* version = NULL;
+ const char* version = NULL;
- Sized_symbol<size>* sym;
- Sized_symbol<size>* oldsym;
- bool resolve_oldsym;
- if (parameters->target().is_big_endian())
- {
+ Sized_symbol<size>* sym;
+ Sized_symbol<size>* oldsym;
+ bool resolve_oldsym;
+ if (parameters->target().is_big_endian())
+ {
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
- sym = this->define_special_symbol<size, true>(&name, &version,
- false, &oldsym,
- &resolve_oldsym);
+ sym = this->define_special_symbol<size, true>(&name, &version,
+ false, &oldsym,
+ &resolve_oldsym);
#else
- gold_unreachable();
+ gold_unreachable();
#endif
- }
- else
- {
+ }
+ else
+ {
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
- sym = this->define_special_symbol<size, false>(&name, &version,
- false, &oldsym,
- &resolve_oldsym);
+ sym = this->define_special_symbol<size, false>(&name, &version,
+ false, &oldsym,
+ &resolve_oldsym);
#else
- gold_unreachable();
+ gold_unreachable();
#endif
- }
+ }
- gold_assert(oldsym == NULL);
+ gold_assert(oldsym == NULL);
- sym->init_undefined(name, version, elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
- elfcpp::STV_DEFAULT, 0);
- ++this->saw_undefined_;
- }
+ sym->init_undefined(name, version, elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
+ elfcpp::STV_DEFAULT, 0);
+ ++this->saw_undefined_;
}
// Set the dynamic symbol indexes. INDEX is the index of the first
// During garbage collection, this keeps undefined symbols.
void
- gc_mark_undef_symbols();
+ gc_mark_undef_symbols(Layout*);
// During garbage collection, this ensures externally visible symbols
// are not treated as garbage while building shared objects.
// Add any undefined symbols named on the command line to the symbol
// table.
void
- add_undefined_symbols_from_command_line();
+ add_undefined_symbols_from_command_line(Layout*);
// SYM is defined using a COPY reloc. Return the dynamic object
// where the original definition was found.
// table, sized version.
template<int size>
void
- do_add_undefined_symbols_from_command_line();
+ do_add_undefined_symbols_from_command_line(Layout*);
+
+ // Add one undefined symbol.
+ template<int size>
+ void
+ add_undefined_symbol_from_command_line(const char* name);
// Types of common symbols.
| INTEGER
{ $$ = script_exp_integer($1); }
| string
- { $$ = script_exp_string($1.value, $1.length); }
+ { $$ = script_symbol(closure, $1.value, $1.length); }
| MAX_K '(' exp ',' exp ')'
{ $$ = script_exp_function_max($3, $5); }
| MIN_K '(' exp ',' exp ')'