Index: binutils/gold/dynobj.cc |
diff --git a/binutils/gold/dynobj.cc b/binutils/gold/dynobj.cc |
index b14d06db12dd8f360067ab47afd1b8fad8f6eb72..dec6f3d0f3d8bf77b0c80c8836982f48851d757d 100644 |
--- a/binutils/gold/dynobj.cc |
+++ b/binutils/gold/dynobj.cc |
@@ -1300,27 +1300,18 @@ Verneed::write(const Stringpool* dynpool, bool is_last, |
Versions::Versions(const Version_script_info& version_script, |
Stringpool* dynpool) |
: defs_(), needs_(), version_table_(), |
- is_finalized_(false), version_script_(version_script) |
+ is_finalized_(false), version_script_(version_script), |
+ needs_base_version_(parameters->options().shared()) |
{ |
- // 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_. |
- if (parameters->options().shared()) |
- { |
- const char* name = parameters->options().soname(); |
- if (name == NULL) |
- name = parameters->options().output_file_name(); |
- name = dynpool->add(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(); |
+ |
+ if (this->needs_base_version_ && !versions.empty()) |
+ this->define_base_version(dynpool); |
+ |
for (size_t k = 0; k < versions.size(); ++k) |
{ |
Stringpool::Key version_key; |
@@ -1350,6 +1341,28 @@ Versions::~Versions() |
delete *p; |
} |
+// Define the base version of a shared library. The base version definition |
+// must be the first entry in defs_. We insert it lazily so that defs_ is |
+// empty if no symbol versioning is used. Then layout can just drop the |
+// version sections. |
+ |
+void |
+Versions::define_base_version(Stringpool* dynpool) |
+{ |
+ // If we do any versioning at all, 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_. |
+ gold_assert(this->defs_.empty()); |
+ const char* name = parameters->options().soname(); |
+ if (name == NULL) |
+ name = parameters->options().output_file_name(); |
+ name = dynpool->add(name, false, NULL); |
+ Verdef* vdbase = new Verdef(name, std::vector<std::string>(), |
+ true, false, true); |
+ this->defs_.push_back(vdbase); |
+ this->needs_base_version_ = false; |
+} |
+ |
// Return the dynamic object which a symbol refers to. |
Dynobj* |
@@ -1421,7 +1434,10 @@ Versions::add_def(const Symbol* sym, const char* version, |
if (parameters->options().shared()) |
gold_error(_("symbol %s has undefined version %s"), |
sym->demangled_name().c_str(), version); |
- |
+ else |
+ // We only insert a base version for shared library. |
+ gold_assert(!this->needs_base_version_); |
+ |
// When creating a regular executable, automatically define |
// a new version. |
Verdef* vd = new Verdef(version, std::vector<std::string>(), |
@@ -1468,6 +1484,10 @@ Versions::add_need(Stringpool* dynpool, const char* filename, const char* name, |
if (vn == NULL) |
{ |
+ // Create base version definition lazily for shared library. |
+ if (this->needs_base_version_) |
+ this->define_base_version(dynpool); |
+ |
// We have a new filename. |
vn = new Verneed(filename); |
this->needs_.push_back(vn); |