diff options
Diffstat (limited to 'lld/ELF/InputFiles.cpp')
-rw-r--r-- | lld/ELF/InputFiles.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
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>(); |