forked from OSchip/llvm-project
[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:
parent
144ee2b4d7
commit
175af4bcc7
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue