From fba2c04f31e119eacf142fcbbaabd5a9e63a39ed Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Wed, 6 Jan 2016 20:07:13 +0000 Subject: Vendor import of lld trunk r256945: https://llvm.org/svn/llvm-project/lld/trunk@256945 --- ELF/Config.h | 5 + ELF/Driver.cpp | 28 ++- ELF/Driver.h | 1 - ELF/InputFiles.cpp | 112 +++++------ ELF/InputFiles.h | 15 +- ELF/InputSection.h | 8 + ELF/MarkLive.cpp | 6 +- ELF/OutputSections.cpp | 31 +-- ELF/SymbolTable.cpp | 56 +++--- ELF/SymbolTable.h | 9 +- ELF/Symbols.cpp | 3 +- ELF/Symbols.h | 6 +- ELF/Target.cpp | 2 +- ELF/Writer.cpp | 45 +++-- lib/ReaderWriter/MachO/ArchHandler_arm64.cpp | 17 ++ lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp | 24 ++- .../MachO/MachONormalizedFileFromAtoms.cpp | 210 ++++++++++----------- test/ELF/dt_tags.s | 18 ++ test/ELF/dynamic-reloc.s | 1 + test/ELF/got.s | 18 +- test/ELF/local-got.s | 12 +- test/ELF/relocation-i686.s | 4 +- test/ELF/relocation.s | 6 +- test/ELF/relro.s | 20 +- test/ELF/shared-be.s | 1 + test/ELF/shared.s | 1 + test/ELF/tls-got.s | 16 +- test/ELF/tls-opt-gdie.s | 16 +- test/ELF/tls-opt-gdiele-i686.s | 4 +- test/ELF/tls-opt-iele-i686-nopic.s | 16 +- test/mach-o/arm64-reloc-negDelta32-fixup.yaml | 10 +- test/mach-o/arm64-section-order.yaml | 67 +++++++ test/mach-o/parse-data-relocs-x86_64.yaml | 2 +- 33 files changed, 446 insertions(+), 344 deletions(-) create mode 100644 test/ELF/dt_tags.s create mode 100644 test/mach-o/arm64-section-order.yaml diff --git a/ELF/Config.h b/ELF/Config.h index 7b820f18b8c7..c279b99b43c1 100644 --- a/ELF/Config.h +++ b/ELF/Config.h @@ -30,6 +30,10 @@ enum ELFKind { ELF64BEKind }; +// This struct contains the global configuration for the linker. +// Most fields are direct mapping from the command line options +// and such fields have the same name as the corresponding options. +// Most fields are initialized by the driver. struct Configuration { SymbolBody *EntrySym = nullptr; SymbolBody *MipsGpDisp = nullptr; @@ -76,6 +80,7 @@ struct Configuration { unsigned Optimize = 0; }; +// The only instance of Configuration struct. extern Configuration *Config; } // namespace elf2 diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp index 6d881373b303..2a3ecfa61586 100644 --- a/ELF/Driver.cpp +++ b/ELF/Driver.cpp @@ -57,6 +57,24 @@ static std::pair parseEmulation(StringRef S) { error("Unknown emulation: " + S); } +// Returns slices of MB by parsing MB as an archive file. +// Each slice consists of a member file in the archive. +static std::vector getArchiveMembers(MemoryBufferRef MB) { + ErrorOr> FileOrErr = Archive::create(MB); + error(FileOrErr, "Failed to parse archive"); + std::unique_ptr File = std::move(*FileOrErr); + + std::vector V; + for (const ErrorOr &C : File->children()) { + error(C, "Could not get the child of the archive " + File->getFileName()); + ErrorOr MbOrErr = C->getMemoryBufferRef(); + error(MbOrErr, "Could not get the buffer for a child of the archive " + + File->getFileName()); + V.push_back(*MbOrErr); + } + return V; +} + // Opens and parses a file. Path has to be resolved already. // Newly created memory buffers are owned by this driver. void LinkerDriver::addFile(StringRef Path) { @@ -75,19 +93,17 @@ void LinkerDriver::addFile(StringRef Path) { return; case file_magic::archive: if (WholeArchive) { - auto File = make_unique(MBRef); - for (MemoryBufferRef &MB : File->getMembers()) - Files.push_back(createELFFile(MB)); - OwningArchives.emplace_back(std::move(File)); + for (MemoryBufferRef MB : getArchiveMembers(MBRef)) + Files.push_back(createObjectFile(MB)); return; } Files.push_back(make_unique(MBRef)); return; case file_magic::elf_shared_object: - Files.push_back(createELFFile(MBRef)); + Files.push_back(createSharedFile(MBRef)); return; default: - Files.push_back(createELFFile(MBRef)); + Files.push_back(createObjectFile(MBRef)); } } diff --git a/ELF/Driver.h b/ELF/Driver.h index 2641155104dc..bfae2b3f4dfa 100644 --- a/ELF/Driver.h +++ b/ELF/Driver.h @@ -38,7 +38,6 @@ private: llvm::BumpPtrAllocator Alloc; bool WholeArchive = false; std::vector> Files; - std::vector> OwningArchives; std::vector> OwningMBs; }; diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp index e0827a3ee43d..d9df6abbf233 100644 --- a/ELF/InputFiles.cpp +++ b/ELF/InputFiles.cpp @@ -37,10 +37,9 @@ ELFFileBase::ELFFileBase(Kind K, MemoryBufferRef M) template ELFKind ELFFileBase::getELFKind() { - using llvm::support::little; - if (ELFT::Is64Bits) - return ELFT::TargetEndianness == little ? ELF64LEKind : ELF64BEKind; - return ELFT::TargetEndianness == little ? ELF32LEKind : ELF32BEKind; + if (ELFT::TargetEndianness == support::little) + return ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind; + return ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind; } template @@ -63,8 +62,7 @@ template uint32_t ELFFileBase::getSectionIndex(const Elf_Sym &Sym) const { uint32_t I = Sym.st_shndx; if (I == ELF::SHN_XINDEX) - return this->ELFObj.getExtendedSymbolTableIndex(&Sym, this->Symtab, - SymtabSHNDX); + return ELFObj.getExtendedSymbolTableIndex(&Sym, Symtab, SymtabSHNDX); if (I >= ELF::SHN_LORESERVE || I == ELF::SHN_ABS) return 0; return I; @@ -74,7 +72,7 @@ template void ELFFileBase::initStringTable() { if (!Symtab) return; ErrorOr StringTableOrErr = ELFObj.getStringTableForSymtab(*Symtab); - error(StringTableOrErr.getError()); + error(StringTableOrErr); StringTable = *StringTableOrErr; } @@ -108,9 +106,9 @@ ObjectFile::getLocalSymbol(uintX_t SymIndex) { } template -void elf2::ObjectFile::parse(DenseSet &Comdats) { +void ObjectFile::parse(DenseSet &ComdatGroups) { // Read section and symbol tables. - initializeSections(Comdats); + initializeSections(ComdatGroups); initializeSymbols(); } @@ -139,7 +137,7 @@ ObjectFile::getShtGroupEntries(const Elf_Shdr &Sec) { const ELFFile &Obj = this->ELFObj; ErrorOr> EntriesOrErr = Obj.template getSectionContentsAsArray(&Sec); - error(EntriesOrErr.getError()); + error(EntriesOrErr); ArrayRef Entries = *EntriesOrErr; if (Entries.empty() || Entries[0] != GRP_COMDAT) error("Unsupported SHT_GROUP format"); @@ -174,7 +172,7 @@ static bool shouldMerge(const typename ELFFile::Elf_Shdr &Sec) { } template -void elf2::ObjectFile::initializeSections(DenseSet &Comdats) { +void ObjectFile::initializeSections(DenseSet &ComdatGroups) { uint64_t Size = this->ELFObj.getNumSections(); Sections.resize(Size); unsigned I = -1; @@ -187,7 +185,7 @@ void elf2::ObjectFile::initializeSections(DenseSet &Comdats) { switch (Sec.sh_type) { case SHT_GROUP: Sections[I] = &InputSection::Discarded; - if (Comdats.insert(getShtGroupSignature(Sec)).second) + if (ComdatGroups.insert(getShtGroupSignature(Sec)).second) continue; for (GroupEntryType E : getShtGroupEntries(Sec)) { uint32_t SecIndex = E; @@ -235,7 +233,7 @@ void elf2::ObjectFile::initializeSections(DenseSet &Comdats) { } template InputSectionBase * -elf2::ObjectFile::createInputSection(const Elf_Shdr &Sec) { +ObjectFile::createInputSection(const Elf_Shdr &Sec) { ErrorOr NameOrErr = this->ELFObj.getSectionName(&Sec); error(NameOrErr); StringRef Name = *NameOrErr; @@ -250,29 +248,29 @@ elf2::ObjectFile::createInputSection(const Elf_Shdr &Sec) { // A MIPS object file has a special section that contains register // usage info, which needs to be handled by the linker specially. if (Config->EMachine == EM_MIPS && Name == ".reginfo") { - MipsReginfo = new (this->Alloc) MipsReginfoInputSection(this, &Sec); + MipsReginfo = new (Alloc) MipsReginfoInputSection(this, &Sec); return MipsReginfo; } if (Name == ".eh_frame") - return new (this->EHAlloc.Allocate()) EHInputSection(this, &Sec); + return new (EHAlloc.Allocate()) EHInputSection(this, &Sec); if (shouldMerge(Sec)) - return new (this->MAlloc.Allocate()) MergeInputSection(this, &Sec); - return new (this->Alloc) InputSection(this, &Sec); + return new (MAlloc.Allocate()) MergeInputSection(this, &Sec); + return new (Alloc) InputSection(this, &Sec); } -template void elf2::ObjectFile::initializeSymbols() { +template void ObjectFile::initializeSymbols() { this->initStringTable(); Elf_Sym_Range Syms = this->getNonLocalSymbols(); uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); - this->SymbolBodies.reserve(NumSymbols); + SymbolBodies.reserve(NumSymbols); for (const Elf_Sym &Sym : Syms) - this->SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym)); + SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym)); } template InputSectionBase * -elf2::ObjectFile::getSection(const Elf_Sym &Sym) const { +ObjectFile::getSection(const Elf_Sym &Sym) const { uint32_t Index = this->getSectionIndex(Sym); if (Index == 0) return nullptr; @@ -282,19 +280,19 @@ elf2::ObjectFile::getSection(const Elf_Sym &Sym) const { } template -SymbolBody *elf2::ObjectFile::createSymbolBody(StringRef StringTable, +SymbolBody *ObjectFile::createSymbolBody(StringRef StringTable, const Elf_Sym *Sym) { ErrorOr NameOrErr = Sym->getName(StringTable); - error(NameOrErr.getError()); + error(NameOrErr); StringRef Name = *NameOrErr; switch (Sym->st_shndx) { case SHN_UNDEF: - return new (this->Alloc) UndefinedElf(Name, *Sym); + return new (Alloc) UndefinedElf(Name, *Sym); case SHN_COMMON: - return new (this->Alloc) DefinedCommon( - Name, Sym->st_size, Sym->st_value, - Sym->getBinding() == llvm::ELF::STB_WEAK, Sym->getVisibility()); + return new (Alloc) DefinedCommon(Name, Sym->st_size, Sym->st_value, + Sym->getBinding() == llvm::ELF::STB_WEAK, + Sym->getVisibility()); } switch (Sym->getBinding()) { @@ -305,20 +303,16 @@ SymbolBody *elf2::ObjectFile::createSymbolBody(StringRef StringTable, case STB_GNU_UNIQUE: { InputSectionBase *Sec = getSection(*Sym); if (Sec == &InputSection::Discarded) - return new (this->Alloc) UndefinedElf(Name, *Sym); - return new (this->Alloc) DefinedRegular(Name, *Sym, Sec); + return new (Alloc) UndefinedElf(Name, *Sym); + return new (Alloc) DefinedRegular(Name, *Sym, Sec); } } } -static std::unique_ptr openArchive(MemoryBufferRef MB) { - ErrorOr> ArchiveOrErr = Archive::create(MB); - error(ArchiveOrErr, "Failed to parse archive"); - return std::move(*ArchiveOrErr); -} - void ArchiveFile::parse() { - File = openArchive(MB); + ErrorOr> FileOrErr = Archive::create(MB); + error(FileOrErr, "Failed to parse archive"); + File = std::move(*FileOrErr); // Allocate a buffer for Lazy objects. size_t NumSyms = File->getNumberOfSymbols(); @@ -345,28 +339,9 @@ MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) { return *RefOrErr; } -std::vector ArchiveFile::getMembers() { - File = openArchive(MB); - - std::vector Result; - for (auto &ChildOrErr : File->children()) { - error(ChildOrErr, - "Could not get the child of the archive " + File->getFileName()); - const Archive::Child Child(*ChildOrErr); - ErrorOr MbOrErr = Child.getMemoryBufferRef(); - if (!MbOrErr) - error(MbOrErr, "Could not get the buffer for a child of the archive " + - File->getFileName()); - Result.push_back(MbOrErr.get()); - } - return Result; -} - template SharedFile::SharedFile(MemoryBufferRef M) - : ELFFileBase(Base::SharedKind, M) { - AsNeeded = Config->AsNeeded; -} + : ELFFileBase(Base::SharedKind, M), AsNeeded(Config->AsNeeded) {} template const typename ELFFile::Elf_Shdr * @@ -379,6 +354,8 @@ SharedFile::getSection(const Elf_Sym &Sym) const { return *Ret; } +// Partially parse the shared object file so that we can call +// getSoName on this object. template void SharedFile::parseSoName() { typedef typename ELFFile::Elf_Dyn Elf_Dyn; typedef typename ELFFile::uintX_t uintX_t; @@ -405,7 +382,7 @@ template void SharedFile::parseSoName() { } this->initStringTable(); - this->SoName = this->getName(); + SoName = this->getName(); if (!DynamicSec) return; @@ -418,13 +395,14 @@ template void SharedFile::parseSoName() { uintX_t Val = Dyn.getVal(); if (Val >= this->StringTable.size()) error("Invalid DT_SONAME entry"); - this->SoName = StringRef(this->StringTable.data() + Val); + SoName = StringRef(this->StringTable.data() + Val); return; } } } -template void SharedFile::parse() { +// Fully parse the shared object file. This must be called after parseSoName(). +template void SharedFile::parseRest() { Elf_Sym_Range Syms = this->getNonLocalSymbols(); uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end()); SymbolBodies.reserve(NumSymbols); @@ -456,7 +434,7 @@ static std::unique_ptr createELFFileAux(MemoryBufferRef MB) { } template