// archive.cc -- archive support for gold
-// Copyright (C) 2006-2014 Free Software Foundation, Inc.
+// Copyright (C) 2006-2020 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
return Library_base::SHOULD_INCLUDE_YES;
}
- if (strcmp(sym_name, parameters->entry()) == 0)
+ if (!parameters->options().relocatable())
{
- *why = "entry symbol ";
- *why += sym_name;
- return Library_base::SHOULD_INCLUDE_YES;
+ const char* entry_sym = parameters->entry();
+ if (entry_sym != NULL && strcmp(sym_name, entry_sym) == 0)
+ {
+ *why = "entry symbol ";
+ *why += sym_name;
+ return Library_base::SHOULD_INCLUDE_YES;
+ }
}
return Library_base::SHOULD_INCLUDE_UNKNOWN;
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_(),
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())
// Read the archive symbol map.
+template<int mapsize>
void
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<const elfcpp::Elf_Word*>(p);
- unsigned int nsyms = elfcpp::Swap<32, true>::readval(pword);
+ typedef typename elfcpp::Elf_types<mapsize>::Elf_Addr Entry_type;
+ const Entry_type* pword = reinterpret_cast<const Entry_type*>(p);
+ unsigned long nsyms = convert_types<unsigned long, Entry_type>(
+ elfcpp::Swap<mapsize, true>::readval(pword));
++pword;
// Note that the addition is in units of sizeof(elfcpp::Elf_Word).
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<off_t, Entry_type>(
+ elfcpp::Swap<mapsize, true>::readval(pword));
name_offset += strlen(pnames + name_offset) + 1;
++pword;
if (this->armap_[i].file_offset != last_seen_offset)
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.
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;
int read_size;
Object *obj = NULL;
bool is_elf_obj = false;
+ bool unclaimed = false;
if (is_elf_object(input_file, memoff, &ehdr, &read_size))
{
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<size_t>(off));
+ if (unclaimed)
+ gold_error(_("%s: plugin failed to claim member %s at %zu"),
+ this->name().c_str(), member_name.c_str(),
+ static_cast<size_t>(off));
+ else
+ gold_error(_("%s: member %s at %zu is not an ELF object"),
+ this->name().c_str(), member_name.c_str(),
+ static_cast<size_t>(off));
return NULL;
}
return ret;
}
+// RAII class to ensure we unlock the object if it's a member of a
+// thin archive. We can't use Task_lock_obj in Archive::include_member
+// because the object file is already locked when it's opened by
+// get_elf_object_for_member.
+
+class Thin_archive_object_unlocker
+{
+ public:
+ Thin_archive_object_unlocker(const Task *task, Object* obj)
+ : task_(task), obj_(obj)
+ { }
+
+ ~Thin_archive_object_unlocker()
+ {
+ if (this->obj_->offset() == 0)
+ this->obj_->unlock(this->task_);
+ }
+
+ private:
+ Thin_archive_object_unlocker(const Thin_archive_object_unlocker&);
+ Thin_archive_object_unlocker& operator=(const Thin_archive_object_unlocker&);
+
+ const Task* task_;
+ Object* obj_;
+};
+
// Include an archive member in the link. OFF is the file offset of
// the member header. WHY is the reason we are including this member.
// Return true if we added the member or if we had an error, return
return unconfigured ? false : true;
}
+ // If the object is an external member of a thin archive,
+ // unlock it when we're done here.
+ Thin_archive_object_unlocker unlocker(this->task_, obj);
+
if (mapfile != NULL)
mapfile->report_include_archive_member(obj->name(), sym, why);
if (!input_objects->add_object(obj))
{
- // If this is an external member of a thin archive, unlock the
- // file.
- if (obj->offset() == 0)
- obj->unlock(this->task_);
delete obj;
+ return true;
}
- else
- {
- {
- if (layout->incremental_inputs() != NULL)
- layout->incremental_inputs()->report_object(obj, 0, this, NULL);
- Read_symbols_data sd;
- obj->read_symbols(&sd);
- obj->layout(symtab, layout, &sd);
- obj->add_symbols(symtab, &sd, layout);
- }
-
- // If this is an external member of a thin archive, unlock the file
- // for the next task.
- if (obj->offset() == 0)
- obj->unlock(this->task_);
- this->included_member_ = true;
- }
+ if (layout->incremental_inputs() != NULL)
+ layout->incremental_inputs()->report_object(obj, 0, this, NULL);
+
+ {
+ Read_symbols_data sd;
+ obj->read_symbols(&sd);
+ obj->layout(symtab, layout, &sd);
+ obj->add_symbols(symtab, &sd, layout);
+ }
+ this->included_member_ = true;
return true;
}