diff options
-rw-r--r-- | lld/ELF/Driver.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/InputFiles.cpp | 87 | ||||
-rw-r--r-- | lld/ELF/InputFiles.h | 3 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 88 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.h | 1 |
5 files changed, 95 insertions, 86 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 0e5f1a72e6e..9411882cc48 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1526,7 +1526,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. for (InputFile *F : Files) - Symtab->addFile<ELFT>(F); + parseFile<ELFT>(F); // Now that we have every file, we can decide if we will need a // dynamic symbol table. diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index d8856d06628..99545a11f11 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -78,6 +78,88 @@ Optional<MemoryBufferRef> elf::readFile(StringRef Path) { return MBRef; } +// All input object files must be for the same architecture +// (e.g. it does not make sense to link x86 object files with +// MIPS object files.) This function checks for that error. +static bool isCompatible(InputFile *File) { + if (!File->isElf() && !isa<BitcodeFile>(File)) + return true; + + if (File->EKind == Config->EKind && File->EMachine == Config->EMachine) { + if (Config->EMachine != EM_MIPS) + return true; + if (isMipsN32Abi(File) == Config->MipsN32Abi) + return true; + } + + if (!Config->Emulation.empty()) { + error(toString(File) + " is incompatible with " + Config->Emulation); + } else { + InputFile *Existing; + if (!ObjectFiles.empty()) + Existing = ObjectFiles[0]; + else if (!SharedFiles.empty()) + Existing = SharedFiles[0]; + else + Existing = BitcodeFiles[0]; + + error(toString(File) + " is incompatible with " + toString(Existing)); + } + + return false; +} + +// Add symbols in File to the symbol table. +template <class ELFT> void elf::parseFile(InputFile *File) { + // Comdat groups define "link once" sections. If two comdat groups have the + // same name, only one of them is linked, and the other is ignored. This set + // is used to uniquify them. + static llvm::DenseSet<llvm::CachedHashStringRef> ComdatGroups; + + if (!isCompatible(File)) + return; + + // Binary file + if (auto *F = dyn_cast<BinaryFile>(File)) { + BinaryFiles.push_back(F); + F->parse(); + return; + } + + // .a file + if (auto *F = dyn_cast<ArchiveFile>(File)) { + F->parse<ELFT>(); + return; + } + + // Lazy object file + if (auto *F = dyn_cast<LazyObjFile>(File)) { + LazyObjFiles.push_back(F); + F->parse<ELFT>(); + return; + } + + if (Config->Trace) + message(toString(File)); + + // .so file + if (auto *F = dyn_cast<SharedFile>(File)) { + F->parse<ELFT>(); + return; + } + + // LLVM bitcode file + if (auto *F = dyn_cast<BitcodeFile>(File)) { + BitcodeFiles.push_back(F); + F->parse<ELFT>(ComdatGroups); + return; + } + + // Regular object file + ObjectFiles.push_back(File); + cast<ObjFile<ELFT>>(File)->parse(ComdatGroups); +} + // Concatenates arguments to construct a string representing an error location. static std::string createFileLineMsg(StringRef Path, unsigned Line) { std::string Filename = path::filename(Path); @@ -1359,6 +1441,11 @@ std::string elf::replaceThinLTOSuffix(StringRef Path) { return Path; } +template void elf::parseFile<ELF32LE>(InputFile *); +template void elf::parseFile<ELF32BE>(InputFile *); +template void elf::parseFile<ELF64LE>(InputFile *); +template void elf::parseFile<ELF64BE>(InputFile *); + template void ArchiveFile::parse<ELF32LE>(); template void ArchiveFile::parse<ELF32BE>(); template void ArchiveFile::parse<ELF64LE>(); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index c9846347df0..96b16b37e9a 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -54,6 +54,9 @@ extern std::unique_ptr<llvm::TarWriter> Tar; // Opens a given file. llvm::Optional<MemoryBufferRef> readFile(StringRef Path); +// Add symbols in File to the symbol table. +template <class ELFT> void parseFile(InputFile *File); + // The root class of input files. class InputFile { public: diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 6e69b25c61e..95c2d43494a 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -32,81 +32,6 @@ using namespace lld::elf; SymbolTable *elf::Symtab; -static InputFile *getFirstElf() { - if (!ObjectFiles.empty()) - return ObjectFiles[0]; - if (!SharedFiles.empty()) - return SharedFiles[0]; - return BitcodeFiles[0]; -} - -// All input object files must be for the same architecture -// (e.g. it does not make sense to link x86 object files with -// MIPS object files.) This function checks for that error. -static bool isCompatible(InputFile *F) { - if (!F->isElf() && !isa<BitcodeFile>(F)) - return true; - - if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) { - if (Config->EMachine != EM_MIPS) - return true; - if (isMipsN32Abi(F) == Config->MipsN32Abi) - return true; - } - - if (!Config->Emulation.empty()) - error(toString(F) + " is incompatible with " + Config->Emulation); - else - error(toString(F) + " is incompatible with " + toString(getFirstElf())); - return false; -} - -// Add symbols in File to the symbol table. -template <class ELFT> void SymbolTable::addFile(InputFile *File) { - if (!isCompatible(File)) - return; - - // Binary file - if (auto *F = dyn_cast<BinaryFile>(File)) { - BinaryFiles.push_back(F); - F->parse(); - return; - } - - // .a file - if (auto *F = dyn_cast<ArchiveFile>(File)) { - F->parse<ELFT>(); - return; - } - - // Lazy object file - if (auto *F = dyn_cast<LazyObjFile>(File)) { - LazyObjFiles.push_back(F); - F->parse<ELFT>(); - return; - } - - if (Config->Trace) - message(toString(File)); - - // .so file - if (auto *F = dyn_cast<SharedFile>(File)) { - F->parse<ELFT>(); - return; - } - - // LLVM bitcode file - if (auto *F = dyn_cast<BitcodeFile>(File)) { - BitcodeFiles.push_back(F); - F->parse<ELFT>(ComdatGroups); - return; - } - - // Regular object file - ObjectFiles.push_back(File); - cast<ObjFile<ELFT>>(File)->parse(ComdatGroups); -} - // This function is where all the optimizations of link-time // optimization happens. When LTO is in use, some input files are // not in native object file format but in the LLVM bitcode format. @@ -539,7 +464,7 @@ void SymbolTable::addLazyArchive(StringRef Name, ArchiveFile &File, } if (InputFile *F = File.fetch(Sym)) - addFile<ELFT>(F); + parseFile<ELFT>(F); } template <class ELFT> @@ -563,19 +488,19 @@ void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &File) { } if (InputFile *F = File.fetch()) - addFile<ELFT>(F); + parseFile<ELFT>(F); } template <class ELFT> void SymbolTable::fetchLazy(Symbol *Sym) { if (auto *S = dyn_cast<LazyArchive>(Sym)) { if (InputFile *File = S->fetch()) - addFile<ELFT>(File); + parseFile<ELFT>(File); return; } auto *S = cast<LazyObject>(Sym); if (InputFile *File = cast<LazyObjFile>(S->File)->fetch()) - addFile<ELFT>(File); + parseFile<ELFT>(File); } // Initialize DemangledSyms with a map from demangled symbols to symbol @@ -739,11 +664,6 @@ void SymbolTable::scanVersionScript() { Sym->parseSymbolVersion(); } -template void SymbolTable::addFile<ELF32LE>(InputFile *); -template void SymbolTable::addFile<ELF32BE>(InputFile *); -template void SymbolTable::addFile<ELF64LE>(InputFile *); -template void SymbolTable::addFile<ELF64BE>(InputFile *); - template Symbol *SymbolTable::addUndefined<ELF32LE>(StringRef, uint8_t, uint8_t, uint8_t, bool, InputFile *); template Symbol *SymbolTable::addUndefined<ELF32BE>(StringRef, uint8_t, uint8_t, diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index d6fb00fba47..eb44324407a 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -34,7 +34,6 @@ class SectionBase; // is one add* function per symbol type. class SymbolTable { public: - template <class ELFT> void addFile(InputFile *File); template <class ELFT> void addCombinedLTOObject(); void wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap); |