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);
|
TypeServer2Record &TS);
|
||||||
|
|
||||||
/// Add the section map and section contributions to the PDB.
|
/// 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.
|
/// Write the PDB to disk.
|
||||||
void commit();
|
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,
|
static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
|
||||||
StringRef Name) {
|
StringRef Name) {
|
||||||
for (SectionChunk *C : Sections)
|
for (SectionChunk *C : Sections)
|
||||||
|
@ -648,12 +644,14 @@ static void addLinkerModuleSymbols(StringRef Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a PDB file.
|
// 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) {
|
const llvm::codeview::DebugInfo *DI) {
|
||||||
PDBLinker PDB(Symtab);
|
PDBLinker PDB(Symtab);
|
||||||
PDB.initialize(DI);
|
PDB.initialize(DI);
|
||||||
PDB.addObjectsToPDB();
|
PDB.addObjectsToPDB();
|
||||||
PDB.addSections(SectionTable);
|
PDB.addSections(OutputSections, SectionTable);
|
||||||
PDB.commit();
|
PDB.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,19 +680,30 @@ void PDBLinker::initialize(const llvm::codeview::DebugInfo *DI) {
|
||||||
ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {}));
|
ExitOnErr(DbiBuilder.addDbgStream(pdb::DbgHeaderType::NewFPO, {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDBLinker::addSections(ArrayRef<uint8_t> SectionTable) {
|
void PDBLinker::addSectionContrib(pdb::DbiModuleDescriptorBuilder &LinkerModule,
|
||||||
// Add Section Contributions.
|
OutputSection *OS, Chunk *C) {
|
||||||
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
|
pdb::SectionContrib SC;
|
||||||
addSectionContribs(Symtab, DbiBuilder);
|
memset(&SC, 0, sizeof(SC));
|
||||||
|
SC.ISect = OS->SectionIndex;
|
||||||
// Add Section Map stream.
|
SC.Off = C->getRVA() - OS->getRVA();
|
||||||
ArrayRef<object::coff_section> Sections = {
|
SC.Size = C->getSize();
|
||||||
(const object::coff_section *)SectionTable.data(),
|
if (auto *SecChunk = dyn_cast<SectionChunk>(C)) {
|
||||||
SectionTable.size() / sizeof(object::coff_section)};
|
SC.Characteristics = SecChunk->Header->Characteristics;
|
||||||
SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections);
|
SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex();
|
||||||
DbiBuilder.setSectionMap(SectionMap);
|
} 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.
|
// It's not entirely clear what this is, but the * Linker * module uses it.
|
||||||
|
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
|
||||||
NativePath = Config->PDBPath;
|
NativePath = Config->PDBPath;
|
||||||
sys::fs::make_absolute(NativePath);
|
sys::fs::make_absolute(NativePath);
|
||||||
sys::path::native(NativePath, sys::path::Style::windows);
|
sys::path::native(NativePath, sys::path::Style::windows);
|
||||||
|
@ -703,6 +712,18 @@ void PDBLinker::addSections(ArrayRef<uint8_t> SectionTable) {
|
||||||
LinkerModule.setPdbFilePathNI(PdbFilePathNI);
|
LinkerModule.setPdbFilePathNI(PdbFilePathNI);
|
||||||
addLinkerModuleSymbols(NativePath, LinkerModule, Alloc);
|
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.
|
// Add COFF section header stream.
|
||||||
ExitOnErr(
|
ExitOnErr(
|
||||||
DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));
|
DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));
|
||||||
|
|
|
@ -21,9 +21,12 @@ union DebugInfo;
|
||||||
|
|
||||||
namespace lld {
|
namespace lld {
|
||||||
namespace coff {
|
namespace coff {
|
||||||
|
class OutputSection;
|
||||||
class SymbolTable;
|
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);
|
const llvm::codeview::DebugInfo *DI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,7 +240,7 @@ void Writer::run() {
|
||||||
const llvm::codeview::DebugInfo *DI = nullptr;
|
const llvm::codeview::DebugInfo *DI = nullptr;
|
||||||
if (Config->DebugTypes & static_cast<unsigned>(coff::DebugType::CV))
|
if (Config->DebugTypes & static_cast<unsigned>(coff::DebugType::CV))
|
||||||
DI = BuildId->DI;
|
DI = BuildId->DI;
|
||||||
createPDB(Symtab, SectionTable, DI);
|
createPDB(Symtab, OutputSections, SectionTable, DI);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeMapFile(OutputSections);
|
writeMapFile(OutputSections);
|
||||||
|
|
|
@ -7,7 +7,7 @@ RUN: lld-link /out:%t1.dll /dll %t1.obj /implib:%t1.lib \
|
||||||
RUN: /export:exportfn1 /export:exportfn2
|
RUN: /export:exportfn1 /export:exportfn2
|
||||||
RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj
|
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: 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: Public Symbols
|
||||||
CHECK-NEXT: ============================================================
|
CHECK-NEXT: ============================================================
|
||||||
|
@ -21,3 +21,21 @@ CHECK-NEXT: 32 | S_PUB32 [size = 32] `__imp_exportfn2`
|
||||||
CHECK-NEXT: flags = none, addr = 0003:0072
|
CHECK-NEXT: flags = none, addr = 0003:0072
|
||||||
CHECK-NEXT: 0 | S_PUB32 [size = 32] `__imp_exportfn1`
|
CHECK-NEXT: 0 | S_PUB32 [size = 32] `__imp_exportfn1`
|
||||||
CHECK-NEXT: flags = none, addr = 0003:0064
|
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-NEXT: off = 0
|
||||||
RAW: Section Contributions
|
RAW: Section Contributions
|
||||||
RAW-NEXT: ============================================================
|
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_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
|
||||||
RAW-NEXT: IMAGE_SCN_MEM_READ
|
RAW-NEXT: IMAGE_SCN_MEM_READ
|
||||||
RAW-NEXT: SC | mod = 0, 65535:1312, size = 8, 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_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: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
|
RAW-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
|
||||||
RAW-NEXT: IMAGE_SCN_MEM_READ
|
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: Section Map
|
||||||
RAW-NEXT: ============================================================
|
RAW-NEXT: ============================================================
|
||||||
RAW-NEXT: Section 0000 | ovl = 0, group = 0, frame = 0, name = 1
|
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);
|
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer);
|
||||||
|
|
||||||
void addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi,
|
void addSectionContrib(const SectionContrib &SC) {
|
||||||
const llvm::object::coff_section *SecHdr);
|
SectionContribs.emplace_back(SC);
|
||||||
|
}
|
||||||
|
|
||||||
// A helper function to create a Section Map from a COFF section header.
|
// A helper function to create a Section Map from a COFF section header.
|
||||||
static std::vector<SecMapEntry>
|
static std::vector<SecMapEntry>
|
||||||
|
|
|
@ -311,19 +311,6 @@ static uint16_t toSecMapFlags(uint32_t Flags) {
|
||||||
return Ret;
|
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 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.
|
// A Section Map seem to be a copy of a COFF section list in other format.
|
||||||
|
|
Loading…
Reference in New Issue