[PDB] Fix section contributions

Summary:
PDB section contributions are supposed to use output section indices and
offsets, not input section indices and offsets.

This allows the debugger to look up the index of the module that it
should look up in the modules stream for symbol information. With this
change, windbg can now find line tables, but it still cannot print local
variables.

Fixes PR34048

Reviewers: zturner

Subscribers: hiraditya, ruiu, llvm-commits

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

llvm-svn: 309987
This commit is contained in:
Reid Kleckner 2017-08-03 21:15:09 +00:00
parent 144ee2b4d7
commit 175af4bcc7
7 changed files with 76 additions and 46 deletions

View File

@ -98,7 +98,11 @@ public:
TypeServer2Record &TS);
/// Add the section map and section contributions to the PDB.
void addSections(ArrayRef<uint8_t> SectionTable);
void addSections(ArrayRef<OutputSection *> OutputSections,
ArrayRef<uint8_t> SectionTable);
void addSectionContrib(pdb::DbiModuleDescriptorBuilder &LinkerModule,
OutputSection *OS, Chunk *C);
/// Write the PDB to disk.
void commit();
@ -129,14 +133,6 @@ private:
};
}
// Returns a list of all SectionChunks.
static void addSectionContribs(SymbolTable *Symtab,
pdb::DbiStreamBuilder &DbiBuilder) {
for (Chunk *C : Symtab->getChunks())
if (auto *SC = dyn_cast<SectionChunk>(C))
DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header);
}
static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
StringRef Name) {
for (SectionChunk *C : Sections)
@ -648,12 +644,14 @@ static void addLinkerModuleSymbols(StringRef Path,
}
// Creates a PDB file.
void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
void coff::createPDB(SymbolTable *Symtab,
ArrayRef<OutputSection *> OutputSections,
ArrayRef<uint8_t> SectionTable,
const llvm::codeview::DebugInfo *DI) {
PDBLinker PDB(Symtab);
PDB.initialize(DI);
PDB.addObjectsToPDB();
PDB.addSections(SectionTable);
PDB.addSections(OutputSections, SectionTable);
PDB.commit();
}
@ -682,19 +680,30 @@ void PDBLinker::initialize(const llvm::codeview::DebugInfo *DI) {
ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {}));
}
void PDBLinker::addSections(ArrayRef<uint8_t> SectionTable) {
// Add Section Contributions.
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
addSectionContribs(Symtab, DbiBuilder);
// Add Section Map stream.
ArrayRef<object::coff_section> Sections = {
(const object::coff_section *)SectionTable.data(),
SectionTable.size() / sizeof(object::coff_section)};
SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections);
DbiBuilder.setSectionMap(SectionMap);
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();
} else {
SC.Characteristics = OS->getCharacteristics();
// FIXME: When we start creating DBI for import libraries, use those here.
SC.Imod = LinkerModule.getModuleIndex();
}
SC.DataCrc = 0; // FIXME
SC.RelocCrc = 0; // FIXME
Builder.getDbiBuilder().addSectionContrib(SC);
}
void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections,
ArrayRef<uint8_t> SectionTable) {
// It's not entirely clear what this is, but the * Linker * module uses it.
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
NativePath = Config->PDBPath;
sys::fs::make_absolute(NativePath);
sys::path::native(NativePath, sys::path::Style::windows);
@ -703,6 +712,18 @@ void PDBLinker::addSections(ArrayRef<uint8_t> SectionTable) {
LinkerModule.setPdbFilePathNI(PdbFilePathNI);
addLinkerModuleSymbols(NativePath, LinkerModule, Alloc);
// Add section contributions. They must be ordered by ascending RVA.
for (OutputSection *OS : OutputSections)
for (Chunk *C : OS->getChunks())
addSectionContrib(LinkerModule, OS, C);
// Add Section Map stream.
ArrayRef<object::coff_section> Sections = {
(const object::coff_section *)SectionTable.data(),
SectionTable.size() / sizeof(object::coff_section)};
SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections);
DbiBuilder.setSectionMap(SectionMap);
// Add COFF section header stream.
ExitOnErr(
DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));

View File

