Accept archive files with no symbol table instad of warning on them.

It seems virtually everyone who tries to do LTO build with Clang and
LLD was hit by a mistake to forget using llvm-ar command to create
archive files. I wasn't an exception. Since this is an annoying common
issue, it is probably better to handle that gracefully rather than
reporting an error and tell the user to redo build with different
configuration.

Differential Revision: https://reviews.llvm.org/D32721

llvm-svn: 302083
This commit is contained in:
Rui Ueyama 2017-05-03 21:03:08 +00:00
parent 1f8b73d15c
commit fd7deda57a
6 changed files with 32 additions and 45 deletions

View File

@ -99,7 +99,6 @@ struct Configuration {
std::vector<SymbolVersion> VersionScriptLocals;
std::vector<uint8_t> BuildIdVector;
bool AllowMultipleDefinition;
bool ArchiveWithoutSymbolsSeen = false;
bool AsNeeded = false;
bool Bsymbolic;
bool BsymbolicFunctions;

View File

@ -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<ArchiveFile>(MBRef));
std::unique_ptr<Archive> 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<LazyObjectFile>(MB));
return;
}
// Handle the regular case.
Files.push_back(make<ArchiveFile>(std::move(File)));
return;
}
case file_magic::elf_shared_object:
if (Config->Relocatable) {
error("attempted static link of dynamic object " + Path);

View File

@ -596,17 +596,13 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
}
}
ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File)
: InputFile(ArchiveKind, File->getMemoryBufferRef()),
File(std::move(File)) {}
template <class ELFT> 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<ELFT>::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.

View File

@ -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<Archive> &&File);
static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
template <class ELFT> void parse();

View File

@ -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;
}
}
}

View File

@ -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"