X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Farchive.cc;h=75ad5517b8bed814470f1ac8c9994e56da7c30ee;hb=40c75bc8b07abc5d5774ea1c439b69c96e7fd485;hp=cc69c40fb9887adea97a35dda4857c4a3783a959;hpb=cb5cf5e26ea2e42937a2ce1b662e61e4772ba6f9;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/archive.cc b/gold/archive.cc index cc69c40fb9..75ad5517b8 100644 --- a/gold/archive.cc +++ b/gold/archive.cc @@ -1,6 +1,6 @@ // archive.cc -- archive support for gold -// Copyright (C) 2006-2015 Free Software Foundation, Inc. +// Copyright (C) 2006-2020 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -193,6 +193,8 @@ const char Archive::armagt[sarmag] = const char Archive::arfmag[2] = { '`', '\n' }; +const char Archive::sym64name[7] = { '/', 'S', 'Y', 'M', '6', '4', '/' }; + Archive::Archive(const std::string& name, Input_file* input_file, bool is_thin_archive, Dirsearch* dirpath, Task* task) : Library_base(task), name_(name), input_file_(input_file), armap_(), @@ -225,7 +227,12 @@ Archive::setup() off_t off = sarmag; if (armap_name.empty()) { - this->read_armap(sarmag + sizeof(Archive_header), armap_size); + this->read_armap<32>(sarmag + sizeof(Archive_header), armap_size); + off = sarmag + sizeof(Archive_header) + armap_size; + } + else if (armap_name == "/SYM64/") + { + this->read_armap<64>(sarmag + sizeof(Archive_header), armap_size); off = sarmag + sizeof(Archive_header) + armap_size; } else if (!this->input_file_->options().whole_archive()) @@ -277,6 +284,7 @@ Archive::unlock_nested_archives() // Read the archive symbol map. +template void Archive::read_armap(off_t start, section_size_type size) { @@ -290,8 +298,10 @@ Archive::read_armap(off_t start, section_size_type size) const unsigned char* p = this->get_view(start, size, true, false); // Numbers in the armap are always big-endian. - const elfcpp::Elf_Word* pword = reinterpret_cast(p); - unsigned int nsyms = elfcpp::Swap<32, true>::readval(pword); + typedef typename elfcpp::Elf_types::Elf_Addr Entry_type; + const Entry_type* pword = reinterpret_cast(p); + unsigned long nsyms = convert_types( + elfcpp::Swap::readval(pword)); ++pword; // Note that the addition is in units of sizeof(elfcpp::Elf_Word). @@ -303,10 +313,11 @@ Archive::read_armap(off_t start, section_size_type size) this->armap_.resize(nsyms); section_offset_type name_offset = 0; - for (unsigned int i = 0; i < nsyms; ++i) + for (unsigned long i = 0; i < nsyms; ++i) { this->armap_[i].name_offset = name_offset; - this->armap_[i].file_offset = elfcpp::Swap<32, true>::readval(pword); + this->armap_[i].file_offset = convert_types( + elfcpp::Swap::readval(pword)); name_offset += strlen(pnames + name_offset) + 1; ++pword; if (this->armap_[i].file_offset != last_seen_offset) @@ -394,6 +405,11 @@ Archive::interpret_header(const Archive_header* hdr, off_t off, if (!pname->empty()) pname->clear(); } + else if (memcmp(hdr->ar_name, sym64name, sizeof sym64name) == 0) + { + // This is the symbol table, 64-bit version. + pname->assign(sym64name, sizeof sym64name); + } else if (hdr->ar_name[1] == '/') { // This is the extended name table. @@ -544,7 +560,9 @@ Archive::const_iterator::read_next_header() this->header_.off = this->off_; // Skip special members. - if (!this->header_.name.empty() && this->header_.name != "/") + if (!this->header_.name.empty() + && this->header_.name != "/" + && this->header_.name != "/SYM64/") return; this->off_ += sizeof(Archive_header) + this->header_.size; @@ -672,6 +690,7 @@ Archive::get_elf_object_for_member(off_t off, bool* punconfigured) int read_size; Object *obj = NULL; bool is_elf_obj = false; + bool unclaimed = false; if (is_elf_object(input_file, memoff, &ehdr, &read_size)) { @@ -698,12 +717,20 @@ Archive::get_elf_object_for_member(off_t off, bool* punconfigured) delete obj; return plugin_obj; } + + unclaimed = true; } if (!is_elf_obj) { - gold_error(_("%s: member at %zu is not an ELF object"), - this->name().c_str(), static_cast(off)); + if (unclaimed) + gold_error(_("%s: plugin failed to claim member %s at %zu"), + this->name().c_str(), member_name.c_str(), + static_cast(off)); + else + gold_error(_("%s: member %s at %zu is not an ELF object"), + this->name().c_str(), member_name.c_str(), + static_cast(off)); return NULL; }