[lld] r341486 - lld-link: Write an empty "repro" debug directory entry if /Brepro is passed

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 5 11:02:43 PDT 2018


Author: nico
Date: Wed Sep  5 11:02:43 2018
New Revision: 341486

URL: http://llvm.org/viewvc/llvm-project?rev=341486&view=rev
Log:
lld-link: Write an empty "repro" debug directory entry if /Brepro is passed

If the coff timestamp is set to a hash, like lld-link does if /Brepro is
passed, the coff spec suggests that a IMAGE_DEBUG_TYPE_REPRO entry is in the
debug directory. This lets lld-link write such a section.
Fixes PR38429, see bug for details.

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

Modified:
    lld/trunk/COFF/Writer.cpp
    lld/trunk/test/COFF/rsds.test

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=341486&r1=341485&r2=341486&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Wed Sep  5 11:02:43 2018
@@ -83,30 +83,32 @@ namespace {
 
 class DebugDirectoryChunk : public Chunk {
 public:
-  DebugDirectoryChunk(const std::vector<Chunk *> &R) : Records(R) {}
+  DebugDirectoryChunk(const std::vector<Chunk *> &R, bool WriteRepro)
+      : Records(R), WriteRepro(WriteRepro) {}
 
   size_t getSize() const override {
-    return Records.size() * sizeof(debug_directory);
+    return (Records.size() + int(WriteRepro)) * sizeof(debug_directory);
   }
 
   void writeTo(uint8_t *B) const override {
     auto *D = reinterpret_cast<debug_directory *>(B + OutputSectionOff);
 
     for (const Chunk *Record : Records) {
-      D->Characteristics = 0;
-      D->TimeDateStamp = 0;
-      D->MajorVersion = 0;
-      D->MinorVersion = 0;
-      D->Type = COFF::IMAGE_DEBUG_TYPE_CODEVIEW;
-      D->SizeOfData = Record->getSize();
-      D->AddressOfRawData = Record->getRVA();
       OutputSection *OS = Record->getOutputSection();
       uint64_t Offs = OS->getFileOff() + (Record->getRVA() - OS->getRVA());
-      D->PointerToRawData = Offs;
-
-      TimeDateStamps.push_back(&D->TimeDateStamp);
+      fillEntry(D, COFF::IMAGE_DEBUG_TYPE_CODEVIEW, Record->getSize(),
+                Record->getRVA(), Offs);
       ++D;
     }
+
+    if (WriteRepro) {
+      // FIXME: The COFF spec allows either a 0-sized entry to just say
+      // "the timestamp field is really a hash", or a 4-byte size field
+      // followed by that many bytes containing a longer hash (with the
+      // lowest 4 bytes usually being the timestamp in little-endian order).
+      // Consider storing the full 8 bytes computed by xxHash64 here.
+      fillEntry(D, COFF::IMAGE_DEBUG_TYPE_REPRO, 0, 0, 0);
+    }
   }
 
   void setTimeDateStamp(uint32_t TimeDateStamp) {
@@ -115,8 +117,23 @@ public:
   }
 
 private:
+  void fillEntry(debug_directory *D, COFF::DebugType DebugType, size_t Size,
+                 uint64_t RVA, uint64_t Offs) const {
+    D->Characteristics = 0;
+    D->TimeDateStamp = 0;
+    D->MajorVersion = 0;
+    D->MinorVersion = 0;
+    D->Type = DebugType;
+    D->SizeOfData = Size;
+    D->AddressOfRawData = RVA;
+    D->PointerToRawData = Offs;
+
+    TimeDateStamps.push_back(&D->TimeDateStamp);
+  }
+
   mutable std::vector<support::ulittle32_t *> TimeDateStamps;
   const std::vector<Chunk *> &Records;
+  bool WriteRepro;
 };
 
 class CVDebugRecordChunk : public Chunk {
@@ -500,11 +517,13 @@ void Writer::createMiscChunks() {
   }
 
   // Create Debug Information Chunks
-  if (Config->Debug) {
-    DebugDirectory = make<DebugDirectoryChunk>(DebugRecords);
-
-    OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec;
+  OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec;
+  if (Config->Debug || Config->Repro) {
+    DebugDirectory = make<DebugDirectoryChunk>(DebugRecords, Config->Repro);
+    DebugInfoSec->addChunk(DebugDirectory);
+  }
 
+  if (Config->Debug) {
     // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified.  We
     // output a PDB no matter what, and this chunk provides the only means of
     // allowing a debugger to match a PDB and an executable.  So we need it even
@@ -513,7 +532,6 @@ void Writer::createMiscChunks() {
     BuildId = CVChunk;
     DebugRecords.push_back(CVChunk);
 
-    DebugInfoSec->addChunk(DebugDirectory);
     for (Chunk *C : DebugRecords)
       DebugInfoSec->addChunk(C);
   }
@@ -911,7 +929,7 @@ template <typename PEHeaderTy> void Writ
                                 : sizeof(object::coff_tls_directory32);
     }
   }
-  if (Config->Debug) {
+  if (DebugDirectory) {
     Dir[DEBUG_DIRECTORY].RelativeVirtualAddress = DebugDirectory->getRVA();
     Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize();
   }

Modified: lld/trunk/test/COFF/rsds.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/rsds.test?rev=341486&r1=341485&r2=341486&view=diff
==============================================================================
--- lld/trunk/test/COFF/rsds.test (original)
+++ lld/trunk/test/COFF/rsds.test Wed Sep  5 11:02:43 2018
@@ -14,6 +14,14 @@
 # RUN: llvm-readobj -coff-debug-directory %t.dll > %t.4.txt
 # RUN: cat %t.3.txt %t.4.txt | FileCheck %s
 
+# RUN: rm -f %t.dll %t.pdb
+# RUN: lld-link /Brepro /dll /out:%t.dll /entry:DllMain %t.obj
+# RUN: llvm-readobj -coff-debug-directory %t.dll | FileCheck --check-prefix REPRO %s
+
+# RUN: rm -f %t.dll %t.pdb
+# RUN: lld-link /Brepro /debug /dll /out:%t.dll /entry:DllMain %t.obj
+# RUN: llvm-readobj -coff-debug-directory %t.dll | FileCheck --check-prefix REPRODEBUG %s
+
 # CHECK: File: [[FILE:.*]].dll
 # CHECK: DebugDirectory [
 # CHECK:   DebugEntry {
@@ -53,6 +61,49 @@
 # CHECK:   }
 # CHECK: ]
 
+# REPRO: File: {{.*}}.dll
+# REPRO: DebugDirectory [
+# REPRO:   DebugEntry {
+# REPRO:     Characteristics: 0x0
+# REPRO:     TimeDateStamp: 
+# REPRO:     MajorVersion: 0x0
+# REPRO:     MinorVersion: 0x0
+# REPRO:     Type: Repro (0x10)
+# REPRO:     SizeOfData: 0x0
+# REPRO:     AddressOfRawData: 0x0
+# REPRO:     PointerToRawData: 0x0
+# REPRO:   }
+# REPRO: ]
+
+# REPRODEBUG: File: {{.*}}.dll
+# REPRODEBUG: DebugDirectory [
+# REPRODEBUG:   DebugEntry {
+# REPRODEBUG:     Characteristics: 0x0
+# REPRODEBUG:     TimeDateStamp: 
+# REPRODEBUG:     MajorVersion: 0x0
+# REPRODEBUG:     MinorVersion: 0x0
+# REPRODEBUG:     Type: CodeView (0x2)
+# REPRODEBUG:     SizeOfData: 0x{{[^0]}}
+# REPRODEBUG:     AddressOfRawData: 0x{{[^0]}}
+# REPRODEBUG:     PointerToRawData: 0x{{[^0]}}
+# REPRODEBUG:     PDBInfo {
+# REPRODEBUG:       PDBSignature: 0x53445352
+# REPRODEBUG:       PDBGUID: 
+# REPRODEBUG:       PDBAge: 1
+# REPRODEBUG:       PDBFileName:
+# REPRODEBUG:     }
+# REPRODEBUG:   }
+# REPRODEBUG:   DebugEntry {
+# REPRODEBUG:     Characteristics: 0x0
+# REPRODEBUG:     TimeDateStamp: 
+# REPRODEBUG:     MajorVersion: 0x0
+# REPRODEBUG:     MinorVersion: 0x0
+# REPRODEBUG:     Type: Repro (0x10)
+# REPRODEBUG:     SizeOfData: 0x0
+# REPRODEBUG:     AddressOfRawData: 0x0
+# REPRODEBUG:     PointerToRawData: 0x0
+# REPRODEBUG:   }
+# REPRODEBUG: ]
 --- !COFF
 header:
   Machine:         IMAGE_FILE_MACHINE_I386




More information about the llvm-commits mailing list