[lld] r358440 - [LLD][COFF] use offset in archive to disambiguate archive members

Bob Haarman via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 15 12:48:32 PDT 2019


Author: inglorion
Date: Mon Apr 15 12:48:32 2019
New Revision: 358440

URL: http://llvm.org/viewvc/llvm-project?rev=358440&view=rev
Log:
[LLD][COFF] use offset in archive to disambiguate archive members

Summary:
Archives can contain multiple members with the same name. This would
cause ThinLTO links to fail ("Expected at most one ThinLTO module per
bitcode file"). This change implements the same strategy we use in
the ELF linker: make the offset in the archive part of the module
name so that names are unique.

Reviewers: pcc, mehdi_amini, ruiu

Reviewed By: ruiu

Subscribers: eraman, steven_wu, dexonsmith, llvm-commits

Tags: #llvm

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

Added:
    lld/trunk/test/COFF/thinlto-archivecollision.ll
Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Driver.h
    lld/trunk/COFF/InputFiles.cpp
    lld/trunk/COFF/InputFiles.h
    lld/trunk/test/COFF/thinlto-archives.ll

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=358440&r1=358439&r2=358440&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Mon Apr 15 12:48:32 2019
@@ -169,13 +169,13 @@ void LinkerDriver::addBuffer(std::unique
           CHECK(Archive::create(MBRef), Filename + ": failed to parse archive");
 
       for (MemoryBufferRef M : getArchiveMembers(File.get()))
-        addArchiveBuffer(M, "<whole-archive>", Filename);
+        addArchiveBuffer(M, "<whole-archive>", Filename, 0);
       return;
     }
     Symtab->addFile(make<ArchiveFile>(MBRef));
     break;
   case file_magic::bitcode:
-    Symtab->addFile(make<BitcodeFile>(MBRef));
+    Symtab->addFile(make<BitcodeFile>(MBRef, "", 0));
     break;
   case file_magic::coff_object:
   case file_magic::coff_import_library:
@@ -211,7 +211,8 @@ void LinkerDriver::enqueuePath(StringRef
 }
 
 void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName,
-                                    StringRef ParentName) {
+                                    StringRef ParentName,
+                                    uint64_t OffsetInArchive) {
   file_magic Magic = identify_magic(MB.getBuffer());
   if (Magic == file_magic::coff_import_library) {
     InputFile *Imp = make<ImportFile>(MB);
@@ -224,7 +225,7 @@ void LinkerDriver::addArchiveBuffer(Memo
   if (Magic == file_magic::coff_object) {
     Obj = make<ObjFile>(MB);
   } else if (Magic == file_magic::bitcode) {
-    Obj = make<BitcodeFile>(MB);
+    Obj = make<BitcodeFile>(MB, ParentName, OffsetInArchive);
   } else {
     error("unknown file type: " + MB.getBufferIdentifier());
     return;
@@ -247,11 +248,14 @@ void LinkerDriver::enqueueArchiveMember(
   };
 
   if (!C.getParent()->isThin()) {
+    uint64_t OffsetInArchive = C.getChildOffset();
     Expected<MemoryBufferRef> MBOrErr = C.getMemoryBufferRef();
     if (!MBOrErr)
       ReportBufferError(MBOrErr.takeError(), check(C.getFullName()));
     MemoryBufferRef MB = MBOrErr.get();
-    enqueueTask([=]() { Driver->addArchiveBuffer(MB, SymName, ParentName); });
+    enqueueTask([=]() {
+      Driver->addArchiveBuffer(MB, SymName, ParentName, OffsetInArchive);
+    });
     return;
   }
 
@@ -266,7 +270,7 @@ void LinkerDriver::enqueueArchiveMember(
     if (MBOrErr.second)
       ReportBufferError(errorCodeToError(MBOrErr.second), ChildName);
     Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName,
-                             ParentName);
+                             ParentName, /* OffsetInArchive */ 0);
   });
 }
 

Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=358440&r1=358439&r2=358440&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Mon Apr 15 12:48:32 2019
@@ -118,7 +118,7 @@ private:
 
   void addBuffer(std::unique_ptr<MemoryBuffer> MB, bool WholeArchive);
   void addArchiveBuffer(MemoryBufferRef MBRef, StringRef SymName,
-                        StringRef ParentName);
+                        StringRef ParentName, uint64_t OffsetInArchive);
 
   void enqueuePath(StringRef Path, bool WholeArchive);
 

Modified: lld/trunk/COFF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=358440&r1=358439&r2=358440&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.cpp (original)
+++ lld/trunk/COFF/InputFiles.cpp Mon Apr 15 12:48:32 2019
@@ -769,9 +769,26 @@ void ImportFile::parse() {
         Name, cast_or_null<DefinedImportData>(ImpSym), Hdr->Machine);
 }
 
+BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName,
+                         uint64_t OffsetInArchive)
+    : InputFile(BitcodeKind, MB) {
+  std::string Path = MB.getBufferIdentifier().str();
+
+  // ThinLTO assumes that all MemoryBufferRefs given to it have a unique
+  // name. If two archives define two members with the same name, this
+  // causes a collision which result in only one of the objects being taken
+  // into consideration at LTO time (which very likely causes undefined
+  // symbols later in the link stage). So we append file offset to make
+  // filename unique.
+  MemoryBufferRef MBRef(
+      MB.getBuffer(),
+      Saver.save(ArchiveName + Path +
+                 (ArchiveName.empty() ? "" : utostr(OffsetInArchive))));
+
+  Obj = check(lto::InputFile::create(MBRef));
+}
+
 void BitcodeFile::parse() {
-  Obj = check(lto::InputFile::create(MemoryBufferRef(
-      MB.getBuffer(), Saver.save(ParentName + MB.getBufferIdentifier()))));
   std::vector<std::pair<Symbol *, bool>> Comdat(Obj->getComdatTable().size());
   for (size_t I = 0; I != Obj->getComdatTable().size(); ++I)
     // FIXME: lto::InputFile doesn't keep enough data to do correct comdat

Modified: lld/trunk/COFF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.h?rev=358440&r1=358439&r2=358440&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.h (original)
+++ lld/trunk/COFF/InputFiles.h Mon Apr 15 12:48:32 2019
@@ -295,7 +295,8 @@ public:
 // Used for LTO.
 class BitcodeFile : public InputFile {
 public:
-  explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}
+  BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName,
+              uint64_t OffsetInArchive);
   static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }
   ArrayRef<Symbol *> getSymbols() { return Symbols; }
   MachineTypes getMachineType() override;

Added: lld/trunk/test/COFF/thinlto-archivecollision.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/thinlto-archivecollision.ll?rev=358440&view=auto
==============================================================================
--- lld/trunk/test/COFF/thinlto-archivecollision.ll (added)
+++ lld/trunk/test/COFF/thinlto-archivecollision.ll Mon Apr 15 12:48:32 2019
@@ -0,0 +1,29 @@
+; REQUIRES: x86
+; RUN: rm -fr %t
+; RUN: mkdir %t %t/a %t/b
+; RUN: opt -thinlto-bc -o %t/main.obj %s
+; RUN: opt -thinlto-bc -o %t/a/bar.obj %S/Inputs/lto-dep.ll
+; RUN: opt -thinlto-bc -o %t/b/bar.obj %S/Inputs/bar.ll
+; RUN: llvm-ar crs %t/libbar.lib %t/a/bar.obj %t/b/bar.obj
+; RUN: lld-link -out:%t/main.exe -entry:main -lldsavetemps \
+; RUN:     -subsystem:console %t/main.obj %t/libbar.lib
+; RUN: FileCheck %s < %t/main.exe.resolution.txt
+
+; CHECK: {{/thinlto-archivecollision.ll.tmp/main.obj$}}
+; CHECK: {{^-r=.*/thinlto-archivecollision.ll.tmp/main.obj,main,px$}}
+; CHECK: {{/thinlto-archivecollision.ll.tmp/libbar.libbar.obj[0-9]+$}}
+; CHECK-NEXT: {{^-r=.*/thinlto-archivecollision.ll.tmp/libbar.libbar.obj[0-9]+,foo,p$}}
+; CHECK-NEXT: {{/thinlto-archivecollision.ll.tmp/libbar.libbar.obj[0-9]+$}}
+; CHECK-NEXT: {{^-r=.*/thinlto-archivecollision.ll.tmp/libbar.libbar.obj[0-9]+,bar,p$}}
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+declare void @bar()
+declare void @foo()
+
+define i32 @main() {
+  call void @foo()
+  call void @bar()
+  ret i32 0
+}

Modified: lld/trunk/test/COFF/thinlto-archives.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/thinlto-archives.ll?rev=358440&r1=358439&r2=358440&view=diff
==============================================================================
--- lld/trunk/test/COFF/thinlto-archives.ll (original)
+++ lld/trunk/test/COFF/thinlto-archives.ll Mon Apr 15 12:48:32 2019
@@ -13,10 +13,10 @@
 
 ; CHECK: {{/thinlto-archives/main.obj$}}
 ; CHECK: {{^-r=.*/thinlto-archives/main.obj,main,px$}}
-; CHECK: {{/thinlto-archives/a.libbar.obj$}}
-; CHECK-NEXT: {{^-r=.*/thinlto-archives/a.libbar.obj,foo,p$}}
-; CHECK-NEXT: {{/thinlto-archives/b.libbar.obj$}}
-; CHECK-NEXT: {{^-r=.*/thinlto-archives/b.libbar.obj,bar,p$}}
+; CHECK: {{/thinlto-archives/a.libbar.obj[0-9]+$}}
+; CHECK-NEXT: {{^-r=.*/thinlto-archives/a.libbar.obj[0-9]+,foo,p$}}
+; CHECK-NEXT: {{/thinlto-archives/b.libbar.obj[0-9]+$}}
+; CHECK-NEXT: {{^-r=.*/thinlto-archives/b.libbar.obj[0-9]+,bar,p$}}
 
 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-pc-windows-msvc"




More information about the llvm-commits mailing list