[PDB] Add a module descriptor for every object file

Summary:
Expose the module descriptor index and fill it in for section
contributions.

Reviewers: zturner

Subscribers: llvm-commits, ruiu, hiraditya

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

llvm-svn: 305296
This commit is contained in:
Reid Kleckner 2017-06-13 15:49:13 +00:00
parent 41ff570657
commit 8cbdd0c0f2
8 changed files with 154 additions and 51 deletions

View File

@ -22,6 +22,12 @@
#include <set>
#include <vector>
namespace llvm {
namespace pdb {
class DbiModuleDescriptorBuilder;
}
}
namespace lld {
namespace coff {
@ -122,6 +128,12 @@ public:
// COFF-specific and x86-only.
std::set<SymbolBody *> SEHandlers;
// Pointer to the PDB module descriptor builder. Various debug info records
// will reference object files by "module index", which is here. Things like
// source files and section contributions are also recorded here. Will be null
// if we are not producing a PDB.
llvm::pdb::DbiModuleDescriptorBuilder *ModuleDBI = nullptr;
private:
void initializeChunks();
void initializeSymbols();

View File

@ -29,6 +29,7 @@
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
@ -53,12 +54,10 @@ using llvm::object::coff_section;
static ExitOnError ExitOnErr;
// Returns a list of all SectionChunks.
static std::vector<coff_section> getInputSections(SymbolTable *Symtab) {
std::vector<coff_section> V;
static void addSectionContribs(SymbolTable *Symtab, pdb::DbiStreamBuilder &DbiBuilder) {
for (Chunk *C : Symtab->getChunks())
if (auto *SC = dyn_cast<SectionChunk>(C))
V.push_back(*SC->Header);
return V;
DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header);
}
static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
@ -95,10 +94,11 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
});
}
// Merge .debug$T sections into IpiData and TpiData.
static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
codeview::TypeTableBuilder &TypeTable,
codeview::TypeTableBuilder &IDTable) {
// Add all object files to the PDB. Merge .debug$T sections into IpiData and
// TpiData.
static void addObjectsToPDB(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
codeview::TypeTableBuilder &TypeTable,
codeview::TypeTableBuilder &IDTable) {
// Follow type servers. If the same type server is encountered more than
// once for this instance of `PDBTypeServerHandler` (for example if many
// object files reference the same TypeServer), the types from the
@ -107,6 +107,20 @@ static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
// Visit all .debug$T sections to add them to Builder.
for (ObjectFile *File : Symtab->ObjectFiles) {
// 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 absolute. If it's an object in an archive, we make the archive path
// absolute.
bool InArchive = !File->ParentName.empty();
SmallString<128> Path = InArchive ? File->ParentName : File->getName();
sys::fs::make_absolute(Path);
StringRef Name = InArchive ? File->getName() : StringRef(Path);
File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
File->ModuleDBI->setObjFileName(Path);
// FIXME: Walk the .debug$S sections and add them. Do things like recording
// source files.
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
if (Data.empty())
continue;
@ -202,17 +216,15 @@ void coff::createPDB(StringRef Path, SymbolTable *Symtab,
InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);
// Add an empty DPI stream.
auto &DbiBuilder = Builder.getDbiBuilder();
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
DbiBuilder.setVersionHeader(pdb::PdbDbiV110);
codeview::TypeTableBuilder TypeTable(BAlloc);
codeview::TypeTableBuilder IDTable(BAlloc);
mergeDebugT(Symtab, Builder, TypeTable, IDTable);
addObjectsToPDB(Symtab, Builder, TypeTable, IDTable);
// Add Section Contributions.
std::vector<pdb::SectionContrib> Contribs =
pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab));
DbiBuilder.setSectionContribs(Contribs);
addSectionContribs(Symtab, DbiBuilder);
// Add Section Map stream.
ArrayRef<object::coff_section> Sections = {

63
lld/test/COFF/pdb-lib.s Normal file
View File

@ -0,0 +1,63 @@
# RUN: rm -rf %t && mkdir -p %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o foo.obj
# RUN: llc %S/Inputs/bar.ll -filetype=obj -mtriple=i686-windows-msvc -o bar.obj
# RUN: llvm-lib bar.obj -out:bar.lib
# RUN: lld-link -debug -pdb:foo.pdb foo.obj bar.lib -out:foo.exe -entry:main
# RUN: llvm-pdbutil raw -modules %t/foo.pdb | FileCheck %s
# Make sure that the PDB has module descriptors. foo.obj and bar.lib should be
# absolute paths, and bar.obj should be the relative path passed to llvm-lib.
# CHECK-LABEL: Modules [
# CHECK-NEXT: {
# CHECK-NEXT: Name: {{.*pdb-lib.s.tmp[/\\]foo.obj}}
# CHECK-NEXT: Debug Stream Index:
# CHECK-NEXT: Object File Name: {{.*pdb-lib.s.tmp[/\\]foo.obj}}
# CHECK-NEXT: Num Files: 0
# CHECK-NEXT: Source File Name Idx: 0
# CHECK-NEXT: Pdb File Name Idx: 0
# CHECK-NEXT: Line Info Byte Size: 0
# CHECK-NEXT: C13 Line Info Byte Size: 0
# CHECK-NEXT: Symbol Byte Size: 4
# CHECK-NEXT: Type Server Index: 0
# CHECK-NEXT: Has EC Info: No
# CHECK-NEXT: }
# CHECK-NEXT: {
# CHECK-NEXT: Name: bar.obj
# CHECK-NEXT: Debug Stream Index:
# CHECK-NEXT: Object File Name: {{.*pdb-lib.s.tmp[/\\]bar.lib}}
# CHECK-NEXT: Num Files: 0
# CHECK-NEXT: Source File Name Idx: 0
# CHECK-NEXT: Pdb File Name Idx: 0
# CHECK-NEXT: Line Info Byte Size: 0
# CHECK-NEXT: C13 Line Info Byte Size: 0
# CHECK-NEXT: Symbol Byte Size: 4
# CHECK-NEXT: Type Server Index: 0
# CHECK-NEXT: Has EC Info: No
# CHECK-NEXT: }
# CHECK-NEXT: {
# CHECK-NEXT: Name: * Linker *
# CHECK-NEXT: Debug Stream Index:
# CHECK-NEXT: Object File Name:
# CHECK-NEXT: Num Files: 0
# CHECK-NEXT: Source File Name Idx: 0
# CHECK-NEXT: Pdb File Name Idx: 0
# CHECK-NEXT: Line Info Byte Size: 0
# CHECK-NEXT: C13 Line Info Byte Size: 0
# CHECK-NEXT: Symbol Byte Size: 4
# CHECK-NEXT: Type Server Index: 0
# CHECK-NEXT: Has EC Info: No
# CHECK-NEXT: }
# CHECK-NEXT: ]
.def _main;
.scl 2;
.type 32;
.endef
.globl _main
_main:
calll _bar
xor %eax, %eax
retl

View File

@ -2,6 +2,7 @@
# RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj
; If /DEBUG is not specified, /pdb is ignored.
# RUN: rm -f %t.pdb
# RUN: lld-link /pdb:%t.pdb /entry:main /nodefaultlib %t1.obj %t2.obj
# RUN: not ls %t.pdb

View File

@ -191,8 +191,34 @@
# RAW-NEXT: mspdb00.dll version: 0.0.0
# RAW-NEXT: Modules [
# RAW-NEXT: {
# RAW-NEXT: Name: * Linker *
# RAW-NEXT: Name: {{.*}}tmp1.obj
# RAW-NEXT: Debug Stream Index: 9
# RAW-NEXT: Object File Name: {{.*}}tmp1.obj
# RAW-NEXT: Num Files: 0
# RAW-NEXT: Source File Name Idx: 0
# RAW-NEXT: Pdb File Name Idx: 0
# RAW-NEXT: Line Info Byte Size: 0
# RAW-NEXT: C13 Line Info Byte Size: 0
# RAW-NEXT: Symbol Byte Size: 4
# RAW-NEXT: Type Server Index: 0
# RAW-NEXT: Has EC Info: No
# RAW-NEXT: }
# RAW-NEXT: {
# RAW-NEXT: Name: {{.*}}tmp2.obj
# RAW-NEXT: Debug Stream Index: 10
# RAW-NEXT: Object File Name: {{.*}}tmp2.obj
# RAW-NEXT: Num Files: 0
# RAW-NEXT: Source File Name Idx: 0
# RAW-NEXT: Pdb File Name Idx: 0
# RAW-NEXT: Line Info Byte Size: 0
# RAW-NEXT: C13 Line Info Byte Size: 0
# RAW-NEXT: Symbol Byte Size: 4
# RAW-NEXT: Type Server Index: 0
# RAW-NEXT: Has EC Info: No
# RAW-NEXT: }
# RAW-NEXT: {
# RAW-NEXT: Name: * Linker *
# RAW-NEXT: Debug Stream Index: 11
# RAW-NEXT: Object File Name:
# RAW-NEXT: Num Files: 0
# RAW-NEXT: Source File Name Idx: 0
@ -207,7 +233,7 @@
# RAW-NEXT: }
# RAW-NEXT: Section Contributions [
# RAW-NEXT: Contribution {
# RAW-NEXT: ISect: 0
# RAW-NEXT: ISect: 65535
# RAW-NEXT: Off: 1288
# RAW-NEXT: Size: 14
# RAW-NEXT: Characteristics [ (0x60500020)
@ -218,13 +244,13 @@
# RAW-NEXT: ]
# RAW-NEXT: Module {
# RAW-NEXT: Index: 0
# RAW-NEXT: Name: * Linker *
# RAW-NEXT: Name: {{.*}}tmp1.obj
# RAW-NEXT: }
# RAW-NEXT: Data CRC: 0
# RAW-NEXT: Reloc CRC: 0
# RAW-NEXT: }
# RAW-NEXT: Contribution {
# RAW-NEXT: ISect: 0
# RAW-NEXT: ISect: 65535
# RAW-NEXT: Off: 1312
# RAW-NEXT: Size: 8
# RAW-NEXT: Characteristics [ (0x40300040)
@ -234,13 +260,13 @@
# RAW-NEXT: ]
# RAW-NEXT: Module {
# RAW-NEXT: Index: 0
# RAW-NEXT: Name: * Linker *
# RAW-NEXT: Name: {{.*}}tmp1.obj
# RAW-NEXT: }
# RAW-NEXT: Data CRC: 0
# RAW-NEXT: Reloc CRC: 0
# RAW-NEXT: }
# RAW-NEXT: Contribution {
# RAW-NEXT: ISect: 0
# RAW-NEXT: ISect: 65535
# RAW-NEXT: Off: 1320
# RAW-NEXT: Size: 12
# RAW-NEXT: Characteristics [ (0x40300040)
@ -250,13 +276,13 @@
# RAW-NEXT: ]
# RAW-NEXT: Module {
# RAW-NEXT: Index: 0
# RAW-NEXT: Name: * Linker *
# RAW-NEXT: Name: {{.*}}tmp1.obj
# RAW-NEXT: }
# RAW-NEXT: Data CRC: 0
# RAW-NEXT: Reloc CRC: 0
# RAW-NEXT: }
# RAW-NEXT: Contribution {
# RAW-NEXT: ISect: 0
# RAW-NEXT: ISect: 65535
# RAW-NEXT: Off: 1144
# RAW-NEXT: Size: 6
# RAW-NEXT: Characteristics [ (0x60500020)
@ -266,8 +292,8 @@
# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
# RAW-NEXT: ]
# RAW-NEXT: Module {
# RAW-NEXT: Index: 0
# RAW-NEXT: Name: * Linker *
# RAW-NEXT: Index: 1
# RAW-NEXT: Name: {{.*}}tmp2.obj
# RAW-NEXT: }
# RAW-NEXT: Data CRC: 0
# RAW-NEXT: Reloc CRC: 0

View File

@ -56,6 +56,8 @@ public:
StringRef getModuleName() const { return ModuleName; }
StringRef getObjFileName() const { return ObjFileName; }
unsigned getModuleIndex() const { return Layout.Mod; }
ArrayRef<std::string> source_files() const {
return makeArrayRef(SourceFiles);
}

View File

@ -49,7 +49,6 @@ public:
void setPdbDllRbld(uint16_t R);
void setFlags(uint16_t F);
void setMachineType(PDB_Machine M);
void setSectionContribs(ArrayRef<SectionContrib> SecMap);
void setSectionMap(ArrayRef<SecMapEntry> SecMap);
// Add given bytes as a new stream.
@ -65,10 +64,8 @@ public:
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer);
// A helper function to create Section Contributions from COFF input
// section headers.
static std::vector<SectionContrib>
createSectionContribs(ArrayRef<llvm::object::coff_section> SecHdrs);
void addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi,
const llvm::object::coff_section *SecHdr);
// A helper function to create a Section Map from a COFF section header.
static std::vector<SecMapEntry>
@ -112,7 +109,7 @@ private:
WritableBinaryStreamRef NamesBuffer;
MutableBinaryByteStream FileInfoBuffer;
ArrayRef<SectionContrib> SectionContribs;
std::vector<SectionContrib> SectionContribs;
ArrayRef<SecMapEntry> SectionMap;
llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams;
};

View File

@ -45,10 +45,6 @@ void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
void DbiStreamBuilder::setSectionContribs(ArrayRef<SectionContrib> Arr) {
SectionContribs = Arr;
}
void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {
SectionMap = SecMap;
}
@ -293,23 +289,17 @@ static uint16_t toSecMapFlags(uint32_t Flags) {
return Ret;
}
// A utility function to create Section Contributions
// for a given input sections.
std::vector<SectionContrib> DbiStreamBuilder::createSectionContribs(
ArrayRef<object::coff_section> SecHdrs) {
std::vector<SectionContrib> Ret;
// Create a SectionContrib for each input section.
for (auto &Sec : SecHdrs) {
Ret.emplace_back();
auto &Entry = Ret.back();
memset(&Entry, 0, sizeof(Entry));
Entry.Off = Sec.PointerToRawData;
Entry.Size = Sec.SizeOfRawData;
Entry.Characteristics = Sec.Characteristics;
}
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.
@ -372,7 +362,7 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
if (!SectionContribs.empty()) {
if (auto EC = Writer.writeEnum(DbiSecContribVer60))
return EC;
if (auto EC = Writer.writeArray(SectionContribs))
if (auto EC = Writer.writeArray(makeArrayRef(SectionContribs)))
return EC;
}