X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Fdynobj.cc;h=0a8d897c65ce754c73afada6f0096ecd4f7ae87b;hb=deeafabb678e59d8585be6d765c7fbd0e7060b6c;hp=baf8489452c13f80b8367680e3f986f1121db307;hpb=f35c4853cc5b0e51d8a460be390f7a20cd44ba44;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/dynobj.cc b/gold/dynobj.cc index baf8489452..0a8d897c65 100644 --- a/gold/dynobj.cc +++ b/gold/dynobj.cc @@ -1,6 +1,6 @@ // dynobj.cc -- dynamic object support for gold -// Copyright (C) 2006-2014 Free Software Foundation, Inc. +// Copyright (C) 2006-2019 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -374,6 +374,17 @@ Sized_dynobj::base_read_symbols(Read_symbols_data* sd) sd->verneed_size = 0; sd->verneed_info = 0; + const unsigned char* namesu = sd->section_names->data(); + const char* names = reinterpret_cast(namesu); + if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL) + { + Compressed_section_map* compressed_sections = + build_compressed_section_map( + pshdrs, this->shnum(), names, sd->section_names_size, this, true); + if (compressed_sections != NULL) + this->set_compressed_sections(compressed_sections); + } + if (this->dynsym_shndx_ != -1U) { // Get the dynamic symbols. @@ -935,31 +946,59 @@ Dynobj::create_elf_hash_table(const std::vector& dynsyms, bucket[bucketpos] = dynsym_index; } + int size = parameters->target().hash_entry_size(); unsigned int hashlen = ((2 + bucketcount + local_dynsym_count + dynsym_count) - * 4); + * size / 8); unsigned char* phash = new unsigned char[hashlen]; - if (parameters->target().is_big_endian()) + bool big_endian = parameters->target().is_big_endian(); + if (size == 32) { + if (big_endian) + { #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG) - Dynobj::sized_create_elf_hash_table(bucket, chain, phash, - hashlen); + Dynobj::sized_create_elf_hash_table<32, true>(bucket, chain, phash, + hashlen); #else - gold_unreachable(); + gold_unreachable(); #endif + } + else + { +#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE) + Dynobj::sized_create_elf_hash_table<32, false>(bucket, chain, phash, + hashlen); +#else + gold_unreachable(); +#endif + } } - else + else if (size == 64) { + if (big_endian) + { +#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG) + Dynobj::sized_create_elf_hash_table<64, true>(bucket, chain, phash, + hashlen); +#else + gold_unreachable(); +#endif + } + else + { #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE) - Dynobj::sized_create_elf_hash_table(bucket, chain, phash, - hashlen); + Dynobj::sized_create_elf_hash_table<64, false>(bucket, chain, phash, + hashlen); #else - gold_unreachable(); + gold_unreachable(); #endif + } } + else + gold_unreachable(); *pphash = phash; *phashlen = hashlen; @@ -967,7 +1006,7 @@ Dynobj::create_elf_hash_table(const std::vector& dynsyms, // Fill in an ELF hash table. -template +template void Dynobj::sized_create_elf_hash_table(const std::vector& bucket, const std::vector& chain, @@ -979,21 +1018,21 @@ Dynobj::sized_create_elf_hash_table(const std::vector& bucket, const unsigned int bucketcount = bucket.size(); const unsigned int chaincount = chain.size(); - elfcpp::Swap<32, big_endian>::writeval(p, bucketcount); - p += 4; - elfcpp::Swap<32, big_endian>::writeval(p, chaincount); - p += 4; + elfcpp::Swap::writeval(p, bucketcount); + p += size / 8; + elfcpp::Swap::writeval(p, chaincount); + p += size / 8; for (unsigned int i = 0; i < bucketcount; ++i) { - elfcpp::Swap<32, big_endian>::writeval(p, bucket[i]); - p += 4; + elfcpp::Swap::writeval(p, bucket[i]); + p += size / 8; } for (unsigned int i = 0; i < chaincount; ++i) { - elfcpp::Swap<32, big_endian>::writeval(p, chain[i]); - p += 4; + elfcpp::Swap::writeval(p, chain[i]); + p += size / 8; } gold_assert(static_cast(p - phash) == hashlen); @@ -1400,7 +1439,7 @@ Versions::Versions(const Version_script_info& version_script, Stringpool* dynpool) : defs_(), needs_(), version_table_(), is_finalized_(false), version_script_(version_script), - needs_base_version_(parameters->options().shared()) + needs_base_version_(true) { if (!this->version_script_.empty()) { @@ -1488,13 +1527,16 @@ Versions::record_version(const Symbol_table* symtab, gold_assert(!this->is_finalized_); gold_assert(sym->version() != NULL); + // A symbol defined as "sym@" is bound to an unspecified base version. + if (sym->version()[0] == '\0') + return; + Stringpool::Key version_key; const char* version = dynpool->add(sym->version(), false, &version_key); if (!sym->is_from_dynobj() && !sym->is_copied_from_dynobj()) { - if (parameters->options().shared()) - this->add_def(dynpool, sym, version, version_key); + this->add_def(dynpool, sym, version, version_key); } else { @@ -1531,18 +1573,13 @@ Versions::add_def(Stringpool* dynpool, const Symbol* sym, const char* version, // find a definition of a symbol with a version which is not // in the version script. if (parameters->options().shared()) - { - gold_error(_("symbol %s has undefined version %s"), - sym->demangled_name().c_str(), version); - if (this->needs_base_version_) - this->define_base_version(dynpool); - } - else - // We only insert a base version for shared library. - gold_assert(!this->needs_base_version_); - + gold_error(_("symbol %s has undefined version %s"), + sym->demangled_name().c_str(), version); + // When creating a regular executable, automatically define // a new version. + if (this->needs_base_version_) + this->define_base_version(dynpool); Verdef* vd = new Verdef(version, std::vector(), false, false, false, false); this->defs_.push_back(vd); @@ -1588,7 +1625,7 @@ 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_) + if (parameters->options().shared() && this->needs_base_version_) this->define_base_version(dynpool); // We have a new filename. @@ -1672,8 +1709,6 @@ Versions::version_index(const Symbol_table* symtab, const Stringpool* dynpool, Key k; if (!sym->is_from_dynobj() && !sym->is_copied_from_dynobj()) { - if (!parameters->options().shared()) - return elfcpp::VER_NDX_GLOBAL; k = Key(version_key, 0); } else @@ -1720,18 +1755,23 @@ Versions::symbol_section_contents(const Symbol_table* symtab, { unsigned int version_index; const char* version = (*p)->version(); - if (version != NULL) - version_index = this->version_index(symtab, dynpool, *p); - else + if (version == NULL) { if ((*p)->is_defined() && !(*p)->is_from_dynobj()) version_index = elfcpp::VER_NDX_GLOBAL; else version_index = elfcpp::VER_NDX_LOCAL; } + else if (version[0] == '\0') + version_index = elfcpp::VER_NDX_GLOBAL; + 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()) + if ((*p)->version() != NULL + && (*p)->is_defined() + && !(*p)->is_default() + && !(*p)->from_dyn()) version_index |= elfcpp::VERSYM_HIDDEN; elfcpp::Swap<16, big_endian>::writeval(pbuf + (*p)->dynsym_index() * 2, version_index);