[lld] r289280 - COFF: New symbol table design.
Mike Aizatsky via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 12 09:36:56 PST 2016
Peter,
I think this breaks asan bot:
http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/414/steps/check-lld%20asan/logs/stdio
=================================================================
==6557==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 56 byte(s) in 1 object(s) allocated from:
#0 0x706540 in operator new(unsigned long)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:82
#1 0x7a7b39 in
lld::coff::DefinedImportThunk::DefinedImportThunk(llvm::StringRef,
lld::coff::DefinedImportData*, unsigned short)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/Symbols.cpp:64:26
#2 0x79e014 in replaceBody<lld::coff::DefinedImportThunk,
llvm::StringRef &, lld::coff::DefinedImportData *&, unsigned short &>
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/Symbols.h:417:24
#3 0x79e014 in
lld::coff::SymbolTable::addImportThunk(llvm::StringRef,
lld::coff::DefinedImportData*, unsigned short)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:276
#4 0x780413 in lld::coff::ImportFile::parse()
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/InputFiles.cpp:349:15
#5 0x79719b in
lld::coff::SymbolTable::addFile(lld::coff::InputFile*)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:32:9
#6 0x79b35e in
lld::coff::SymbolTable::addMemberFile(lld::coff::ArchiveFile*,
llvm::object::Archive::Symbol)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:292:3
#7 0x79b715 in
lld::coff::SymbolTable::addLazy(lld::coff::ArchiveFile*,
llvm::object::Archive::Symbol)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:156:3
#8 0x775f2c in lld::coff::ArchiveFile::parse()
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/InputFiles.cpp:60:13
#9 0x79719b in
lld::coff::SymbolTable::addFile(lld::coff::InputFile*)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/SymbolTable.cpp:32:9
#10 0x735c7b in lld::coff::LinkerDriver::link(llvm::ArrayRef<char
const*>) /mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/Driver.cpp:580:12
#11 0x72eaa6 in lld::coff::link(llvm::ArrayRef<char const*>)
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/COFF/Driver.cpp:49:11
#12 0x70adfd in main
/mnt/b/sanitizer-buildbot2/sanitizer-x86_64-linux-bootstrap/build/llvm/tools/lld/tools/lld/lld.cpp:106:13
#13 0x7f899f22af44 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x21f44)
SUMMARY: AddressSanitizer: 56 byte(s) leaked in 1 allocation(s).
On Fri, Dec 9, 2016 at 2:05 PM Peter Collingbourne via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: pcc
> Date: Fri Dec 9 15:55:24 2016
> New Revision: 289280
>
> URL: http://llvm.org/viewvc/llvm-project?rev=289280&view=rev
> Log:
> COFF: New symbol table design.
>
> This ports the ELF linker's symbol table design, introduced in r268178,
> to the COFF linker.
>
> Differential Revision: http://reviews.llvm.org/D21166
>
> Modified:
> lld/trunk/COFF/Chunks.cpp
> lld/trunk/COFF/Chunks.h
> lld/trunk/COFF/Config.h
> lld/trunk/COFF/DLL.cpp
> lld/trunk/COFF/Driver.cpp
> lld/trunk/COFF/Driver.h
> lld/trunk/COFF/DriverUtils.cpp
> lld/trunk/COFF/ICF.cpp
> lld/trunk/COFF/InputFiles.cpp
> lld/trunk/COFF/InputFiles.h
> lld/trunk/COFF/MarkLive.cpp
> lld/trunk/COFF/SymbolTable.cpp
> lld/trunk/COFF/SymbolTable.h
> lld/trunk/COFF/Symbols.cpp
> lld/trunk/COFF/Symbols.h
> lld/trunk/COFF/Writer.cpp
> lld/trunk/test/COFF/include2.test
> lld/trunk/test/COFF/order.test
> lld/trunk/test/COFF/symtab.test
>
> Modified: lld/trunk/COFF/Chunks.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/Chunks.cpp (original)
> +++ lld/trunk/COFF/Chunks.cpp Fri Dec 9 15:55:24 2016
> @@ -150,7 +150,7 @@ void SectionChunk::writeTo(uint8_t *Buf)
> // Apply relocations.
> for (const coff_relocation &Rel : Relocs) {
> uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress;
> - SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
> + SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex);
> Defined *Sym = cast<Defined>(Body);
> uint64_t P = RVA + Rel.VirtualAddress;
> switch (Config->Machine) {
> @@ -203,7 +203,7 @@ void SectionChunk::getBaserels(std::vect
> uint8_t Ty = getBaserelType(Rel);
> if (Ty == IMAGE_REL_BASED_ABSOLUTE)
> continue;
> - SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
> + SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex);
> if (isa<DefinedAbsolute>(Body))
> continue;
> Res->emplace_back(RVA + Rel.VirtualAddress, Ty);
>
> Modified: lld/trunk/COFF/Chunks.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/Chunks.h (original)
> +++ lld/trunk/COFF/Chunks.h Fri Dec 9 15:55:24 2016
> @@ -28,7 +28,6 @@ using llvm::object::COFFSymbolRef;
> using llvm::object::SectionRef;
> using llvm::object::coff_relocation;
> using llvm::object::coff_section;
> -using llvm::sys::fs::file_magic;
>
> class Baserel;
> class Defined;
>
> Modified: lld/trunk/COFF/Config.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/Config.h (original)
> +++ lld/trunk/COFF/Config.h Fri Dec 9 15:55:24 2016
> @@ -26,7 +26,8 @@ using llvm::StringRef;
> class DefinedAbsolute;
> class DefinedRelative;
> class StringChunk;
> -class Undefined;
> +struct Symbol;
> +class SymbolBody;
>
> // Short aliases.
> static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
> @@ -37,7 +38,7 @@ static const auto I386 = llvm::COFF::IMA
> struct Export {
> StringRef Name; // N in /export:N or /export:E=N
> StringRef ExtName; // E in /export:E=N
> - Undefined *Sym = nullptr;
> + SymbolBody *Sym = nullptr;
> uint16_t Ordinal = 0;
> bool Noname = false;
> bool Data = false;
> @@ -76,7 +77,7 @@ struct Configuration {
> llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN;
> bool Verbose = false;
> WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
> - Undefined *Entry = nullptr;
> + SymbolBody *Entry = nullptr;
> bool NoEntry = false;
> std::string OutputFile;
> bool DoGC = true;
> @@ -89,7 +90,7 @@ struct Configuration {
> StringRef PDBPath;
>
> // Symbols in this set are considered as live by the garbage collector.
> - std::set<Undefined *> GCRoot;
> + std::set<SymbolBody *> GCRoot;
>
> std::set<StringRef> NoDefaultLibs;
> bool NoDefaultLibAll = false;
> @@ -100,11 +101,11 @@ struct Configuration {
> std::vector<Export> Exports;
> std::set<std::string> DelayLoads;
> std::map<std::string, int> DLLOrder;
> - Undefined *DelayLoadHelper = nullptr;
> + SymbolBody *DelayLoadHelper = nullptr;
>
> // Used for SafeSEH.
> - DefinedRelative *SEHTable = nullptr;
> - DefinedAbsolute *SEHCount = nullptr;
> + Symbol *SEHTable = nullptr;
> + Symbol *SEHCount = nullptr;
>
> // Used for /opt:lldlto=N
> unsigned LTOOptLevel = 2;
>
> Modified: lld/trunk/COFF/DLL.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/DLL.cpp (original)
> +++ lld/trunk/COFF/DLL.cpp Fri Dec 9 15:55:24 2016
> @@ -324,7 +324,7 @@ public:
> if (E.ForwardChunk) {
> write32le(P, E.ForwardChunk->getRVA());
> } else {
> - write32le(P, cast<Defined>(E.Sym->repl())->getRVA());
> + write32le(P, cast<Defined>(E.Sym)->getRVA());
> }
> }
> }
>
> Modified: lld/trunk/COFF/Driver.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/Driver.cpp (original)
> +++ lld/trunk/COFF/Driver.cpp Fri Dec 9 15:55:24 2016
> @@ -207,10 +207,10 @@ void LinkerDriver::addLibSearchPaths() {
> }
> }
>
> -Undefined *LinkerDriver::addUndefined(StringRef Name) {
> - Undefined *U = Symtab.addUndefined(Name);
> - Config->GCRoot.insert(U);
> - return U;
> +SymbolBody *LinkerDriver::addUndefined(StringRef Name) {
> + SymbolBody *B = Symtab.addUndefined(Name);
> + Config->GCRoot.insert(B);
> + return B;
> }
>
> // Symbol names are mangled by appending "_" prefix on x86.
> @@ -232,7 +232,7 @@ StringRef LinkerDriver::findDefaultEntry
> };
> for (auto E : Entries) {
> StringRef Entry = Symtab.findMangle(mangle(E[0]));
> - if (!Entry.empty() && !isa<Undefined>(Symtab.find(Entry)->Body))
> + if (!Entry.empty() && !isa<Undefined>(Symtab.find(Entry)->body()))
> return mangle(E[1]);
> }
> return "";
> @@ -715,7 +715,7 @@ void LinkerDriver::link(ArrayRef<const c
> Symbol *Sym = Symtab.find(From);
> if (!Sym)
> continue;
> - if (auto *U = dyn_cast<Undefined>(Sym->Body))
> + if (auto *U = dyn_cast<Undefined>(Sym->body()))
> if (!U->WeakAlias)
> U->WeakAlias = Symtab.addUndefined(To);
> }
> @@ -734,7 +734,7 @@ void LinkerDriver::link(ArrayRef<const c
> Symtab.addCombinedLTOObjects();
>
> // Make sure we have resolved all symbols.
> - Symtab.reportRemainingUndefines(/*Resolve=*/true);
> + Symtab.reportRemainingUndefines();
>
> // Windows specific -- if no /subsystem is given, we need to infer
> // that from entry point name.
>
> Modified: lld/trunk/COFF/Driver.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/Driver.h (original)
> +++ lld/trunk/COFF/Driver.h Fri Dec 9 15:55:24 2016
> @@ -59,6 +59,7 @@ private:
>
> class LinkerDriver {
> public:
> + LinkerDriver() { coff::Symtab = &Symtab; }
> void link(llvm::ArrayRef<const char *> Args);
>
> // Used by the resolver to parse .drectve section contents.
> @@ -86,7 +87,7 @@ private:
> std::vector<StringRef> SearchPaths;
> std::set<std::string> VisitedFiles;
>
> - Undefined *addUndefined(StringRef Sym);
> + SymbolBody *addUndefined(StringRef Sym);
> StringRef mangle(StringRef Sym);
>
> // Windows specific -- "main" is not the only main function in Windows.
>
> Modified: lld/trunk/COFF/DriverUtils.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/DriverUtils.cpp (original)
> +++ lld/trunk/COFF/DriverUtils.cpp Fri Dec 9 15:55:24 2016
> @@ -510,13 +510,13 @@ void fixupExports() {
> }
>
> for (Export &E : Config->Exports) {
> + SymbolBody *Sym = E.Sym;
> if (!E.ForwardTo.empty()) {
> E.SymbolName = E.Name;
> - } else if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
> - E.SymbolName = U->getName();
> - } else {
> - E.SymbolName = E.Sym->getName();
> - }
> + } else if (auto *U = dyn_cast<Undefined>(Sym))
> + if (U->WeakAlias)
> + Sym = U->WeakAlias;
> + E.SymbolName = Sym->getName();
> }
>
> for (Export &E : Config->Exports) {
>
> Modified: lld/trunk/COFF/ICF.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/ICF.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/ICF.cpp (original)
> +++ lld/trunk/COFF/ICF.cpp Fri Dec 9 15:55:24 2016
> @@ -115,8 +115,8 @@ bool ICF::equalsConstant(const SectionCh
> R1.VirtualAddress != R2.VirtualAddress) {
> return false;
> }
> - SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex)->repl();
> - SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex)->repl();
> + SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex);
> + SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex);
> if (B1 == B2)
> return true;
> if (auto *D1 = dyn_cast<DefinedRegular>(B1))
> @@ -141,8 +141,8 @@ bool ICF::equalsConstant(const SectionCh
> bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) {
> // Compare relocations.
> auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) {
> - SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex)->repl();
> - SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex)->repl();
> + SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex);
> + SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex);
> if (B1 == B2)
> return true;
> if (auto *D1 = dyn_cast<DefinedRegular>(B1))
>
> Modified: lld/trunk/COFF/InputFiles.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/InputFiles.cpp (original)
> +++ lld/trunk/COFF/InputFiles.cpp Fri Dec 9 15:55:24 2016
> @@ -12,7 +12,9 @@
> #include "Driver.h"
> #include "Error.h"
> #include "InputFiles.h"
> +#include "SymbolTable.h"
> #include "Symbols.h"
> +#include "lld/Support/Memory.h"
> #include "llvm/ADT/SmallVector.h"
> #include "llvm/ADT/Triple.h"
> #include "llvm/ADT/Twine.h"
> @@ -39,13 +41,13 @@ using namespace llvm::support::endian;
>
> using llvm::Triple;
> using llvm::support::ulittle32_t;
> +using llvm::sys::fs::file_magic;
> +using llvm::sys::fs::identify_magic;
>
> namespace lld {
> namespace coff {
>
> -int InputFile::NextIndex = 0;
> LLVMContext BitcodeFile::Context;
> -std::mutex BitcodeFile::Mu;
>
> ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
>
> @@ -53,14 +55,6 @@ void ArchiveFile::parse() {
> // Parse a MemoryBufferRef as an archive file.
> File = check(Archive::create(MB), toString(this));
>
> - // Allocate a buffer for Lazy objects.
> - size_t NumSyms = File->getNumberOfSymbols();
> - LazySymbols.reserve(NumSyms);
> -
> - // Read the symbol table to construct Lazy objects.
> - for (const Archive::Symbol &Sym : File->symbols())
> - LazySymbols.emplace_back(this, Sym);
> -
> // Seen is a map from member files to boolean values. Initially
> // all members are mapped to false, which indicates all these files
> // are not read yet.
> @@ -69,18 +63,22 @@ void ArchiveFile::parse() {
> Seen[Child.getChildOffset()].clear();
> if (Err)
> fatal(Err, toString(this));
> +
> + // Read the symbol table to construct Lazy objects.
> + for (const Archive::Symbol &Sym : File->symbols())
> + Symtab->addLazy(this, Sym);
> }
>
> // Returns a buffer pointing to a member file containing a given symbol.
> // This function is thread-safe.
> -MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
> +InputFile *ArchiveFile::getMember(const Archive::Symbol *Sym) {
> const Archive::Child &C =
> check(Sym->getMember(),
> "could not get the member for symbol " + Sym->getName());
>
> // Return an empty buffer if we have already returned the same buffer.
> if (Seen[C.getChildOffset()].test_and_set())
> - return MemoryBufferRef();
> + return nullptr;
>
> MemoryBufferRef MB =
> check(C.getMemoryBufferRef(),
> @@ -90,10 +88,21 @@ MemoryBufferRef ArchiveFile::getMember(c
> Driver->Cpio->append(relativeToRoot(check(C.getFullName())),
> MB.getBuffer());
>
> - return MB;
> -}
> + file_magic Magic = identify_magic(MB.getBuffer());
> + if (Magic == file_magic::coff_import_library)
> + return make<ImportFile>(MB);
> +
> + InputFile *Obj;
> + if (Magic == file_magic::coff_object)
> + Obj = make<ObjectFile>(MB);
> + else if (Magic == file_magic::bitcode)
> + Obj = make<BitcodeFile>(MB);
> + else
> + fatal("unknown file type: " + MB.getBufferIdentifier());
>
> -MutableArrayRef<Lazy> ArchiveFile::getLazySymbols() { return LazySymbols;
> }
> + Obj->ParentName = getName();
> + return Obj;
> +}
>
> void ObjectFile::parse() {
> // Parse a memory buffer as a COFF file.
> @@ -167,7 +176,7 @@ void ObjectFile::initializeSymbols() {
> uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
> SymbolBodies.reserve(NumSymbols);
> SparseSymbolBodies.resize(NumSymbols);
> - SmallVector<std::pair<Undefined *, uint32_t>, 8> WeakAliases;
> + SmallVector<std::pair<SymbolBody *, uint32_t>, 8> WeakAliases;
> int32_t LastSectionNumber = 0;
> for (uint32_t I = 0; I < NumSymbols; ++I) {
> // Get a COFFSymbolRef object.
> @@ -188,7 +197,7 @@ void ObjectFile::initializeSymbols() {
> Body = createUndefined(Sym);
> uint32_t TagIndex =
> static_cast<const coff_aux_weak_external *>(AuxP)->TagIndex;
> - WeakAliases.emplace_back((Undefined *)Body, TagIndex);
> + WeakAliases.emplace_back(Body, TagIndex);
> } else {
> Body = createDefined(Sym, AuxP, IsFirst);
> }
> @@ -199,23 +208,30 @@ void ObjectFile::initializeSymbols() {
> I += Sym.getNumberOfAuxSymbols();
> LastSectionNumber = Sym.getSectionNumber();
> }
> - for (auto WeakAlias : WeakAliases)
> - WeakAlias.first->WeakAlias = SparseSymbolBodies[WeakAlias.second];
> + for (auto WeakAlias : WeakAliases) {
> + auto *U = dyn_cast<Undefined>(WeakAlias.first);
> + if (!U)
> + continue;
> + // Report an error if two undefined symbols have different weak
> aliases.
> + if (U->WeakAlias && U->WeakAlias !=
> SparseSymbolBodies[WeakAlias.second])
> + Symtab->reportDuplicate(U->symbol(), this);
> + U->WeakAlias = SparseSymbolBodies[WeakAlias.second];
> + }
> }
>
> -Undefined *ObjectFile::createUndefined(COFFSymbolRef Sym) {
> +SymbolBody *ObjectFile::createUndefined(COFFSymbolRef Sym) {
> StringRef Name;
> COFFObj->getSymbolName(Sym, Name);
> - return new (Alloc) Undefined(Name);
> + return Symtab->addUndefined(Name, this, Sym.isWeakExternal())->body();
> }
>
> -Defined *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
> - bool IsFirst) {
> +SymbolBody *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
> + bool IsFirst) {
> StringRef Name;
> if (Sym.isCommon()) {
> auto *C = new (Alloc) CommonChunk(Sym);
> Chunks.push_back(C);
> - return new (Alloc) DefinedCommon(this, Sym, C);
> + return Symtab->addCommon(this, Sym, C)->body();
> }
> if (Sym.isAbsolute()) {
> COFFObj->getSymbolName(Sym, Name);
> @@ -228,7 +244,10 @@ Defined *ObjectFile::createDefined(COFFS
> SEHCompat = true;
> return nullptr;
> }
> - return new (Alloc) DefinedAbsolute(Name, Sym);
> + if (Sym.isExternal())
> + return Symtab->addAbsolute(Name, Sym)->body();
> + else
> + return new (Alloc) DefinedAbsolute(Name, Sym);
> }
> int32_t SectionNumber = Sym.getSectionNumber();
> if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
> @@ -258,7 +277,11 @@ Defined *ObjectFile::createDefined(COFFS
> SC->Checksum = Aux->CheckSum;
> }
>
> - auto *B = new (Alloc) DefinedRegular(this, Sym, SC);
> + DefinedRegular *B;
> + if (Sym.isExternal())
> + B = cast<DefinedRegular>(Symtab->addRegular(this, Sym, SC)->body());
> + else
> + B = new (Alloc) DefinedRegular(this, Sym, SC);
> if (SC->isCOMDAT() && Sym.getValue() == 0 && !AuxP)
> SC->setSymbol(B);
>
> @@ -320,22 +343,23 @@ void ImportFile::parse() {
> ExtName = ExtName.substr(0, ExtName.find('@'));
> break;
> }
> - ImpSym = new (Alloc) DefinedImportData(DLLName, ImpName, ExtName, Hdr);
> - SymbolBodies.push_back(ImpSym);
> +
> + this->Hdr = Hdr;
> + ExternalName = ExtName;
> +
> + ImpSym = cast<DefinedImportData>(
> + Symtab->addImportData(ImpName, this)->body());
>
> // If type is function, we need to create a thunk which jump to an
> // address pointed by the __imp_ symbol. (This allows you to call
> // DLL functions just like regular non-DLL functions.)
> if (Hdr->getType() != llvm::COFF::IMPORT_CODE)
> return;
> - ThunkSym = new (Alloc) DefinedImportThunk(Name, ImpSym, Hdr->Machine);
> - SymbolBodies.push_back(ThunkSym);
> + ThunkSym = cast<DefinedImportThunk>(
> + Symtab->addImportThunk(Name, ImpSym, Hdr->Machine)->body());
> }
>
> void BitcodeFile::parse() {
> - // Usually parse() is thread-safe, but bitcode file is an exception.
> - std::lock_guard<std::mutex> Lock(Mu);
> -
> Context.enableDebugTypeODRUniquing();
> ErrorOr<std::unique_ptr<LTOModule>> ModOrErr =
> LTOModule::createFromBuffer(
> Context, MB.getBufferStart(), MB.getBufferSize(),
> llvm::TargetOptions());
> @@ -350,15 +374,15 @@ void BitcodeFile::parse() {
> StringRef SymName = Saver.save(M->getSymbolName(I));
> int SymbolDef = Attrs & LTO_SYMBOL_DEFINITION_MASK;
> if (SymbolDef == LTO_SYMBOL_DEFINITION_UNDEFINED) {
> - SymbolBodies.push_back(new (Alloc) Undefined(SymName));
> + SymbolBodies.push_back(Symtab->addUndefined(SymName, this,
> false)->body());
> } else {
> bool Replaceable =
> (SymbolDef == LTO_SYMBOL_DEFINITION_TENTATIVE || // common
> (Attrs & LTO_SYMBOL_COMDAT) || // comdat
> (SymbolDef == LTO_SYMBOL_DEFINITION_WEAK && // weak
> external
> (Attrs & LTO_SYMBOL_ALIAS)));
> - SymbolBodies.push_back(new (Alloc) DefinedBitcode(this, SymName,
> - Replaceable));
> + SymbolBodies.push_back(
> + Symtab->addBitcode(this, SymName, Replaceable)->body());
> }
> }
>
>
> Modified: lld/trunk/COFF/InputFiles.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.h?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/InputFiles.h (original)
> +++ lld/trunk/COFF/InputFiles.h Fri Dec 9 15:55:24 2016
> @@ -31,6 +31,7 @@ using llvm::COFF::MachineTypes;
> using llvm::object::Archive;
> using llvm::object::COFFObjectFile;
> using llvm::object::COFFSymbolRef;
> +using llvm::object::coff_import_header;
> using llvm::object::coff_section;
>
> class Chunk;
> @@ -39,6 +40,7 @@ class DefinedImportData;
> class DefinedImportThunk;
> class Lazy;
> class SectionChunk;
> +struct Symbol;
> class SymbolBody;
> class Undefined;
>
> @@ -52,9 +54,6 @@ public:
> // Returns the filename.
> StringRef getName() { return MB.getBufferIdentifier(); }
>
> - // Returns symbols defined by this file.
> - virtual std::vector<SymbolBody *> &getSymbols() = 0;
> -
> // Reads a file (the constructor doesn't do that).
> virtual void parse() = 0;
>
> @@ -67,14 +66,8 @@ public:
> // Returns .drectve section contents if exist.
> StringRef getDirectives() { return StringRef(Directives).trim(); }
>
> - // Each file has a unique index. The index number is used to
> - // resolve ties in symbol resolution.
> - int Index;
> - static int NextIndex;
> -
> protected:
> - InputFile(Kind K, MemoryBufferRef M)
> - : Index(NextIndex++), MB(M), FileKind(K) {}
> + InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
>
> MemoryBufferRef MB;
> std::string Directives;
> @@ -90,22 +83,14 @@ public:
> static bool classof(const InputFile *F) { return F->kind() ==
> ArchiveKind; }
> void parse() override;
>
> - // Returns a memory buffer for a given symbol. An empty memory buffer
> - // is returned if we have already returned the same memory buffer.
> - // (So that we don't instantiate same members more than once.)
> - MemoryBufferRef getMember(const Archive::Symbol *Sym);
> -
> - llvm::MutableArrayRef<Lazy> getLazySymbols();
> -
> - // All symbols returned by ArchiveFiles are of Lazy type.
> - std::vector<SymbolBody *> &getSymbols() override {
> - llvm_unreachable("internal fatal");
> - }
> + // Returns an input file for a given symbol. A null pointer is returned
> if we
> + // have already returned the same input file. (So that we don't
> instantiate
> + // the same member more than once.)
> + InputFile *getMember(const Archive::Symbol *Sym);
>
> private:
> std::unique_ptr<Archive> File;
> std::string Filename;
> - std::vector<Lazy> LazySymbols;
> std::map<uint64_t, std::atomic_flag> Seen;
> };
>
> @@ -118,7 +103,7 @@ public:
> MachineTypes getMachineType() override;
> std::vector<Chunk *> &getChunks() { return Chunks; }
> std::vector<SectionChunk *> &getDebugChunks() { return DebugChunks; }
> - std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies;
> }
> + std::vector<SymbolBody *> &getSymbols() { return SymbolBodies; }
>
> // Returns a SymbolBody object for the SymbolIndex'th symbol in the
> // underlying object file.
> @@ -142,8 +127,8 @@ private:
> void initializeSymbols();
> void initializeSEH();
>
> - Defined *createDefined(COFFSymbolRef Sym, const void *Aux, bool
> IsFirst);
> - Undefined *createUndefined(COFFSymbolRef Sym);
> + SymbolBody *createDefined(COFFSymbolRef Sym, const void *Aux, bool
> IsFirst);
> + SymbolBody *createUndefined(COFFSymbolRef Sym);
>
> std::unique_ptr<COFFObjectFile> COFFObj;
> llvm::BumpPtrAllocator Alloc;
> @@ -181,7 +166,6 @@ public:
> explicit ImportFile(MemoryBufferRef M)
> : InputFile(ImportKind, M), StringAlloc(StringAllocAux) {}
> static bool classof(const InputFile *F) { return F->kind() ==
> ImportKind; }
> - std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies;
> }
>
> DefinedImportData *ImpSym = nullptr;
> DefinedImportThunk *ThunkSym = nullptr;
> @@ -190,10 +174,14 @@ public:
> private:
> void parse() override;
>
> - std::vector<SymbolBody *> SymbolBodies;
> llvm::BumpPtrAllocator Alloc;
> llvm::BumpPtrAllocator StringAllocAux;
> llvm::StringSaver StringAlloc;
> +
> +public:
> + StringRef ExternalName;
> + const coff_import_header *Hdr;
> + Chunk *Location = nullptr;
> };
>
> // Used for LTO.
> @@ -201,7 +189,7 @@ class BitcodeFile : public InputFile {
> public:
> explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}
> static bool classof(const InputFile *F) { return F->kind() ==
> BitcodeKind; }
> - std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies;
> }
> + std::vector<SymbolBody *> &getSymbols() { return SymbolBodies; }
> MachineTypes getMachineType() override;
> std::unique_ptr<LTOModule> takeModule() { return std::move(M); }
>
>
> Modified: lld/trunk/COFF/MarkLive.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/MarkLive.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/MarkLive.cpp (original)
> +++ lld/trunk/COFF/MarkLive.cpp Fri Dec 9 15:55:24 2016
> @@ -38,8 +38,8 @@ void markLive(const std::vector<Chunk *>
> };
>
> // Add GC root chunks.
> - for (Undefined *U : Config->GCRoot)
> - if (auto *D = dyn_cast<DefinedRegular>(U->repl()))
> + for (SymbolBody *B : Config->GCRoot)
> + if (auto *D = dyn_cast<DefinedRegular>(B))
> Enqueue(D->getChunk());
>
> while (!Worklist.empty()) {
> @@ -48,7 +48,7 @@ void markLive(const std::vector<Chunk *>
>
> // Mark all symbols listed in the relocation table for this section.
> for (SymbolBody *S : SC->symbols())
> - if (auto *D = dyn_cast<DefinedRegular>(S->repl()))
> + if (auto *D = dyn_cast<DefinedRegular>(S))
> Enqueue(D->getChunk());
>
> // Mark associative sections if any.
>
> Modified: lld/trunk/COFF/SymbolTable.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/SymbolTable.cpp (original)
> +++ lld/trunk/COFF/SymbolTable.cpp Fri Dec 9 15:55:24 2016
> @@ -12,7 +12,6 @@
> #include "Driver.h"
> #include "Error.h"
> #include "Symbols.h"
> -#include "lld/Core/Parallel.h"
> #include "lld/Support/Memory.h"
> #include "llvm/IR/LLVMContext.h"
> #include "llvm/LTO/legacy/LTOCodeGenerator.h"
> @@ -25,21 +24,15 @@ using namespace llvm;
> namespace lld {
> namespace coff {
>
> -void SymbolTable::addFile(InputFile *File) {
> -#if LLVM_ENABLE_THREADS
> - std::launch Policy = std::launch::async;
> -#else
> - std::launch Policy = std::launch::deferred;
> -#endif
> +SymbolTable *Symtab;
>
> +void SymbolTable::addFile(InputFile *File) {
> Files.push_back(File);
> if (auto *F = dyn_cast<ArchiveFile>(File)) {
> - ArchiveQueue.push_back(
> - std::async(Policy, [=]() { F->parse(); return F; }));
> + ArchiveQueue.push_back(F);
> return;
> }
> - ObjectQueue.push_back(
> - std::async(Policy, [=]() { File->parse(); return File; }));
> + ObjectQueue.push_back(File);
> if (auto *F = dyn_cast<ObjectFile>(File)) {
> ObjectFiles.push_back(F);
> } else if (auto *F = dyn_cast<BitcodeFile>(File)) {
> @@ -53,7 +46,7 @@ void SymbolTable::step() {
> if (queueEmpty())
> return;
> readObjects();
> - readArchives();
> + readArchive();
> }
>
> void SymbolTable::run() {
> @@ -61,26 +54,17 @@ void SymbolTable::run() {
> step();
> }
>
> -void SymbolTable::readArchives() {
> +void SymbolTable::readArchive() {
> if (ArchiveQueue.empty())
> return;
>
> // Add lazy symbols to the symbol table. Lazy symbols that conflict
> // with existing undefined symbols are accumulated in LazySyms.
> - std::vector<Symbol *> LazySyms;
> - for (std::future<ArchiveFile *> &Future : ArchiveQueue) {
> - ArchiveFile *File = Future.get();
> - if (Config->Verbose)
> - outs() << "Reading " << toString(File) << "\n";
> - for (Lazy &Sym : File->getLazySymbols())
> - addLazy(&Sym, &LazySyms);
> - }
> - ArchiveQueue.clear();
> -
> - // Add archive member files to ObjectQueue that should resolve
> - // existing undefined symbols.
> - for (Symbol *Sym : LazySyms)
> - addMemberFile(cast<Lazy>(Sym->Body));
> + ArchiveFile *File = ArchiveQueue.front();
> + ArchiveQueue.pop_front();
> + if (Config->Verbose)
> + outs() << "Reading " << toString(File) << "\n";
> + File->parse();
> }
>
> void SymbolTable::readObjects() {
> @@ -90,14 +74,12 @@ void SymbolTable::readObjects() {
> // Add defined and undefined symbols to the symbol table.
> std::vector<StringRef> Directives;
> for (size_t I = 0; I < ObjectQueue.size(); ++I) {
> - InputFile *File = ObjectQueue[I].get();
> + InputFile *File = ObjectQueue[I];
> if (Config->Verbose)
> outs() << "Reading " << toString(File) << "\n";
> + File->parse();
> // Adding symbols may add more files to ObjectQueue
> // (but not to ArchiveQueue).
> - for (SymbolBody *Sym : File->getSymbols())
> - if (Sym->isExternal())
> - addSymbol(Sym);
> StringRef S = File->getDirectives();
> if (!S.empty()) {
> Directives.push_back(S);
> @@ -117,127 +99,239 @@ bool SymbolTable::queueEmpty() {
> return ArchiveQueue.empty() && ObjectQueue.empty();
> }
>
> -void SymbolTable::reportRemainingUndefines(bool Resolve) {
> +void SymbolTable::reportRemainingUndefines() {
> SmallPtrSet<SymbolBody *, 8> Undefs;
> for (auto &I : Symtab) {
> Symbol *Sym = I.second;
> - auto *Undef = dyn_cast<Undefined>(Sym->Body);
> + auto *Undef = dyn_cast<Undefined>(Sym->body());
> if (!Undef)
> continue;
> + if (!Sym->IsUsedInRegularObj)
> + continue;
> StringRef Name = Undef->getName();
> // A weak alias may have been resolved, so check for that.
> if (Defined *D = Undef->getWeakAlias()) {
> - if (Resolve)
> - Sym->Body = D;
> + // We resolve weak aliases by replacing the alias's SymbolBody with
> the
> + // target's SymbolBody. This causes all SymbolBody pointers
> referring to
> + // the old symbol to instead refer to the new symbol. However, we
> can't
> + // just blindly copy sizeof(Symbol::Body) bytes from D to Sym->Body
> + // because D may be an internal symbol, and internal symbols are
> stored as
> + // "unparented" SymbolBodies. For that reason we need to check
> which type
> + // of symbol we are dealing with and copy the correct number of
> bytes.
> + if (isa<DefinedRegular>(D))
> + memcpy(Sym->Body.buffer, D, sizeof(DefinedRegular));
> + else if (isa<DefinedAbsolute>(D))
> + memcpy(Sym->Body.buffer, D, sizeof(DefinedAbsolute));
> + else
> + // No other internal symbols are possible.
> + Sym->Body = D->symbol()->Body;
> continue;
> }
> // If we can resolve a symbol by removing __imp_ prefix, do that.
> // This odd rule is for compatibility with MSVC linker.
> if (Name.startswith("__imp_")) {
> Symbol *Imp = find(Name.substr(strlen("__imp_")));
> - if (Imp && isa<Defined>(Imp->Body)) {
> - if (!Resolve)
> - continue;
> - auto *D = cast<Defined>(Imp->Body);
> - auto *S = make<DefinedLocalImport>(Name, D);
> - LocalImportChunks.push_back(S->getChunk());
> - Sym->Body = S;
> + if (Imp && isa<Defined>(Imp->body())) {
> + auto *D = cast<Defined>(Imp->body());
> + replaceBody<DefinedLocalImport>(Sym, Name, D);
> + LocalImportChunks.push_back(
> + cast<DefinedLocalImport>(Sym->body())->getChunk());
> continue;
> }
> }
> // Remaining undefined symbols are not fatal if /force is specified.
> // They are replaced with dummy defined symbols.
> - if (Config->Force && Resolve)
> - Sym->Body = make<DefinedAbsolute>(Name, 0);
> - Undefs.insert(Sym->Body);
> + if (Config->Force)
> + replaceBody<DefinedAbsolute>(Sym, Name, 0);
> + Undefs.insert(Sym->body());
> }
> if (Undefs.empty())
> return;
> - for (Undefined *U : Config->GCRoot)
> - if (Undefs.count(U->repl()))
> - errs() << "<root>: undefined symbol: " << U->getName() << "\n";
> - for (InputFile *File : Files)
> - if (!isa<ArchiveFile>(File))
> - for (SymbolBody *Sym : File->getSymbols())
> - if (Undefs.count(Sym->repl()))
> - errs() << toString(File) << ": undefined symbol: " <<
> Sym->getName()
> - << "\n";
> + for (SymbolBody *B : Config->GCRoot)
> + if (Undefs.count(B))
> + errs() << "<root>: undefined symbol: " << B->getName() << "\n";
> + for (ObjectFile *File : ObjectFiles)
> + for (SymbolBody *Sym : File->getSymbols())
> + if (Undefs.count(Sym))
> + errs() << toString(File) << ": undefined symbol: " <<
> Sym->getName()
> + << "\n";
> if (!Config->Force)
> fatal("link failed");
> }
>
> -void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
> - Symbol *Sym = insert(New);
> - if (Sym->Body == New)
> - return;
> - SymbolBody *Existing = Sym->Body;
> - if (isa<Defined>(Existing))
> - return;
> - if (Lazy *L = dyn_cast<Lazy>(Existing))
> - if (L->getFileIndex() < New->getFileIndex())
> - return;
> - Sym->Body = New;
> - New->setBackref(Sym);
> - if (isa<Undefined>(Existing))
> - Accum->push_back(Sym);
> -}
> -
> -void SymbolTable::addSymbol(SymbolBody *New) {
> - // Find an existing symbol or create and insert a new one.
> - assert(isa<Defined>(New) || isa<Undefined>(New));
> - Symbol *Sym = insert(New);
> - if (Sym->Body == New)
> - return;
> - SymbolBody *Existing = Sym->Body;
> -
> - // If we have an undefined symbol and a lazy symbol,
> - // let the lazy symbol to read a member file.
> - if (auto *L = dyn_cast<Lazy>(Existing)) {
> - // Undefined symbols with weak aliases need not to be resolved,
> - // since they would be replaced with weak aliases if they remain
> - // undefined.
> - if (auto *U = dyn_cast<Undefined>(New)) {
> - if (!U->WeakAlias) {
> - addMemberFile(L);
> - return;
> - }
> - }
> - Sym->Body = New;
> - return;
> +std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
> + Symbol *&Sym = Symtab[Name];
> + if (Sym)
> + return {Sym, false};
> + Sym = make<Symbol>();
> + Sym->IsUsedInRegularObj = false;
> + return {Sym, true};
> +}
> +
> +Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F,
> + bool IsWeakAlias) {
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(Name);
> + if (!F || !isa<BitcodeFile>(F))
> + S->IsUsedInRegularObj = true;
> + if (WasInserted || (isa<Lazy>(S->body()) && IsWeakAlias)) {
> + replaceBody<Undefined>(S, Name);
> + return S;
> }
> -
> - // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
> - // equivalent (conflicting), or more preferable, respectively.
> - int Comp = Existing->compare(New);
> - if (Comp == 0)
> - fatal("duplicate symbol: " + toString(*Existing) + " in " +
> - toString(Existing->getFile()) + " and in " +
> - toString(New->getFile()));
> - if (Comp < 0)
> - Sym->Body = New;
> -}
> -
> -Symbol *SymbolTable::insert(SymbolBody *New) {
> - Symbol *&Sym = Symtab[New->getName()];
> - if (Sym) {
> - New->setBackref(Sym);
> - return Sym;
> - }
> - Sym = make<Symbol>(New);
> - New->setBackref(Sym);
> - return Sym;
> + if (auto *L = dyn_cast<Lazy>(S->body()))
> + addMemberFile(L->File, L->Sym);
> + return S;
> +}
> +
> +void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) {
> + StringRef Name = Sym.getName();
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(Name);
> + if (WasInserted) {
> + replaceBody<Lazy>(S, F, Sym);
> + return;
> + }
> + auto *U = dyn_cast<Undefined>(S->body());
> + if (!U || U->WeakAlias)
> + return;
> + addMemberFile(F, Sym);
> +}
> +
> +void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
> + fatal("duplicate symbol: " + toString(*Existing->body()) + " in " +
> + toString(Existing->body()->getFile()) + " and in " +
> + (NewFile ? toString(NewFile) : "(internal)"));
> +}
> +
> +Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) {
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(N);
> + S->IsUsedInRegularObj = true;
> + if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
> + replaceBody<DefinedAbsolute>(S, N, Sym);
> + else if (!isa<DefinedCOFF>(S->body()))
> + reportDuplicate(S, nullptr);
> + return S;
> +}
> +
> +Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) {
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(N);
> + S->IsUsedInRegularObj = true;
> + if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
> + replaceBody<DefinedAbsolute>(S, N, VA);
> + else if (!isa<DefinedCOFF>(S->body()))
> + reportDuplicate(S, nullptr);
> + return S;
> +}
> +
> +Symbol *SymbolTable::addRelative(StringRef N, uint64_t VA) {
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(N);
> + S->IsUsedInRegularObj = true;
> + if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
> + replaceBody<DefinedRelative>(S, N, VA);
> + else if (!isa<DefinedCOFF>(S->body()))
> + reportDuplicate(S, nullptr);
> + return S;
> +}
> +
> +Symbol *SymbolTable::addRegular(ObjectFile *F, COFFSymbolRef Sym,
> + SectionChunk *C) {
> + StringRef Name;
> + F->getCOFFObj()->getSymbolName(Sym, Name);
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(Name);
> + S->IsUsedInRegularObj = true;
> + if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
> + replaceBody<DefinedRegular>(S, F, Sym, C);
> + else if (auto *R = dyn_cast<DefinedRegular>(S->body())) {
> + if (!C->isCOMDAT() || !R->isCOMDAT())
> + reportDuplicate(S, F);
> + } else if (auto *B = dyn_cast<DefinedBitcode>(S->body())) {
> + if (B->IsReplaceable)
> + replaceBody<DefinedRegular>(S, F, Sym, C);
> + else if (!C->isCOMDAT())
> + reportDuplicate(S, F);
> + } else
> + replaceBody<DefinedRegular>(S, F, Sym, C);
> + return S;
> +}
> +
> +Symbol *SymbolTable::addBitcode(BitcodeFile *F, StringRef N, bool
> IsReplaceable) {
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(N);
> + if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body())) {
> + replaceBody<DefinedBitcode>(S, F, N, IsReplaceable);
> + return S;
> + }
> + if (isa<DefinedCommon>(S->body()))
> + return S;
> + if (IsReplaceable)
> + if (isa<DefinedRegular>(S->body()) || isa<DefinedBitcode>(S->body()))
> + return S;
> + reportDuplicate(S, F);
> + return S;
> +}
> +
> +Symbol *SymbolTable::addCommon(ObjectFile *F, COFFSymbolRef Sym,
> + CommonChunk *C) {
> + StringRef Name;
> + F->getCOFFObj()->getSymbolName(Sym, Name);
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(Name);
> + S->IsUsedInRegularObj = true;
> + if (WasInserted || !isa<DefinedCOFF>(S->body()))
> + replaceBody<DefinedCommon>(S, F, Sym, C);
> + else if (auto *DC = dyn_cast<DefinedCommon>(S->body()))
> + if (Sym.getValue() > DC->getSize())
> + replaceBody<DefinedCommon>(S, F, Sym, C);
> + return S;
> +}
> +
> +Symbol *SymbolTable::addImportData(StringRef N, ImportFile *F) {
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(N);
> + S->IsUsedInRegularObj = true;
> + if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
> + replaceBody<DefinedImportData>(S, N, F);
> + else if (!isa<DefinedCOFF>(S->body()))
> + reportDuplicate(S, nullptr);
> + return S;
> +}
> +
> +Symbol *SymbolTable::addImportThunk(StringRef Name, DefinedImportData *ID,
> + uint16_t Machine) {
> + Symbol *S;
> + bool WasInserted;
> + std::tie(S, WasInserted) = insert(Name);
> + S->IsUsedInRegularObj = true;
> + if (WasInserted || isa<Undefined>(S->body()) || isa<Lazy>(S->body()))
> + replaceBody<DefinedImportThunk>(S, Name, ID, Machine);
> + else if (!isa<DefinedCOFF>(S->body()))
> + reportDuplicate(S, nullptr);
> + return S;
> }
>
> // Reads an archive member file pointed by a given symbol.
> -void SymbolTable::addMemberFile(Lazy *Body) {
> - InputFile *File = Body->getMember();
> +void SymbolTable::addMemberFile(ArchiveFile *F, const Archive::Symbol
> Sym) {
> + InputFile *File = F->getMember(&Sym);
>
> // getMember returns an empty buffer if the member was already
> // read from the library.
> if (!File)
> return;
> if (Config->Verbose)
> - outs() << "Loaded " << toString(File) << " for " << Body->getName()
> << "\n";
> + outs() << "Loaded " << toString(File) << " for " << Sym.getName() <<
> "\n";
> addFile(File);
> }
>
> @@ -274,7 +368,7 @@ StringRef SymbolTable::findByPrefix(Stri
>
> StringRef SymbolTable::findMangle(StringRef Name) {
> if (Symbol *Sym = find(Name))
> - if (!isa<Undefined>(Sym->Body))
> + if (!isa<Undefined>(Sym->body()))
> return Name;
> if (Config->Machine != I386)
> return findByPrefix(("?" + Name + "@@Y").str());
> @@ -288,34 +382,17 @@ StringRef SymbolTable::findMangle(String
> return findByPrefix(("?" + Name.substr(1) + "@@Y").str());
> }
>
> -void SymbolTable::mangleMaybe(Undefined *U) {
> - if (U->WeakAlias)
> - return;
> - if (!isa<Undefined>(U->repl()))
> +void SymbolTable::mangleMaybe(SymbolBody *B) {
> + auto *U = dyn_cast<Undefined>(B);
> + if (!U || U->WeakAlias)
> return;
> StringRef Alias = findMangle(U->getName());
> if (!Alias.empty())
> U->WeakAlias = addUndefined(Alias);
> }
>
> -Undefined *SymbolTable::addUndefined(StringRef Name) {
> - auto *New = make<Undefined>(Name);
> - addSymbol(New);
> - if (auto *U = dyn_cast<Undefined>(New->repl()))
> - return U;
> - return New;
> -}
> -
> -DefinedRelative *SymbolTable::addRelative(StringRef Name, uint64_t VA) {
> - auto *New = make<DefinedRelative>(Name, VA);
> - addSymbol(New);
> - return New;
> -}
> -
> -DefinedAbsolute *SymbolTable::addAbsolute(StringRef Name, uint64_t VA) {
> - auto *New = make<DefinedAbsolute>(Name, VA);
> - addSymbol(New);
> - return New;
> +SymbolBody *SymbolTable::addUndefined(StringRef Name) {
> + return addUndefined(Name, nullptr, false)->body();
> }
>
> void SymbolTable::printMap(llvm::raw_ostream &OS) {
> @@ -329,59 +406,19 @@ void SymbolTable::printMap(llvm::raw_ost
> }
> }
>
> -void SymbolTable::addCombinedLTOObject(ObjectFile *Obj) {
> - for (SymbolBody *Body : Obj->getSymbols()) {
> - if (!Body->isExternal())
> - continue;
> - // We should not see any new undefined symbols at this point, but
> we'll
> - // diagnose them later in reportRemainingUndefines().
> - StringRef Name = Body->getName();
> - Symbol *Sym = insert(Body);
> - SymbolBody *Existing = Sym->Body;
> -
> - if (Existing == Body)
> - continue;
> -
> - if (isa<DefinedBitcode>(Existing)) {
> - Sym->Body = Body;
> - continue;
> - }
> - if (isa<Undefined>(Body)) {
> - if (auto *L = dyn_cast<Lazy>(Existing)) {
> - // We may see new references to runtime library symbols such as
> __chkstk
> - // here. These symbols must be wholly defined in non-bitcode
> files.
> - addMemberFile(L);
> - continue;
> - }
> - }
> -
> - int Comp = Existing->compare(Body);
> - if (Comp == 0)
> - fatal("LTO: unexpected duplicate symbol: " + Name);
> - if (Comp < 0)
> - Sym->Body = Body;
> - }
> -}
> -
> void SymbolTable::addCombinedLTOObjects() {
> if (BitcodeFiles.empty())
> return;
>
> - // Diagnose any undefined symbols early, but do not resolve weak
> externals,
> - // as resolution breaks the invariant that each Symbol points to a
> unique
> - // SymbolBody, which we rely on to replace DefinedBitcode symbols
> correctly.
> - reportRemainingUndefines(/*Resolve=*/false);
> -
> // Create an object file and add it to the symbol table by replacing any
> // DefinedBitcode symbols with the definitions in the object file.
> LTOCodeGenerator CG(BitcodeFile::Context);
> CG.setOptLevel(Config->LTOOptLevel);
> std::vector<ObjectFile *> Objs = createLTOObjects(&CG);
>
> - for (ObjectFile *Obj : Objs)
> - addCombinedLTOObject(Obj);
> -
> size_t NumBitcodeFiles = BitcodeFiles.size();
> + for (ObjectFile *Obj : Objs)
> + Obj->parse();
> run();
> if (BitcodeFiles.size() != NumBitcodeFiles)
> fatal("LTO: late loaded symbol created new bitcode reference");
> @@ -390,25 +427,17 @@ void SymbolTable::addCombinedLTOObjects(
> // Combine and compile bitcode files and then return the result
> // as a vector of regular COFF object files.
> std::vector<ObjectFile *> SymbolTable::createLTOObjects(LTOCodeGenerator
> *CG) {
> - // All symbols referenced by non-bitcode objects must be preserved.
> - for (ObjectFile *File : ObjectFiles)
> - for (SymbolBody *Body : File->getSymbols())
> - if (auto *S = dyn_cast<DefinedBitcode>(Body->repl()))
> - CG->addMustPreserveSymbol(S->getName());
> -
> - // Likewise for bitcode symbols which we initially resolved to
> non-bitcode.
> + // All symbols referenced by non-bitcode objects, including GC roots,
> must be
> + // preserved. We must also replace bitcode symbols with undefined
> symbols so
> + // that they may be replaced with real definitions without conflicting.
> for (BitcodeFile *File : BitcodeFiles)
> - for (SymbolBody *Body : File->getSymbols())
> - if (isa<DefinedBitcode>(Body) && !isa<DefinedBitcode>(Body->repl()))
> + for (SymbolBody *Body : File->getSymbols()) {
> + if (!isa<DefinedBitcode>(Body))
> + continue;
> + if (Body->symbol()->IsUsedInRegularObj)
> CG->addMustPreserveSymbol(Body->getName());
> -
> - // Likewise for other symbols that must be preserved.
> - for (Undefined *U : Config->GCRoot) {
> - if (auto *S = dyn_cast<DefinedBitcode>(U->repl()))
> - CG->addMustPreserveSymbol(S->getName());
> - else if (auto *S =
> dyn_cast_or_null<DefinedBitcode>(U->getWeakAlias()))
> - CG->addMustPreserveSymbol(S->getName());
> - }
> + replaceBody<Undefined>(Body->symbol(), Body->getName());
> + }
>
> CG->setModule(BitcodeFiles[0]->takeModule());
> for (unsigned I = 1, E = BitcodeFiles.size(); I != E; ++I)
> @@ -438,7 +467,6 @@ std::vector<ObjectFile *> SymbolTable::c
> auto *ObjFile = new ObjectFile(MemoryBufferRef(Obj, "<LTO object>"));
> Files.emplace_back(ObjFile);
> ObjectFiles.push_back(ObjFile);
> - ObjFile->parse();
> ObjFiles.push_back(ObjFile);
> }
>
>
> Modified: lld/trunk/COFF/SymbolTable.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.h?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/SymbolTable.h (original)
> +++ lld/trunk/COFF/SymbolTable.h Fri Dec 9 15:55:24 2016
> @@ -22,6 +22,7 @@
> #endif
>
> #include <future>
> +#include <list>
>
> namespace llvm {
> struct LTOCodeGenerator;
> @@ -31,6 +32,7 @@ namespace lld {
> namespace coff {
>
> class Chunk;
> +class CommonChunk;
> class Defined;
> class DefinedAbsolute;
> class DefinedRelative;
> @@ -48,7 +50,9 @@ struct Symbol;
> // conflicts. For example, obviously, a defined symbol is better than
> // an undefined symbol. Or, if there's a conflict between a lazy and a
> // undefined, it'll read an archive member to read a real definition
> -// to replace the lazy symbol. The logic is implemented in resolve().
> +// to replace the lazy symbol. The logic is implemented in the
> +// add*() functions, which are called by input files as they are parsed.
> +// There is one add* function per symbol type.
> class SymbolTable {
> public:
> void addFile(InputFile *File);
> @@ -57,9 +61,10 @@ public:
> void run();
> bool queueEmpty();
>
> - // Print an error message on undefined symbols. If Resolve is true, try
> to
> - // resolve any undefined symbols and update the symbol table
> accordingly.
> - void reportRemainingUndefines(bool Resolve);
> + // Try to resolve any undefined symbols and update the symbol table
> + // accordingly, then print an error message for any remaining undefined
> + // symbols.
> + void reportRemainingUndefines();
>
> // Returns a list of chunks of selected symbols.
> std::vector<Chunk *> getChunks();
> @@ -72,7 +77,7 @@ public:
> // mangled symbol. This function tries to find a mangled name
> // for U from the symbol table, and if found, set the symbol as
> // a weak alias for U.
> - void mangleMaybe(Undefined *U);
> + void mangleMaybe(SymbolBody *B);
> StringRef findMangle(StringRef Name);
>
> // Print a layout map to OS.
> @@ -91,36 +96,49 @@ public:
> std::vector<ObjectFile *> ObjectFiles;
>
> // Creates an Undefined symbol for a given name.
> - Undefined *addUndefined(StringRef Name);
> - DefinedRelative *addRelative(StringRef Name, uint64_t VA);
> - DefinedAbsolute *addAbsolute(StringRef Name, uint64_t VA);
> + SymbolBody *addUndefined(StringRef Name);
> +
> + Symbol *addRelative(StringRef N, uint64_t VA);
> + Symbol *addAbsolute(StringRef N, uint64_t VA);
> +
> + Symbol *addUndefined(StringRef Name, InputFile *F, bool IsWeakAlias);
> + void addLazy(ArchiveFile *F, const Archive::Symbol Sym);
> + Symbol *addAbsolute(StringRef N, COFFSymbolRef S);
> + Symbol *addRegular(ObjectFile *F, COFFSymbolRef S, SectionChunk *C);
> + Symbol *addBitcode(BitcodeFile *F, StringRef N, bool IsReplaceable);
> + Symbol *addCommon(ObjectFile *F, COFFSymbolRef S, CommonChunk *C);
> + Symbol *addImportData(StringRef N, ImportFile *F);
> + Symbol *addImportThunk(StringRef Name, DefinedImportData *S,
> + uint16_t Machine);
> +
> + void reportDuplicate(Symbol *Existing, InputFile *NewFile);
>
> // A list of chunks which to be added to .rdata.
> std::vector<Chunk *> LocalImportChunks;
>
> private:
> - void readArchives();
> + void readArchive();
> void readObjects();
>
> - void addSymbol(SymbolBody *New);
> - void addLazy(Lazy *New, std::vector<Symbol *> *Accum);
> - Symbol *insert(SymbolBody *New);
> + std::pair<Symbol *, bool> insert(StringRef Name);
> StringRef findByPrefix(StringRef Prefix);
>
> - void addMemberFile(Lazy *Body);
> + void addMemberFile(ArchiveFile *F, const Archive::Symbol Sym);
> void addCombinedLTOObject(ObjectFile *Obj);
> std::vector<ObjectFile *> createLTOObjects(llvm::LTOCodeGenerator *CG);
>
> llvm::DenseMap<StringRef, Symbol *> Symtab;
>
> std::vector<InputFile *> Files;
> - std::vector<std::future<ArchiveFile *>> ArchiveQueue;
> - std::vector<std::future<InputFile *>> ObjectQueue;
> + std::list<ArchiveFile *> ArchiveQueue;
> + std::vector<InputFile *> ObjectQueue;
>
> std::vector<BitcodeFile *> BitcodeFiles;
> std::vector<SmallString<0>> Objs;
> };
>
> +extern SymbolTable *Symtab;
> +
> } // namespace coff
> } // namespace lld
>
>
> Modified: lld/trunk/COFF/Symbols.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Symbols.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/Symbols.cpp (original)
> +++ lld/trunk/COFF/Symbols.cpp Fri Dec 9 15:55:24 2016
> @@ -18,8 +18,6 @@
>
> using namespace llvm;
> using namespace llvm::object;
> -using llvm::sys::fs::identify_magic;
> -using llvm::sys::fs::file_magic;
>
> namespace lld {
> namespace coff {
> @@ -49,120 +47,6 @@ InputFile *SymbolBody::getFile() {
> return nullptr;
> }
>
> -// Returns 1, 0 or -1 if this symbol should take precedence
> -// over the Other, tie or lose, respectively.
> -int SymbolBody::compare(SymbolBody *Other) {
> - Kind LK = kind(), RK = Other->kind();
> -
> - // Normalize so that the smaller kind is on the left.
> - if (LK > RK)
> - return -Other->compare(this);
> -
> - // First handle comparisons between two different kinds.
> - if (LK != RK) {
> - if (RK > LastDefinedKind) {
> - if (LK == LazyKind && cast<Undefined>(Other)->WeakAlias)
> - return -1;
> -
> - // The LHS is either defined or lazy and so it wins.
> - assert((LK <= LastDefinedKind || LK == LazyKind) && "Bad kind!");
> - return 1;
> - }
> -
> - // Bitcode has special complexities.
> - if (RK == DefinedBitcodeKind) {
> - auto *RHS = cast<DefinedBitcode>(Other);
> -
> - switch (LK) {
> - case DefinedCommonKind:
> - return 1;
> -
> - case DefinedRegularKind:
> - // As an approximation, regular symbols win over bitcode symbols,
> - // but we definitely have a conflict if the regular symbol is not
> - // replaceable and neither is the bitcode symbol. We do not
> - // replicate the rest of the symbol resolution logic here; symbol
> - // resolution will be done accurately after lowering bitcode
> symbols
> - // to regular symbols in addCombinedLTOObject().
> - if (cast<DefinedRegular>(this)->isCOMDAT() || RHS->IsReplaceable)
> - return 1;
> -
> - // Fallthrough to the default of a tie otherwise.
> - default:
> - return 0;
> - }
> - }
> -
> - // Either of the object file kind will trump a higher kind.
> - if (LK <= LastDefinedCOFFKind)
> - return 1;
> -
> - // The remaining kind pairs are ties amongst defined symbols.
> - return 0;
> - }
> -
> - // Now handle the case where the kinds are the same.
> - switch (LK) {
> - case DefinedRegularKind: {
> - auto *LHS = cast<DefinedRegular>(this);
> - auto *RHS = cast<DefinedRegular>(Other);
> - if (LHS->isCOMDAT() && RHS->isCOMDAT())
> - return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
> - return 0;
> - }
> -
> - case DefinedCommonKind: {
> - auto *LHS = cast<DefinedCommon>(this);
> - auto *RHS = cast<DefinedCommon>(Other);
> - if (LHS->getSize() == RHS->getSize())
> - return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
> - return LHS->getSize() > RHS->getSize() ? 1 : -1;
> - }
> -
> - case DefinedBitcodeKind: {
> - auto *LHS = cast<DefinedBitcode>(this);
> - auto *RHS = cast<DefinedBitcode>(Other);
> - // If both are non-replaceable, we have a tie.
> - if (!LHS->IsReplaceable && !RHS->IsReplaceable)
> - return 0;
> -
> - // Non-replaceable symbols win, but even two replaceable symboles
> don't
> - // tie. If both symbols are replaceable, choice is arbitrary.
> - if (RHS->IsReplaceable && LHS->IsReplaceable)
> - return uintptr_t(LHS) < uintptr_t(RHS) ? 1 : -1;
> - return LHS->IsReplaceable ? -1 : 1;
> - }
> -
> - case LazyKind: {
> - // Don't tie, pick the earliest.
> - auto *LHS = cast<Lazy>(this);
> - auto *RHS = cast<Lazy>(Other);
> - return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
> - }
> -
> - case UndefinedKind: {
> - auto *LHS = cast<Undefined>(this);
> - auto *RHS = cast<Undefined>(Other);
> - // Tie if both undefined symbols have different weak aliases.
> - if (LHS->WeakAlias && RHS->WeakAlias) {
> - if (LHS->WeakAlias->getName() != RHS->WeakAlias->getName())
> - return 0;
> - return uintptr_t(LHS) < uintptr_t(RHS) ? 1 : -1;
> - }
> - return LHS->WeakAlias ? 1 : -1;
> - }
> -
> - case DefinedLocalImportKind:
> - case DefinedImportThunkKind:
> - case DefinedImportDataKind:
> - case DefinedAbsoluteKind:
> - case DefinedRelativeKind:
> - // These all simply tie.
> - return 0;
> - }
> - llvm_unreachable("unknown symbol kind");
> -}
> -
> COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
> size_t SymSize = File->getCOFFObj()->getSymbolTableEntrySize();
> if (SymSize == sizeof(coff_symbol16))
> @@ -182,34 +66,10 @@ DefinedImportThunk::DefinedImportThunk(S
> }
> }
>
> -InputFile *Lazy::getMember() {
> - MemoryBufferRef MBRef = File->getMember(&Sym);
> -
> - // getMember returns an empty buffer if the member was already
> - // read from the library.
> - if (MBRef.getBuffer().empty())
> - return nullptr;
> -
> - file_magic Magic = identify_magic(MBRef.getBuffer());
> - if (Magic == file_magic::coff_import_library)
> - return make<ImportFile>(MBRef);
> -
> - InputFile *Obj;
> - if (Magic == file_magic::coff_object)
> - Obj = make<ObjectFile>(MBRef);
> - else if (Magic == file_magic::bitcode)
> - Obj = make<BitcodeFile>(MBRef);
> - else
> - fatal("unknown file type: " + File->getName());
> -
> - Obj->ParentName = File->getName();
> - return Obj;
> -}
> -
> Defined *Undefined::getWeakAlias() {
> // A weak alias may be a weak alias to another symbol, so check
> recursively.
> for (SymbolBody *A = WeakAlias; A; A = cast<Undefined>(A)->WeakAlias)
> - if (auto *D = dyn_cast<Defined>(A->repl()))
> + if (auto *D = dyn_cast<Defined>(A))
> return D;
> return nullptr;
> }
>
> Modified: lld/trunk/COFF/Symbols.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Symbols.h?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/Symbols.h (original)
> +++ lld/trunk/COFF/Symbols.h Fri Dec 9 15:55:24 2016
> @@ -32,15 +32,8 @@ class ArchiveFile;
> class BitcodeFile;
> class InputFile;
> class ObjectFile;
> -class SymbolBody;
> -
> -// A real symbol object, SymbolBody, is usually accessed indirectly
> -// through a Symbol. There's always one Symbol for each symbol name.
> -// The resolver updates SymbolBody pointers as it resolves symbols.
> -struct Symbol {
> - explicit Symbol(SymbolBody *P) : Body(P) {}
> - SymbolBody *Body;
> -};
> +struct Symbol;
> +class SymbolTable;
>
> // The base class for real symbol classes.
> class SymbolBody {
> @@ -78,21 +71,13 @@ public:
> // Returns the file from which this symbol was created.
> InputFile *getFile();
>
> - // A SymbolBody has a backreference to a Symbol. Originally they are
> - // doubly-linked. A backreference will never change. But the pointer
> - // in the Symbol may be mutated by the resolver. If you have a
> - // pointer P to a SymbolBody and are not sure whether the resolver
> - // has chosen the object among other objects having the same name,
> - // you can access P->Backref->Body to get the resolver's result.
> - void setBackref(Symbol *P) { Backref = P; }
> - SymbolBody *repl() { return Backref ? Backref->Body : this; }
> -
> - // Decides which symbol should "win" in the symbol table, this or
> - // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
> - // they are duplicate (conflicting) symbols.
> - int compare(SymbolBody *Other);
> + Symbol *symbol();
> + const Symbol *symbol() const {
> + return const_cast<SymbolBody *>(this)->symbol();
> + }
>
> protected:
> + friend SymbolTable;
> explicit SymbolBody(Kind K, StringRef N = "")
> : SymbolKind(K), IsExternal(true), IsCOMDAT(false),
> IsReplaceable(false), Name(N) {}
> @@ -107,7 +92,6 @@ protected:
> unsigned IsReplaceable : 1;
>
> StringRef Name;
> - Symbol *Backref = nullptr;
> };
>
> // The base class for any defined symbols, including absolute symbols,
> @@ -149,7 +133,6 @@ public:
> }
>
> ObjectFile *getFile() { return File; }
> - int getFileIndex() { return File->Index; }
>
> COFFSymbolRef getCOFFSymbol();
>
> @@ -195,7 +178,7 @@ public:
> uint64_t getRVA() { return Data->getRVA(); }
>
> private:
> - friend SymbolBody;
> + friend SymbolTable;
> uint64_t getSize() { return Sym->Value; }
> CommonChunk *Data;
> };
> @@ -254,15 +237,12 @@ public:
>
> static bool classof(const SymbolBody *S) { return S->kind() ==
> LazyKind; }
>
> - // Returns an object file for this symbol, or a nullptr if the file
> - // was already returned.
> - InputFile *getMember();
> -
> - int getFileIndex() { return File->Index; }
> -
> ArchiveFile *File;
>
> private:
> + friend SymbolTable;
> +
> +private:
> const Archive::Symbol Sym;
> };
>
> @@ -295,26 +275,22 @@ public:
> // table in an output. The former has "__imp_" prefix.
> class DefinedImportData : public Defined {
> public:
> - DefinedImportData(StringRef D, StringRef N, StringRef E,
> - const coff_import_header *H)
> - : Defined(DefinedImportDataKind, N), DLLName(D), ExternalName(E),
> Hdr(H) {
> + DefinedImportData(StringRef N, ImportFile *F)
> + : Defined(DefinedImportDataKind, N), File(F) {
> }
>
> static bool classof(const SymbolBody *S) {
> return S->kind() == DefinedImportDataKind;
> }
>
> - uint64_t getRVA() { return Location->getRVA(); }
> - StringRef getDLLName() { return DLLName; }
> - StringRef getExternalName() { return ExternalName; }
> - void setLocation(Chunk *AddressTable) { Location = AddressTable; }
> - uint16_t getOrdinal() { return Hdr->OrdinalHint; }
> + uint64_t getRVA() { return File->Location->getRVA(); }
> + StringRef getDLLName() { return File->DLLName; }
> + StringRef getExternalName() { return File->ExternalName; }
> + void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
> + uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
>
> private:
> - StringRef DLLName;
> - StringRef ExternalName;
> - const coff_import_header *Hdr;
> - Chunk *Location = nullptr;
> + ImportFile *File;
> };
>
> // This class represents a symbol for a jump table entry which jumps
> @@ -345,17 +321,17 @@ private:
> class DefinedLocalImport : public Defined {
> public:
> DefinedLocalImport(StringRef N, Defined *S)
> - : Defined(DefinedLocalImportKind, N), Data(S) {}
> + : Defined(DefinedLocalImportKind, N), Data(new LocalImportChunk(S))
> {}
>
> static bool classof(const SymbolBody *S) {
> return S->kind() == DefinedLocalImportKind;
> }
>
> - uint64_t getRVA() { return Data.getRVA(); }
> - Chunk *getChunk() { return &Data; }
> + uint64_t getRVA() { return Data->getRVA(); }
> + Chunk *getChunk() { return Data.get(); }
>
> private:
> - LocalImportChunk Data;
> + std::unique_ptr<LocalImportChunk> Data;
> };
>
> class DefinedBitcode : public Defined {
> @@ -363,6 +339,11 @@ class DefinedBitcode : public Defined {
> public:
> DefinedBitcode(BitcodeFile *F, StringRef N, bool IsReplaceable)
> : Defined(DefinedBitcodeKind, N), File(F) {
> + // IsReplaceable tracks whether the bitcode symbol may be replaced
> with some
> + // other (defined, common or bitcode) symbol. This is the case for
> common,
> + // comdat and weak external symbols. We try to replace bitcode
> symbols with
> + // "real" symbols (see SymbolTable::add{Regular,Bitcode}), and
> resolve the
> + // result against the real symbol from the combined LTO object.
> this->IsReplaceable = IsReplaceable;
> }
>
> @@ -398,6 +379,45 @@ inline uint64_t Defined::getRVA() {
> llvm_unreachable("unknown symbol kind");
> }
>
> +// A real symbol object, SymbolBody, is usually stored within a Symbol.
> There's
> +// always one Symbol for each symbol name. The resolver updates the
> SymbolBody
> +// stored in the Body field of this object as it resolves symbols. Symbol
> also
> +// holds computed properties of symbol names.
> +struct Symbol {
> + // True if this symbol was referenced by a regular (non-bitcode) object.
> + unsigned IsUsedInRegularObj : 1;
> +
> + // This field is used to store the Symbol's SymbolBody. This
> instantiation of
> + // AlignedCharArrayUnion gives us a struct with a char array field that
> is
> + // large and aligned enough to store any derived class of SymbolBody.
> + llvm::AlignedCharArrayUnion<DefinedRegular, DefinedCommon,
> DefinedAbsolute,
> + DefinedRelative, Lazy, Undefined,
> + DefinedImportData, DefinedImportThunk,
> + DefinedLocalImport, DefinedBitcode>
> + Body;
> +
> + SymbolBody *body() {
> + return reinterpret_cast<SymbolBody *>(Body.buffer);
> + }
> + const SymbolBody *body() const { return const_cast<Symbol
> *>(this)->body(); }
> +};
> +
> +template <typename T, typename... ArgT>
> +void replaceBody(Symbol *S, ArgT &&... Arg) {
> + static_assert(sizeof(T) <= sizeof(S->Body), "Body too small");
> + static_assert(alignof(T) <= alignof(decltype(S->Body)),
> + "Body not aligned enough");
> + assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr
> &&
> + "Not a SymbolBody");
> + new (S->Body.buffer) T(std::forward<ArgT>(Arg)...);
> +}
> +
> +inline Symbol *SymbolBody::symbol() {
> + assert(isExternal());
> + return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) -
> + offsetof(Symbol, Body));
> +}
> +
> std::string toString(SymbolBody &B);
>
> } // namespace coff
>
> Modified: lld/trunk/COFF/Writer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/COFF/Writer.cpp (original)
> +++ lld/trunk/COFF/Writer.cpp Fri Dec 9 15:55:24 2016
> @@ -388,7 +388,7 @@ void Writer::createMiscChunks() {
> if (!File->SEHCompat)
> return;
> for (SymbolBody *B : File->SEHandlers)
> - Handlers.insert(cast<Defined>(B->repl()));
> + Handlers.insert(cast<Defined>(B));
> }
>
> SEHTable.reset(new SEHTableChunk(Handlers));
> @@ -428,7 +428,7 @@ void Writer::createImportTables() {
> Sec->addChunk(C);
> }
> if (!DelayIdata.empty()) {
> - Defined *Helper = cast<Defined>(Config->DelayLoadHelper->repl());
> + Defined *Helper = cast<Defined>(Config->DelayLoadHelper);
> DelayIdata.create(Helper);
> OutputSection *Sec = createSection(".didat");
> for (Chunk *C : DelayIdata.getChunks())
> @@ -471,6 +471,10 @@ size_t Writer::addEntryToStringTable(Str
> }
>
> Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {
> + // Relative symbols are unrepresentable in a COFF symbol table.
> + if (isa<DefinedRelative>(Def))
> + return None;
> +
> if (auto *D = dyn_cast<DefinedRegular>(Def))
> if (!D->getChunk()->isLive())
> return None;
> @@ -497,7 +501,6 @@ Optional<coff_symbol16> Writer::createSy
>
> switch (Def->kind()) {
> case SymbolBody::DefinedAbsoluteKind:
> - case SymbolBody::DefinedRelativeKind:
> Sym.Value = Def->getRVA();
> Sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
> break;
> @@ -530,16 +533,13 @@ void Writer::createSymbolAndStringTable(
> Sec->setStringTableOff(addEntryToStringTable(Name));
> }
>
> + std::set<SymbolBody *> SeenSymbols;
> for (lld::coff::ObjectFile *File : Symtab->ObjectFiles)
> for (SymbolBody *B : File->getSymbols())
> if (auto *D = dyn_cast<Defined>(B))
> - if (Optional<coff_symbol16> Sym = createSymbol(D))
> - OutputSymtab.push_back(*Sym);
> -
> - for (ImportFile *File : Symtab->ImportFiles)
> - for (SymbolBody *B : File->getSymbols())
> - if (Optional<coff_symbol16> Sym = createSymbol(cast<Defined>(B)))
> - OutputSymtab.push_back(*Sym);
> + if (SeenSymbols.insert(D).second)
> + if (Optional<coff_symbol16> Sym = createSymbol(D))
> + OutputSymtab.push_back(*Sym);
>
> OutputSection *LastSection = OutputSections.back();
> // We position the symbol table to be adjacent to the end of the last
> section.
> @@ -630,7 +630,7 @@ template <typename PEHeaderTy> void Writ
> PE->SizeOfImage = SizeOfImage;
> PE->SizeOfHeaders = SizeOfHeaders;
> if (!Config->NoEntry) {
> - Defined *Entry = cast<Defined>(Config->Entry->repl());
> + Defined *Entry = cast<Defined>(Config->Entry);
> PE->AddressOfEntryPoint = Entry->getRVA();
> // Pointer to thumb code must have the LSB set, so adjust it.
> if (Config->Machine == ARMNT)
> @@ -685,7 +685,7 @@ template <typename PEHeaderTy> void Writ
> Dir[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize();
> }
> if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) {
> - if (Defined *B = dyn_cast<Defined>(Sym->Body)) {
> + if (Defined *B = dyn_cast<Defined>(Sym->body())) {
> Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA();
> Dir[TLS_TABLE].Size = Config->is64()
> ? sizeof(object::coff_tls_directory64)
> @@ -697,7 +697,7 @@ template <typename PEHeaderTy> void Writ
> Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize();
> }
> if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) {
> - if (auto *B = dyn_cast<DefinedRegular>(Sym->Body)) {
> + if (auto *B = dyn_cast<DefinedRegular>(Sym->body())) {
> SectionChunk *SC = B->getChunk();
> assert(B->getRVA() >= SC->getRVA());
> uint64_t OffsetInChunk = B->getRVA() - SC->getRVA();
> @@ -754,8 +754,10 @@ void Writer::openFile(StringRef Path) {
> void Writer::fixSafeSEHSymbols() {
> if (!SEHTable)
> return;
> - Config->SEHTable->setRVA(SEHTable->getRVA());
> - Config->SEHCount->setVA(SEHTable->getSize() / 4);
> + if (auto *T = dyn_cast<DefinedRelative>(Config->SEHTable->body()))
> + T->setRVA(SEHTable->getRVA());
> + if (auto *C = dyn_cast<DefinedAbsolute>(Config->SEHCount->body()))
> + C->setVA(SEHTable->getSize() / 4);
> }
>
> // Handles /section options to allow users to overwrite
>
> Modified: lld/trunk/test/COFF/include2.test
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/include2.test?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/test/COFF/include2.test (original)
> +++ lld/trunk/test/COFF/include2.test Fri Dec 9 15:55:24 2016
> @@ -9,6 +9,6 @@
>
> CHECK: include2.test.tmp1.obj
> CHECK: include2.test.tmp2.lib
> -CHECK: include2.test.tmp3.lib
> CHECK: include2.test.tmp2.lib(include2.test.tmp2.obj) for foo
> +CHECK: include2.test.tmp3.lib
> CHECK: include2.test.tmp3.lib(include2.test.tmp3.obj) for bar
>
> Modified: lld/trunk/test/COFF/order.test
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/order.test?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/test/COFF/order.test (original)
> +++ lld/trunk/test/COFF/order.test Fri Dec 9 15:55:24 2016
> @@ -11,5 +11,5 @@
> CHECK: order.test.tmp1.obj
> CHECK: order.test.tmp3.obj
> CHECK: order.test.tmp2.lib
> -CHECK: order.test.tmp3.lib
> CHECK: order.test.tmp2.lib(order.test.tmp2.obj) for foo
> +CHECK: order.test.tmp3.lib
>
> Modified: lld/trunk/test/COFF/symtab.test
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/symtab.test?rev=289280&r1=289279&r2=289280&view=diff
>
> ==============================================================================
> --- lld/trunk/test/COFF/symtab.test (original)
> +++ lld/trunk/test/COFF/symtab.test Fri Dec 9 15:55:24 2016
> @@ -36,17 +36,17 @@
> # CHECK-NEXT: AuxSymbolCount: 0
> # CHECK-NEXT:
--
Mike
Sent from phone
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161212/8eddf5a9/attachment-0001.html>
More information about the llvm-commits
mailing list