@ -21,9 +21,12 @@ union DebugInfo;
namespace lld {
namespace coff {
class OutputSection;
class SymbolTable;
void createPDB(SymbolTable *Symtab, llvm::ArrayRef<uint8_t> SectionTable,
void createPDB(SymbolTable *Symtab,
llvm::ArrayRef<OutputSection *> OutputSections,
llvm::ArrayRef<uint8_t> SectionTable,
const llvm::codeview::DebugInfo *DI);
}
}

View File

@ -240,7 +240,7 @@ void Writer::run() {
const llvm::codeview::DebugInfo *DI = nullptr;
if (Config->DebugTypes & static_cast<unsigned>(coff::DebugType::CV))
DI = BuildId->DI;
createPDB(Symtab, SectionTable, DI);
createPDB(Symtab, OutputSections, SectionTable, DI);
}
writeMapFile(OutputSections);

View File

@ -7,7 +7,7 @@ RUN: lld-link /out:%t1.dll /dll %t1.obj /implib:%t1.lib \
RUN: /export:exportfn1 /export:exportfn2
RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj
RUN: lld-link /out:%t2.exe /pdb:%t2.pdb /debug /entry:main %t2.obj %t1.lib
RUN: llvm-pdbutil dump %t2.pdb -publics | FileCheck %s
RUN: llvm-pdbutil dump %t2.pdb -publics -section-contribs | FileCheck %s
CHECK: Public Symbols
CHECK-NEXT: ============================================================
@ -21,3 +21,21 @@ CHECK-NEXT: 32 | S_PUB32 [size = 32] `__imp_exportfn2`
CHECK-NEXT: flags = none, addr = 0003:0072
CHECK-NEXT: 0 | S_PUB32 [size = 32] `__imp_exportfn1`
CHECK-NEXT: flags = none, addr = 0003:0064
CHECK: Section Contributions
CHECK-NEXT: ============================================================
main
CHECK-NEXT: SC | mod = 0, 0001:0000, size = 8, data crc = 0, reloc crc = 0
CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_EXECUTE |
CHECK-NEXT: IMAGE_SCN_MEM_READ
exportfn1 thunk
CHECK-NEXT: SC | mod = 1, 0001:0016, size = 6, data crc = 0, reloc crc = 0
CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
exportfn2 thunk
CHECK-NEXT: SC | mod = 1, 0001:0032, size = 6, data crc = 0, reloc crc = 0
CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
.rdata debug directory data chunks
CHECK-NEXT: SC | mod = 1, 0002:0000, size = 28, data crc = 0, reloc crc = 0
CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
CHECK-NEXT: SC | mod = 1, 0002:0028, size = 110, data crc = 0, reloc crc = 0
CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ

View File

@ -190,16 +190,16 @@ RAW-NEXT: off = 20
RAW-NEXT: off = 0
RAW: Section Contributions
RAW-NEXT: ============================================================
RAW-NEXT: SC | mod = 0, 65535:1288, size = 14, data crc = 0, reloc crc = 0
RAW-NEXT: SC | mod = 0, 0001:0000, size = 12, data crc = 0, reloc crc = 0
RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ
RAW-NEXT: SC | mod = 0, 0002:0000, size = 14, data crc = 0, reloc crc = 0
RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
RAW-NEXT: IMAGE_SCN_MEM_READ
RAW-NEXT: SC | mod = 0, 65535:1312, size = 8, data crc = 0, reloc crc = 0
RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ
RAW-NEXT: SC | mod = 0, 65535:1320, size = 12, data crc = 0, reloc crc = 0
RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ
RAW-NEXT: SC | mod = 1, 65535:1144, size = 6, data crc = 0, reloc crc = 0
RAW-NEXT: SC | mod = 1, 0002:0016, size = 6, data crc = 0, reloc crc = 0
RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
RAW-NEXT: IMAGE_SCN_MEM_READ
RAW-NEXT: SC | mod = 0, 0003:0000, size = 8, data crc = 0, reloc crc = 0
RAW-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ
RAW: Section Map
RAW-NEXT: ============================================================
RAW-NEXT: Section 0000 | ovl = 0, group = 0, frame = 0, name = 1

View File

@ -72,8 +72,9 @@ public:
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer);
void addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi,
const llvm::object::coff_section *SecHdr);
void addSectionContrib(const SectionContrib &SC) {
SectionContribs.emplace_back(SC);
}
// A helper function to create a Section Map from a COFF section header.
static std::vector<SecMapEntry>

View File

@ -311,19 +311,6 @@ static uint16_t toSecMapFlags(uint32_t Flags) {
return Ret;
}
void DbiStreamBuilder::addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi,
const object::coff_section *SecHdr) {
SectionContrib SC;
memset(&SC, 0, sizeof(SC));
SC.ISect = (uint16_t)~0U; // This represents nil.
SC.Off = SecHdr->PointerToRawData;
SC.Size = SecHdr->SizeOfRawData;
SC.Characteristics = SecHdr->Characteristics;
// Use the module index in the module dbi stream or nil (-1).
SC.Imod = ModuleDbi ? ModuleDbi->getModuleIndex() : (uint16_t)~0U;
SectionContribs.emplace_back(SC);
}
// A utility function to create a Section Map for a given list of COFF sections.
//
// A Section Map seem to be a copy of a COFF section list in other format.