[LLD/PDB] Emit first section contribution for DBI Module Descriptor.

Part of the DBI stream is a list of variable length structures
describing each module that contributes to the final executable.

One member of this structure is a section contribution entry that
describes the first section contribution in the output file for
the given module.

We have been leaving this structure unpopulated until now, so with
this patch it is now filled out correctly.

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

llvm-svn: 330457
This commit is contained in:
Zachary Turner 2018-04-20 18:00:46 +00:00
parent 358af38d37
commit 194be871b9
4 changed files with 55 additions and 34 deletions

View File

@ -125,9 +125,6 @@ public:
void addSections(ArrayRef<OutputSection *> OutputSections, void addSections(ArrayRef<OutputSection *> OutputSections,
ArrayRef<uint8_t> SectionTable); ArrayRef<uint8_t> SectionTable);
void addSectionContrib(pdb::DbiModuleDescriptorBuilder &LinkerModule,
OutputSection *OS, Chunk *C);
/// Write the PDB to disk. /// Write the PDB to disk.
void commit(); void commit();
@ -780,6 +777,32 @@ static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc,
".debug$S"); ".debug$S");
} }
static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) {
OutputSection *OS = C->getOutputSection();
pdb::SectionContrib SC;
memset(&SC, 0, sizeof(SC));
SC.ISect = OS->SectionIndex;
SC.Off = C->getRVA() - OS->getRVA();
SC.Size = C->getSize();
if (auto *SecChunk = dyn_cast<SectionChunk>(C)) {
SC.Characteristics = SecChunk->Header->Characteristics;
SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex();
ArrayRef<uint8_t> Contents = SecChunk->getContents();
JamCRC CRC(0);
ArrayRef<char> CharContents = makeArrayRef(
reinterpret_cast<const char *>(Contents.data()), Contents.size());
CRC.update(CharContents);
SC.DataCrc = CRC.getCRC();
} else {
SC.Characteristics = OS->Header.Characteristics;
// FIXME: When we start creating DBI for import libraries, use those here.
SC.Imod = Modi;
}
SC.RelocCrc = 0; // FIXME
return SC;
}
void PDBLinker::addObjFile(ObjFile *File) { void PDBLinker::addObjFile(ObjFile *File) {
// Add a module descriptor for every object file. We need to put an absolute // Add a module descriptor for every object file. We need to put an absolute
// path to the object into the PDB. If this is a plain object, we make its // path to the object into the PDB. If this is a plain object, we make its
@ -794,6 +817,18 @@ void PDBLinker::addObjFile(ObjFile *File) {
File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name)); File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
File->ModuleDBI->setObjFileName(Path); File->ModuleDBI->setObjFileName(Path);
auto Chunks = File->getChunks();
assert(!Chunks.empty());
uint32_t Modi = File->ModuleDBI->getModuleIndex();
for (Chunk *C : Chunks) {
auto *SecChunk = dyn_cast<SectionChunk>(C);
if (!SecChunk || !SecChunk->isLive())
continue;
pdb::SectionContrib SC = createSectionContrib(SecChunk, Modi);
File->ModuleDBI->setFirstSectionContrib(SC);
break;
}
// Before we can process symbol substreams from .debug$S, we need to process // Before we can process symbol substreams from .debug$S, we need to process
// type information, file checksums, and the string table. Add type info to // type information, file checksums, and the string table. Add type info to
// the PDB first, so that we can get the map from object file type and item // the PDB first, so that we can get the map from object file type and item
@ -1110,31 +1145,6 @@ void PDBLinker::initialize(const llvm::codeview::DebugInfo &BuildId) {
DbiBuilder.setBuildNumber(14, 11); DbiBuilder.setBuildNumber(14, 11);
} }
void PDBLinker::addSectionContrib(pdb::DbiModuleDescriptorBuilder &LinkerModule,
OutputSection *OS, Chunk *C) {
pdb::SectionContrib SC;
memset(&SC, 0, sizeof(SC));
SC.ISect = OS->SectionIndex;
SC.Off = C->getRVA() - OS->getRVA();
SC.Size = C->getSize();
if (auto *SecChunk = dyn_cast<SectionChunk>(C)) {
SC.Characteristics = SecChunk->Header->Characteristics;
SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex();
ArrayRef<uint8_t> Contents = SecChunk->getContents();
JamCRC CRC(0);
ArrayRef<char> CharContents = makeArrayRef(
reinterpret_cast<const char *>(Contents.data()), Contents.size());
CRC.update(CharContents);
SC.DataCrc = CRC.getCRC();
} else {
SC.Characteristics = OS->Header.Characteristics;
// FIXME: When we start creating DBI for import libraries, use those here.
SC.Imod = LinkerModule.getModuleIndex();
}
SC.RelocCrc = 0; // FIXME
Builder.getDbiBuilder().addSectionContrib(SC);
}
void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections, void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections,
ArrayRef<uint8_t> SectionTable) { ArrayRef<uint8_t> SectionTable) {
// It's not entirely clear what this is, but the * Linker * module uses it. // It's not entirely clear what this is, but the * Linker * module uses it.
@ -1150,8 +1160,11 @@ void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections,
// Add section contributions. They must be ordered by ascending RVA. // Add section contributions. They must be ordered by ascending RVA.
for (OutputSection *OS : OutputSections) { for (OutputSection *OS : OutputSections) {
addLinkerModuleSectionSymbol(LinkerModule, *OS, Alloc); addLinkerModuleSectionSymbol(LinkerModule, *OS, Alloc);
for (Chunk *C : OS->getChunks()) for (Chunk *C : OS->getChunks()) {
addSectionContrib(LinkerModule, OS, C); pdb::SectionContrib SC =
createSectionContrib(C, LinkerModule.getModuleIndex());
Builder.getDbiBuilder().addSectionContrib(SC);
}
} }
// Add Section Map stream. // Add Section Map stream.

View File

@ -120,14 +120,16 @@
RAW: Modules RAW: Modules
RAW-NEXT: ============================================================ RAW-NEXT: ============================================================
RAW-NEXT: Mod 0000 | `{{.*}}pdb.test.tmp1.obj`: RAW-NEXT: Mod 0000 | `{{.*}}pdb.test.tmp1.obj`:
RAW-NEXT: SC[???] | mod = 0, 0000:0000, size = 0, data crc = 0, reloc crc = 0 RAW-NEXT: SC[.text] | mod = 0, 0001:0000, size = 14, data crc = 1682752513, reloc crc = 0
RAW-NEXT: none RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
RAW-NEXT: IMAGE_SCN_MEM_READ
RAW-NEXT: Obj: `{{.*}}pdb.test.tmp1.obj`: RAW-NEXT: Obj: `{{.*}}pdb.test.tmp1.obj`:
RAW-NEXT: debug stream: 11, # files: 1, has ec info: false RAW-NEXT: debug stream: 11, # files: 1, has ec info: false
RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
RAW-NEXT: Mod 0001 | `{{.*}}pdb.test.tmp2.obj`: RAW-NEXT: Mod 0001 | `{{.*}}pdb.test.tmp2.obj`:
RAW-NEXT: SC[???] | mod = 1, 0000:0000, size = 0, data crc = 0, reloc crc = 0 RAW-NEXT: SC[.text] | mod = 1, 0001:0016, size = 6, data crc = 2139436471, reloc crc = 0
RAW-NEXT: none RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
RAW-NEXT: IMAGE_SCN_MEM_READ
RAW-NEXT: Obj: `{{.*}}pdb.test.tmp2.obj`: RAW-NEXT: Obj: `{{.*}}pdb.test.tmp2.obj`:
RAW-NEXT: debug stream: 12, # files: 1, has ec info: false RAW-NEXT: debug stream: 12, # files: 1, has ec info: false
RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 ``

View File

@ -49,6 +49,7 @@ public:
void setPdbFilePathNI(uint32_t NI); void setPdbFilePathNI(uint32_t NI);
void setObjFileName(StringRef Name); void setObjFileName(StringRef Name);
void setFirstSectionContrib(const SectionContrib &SC);
void addSymbol(codeview::CVSymbol Symbol); void addSymbol(codeview::CVSymbol Symbol);
void void

View File

@ -60,6 +60,11 @@ void DbiModuleDescriptorBuilder::setPdbFilePathNI(uint32_t NI) {
PdbFilePathNI = NI; PdbFilePathNI = NI;
} }
void DbiModuleDescriptorBuilder::setFirstSectionContrib(
const SectionContrib &SC) {
Layout.SC = SC;
}
void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) { void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) {
Symbols.push_back(Symbol); Symbols.push_back(Symbol);
// Symbols written to a PDB file are required to be 4 byte aligned. The same // Symbols written to a PDB file are required to be 4 byte aligned. The same