X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Fdynobj.cc;h=0a8d897c65ce754c73afada6f0096ecd4f7ae87b;hb=234c306803e0b3c423b3935562a029f3bad04482;hp=cb41402b841b54648162b01b1c962a2ca39ceb30;hpb=abecea76bce25362c9b81d40df7d2f58ee9dc76b;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/dynobj.cc b/gold/dynobj.cc index cb41402b84..0a8d897c65 100644 --- a/gold/dynobj.cc +++ b/gold/dynobj.cc @@ -1,6 +1,6 @@ // dynobj.cc -- dynamic object support for gold -// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2006-2019 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -49,16 +49,23 @@ Dynobj::Dynobj(const std::string& name, Input_file* input_file, off_t offset) // object's filename. The only exception is when the dynamic object // is part of an archive (so the filename is the archive's // filename). In that case, we use just the dynobj's name-in-archive. - this->soname_ = this->input_file()->found_name(); - if (this->offset() != 0) + if (input_file == NULL) + this->soname_ = name; + else { - std::string::size_type open_paren = this->name().find('('); - std::string::size_type close_paren = this->name().find(')'); - if (open_paren != std::string::npos && close_paren != std::string::npos) + this->soname_ = input_file->found_name(); + if (this->offset() != 0) { - // It's an archive, and name() is of the form 'foo.a(bar.so)'. - this->soname_ = this->name().substr(open_paren + 1, - close_paren - (open_paren + 1)); + std::string::size_type open_paren = this->name().find('('); + std::string::size_type close_paren = this->name().find(')'); + if (open_paren != std::string::npos + && close_paren != std::string::npos) + { + // It's an archive, and name() is of the form 'foo.a(bar.so)'. + open_paren += 1; + this->soname_ = this->name().substr(open_paren, + close_paren - open_paren); + } } } } @@ -131,6 +138,7 @@ Sized_dynobj::find_dynsym_sections( break; case elfcpp::SHT_SYMTAB: symtab_shndx = i; + pi = NULL; break; case elfcpp::SHT_GNU_versym: pi = pversym_shndx; @@ -327,6 +335,17 @@ Sized_dynobj::read_dynamic(const unsigned char* pshdrs, template void Sized_dynobj::do_read_symbols(Read_symbols_data* sd) +{ + this->base_read_symbols(sd); +} + +// Read the symbols and sections from a dynamic object. We read the +// dynamic symbols, not the normal symbols. This is common code for +// all target-specific overrides of do_read_symbols(). + +template +void +Sized_dynobj::base_read_symbols(Read_symbols_data* sd) { this->read_section_data(&this->elf_file_, sd); @@ -355,6 +374,17 @@ Sized_dynobj::do_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. @@ -704,10 +734,11 @@ Sized_dynobj::do_add_symbols(Symbol_table* symtab, Version_map version_map; this->make_version_map(sd, &version_map); - // If printing symbol counts or a cross reference table, we want to - // track symbols. + // If printing symbol counts or a cross reference table or + // preparing for an incremental link, we want to track symbols. if (parameters->options().user_set_print_symbol_counts() - || parameters->options().cref()) + || parameters->options().cref() + || parameters->incremental()) { this->symbols_ = new Symbols(); this->symbols_->resize(symcount); @@ -750,6 +781,52 @@ Sized_dynobj::do_add_symbols(Symbol_table* symtab, this->clear_view_cache_marks(); } +template +Archive::Should_include +Sized_dynobj::do_should_include_member(Symbol_table*, + Layout*, + Read_symbols_data*, + std::string*) +{ + return Archive::SHOULD_INCLUDE_YES; +} + +// Iterate over global symbols, calling a visitor class V for each. + +template +void +Sized_dynobj::do_for_all_global_symbols( + Read_symbols_data* sd, + Library_base::Symbol_visitor_base* v) +{ + const char* sym_names = + reinterpret_cast(sd->symbol_names->data()); + const unsigned char* syms = + sd->symbols->data() + sd->external_symbols_offset; + const int sym_size = elfcpp::Elf_sizes::sym_size; + size_t symcount = ((sd->symbols_size - sd->external_symbols_offset) + / sym_size); + const unsigned char* p = syms; + + for (size_t i = 0; i < symcount; ++i, p += sym_size) + { + elfcpp::Sym sym(p); + if (sym.get_st_shndx() != elfcpp::SHN_UNDEF + && sym.get_st_bind() != elfcpp::STB_LOCAL) + v->visit(sym_names + sym.get_st_name()); + } +} + +// Iterate over local symbols, calling a visitor class V for each GOT offset +// associated with a local symbol. + +template +void +Sized_dynobj::do_for_all_local_got_entries( + Got_offset_list::Visitor*) const +{ +} + // Get symbol counts. template @@ -768,7 +845,7 @@ Sized_dynobj::do_get_global_symbol_counts( && (*p)->source() == Symbol::FROM_OBJECT && (*p)->object() == this && (*p)->is_defined() - && (*p)->dynsym_index() != -1U) + && (*p)->has_dynsym_index()) ++count; *used = count; } @@ -869,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(); +#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(); + 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; @@ -901,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, @@ -913,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); @@ -1220,7 +1325,8 @@ Verdef::write(const Stringpool* dynpool, bool is_last, unsigned char* pb) const elfcpp::Verdef_write vd(pb); vd.set_vd_version(elfcpp::VER_DEF_CURRENT); vd.set_vd_flags((this->is_base_ ? elfcpp::VER_FLG_BASE : 0) - | (this->is_weak_ ? elfcpp::VER_FLG_WEAK : 0)); + | (this->is_weak_ ? elfcpp::VER_FLG_WEAK : 0) + | (this->is_info_ ? elfcpp::VER_FLG_INFO : 0)); vd.set_vd_ndx(this->index()); vd.set_vd_cnt(1 + this->deps_.size()); vd.set_vd_hash(Dynobj::elf_hash(this->name())); @@ -1333,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()) { @@ -1352,7 +1458,7 @@ Versions::Versions(const Version_script_info& version_script, Verdef* const vd = new Verdef( version, this->version_script_.get_dependencies(version), - false, false, false); + false, false, false, false); this->defs_.push_back(vd); Key key(version_key, 0); this->version_table_.insert(std::make_pair(key, vd)); @@ -1390,7 +1496,7 @@ Versions::define_base_version(Stringpool* dynpool) name = parameters->options().output_file_name(); name = dynpool->add(name, false, NULL); Verdef* vdbase = new Verdef(name, std::vector(), - true, false, true); + true, false, false, true); this->defs_.push_back(vdbase); this->needs_base_version_ = false; } @@ -1421,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(sym, version, version_key); + this->add_def(dynpool, sym, version, version_key); } else { @@ -1440,7 +1549,7 @@ Versions::record_version(const Symbol_table* symtab, // We've found a symbol SYM defined in version VERSION. void -Versions::add_def(const Symbol* sym, const char* version, +Versions::add_def(Stringpool* dynpool, const Symbol* sym, const char* version, Stringpool::Key version_key) { Key k(version_key, 0); @@ -1466,14 +1575,13 @@ 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. + if (this->needs_base_version_) + this->define_base_version(dynpool); Verdef* vd = new Verdef(version, std::vector(), - false, false, false); + false, false, false, false); this->defs_.push_back(vd); ins.first->second = vd; } @@ -1517,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. @@ -1559,6 +1667,7 @@ Versions::finalize(Symbol_table* symtab, unsigned int dynsym_index, false, false); vsym->set_needs_dynsym_entry(); vsym->set_dynsym_index(dynsym_index); + vsym->set_is_default(); ++dynsym_index; syms->push_back(vsym); // The name is already in the dynamic pool. @@ -1600,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 @@ -1649,12 +1756,22 @@ Versions::symbol_section_contents(const Symbol_table* symtab, unsigned int version_index; const char* version = (*p)->version(); if (version == NULL) - version_index = elfcpp::VER_NDX_GLOBAL; - else + { + 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); @@ -1713,8 +1830,8 @@ Versions::def_section_contents(const Stringpool* dynpool, template void Versions::need_section_contents(const Stringpool* dynpool, - unsigned char** pp, unsigned int *psize, - unsigned int *pentries) const + unsigned char** pp, unsigned int* psize, + unsigned int* pentries) const { gold_assert(this->is_finalized_); gold_assert(!this->needs_.empty());