diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 1ace4aa26fdb..57a0e5a5ec73 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -99,7 +99,6 @@ struct Configuration { std::vector VersionScriptLocals; std::vector BuildIdVector; bool AllowMultipleDefinition; - bool ArchiveWithoutSymbolsSeen = false; bool AsNeeded = false; bool Bsymbolic; bool BsymbolicFunctions; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 6a71eb3ee490..ac0e28dfa087 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -171,14 +171,31 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { case file_magic::unknown: readLinkerScript(MBRef); return; - case file_magic::archive: + case file_magic::archive: { + // Handle -whole-archive. if (InWholeArchive) { for (MemoryBufferRef MB : getArchiveMembers(MBRef)) Files.push_back(createObjectFile(MB, Path)); return; } - Files.push_back(make(MBRef)); + + std::unique_ptr File = + check(Archive::create(MBRef), Path + ": failed to parse archive"); + + // If an archive file has no symbol table, it is likely that a user + // is attempting LTO and using a default ar command that doesn't + // understand the LLVM bitcode file. It is a pretty common error, so + // we'll handle it as if it had a symbol table. + if (!File->hasSymbolTable()) { + for (MemoryBufferRef MB : getArchiveMembers(MBRef)) + Files.push_back(make(MB)); + return; + } + + // Handle the regular case. + Files.push_back(make(std::move(File))); return; + } case file_magic::elf_shared_object: if (Config->Relocatable) { error("attempted static link of dynamic object " + Path); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 260a78ebbf8e..c741c451b626 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -596,17 +596,13 @@ SymbolBody *elf::ObjectFile::createSymbolBody(const Elf_Sym *Sym) { } } +ArchiveFile::ArchiveFile(std::unique_ptr &&File) + : InputFile(ArchiveKind, File->getMemoryBufferRef()), + File(std::move(File)) {} + template void ArchiveFile::parse() { - File = check(Archive::create(MB), - MB.getBufferIdentifier() + ": failed to parse archive"); - - // Read the symbol table to construct Lazy objects. - for (const Archive::Symbol &Sym : File->symbols()) { + for (const Archive::Symbol &Sym : File->symbols()) Symtab::X->addLazyArchive(this, Sym); - } - - if (File->symbols().begin() == File->symbols().end()) - Config->ArchiveWithoutSymbolsSeen = true; } // Returns a buffer pointing to a member file containing a given symbol. diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index d0a45a4a98cf..7798d88ea597 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -239,7 +239,7 @@ private: // An ArchiveFile object represents a .a file. class ArchiveFile : public InputFile { public: - explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} + explicit ArchiveFile(std::unique_ptr &&File); static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } template void parse(); diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index baef0a2f2257..22571ad94bf4 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -694,17 +694,6 @@ static void reportUndefined(SymbolBody &Sym, InputSectionBase &S, warn(Msg); } else { error(Msg); - - if (Config->ArchiveWithoutSymbolsSeen) { - message("At least one archive listed no symbols in its index." - " This can happen when creating archives with a version" - " of ar that does not understand the object files in" - " the archive. For example, if you are using LLVM" - " bitcode objects (such as created by -flto), you may" - " need to use llvm-ar or GNU ar with a plugin."); - // Reset to false so that we print the message only once. - Config->ArchiveWithoutSymbolsSeen = false; - } } } diff --git a/lld/test/ELF/lto/archive-no-index.ll b/lld/test/ELF/lto/archive-no-index.ll index 0dca16ba04fb..48cca0aa0794 100644 --- a/lld/test/ELF/lto/archive-no-index.ll +++ b/lld/test/ELF/lto/archive-no-index.ll @@ -4,29 +4,15 @@ ; encountered an empty archive index and undefined references (to prevent ; noisy false alarms). -; RUN: rm -fr %T/archive-no-index -; RUN: mkdir %T/archive-no-index -; RUN: llvm-as %S/Inputs/archive.ll -o %T/archive-no-index/f.o -; RUN: llvm-ar cr %T/archive-no-index/libf.a -; RUN: llvm-ar qS %T/archive-no-index/libf.a %T/archive-no-index/f.o -; RUN: llvm-as %s -o %t.o -; RUN: not ld.lld -emain -m elf_x86_64 %t.o -o %t %T/archive-no-index/libf.a \ -; RUN: 2>&1 | FileCheck --check-prefix=NOTE %s +; RUN: llvm-as -o %t1.o %s +; RUN: llvm-as -o %t2.o %S/Inputs/archive.ll -; RUN: llvm-ar crs %T/archive-no-index/libfs.a %T/archive-no-index/f.o -; RUN: ld.lld -emain -m elf_x86_64 %t.o -o %t %T/archive-no-index/libf.a \ -; RUN: %T/archive-no-index/libfs.a +; RUN: rm -f %t1.a %t2.a +; RUN: llvm-ar crS %t1.a %t2.o +; RUN: llvm-ar crs %t2.a %t2.o -; RUN: llvm-as %S/Inputs/archive-3.ll -o %T/archive-no-index/foo.o -; RUN: llvm-ar crs %T/archive-no-index/libfoo.a %T/archive-no-index/foo.o -; RUN: not ld.lld -emain -m elf_x86_64 %t.o -o %t %T/archive-no-index/libfoo.a \ -; RUN: 2>&1 | FileCheck --check-prefix=NO-NOTE %s - -; NOTE: undefined symbol: f -; NOTE: archive listed no symbols - -; NO-NOTE: undefined symbol: f -; NO-NOTE-NOT: archive listed no symbols +; RUN: ld.lld -o %t -emain -m elf_x86_64 %t1.o %t1.a +; RUN: ld.lld -o %t -emain -m elf_x86_64 %t1.o %t2.a target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu"