diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -235,23 +235,22 @@ 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 an archive file has no symbol table, it may be intentional (used as a + // group of lazy object files where the symbol table is not useful), or the + // user is attempting LTO and using a default ar command that doesn't + // understand the LLVM bitcode file. Treat the archive as a group of lazy + // object files. if (!file->isEmpty() && !file->hasSymbolTable()) { - // Check if all members are bitcode files. If not, ignore, which is the - // default action without the LTO hack described above. for (const std::pair &p : - getArchiveMembers(mbref)) - if (identify_magic(p.first.getBuffer()) != file_magic::bitcode) { - error(path + ": archive has no index; run ranlib to add one"); - return; - } - - for (const std::pair &p : - getArchiveMembers(mbref)) - files.push_back(createLazyFile(p.first, path, p.second)); + getArchiveMembers(mbref)) { + auto magic = identify_magic(p.first.getBuffer()); + if (magic == file_magic::bitcode || + magic == file_magic::elf_relocatable) + files.push_back(createLazyFile(p.first, path, p.second)); + else + error(path + ": archive member '" + p.first.getBufferIdentifier() + + "' is neither ET_REL nor LLVM bitcode"); + } return; } diff --git a/lld/test/ELF/archive-no-index.s b/lld/test/ELF/archive-no-index.s --- a/lld/test/ELF/archive-no-index.s +++ b/lld/test/ELF/archive-no-index.s @@ -5,9 +5,13 @@ # RUN: rm -f %t.a # RUN: llvm-ar crS %t.a %t.archive.o -# RUN: not ld.lld -o /dev/null %t.o %t.a 2>&1 | FileCheck %s +# RUN: ld.lld %t.o %t.a -o /dev/null 2>&1 | count 0 + +# RUN: ld.lld -shared %t.archive.o -o %t.so +# RUN: llvm-ar crS %t.a %t.so +# RUN: not ld.lld %t.o %t.a --noinhibit-exec -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR + +# ERR: error: {{.*}}.a: archive member '{{.*}}.so' is neither ET_REL nor LLVM bitcode .globl _start _start: - -# CHECK: error: {{.*}}.a: archive has no index; run ranlib to add one diff --git a/lld/test/ELF/lto/archive-no-index.ll b/lld/test/ELF/lto/archive-no-index.ll --- a/lld/test/ELF/lto/archive-no-index.ll +++ b/lld/test/ELF/lto/archive-no-index.ll @@ -1,6 +1,5 @@ ; REQUIRES: x86 -; Tests that we accept an archive file without symbol table -; if all the member files are bitcode files. +; Tests that we accept an archive file without symbol table. ; RUN: llvm-as -o %t1.o %s ; RUN: llvm-as -o %t2.o %S/Inputs/archive.ll @@ -25,10 +24,9 @@ ; RUN: echo 'f:' | llvm-mc -triple=x86_64-pc-linux -filetype=obj - -o %t3.o ; RUN: rm -f %t3.a ; RUN: llvm-ar crS %t3.a %t3.o -; RUN: not ld.lld -o /dev/null -emain %t1.o %t3.a 2>&1 | FileCheck -check-prefix=ERR1 %s -; ERR1: error: {{.*}}.a: archive has no index; run ranlib to add one +; RUN: not ld.lld -o %t -emain %t1.o %t3.a 2>&1 | FileCheck --check-prefix=ERR %s ; RUN: rm -f %t4.a ; RUN: llvm-ar cr %t4.a -; RUN: not ld.lld -o /dev/null -emain %t1.o %t4.a 2>&1 | FileCheck -check-prefix=ERR2 %s -; ERR2: error: undefined symbol: f +; RUN: not ld.lld -o /dev/null -emain %t1.o %t4.a 2>&1 | FileCheck -check-prefix=ERR %s +; ERR: error: undefined symbol: f