forked from OSchip/llvm-project
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 llvm-svn: 341486
This commit is contained in:
parent
893c646938
commit
13b55bbc2f
|
@ -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
|
||||
OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec;
|
||||
if (Config->Debug || Config->Repro) {
|
||||
DebugDirectory = make<DebugDirectoryChunk>(DebugRecords, Config->Repro);
|
||||
DebugInfoSec->addChunk(DebugDirectory);
|
||||
}
|
||||
|
||||
if (Config->Debug) {
|
||||
DebugDirectory = make<DebugDirectoryChunk>(DebugRecords);
|
||||
|
||||
OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec;
|
||||
|
||||
// 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 Writer::writeHeader() {
|
|||
: sizeof(object::coff_tls_directory32);
|
||||
}
|
||||
}
|
||||
if (Config->Debug) {
|
||||
if (DebugDirectory) {
|
||||
Dir[DEBUG_DIRECTORY].RelativeVirtualAddress = DebugDirectory->getRVA();
|
||||
Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue