diff --git a/lld/ELF/Driver.h b/lld/ELF/Driver.h --- a/lld/ELF/Driver.h +++ b/lld/ELF/Driver.h @@ -42,6 +42,9 @@ std::unique_ptr lto; std::vector files; + +public: + SmallVector, 0> archiveFiles; }; // Parses command line options. diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -49,6 +49,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Config/llvm-config.h" #include "llvm/LTO/LTO.h" +#include "llvm/Object/Archive.h" #include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" @@ -96,7 +97,6 @@ inputSections.clear(); outputSections.clear(); memoryBuffers.clear(); - archiveFiles.clear(); binaryFiles.clear(); bitcodeFiles.clear(); lazyBitcodeFiles.clear(); @@ -228,32 +228,20 @@ return; } - std::unique_ptr file = - CHECK(Archive::create(mbref), path + ": failed to parse archive"); - - // 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()) { - // Handle the regular case. - files.push_back(make(std::move(file))); - return; - } + auto members = getArchiveMembers(mbref); + archiveFiles.emplace_back(path, members.size()); // All files within the archive get the same group ID to allow mutual // references for --warn-backrefs. bool saved = InputFile::isInGroup; InputFile::isInGroup = true; - for (const std::pair &p : - getArchiveMembers(mbref)) { + for (const std::pair &p : members) { 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"); + warn(path + ": archive member '" + p.first.getBufferIdentifier() + + "' is neither ET_REL nor LLVM bitcode"); } InputFile::isInGroup = saved; if (!saved) @@ -1475,13 +1463,16 @@ // Iterate over argv to process input files and positional arguments. InputFile::isInGroup = false; + bool hasInput = false; for (auto *arg : args) { switch (arg->getOption().getID()) { case OPT_library: addLibrary(arg->getValue()); + hasInput = true; break; case OPT_INPUT: addFile(arg->getValue(), /*withLOption=*/false); + hasInput = true; break; case OPT_defsym: { StringRef from; @@ -1570,7 +1561,7 @@ } } - if (files.empty() && errorCount() == 0) + if (files.empty() && !hasInput && errorCount() == 0) error("no input files"); } @@ -1726,10 +1717,7 @@ return; MemoryBufferRef mb; - if (auto *lo = dyn_cast(sym)) - mb = lo->file->mb; - else - mb = cast(sym)->getMemberBuffer(); + mb = cast(sym)->file->mb; if (isBitcode(mb)) sym->extract(); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -15,8 +15,8 @@ #include "lld/Common/Reproduce.h" #include "llvm/ADT/DenseSet.h" #include "llvm/BinaryFormat/Magic.h" -#include "llvm/Object/Archive.h" #include "llvm/Object/ELF.h" +#include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/Threading.h" namespace llvm { @@ -35,8 +35,6 @@ namespace elf { -using llvm::object::Archive; - class InputSection; class Symbol; @@ -310,33 +308,6 @@ llvm::once_flag initDwarf; }; -// An ArchiveFile object represents a .a file. -class ArchiveFile : public InputFile { -public: - explicit ArchiveFile(std::unique_ptr &&file); - static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; } - void parse(); - - // Pulls out an object file that contains a definition for Sym and - // returns it. If the same file was instantiated before, this - // function does nothing (so we don't instantiate the same file - // more than once.) - void extract(const Archive::Symbol &sym); - - // Check if a non-common symbol should be extracted to override a common - // definition. - bool shouldExtractForCommon(const Archive::Symbol &sym); - - size_t getMemberCount() const; - size_t getExtractedMemberCount() const { return seen.size(); } - - bool parsed = false; - -private: - std::unique_ptr file; - llvm::DenseSet seen; -}; - class BitcodeFile : public InputFile { public: BitcodeFile(MemoryBufferRef m, StringRef archiveName, @@ -403,7 +374,6 @@ std::string replaceThinLTOSuffix(StringRef path); extern SmallVector> memoryBuffers; -extern SmallVector archiveFiles; extern SmallVector binaryFiles; extern SmallVector bitcodeFiles; extern SmallVector lazyBitcodeFiles; diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -43,7 +43,6 @@ uint32_t InputFile::nextGroupId; SmallVector> elf::memoryBuffers; -SmallVector elf::archiveFiles; SmallVector elf::binaryFiles; SmallVector elf::bitcodeFiles; SmallVector elf::lazyBitcodeFiles; @@ -176,13 +175,6 @@ return; } - // .a file - if (auto *f = dyn_cast(file)) { - archiveFiles.push_back(f); - f->parse(); - return; - } - // Lazy object file if (file->lazy) { if (auto *f = dyn_cast(file)) { @@ -1116,14 +1108,12 @@ // defined symbol in a .eh_frame becomes dangling symbols. if (sec == &InputSection::discarded) { Undefined und{this, StringRef(), binding, stOther, type, secIdx}; - // !ArchiveFile::parsed or !LazyObjFile::lazy means that the file - // containing this object has not finished processing, i.e. this symbol is - // a result of a lazy symbol extract. We should demote the lazy symbol to - // an Undefined so that any relocations outside of the group to it will - // trigger a discarded section error. - if ((sym->symbolKind == Symbol::LazyArchiveKind && - !cast(sym->file)->parsed) || - (sym->symbolKind == Symbol::LazyObjectKind && !sym->file->lazy)) { + // !LazyObjFile::lazy indicates that the file containing this object has + // not finished processing, i.e. this symbol is a result of a lazy symbol + // extract. We should demote the lazy symbol to an Undefined so that any + // relocations outside of the group to it will trigger a discarded section + // error. + if (sym->symbolKind == Symbol::LazyObjectKind && !sym->file->lazy) { sym->replace(und); // Prevent LTO from internalizing the symbol in case there is a // reference to this symbol from this file. @@ -1159,44 +1149,6 @@ } } -ArchiveFile::ArchiveFile(std::unique_ptr &&file) - : InputFile(ArchiveKind, file->getMemoryBufferRef()), - file(std::move(file)) {} - -void ArchiveFile::parse() { - SymbolTable &symtab = *elf::symtab; - for (const Archive::Symbol &sym : file->symbols()) - symtab.addSymbol(LazyArchive{*this, sym}); - - // Inform a future invocation of ObjFile::initializeSymbols() that this - // archive has been processed. - parsed = true; -} - -// Returns a buffer pointing to a member file containing a given symbol. -void ArchiveFile::extract(const Archive::Symbol &sym) { - Archive::Child c = - CHECK(sym.getMember(), toString(this) + - ": could not get the member for symbol " + - toELFString(sym)); - - if (!seen.insert(c.getChildOffset()).second) - return; - - MemoryBufferRef mb = - CHECK(c.getMemoryBufferRef(), - toString(this) + - ": could not get the buffer for the member defining symbol " + - toELFString(sym)); - - if (tar && c.getParent()->isThin()) - tar->append(relativeToRoot(CHECK(c.getFullName(), this)), mb.getBuffer()); - - InputFile *file = createObjectFile(mb, getName(), c.getChildOffset()); - file->groupId = groupId; - parseFile(file); -} - // The handling of tentative definitions (COMMON symbols) in archives is murky. // A tentative definition will be promoted to a global definition if there are // no non-tentative definitions to dominate it. When we hold a tentative @@ -1263,36 +1215,6 @@ } } -bool ArchiveFile::shouldExtractForCommon(const Archive::Symbol &sym) { - Archive::Child c = - CHECK(sym.getMember(), toString(this) + - ": could not get the member for symbol " + - toELFString(sym)); - MemoryBufferRef mb = - CHECK(c.getMemoryBufferRef(), - toString(this) + - ": could not get the buffer for the member defining symbol " + - toELFString(sym)); - - if (isBitcode(mb)) - return isBitcodeNonCommonDef(mb, sym.getName(), getName()); - - return isNonCommonDef(mb, sym.getName(), getName()); -} - -size_t ArchiveFile::getMemberCount() const { - size_t count = 0; - Error err = Error::success(); - for (const Archive::Child &c : file->children(err)) { - (void)c; - ++count; - } - // This function is used by --print-archive-stats=, where an error does not - // really matter. - consumeError(std::move(err)); - return count; -} - unsigned SharedFile::vernauxNum; // Parse the version definitions in the object file if present, and return a diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -19,6 +19,7 @@ //===----------------------------------------------------------------------===// #include "MapFile.h" +#include "Driver.h" #include "InputFiles.h" #include "LinkerScript.h" #include "OutputSections.h" @@ -307,7 +308,19 @@ } os << "members\textracted\tarchive\n"; - for (const ArchiveFile *f : archiveFiles) - os << f->getMemberCount() << '\t' << f->getExtractedMemberCount() << '\t' - << f->getName() << '\n'; + + SmallVector archives; + DenseMap all, extracted; + for (ELFFileBase *file : objectFiles) + if (file->archiveName.size()) + ++extracted[CachedHashStringRef(file->archiveName)]; + for (BitcodeFile *file : bitcodeFiles) + if (file->archiveName.size()) + ++extracted[CachedHashStringRef(file->archiveName)]; + for (std::pair f : driver->archiveFiles) { + unsigned &v = extracted[CachedHashString(f.first)]; + os << f.second << '\t' << v << '\t' << f.first << '\n'; + // If the archive occurs multiple times, other instances have a count of 0. + v = 0; + } } diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -17,7 +17,6 @@ #include "lld/Common/LLVM.h" #include "lld/Common/Memory.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/Object/Archive.h" #include "llvm/Object/ELF.h" #include @@ -25,11 +24,6 @@ // Returns a string representation for a symbol for diagnostics. std::string toString(const elf::Symbol &); -// There are two different ways to convert an Archive::Symbol to a string: -// One for Microsoft name mangling and one for Itanium name mangling. -// Call the functions toCOFFString and toELFString, not just toString. -std::string toELFString(const llvm::object::Archive::Symbol &); - namespace elf { class CommonSymbol; class Defined; @@ -59,7 +53,6 @@ CommonKind, SharedKind, UndefinedKind, - LazyArchiveKind, LazyObjectKind, }; @@ -151,9 +144,7 @@ bool isLocal() const { return binding == llvm::ELF::STB_LOCAL; } - bool isLazy() const { - return symbolKind == LazyArchiveKind || symbolKind == LazyObjectKind; - } + bool isLazy() const { return symbolKind == LazyObjectKind; } // True if this is an undefined weak symbol. This only works once // all input files have been added. @@ -416,36 +407,14 @@ uint32_t alignment; }; -// LazyArchive and LazyObject represent a symbols that is not yet in the link, -// but we know where to find it if needed. If the resolver finds both Undefined -// and Lazy for the same name, it will ask the Lazy to load a file. +// LazyObject symbols represents symbols in object files between +// --start-lib and --end-lib options. // // A special complication is the handling of weak undefined symbols. They should // not load a file, but we have to remember we have seen both the weak undefined // and the lazy. We represent that with a lazy symbol with a weak binding. This // means that code looking for undefined symbols normally also has to take lazy // symbols into consideration. - -// This class represents a symbol defined in an archive file. It is -// created from an archive file header, and it knows how to load an -// object file from an archive to replace itself with a defined -// symbol. -class LazyArchive : public Symbol { -public: - LazyArchive(InputFile &file, const llvm::object::Archive::Symbol s) - : Symbol(LazyArchiveKind, &file, s.getName(), llvm::ELF::STB_GLOBAL, - llvm::ELF::STV_DEFAULT, llvm::ELF::STT_NOTYPE), - sym(s) {} - - static bool classof(const Symbol *s) { return s->kind() == LazyArchiveKind; } - - MemoryBufferRef getMemberBuffer(); - - const llvm::object::Archive::Symbol sym; -}; - -// LazyObject symbols represents symbols in object files between -// --start-lib and --end-lib options. class LazyObject : public Symbol { public: LazyObject(InputFile &file) @@ -504,8 +473,7 @@ alignas(CommonSymbol) char b[sizeof(CommonSymbol)]; alignas(Undefined) char c[sizeof(Undefined)]; alignas(SharedSymbol) char d[sizeof(SharedSymbol)]; - alignas(LazyArchive) char e[sizeof(LazyArchive)]; - alignas(LazyObject) char f[sizeof(LazyObject)]; + alignas(LazyObject) char e[sizeof(LazyObject)]; }; // It is important to keep the size of SymbolUnion small for performance and @@ -526,7 +494,6 @@ AssertSymbol(); AssertSymbol(); AssertSymbol(); - AssertSymbol(); AssertSymbol(); } @@ -538,8 +505,6 @@ return sizeof(CommonSymbol); case DefinedKind: return sizeof(Defined); - case LazyArchiveKind: - return sizeof(LazyArchive); case LazyObjectKind: return sizeof(LazyObject); case SharedKind: diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -33,10 +33,6 @@ return ret; } -std::string lld::toELFString(const Archive::Symbol &b) { - return demangle(b.getName(), config->demangle); -} - Defined *ElfSym::bss; Defined *ElfSym::etext1; Defined *ElfSym::etext2; @@ -129,7 +125,6 @@ case Symbol::SharedKind: case Symbol::UndefinedKind: return 0; - case Symbol::LazyArchiveKind: case Symbol::LazyObjectKind: llvm_unreachable("lazy symbol reached writer"); case Symbol::CommonKind: @@ -246,24 +241,12 @@ } void Symbol::extract() const { - if (auto *sym = dyn_cast(this)) { - cast(sym->file)->extract(sym->sym); - } else if (file->lazy) { + if (file->lazy) { file->lazy = false; parseFile(file); } } -MemoryBufferRef LazyArchive::getMemberBuffer() { - Archive::Child c = - CHECK(sym.getMember(), - "could not get the member for symbol " + toELFString(sym)); - - return CHECK(c.getMemoryBufferRef(), - "could not get the buffer for the member defining symbol " + - toELFString(sym)); -} - uint8_t Symbol::computeBinding() const { if ((visibility != STV_DEFAULT && visibility != STV_PROTECTED) || versionId == VER_NDX_LOCAL) @@ -428,9 +411,6 @@ case Symbol::DefinedKind: resolveDefined(cast(other)); break; - case Symbol::LazyArchiveKind: - resolveLazy(cast(other)); - break; case Symbol::LazyObjectKind: resolveLazy(cast(other)); break; @@ -691,14 +671,7 @@ // For common objects, we want to look for global or weak definitions that // should be extracted as the canonical definition instead. if (isCommon() && elf::config->fortranCommon) { - if (auto *laSym = dyn_cast(&other)) { - ArchiveFile *archive = cast(laSym->file); - const Archive::Symbol &archiveSym = laSym->sym; - if (archive->shouldExtractForCommon(archiveSym)) { - replaceCommon(*this, other); - return; - } - } else if (auto *loSym = dyn_cast(&other)) { + if (auto *loSym = dyn_cast(&other)) { if (loSym->file->shouldExtractForCommon(getName())) { replaceCommon(*this, other); return; diff --git a/lld/test/ELF/archive-as-start-lib.s b/lld/test/ELF/archive-as-start-lib.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/archive-as-start-lib.s @@ -0,0 +1,31 @@ +# REQUIRES: x86 + +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o + +## Create an archive with incomplete index: foo is missing. +# RUN: llvm-ar --format=gnu rc a.a a.o +# RUN: llvm-ar --format=gnu rcS b.a b.o && tail -c +9 b.a > b-tail +# RUN: cat a.a b-tail > weird.a +# RUN: llvm-nm --print-armap weird.a | FileCheck %s --check-prefix=ARMAP + +# ARMAP: Archive map +# ARMAP-NEXT: _start in a.o +# ARMAP-EMPTY: + +## The incomplete archive index is ignored. -u foo extracts weird.a(b.o). +## In GNU ld, foo is undefined. +# RUN: ld.lld -m elf_x86_64 -u foo weird.a -o lazy +# RUN: llvm-nm lazy | FileCheck %s --implicit-check-not={{.}} + +# CHECK: [[#%x,]] T _start +# CHECK: [[#%x,]] T foo + +#--- a.s +.globl _start +_start: + +#--- b.s +.globl foo +foo: 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 @@ -9,9 +9,9 @@ # 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 +# RUN: ld.lld %t.o %t.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN -# ERR: error: {{.*}}.a: archive member '{{.*}}.so' is neither ET_REL nor LLVM bitcode +# WARN: warning: {{.*}}.a: archive member '{{.*}}.so' is neither ET_REL nor LLVM bitcode .globl _start _start: diff --git a/lld/test/ELF/archive-thin-missing-member.s b/lld/test/ELF/archive-thin-missing-member.s --- a/lld/test/ELF/archive-thin-missing-member.s +++ b/lld/test/ELF/archive-thin-missing-member.s @@ -13,13 +13,11 @@ # Test error when thin archive has symbol table but member is missing. # RUN: not ld.lld --entry=_Z1fi -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck -DMSG=%errc_ENOENT %s --check-prefix=ERR2 -# ERR2: {{.*}}-syms.a: could not get the buffer for the member defining symbol f(int): '{{.*}}.o': [[MSG]] -# RUN: not ld.lld --entry=_Z1fi --no-demangle -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck -DMSG=%errc_ENOENT %s --check-prefix=ERR2MANGLE -# ERR2MANGLE: {{.*}}-syms.a: could not get the buffer for the member defining symbol _Z1fi: '{{.*}}.o': [[MSG]] +# RUN: not ld.lld --entry=_Z1fi --no-demangle -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck -DMSG=%errc_ENOENT %s --check-prefix=ERR2 # Test error when thin archive is linked using --whole-archive but member is missing. -# RUN: not ld.lld --entry=_Z1fi --whole-archive %t-syms.a -o /dev/null 2>&1 | FileCheck -DMSG=%errc_ENOENT %s --check-prefix=ERR3 -# ERR3: {{.*}}-syms.a: could not get the buffer for a child of the archive: '{{.*}}.o': [[MSG]] +# RUN: not ld.lld --entry=_Z1fi --whole-archive %t-syms.a -o /dev/null 2>&1 | FileCheck -DMSG=%errc_ENOENT %s --check-prefix=ERR2 +# ERR2: {{.*}}-syms.a: could not get the buffer for a child of the archive: '{{.*}}.o': [[MSG]] .global _Z1fi _Z1fi: diff --git a/lld/test/ELF/incompatible-ar-first.s b/lld/test/ELF/incompatible-ar-first.s --- a/lld/test/ELF/incompatible-ar-first.s +++ b/lld/test/ELF/incompatible-ar-first.s @@ -8,8 +8,7 @@ // We used to crash when // * The first object seen by the symbol table is from an archive. // * -m was not used. -// CHECK: .a({{.*}}a.o) is incompatible with {{.*}}b.o -// RUN: not ld.lld --start-lib %ta.o --end-lib %tb.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK2 +// RUN: not ld.lld --start-lib %ta.o --end-lib %tb.o -o /dev/null 2>&1 | FileCheck %s -// CHECK2: {{.*}}b.o is incompatible{{$}} +// CHECK: {{.*}}b.o is incompatible{{$}} diff --git a/lld/test/ELF/incompatible.s b/lld/test/ELF/incompatible.s --- a/lld/test/ELF/incompatible.s +++ b/lld/test/ELF/incompatible.s @@ -65,7 +65,7 @@ // RUN: llvm-ar rc %t.a %ta.o // RUN: llvm-mc -filetype=obj -triple=i686-linux %s -o %tb.o // RUN: not ld.lld %t.a %tb.o 2>&1 -o /dev/null | FileCheck --check-prefix=ARCHIVE %s -// ARCHIVE: .a({{.*}}a.o) is incompatible with {{.*}}b.o +// ARCHIVE: {{.*}}b.o is incompatible .global _start _start: .data diff --git a/lld/test/ELF/lto/comdat-mixed-archive.test b/lld/test/ELF/lto/comdat-mixed-archive.test --- a/lld/test/ELF/lto/comdat-mixed-archive.test +++ b/lld/test/ELF/lto/comdat-mixed-archive.test @@ -27,8 +27,8 @@ BCSYM-NEXT: W foo ;; Check that the symbols are handled in the expected order. -TRACE: lib.a: lazy definition of foo -TRACE-NEXT: lib.a: lazy definition of bar +TRACE: lib.a(obj.o): lazy definition of foo +TRACE-NEXT: lib.a(obj.o): lazy definition of bar TRACE-NEXT: lib.a(bc.bc): reference to bar TRACE-NEXT: lib.a(obj.o): reference to foo TRACE-NEXT: lib.a(obj.o): definition of bar diff --git a/lld/test/ELF/lto/exclude-libs-libcall.ll b/lld/test/ELF/lto/exclude-libs-libcall.ll --- a/lld/test/ELF/lto/exclude-libs-libcall.ll +++ b/lld/test/ELF/lto/exclude-libs-libcall.ll @@ -6,7 +6,7 @@ ; RUN: ld.lld -shared --exclude-libs=b.a %t/a.bc %t/b.a -o %t.so -y __divti3 2>&1 | FileCheck %s --check-prefix=TRACE ; RUN: llvm-readelf --dyn-syms %t.so | FileCheck %s -; TRACE: {{.*}}/b.a: lazy definition of __divti3 +; TRACE: {{.*}}/b.a(b.o): lazy definition of __divti3 ; TRACE-NEXT: lto.tmp: reference to __divti3 ; TRACE-NEXT: {{.*}}/b.a(b.o): definition of __divti3 diff --git a/lld/test/ELF/no-obj.s b/lld/test/ELF/no-obj.s --- a/lld/test/ELF/no-obj.s +++ b/lld/test/ELF/no-obj.s @@ -2,9 +2,7 @@ // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: rm -f %t.a // RUN: llvm-ar rcs %t.a %t.o -// RUN: not ld.lld -o /dev/null -u _start %t.a 2>&1 | FileCheck %s - -// CHECK: target emulation unknown: -m or at least one .o file required +// RUN: ld.lld -o /dev/null -u _start %t.a 2>&1 | count 0 .global _start _start: diff --git a/lld/test/ELF/trace-symbols.s b/lld/test/ELF/trace-symbols.s --- a/lld/test/ELF/trace-symbols.s +++ b/lld/test/ELF/trace-symbols.s @@ -50,7 +50,7 @@ # RUN: FileCheck -check-prefix=FOO_AND_COMMON %s # FOO_AND_COMMON: trace-symbols.s.tmp: reference to foo # FOO_AND_COMMON: trace-symbols.s.tmp2: definition of foo -# FOO_AND_COMMON: trace-symbols.s.tmp1.a: lazy definition of common +# FOO_AND_COMMON: trace-symbols.s.tmp1.a({{.*}}.tmp1): lazy definition of common # RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 | \ # RUN: FileCheck -check-prefix=SHLIBDCOMMON %s