diff options
-rw-r--r-- | lld/ELF/Driver.cpp | 3 | ||||
-rw-r--r-- | lld/ELF/InputFiles.cpp | 7 | ||||
-rw-r--r-- | lld/ELF/InputFiles.h | 8 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 18 | ||||
-rw-r--r-- | lld/ELF/Symbols.cpp | 2 | ||||
-rw-r--r-- | lld/test/ELF/Inputs/conflict.s | 7 | ||||
-rw-r--r-- | lld/test/ELF/conflict.s | 12 |
7 files changed, 43 insertions, 14 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index fe0a3f5a8b9..4fbf202c9d2 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -95,8 +95,9 @@ void LinkerDriver::addFile(StringRef Path) { return; case file_magic::archive: if (WholeArchive) { + StringRef S = MBRef.getBufferIdentifier(); for (MemoryBufferRef MB : getArchiveMembers(MBRef)) - Files.push_back(createObjectFile(MB)); + Files.push_back(createObjectFile(MB, S)); return; } Files.push_back(make_unique<ArchiveFile>(MBRef)); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index fa7c339da19..cee398bd8a9 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -452,8 +452,11 @@ static std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB) { fatal("Invalid file class: " + MB.getBufferIdentifier()); } -std::unique_ptr<InputFile> elf2::createObjectFile(MemoryBufferRef MB) { - return createELFFile<ObjectFile>(MB); +std::unique_ptr<InputFile> elf2::createObjectFile(MemoryBufferRef MB, + StringRef ArchiveName) { + std::unique_ptr<InputFile> F = createELFFile<ObjectFile>(MB); + F->ArchiveName = ArchiveName; + return F; } std::unique_ptr<InputFile> elf2::createSharedFile(MemoryBufferRef MB) { diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index e530f7fa70a..8ed49b9d393 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -38,6 +38,11 @@ public: StringRef getName() const { return MB.getBufferIdentifier(); } + // Filename of .a which contained this file. If this file was + // not in an archive file, it is the empty string. We use this + // string for creating error messages. + std::string ArchiveName; + protected: InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} MemoryBufferRef MB; @@ -208,7 +213,8 @@ public: bool isNeeded() const { return !AsNeeded || IsUsed; } }; -std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB); +std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB, + StringRef ArchiveName = ""); std::unique_ptr<InputFile> createSharedFile(MemoryBufferRef MB); } // namespace elf2 diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 1e1c8aad589..b5b902d3c5f 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -149,17 +149,23 @@ ELFFileBase<ELFT> *SymbolTable<ELFT>::findFile(SymbolBody *B) { return nullptr; } +// Returns "(internal)", "foo.a(bar.o)" or "baz.o". +template <class ELFT> static std::string getFilename(ELFFileBase<ELFT> *F) { + if (!F) + return "(internal)"; + if (!F->ArchiveName.empty()) + return (F->ArchiveName + "(" + F->getName() + ")").str(); + return F->getName(); +} + // Construct a string in the form of "Sym in File1 and File2". // Used to construct an error message. template <class ELFT> std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) { - ELFFileBase<ELFT> *OldFile = findFile(Old); - ELFFileBase<ELFT> *NewFile = findFile(New); - + ELFFileBase<ELFT> *F1 = findFile(Old); + ELFFileBase<ELFT> *F2 = findFile(New); StringRef Sym = Old->getName(); - StringRef F1 = OldFile ? OldFile->getName() : "(internal)"; - StringRef F2 = NewFile ? NewFile->getName() : "(internal)"; - return (demangle(Sym) + " in " + F1 + " and " + F2).str(); + return demangle(Sym) + " in " + getFilename(F1) + " and " + getFilename(F2); } // This function resolves conflicts if there's an existing symbol with diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 6bc285ce513..c8b8891b6b1 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -187,7 +187,7 @@ std::unique_ptr<InputFile> Lazy::getMember() { // read from the library. if (MBRef.getBuffer().empty()) return std::unique_ptr<InputFile>(nullptr); - return createObjectFile(MBRef); + return createObjectFile(MBRef, File->getName()); } template <class ELFT> static void doInitSymbols() { diff --git a/lld/test/ELF/Inputs/conflict.s b/lld/test/ELF/Inputs/conflict.s new file mode 100644 index 00000000000..545ae99c845 --- /dev/null +++ b/lld/test/ELF/Inputs/conflict.s @@ -0,0 +1,7 @@ +.globl _Z3muldd, foo, baz +_Z3muldd: +foo: +baz: + mov $60, %rax + mov $42, %rdi + syscall diff --git a/lld/test/ELF/conflict.s b/lld/test/ELF/conflict.s index 96c1c3915b7..1a0b75da44d 100644 --- a/lld/test/ELF/conflict.s +++ b/lld/test/ELF/conflict.s @@ -3,15 +3,21 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: not ld.lld %t %t -o %t2 2>&1 | FileCheck -check-prefix=DEMANGLE %s -# RUN: not ld.lld %t %t -o %t2 --no-demangle 2>&1 | \ -# RUN: FileCheck -check-prefix=NO_DEMANGLE %s - # DEMANGLE: duplicate symbol: {{mul\(double, double\)|_Z3muldd}} in # DEMANGLE: duplicate symbol: foo in +# RUN: not ld.lld %t %t -o %t2 --no-demangle 2>&1 | \ +# RUN: FileCheck -check-prefix=NO_DEMANGLE %s + # NO_DEMANGLE: duplicate symbol: _Z3muldd in # NO_DEMANGLE: duplicate symbol: foo in +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/conflict.s -o %t2 +# RUN: llvm-ar rcs %t.a %t2 +# RUN: not ld.lld %t %t.a -u baz -o %t2 2>&1 | FileCheck -check-prefix=ARCHIVE %s + +# ARCHIVE: duplicate symbol: foo in {{.*}}conflict.s.tmp and {{.*}}.a(conflict.s.tmp2) + .globl _Z3muldd, foo _Z3muldd: foo: |