aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2008-01-15 23:41:28 +0000
committerIan Lance Taylor <iant@google.com>2008-01-15 23:41:28 +0000
commit091244672e9cb571cb7272d491826f85de871ced (patch)
tree40be47b8e61a974e262595c7aa516f597970f285 /gold/dynobj.cc
parent * emulparams/shlelf_linux.sh (DATA_START_SYMBOLS): Use PROVIDE (diff)
downloadbinutils-gdb-091244672e9cb571cb7272d491826f85de871ced.tar.gz
binutils-gdb-091244672e9cb571cb7272d491826f85de871ced.tar.bz2
binutils-gdb-091244672e9cb571cb7272d491826f85de871ced.zip
From Andrew Chatham and Craig Silverstein: Add support for version
scripts.
Diffstat (limited to 'gold/dynobj.cc')
-rw-r--r--gold/dynobj.cc64
1 files changed, 51 insertions, 13 deletions
diff --git a/gold/dynobj.cc b/gold/dynobj.cc
index 3c3549d8e27..90abbe76bdf 100644
--- a/gold/dynobj.cc
+++ b/gold/dynobj.cc
@@ -1,6 +1,6 @@
// dynobj.cc -- dynamic object support for gold
-// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -1227,6 +1227,46 @@ Verneed::write(const Stringpool* dynpool, bool is_last,
// Versions methods.
+Versions::Versions(const General_options& options, Stringpool* dynpool)
+ : defs_(), needs_(), version_table_(),
+ is_finalized_(false), version_script_(options.version_script())
+{
+ // We always need a base version, so define that first. Nothing
+ // explicitly declares itself as part of base, so it doesn't need to
+ // be in version_table_.
+ // FIXME: Should use soname here when creating a shared object. Is
+ // this fixme still valid? It looks like it's doing the right thing
+ // to me.
+ if (parameters->output_is_shared())
+ {
+ const char* name = dynpool->add(parameters->output_file_name(),
+ false, NULL);
+ Verdef* vdbase = new Verdef(name, std::vector<std::string>(),
+ true, false, true);
+ this->defs_.push_back(vdbase);
+ }
+
+ if (!this->version_script_.empty())
+ {
+ // Parse the version script, and insert each declared version into
+ // defs_ and version_table_.
+ std::vector<std::string> versions = this->version_script_.get_versions();
+ for (size_t k = 0; k < versions.size(); ++k)
+ {
+ Stringpool::Key version_key;
+ const char* version = dynpool->add(versions[k].c_str(),
+ true, &version_key);
+ Verdef* const vd = new Verdef(
+ version,
+ options.version_script().get_dependencies(version),
+ false, false, false);
+ this->defs_.push_back(vd);
+ Key key(version_key, 0);
+ this->version_table_.insert(std::make_pair(key, vd));
+ }
+ }
+}
+
Versions::~Versions()
{
for (Defs::iterator p = this->defs_.begin();
@@ -1265,7 +1305,7 @@ Versions::record_version(const Symbol_table* symtab,
{
gold_assert(!this->is_finalized_);
gold_assert(sym->version() != NULL);
-
+
Stringpool::Key version_key;
const char* version = dynpool->add(sym->version(), false, &version_key);
@@ -1292,7 +1332,7 @@ Versions::add_def(const Symbol* sym, const char* version,
Version_base* const vbnull = NULL;
std::pair<Version_table::iterator, bool> ins =
this->version_table_.insert(std::make_pair(k, vbnull));
-
+
if (!ins.second)
{
// We already have an entry for this version.
@@ -1318,16 +1358,10 @@ Versions::add_def(const Symbol* sym, const char* version,
return;
}
- // If this is the first version we are defining, first define
- // the base version. FIXME: Should use soname here when
- // creating a shared object.
- Verdef* vdbase = new Verdef(parameters->output_file_name(), true, false,
- true);
- this->defs_.push_back(vdbase);
-
// When creating a regular executable, automatically define
// a new version.
- Verdef* vd = new Verdef(version, false, false, false);
+ Verdef* vd = new Verdef(version, std::vector<std::string>(),
+ false, false, false);
this->defs_.push_back(vd);
ins.first->second = vd;
}
@@ -1499,10 +1533,14 @@ Versions::symbol_section_contents(const Symbol_table* symtab,
const char* version = (*p)->version();
if (version == NULL)
version_index = elfcpp::VER_NDX_GLOBAL;
- else
+ else
version_index = this->version_index(symtab, dynpool, *p);
+ // If the symbol was defined as foo@V1 instead of foo@@V1, add
+ // the hidden bit.
+ if ((*p)->version() != NULL && !(*p)->is_default())
+ version_index |= elfcpp::VERSYM_HIDDEN;
elfcpp::Swap<16, big_endian>::writeval(pbuf + (*p)->dynsym_index() * 2,
- version_index);
+ version_index);
}
*pp = pbuf;