From 71c066d8cfd12a696454377c0592f3697ef207f3 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Tue, 2 Feb 2016 08:22:41 +0000 Subject: [PATCH] ELF: Include archive names in error messages. If object files are drawn from archive files, the error message should be something like "conflict symbols in foo.a(bar.o) and baz.o" instead of "conflict symbols in bar.o and baz.o". This patch implements that. llvm-svn: 259475 --- lld/ELF/Driver.cpp | 3 ++- lld/ELF/InputFiles.cpp | 7 +++++-- lld/ELF/InputFiles.h | 8 +++++++- lld/ELF/SymbolTable.cpp | 18 ++++++++++++------ lld/ELF/Symbols.cpp | 2 +- lld/test/ELF/Inputs/conflict.s | 7 +++++++ lld/test/ELF/conflict.s | 12 +++++++++--- 7 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 lld/test/ELF/Inputs/conflict.s diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index fe0a3f5..4fbf202 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(MBRef)); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index fa7c339..cee398b 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -452,8 +452,11 @@ static std::unique_ptr createELFFile(MemoryBufferRef MB) { fatal("Invalid file class: " + MB.getBufferIdentifier()); } -std::unique_ptr elf2::createObjectFile(MemoryBufferRef MB) { - return createELFFile(MB); +std::unique_ptr elf2::createObjectFile(MemoryBufferRef MB, + StringRef ArchiveName) { + std::unique_ptr F = createELFFile(MB); + F->ArchiveName = ArchiveName; + return F; } std::unique_ptr elf2::createSharedFile(MemoryBufferRef MB) { diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index e530f7f..8ed49b9 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 createObjectFile(MemoryBufferRef MB); +std::unique_ptr createObjectFile(MemoryBufferRef MB, + StringRef ArchiveName = ""); std::unique_ptr createSharedFile(MemoryBufferRef MB); } // namespace elf2 diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 1e1c8aa..b5b902d 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -149,17 +149,23 @@ ELFFileBase *SymbolTable::findFile(SymbolBody *B) { return nullptr; } +// Returns "(internal)", "foo.a(bar.o)" or "baz.o". +template static std::string getFilename(ELFFileBase *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 std::string SymbolTable::conflictMsg(SymbolBody *Old, SymbolBody *New) { - ELFFileBase *OldFile = findFile(Old); - ELFFileBase *NewFile = findFile(New); - + ELFFileBase *F1 = findFile(Old); + ELFFileBase *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 6bc285c..c8b8891 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -187,7 +187,7 @@ std::unique_ptr Lazy::getMember() { // read from the library. if (MBRef.getBuffer().empty()) return std::unique_ptr(nullptr); - return createObjectFile(MBRef); + return createObjectFile(MBRef, File->getName()); } template static void doInitSymbols() { diff --git a/lld/test/ELF/Inputs/conflict.s b/lld/test/ELF/Inputs/conflict.s new file mode 100644 index 0000000..545ae99 --- /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 96c1c39..1a0b75d 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: -- 2.7.4