Index: lld/trunk/COFF/InputFiles.h =================================================================== --- lld/trunk/COFF/InputFiles.h +++ lld/trunk/COFF/InputFiles.h @@ -22,6 +22,12 @@ #include #include +namespace llvm { +namespace pdb { +class DbiModuleDescriptorBuilder; +} +} + namespace lld { namespace coff { @@ -122,6 +128,12 @@ // COFF-specific and x86-only. std::set 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(); Index: lld/trunk/COFF/PDB.cpp =================================================================== --- lld/trunk/COFF/PDB.cpp +++ lld/trunk/COFF/PDB.cpp @@ -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 @@ static ExitOnError ExitOnErr; // Returns a list of all SectionChunks. -static std::vector getInputSections(SymbolTable *Symtab) { - std::vector V; +static void addSectionContribs(SymbolTable *Symtab, pdb::DbiStreamBuilder &DbiBuilder) { for (Chunk *C : Symtab->getChunks()) if (auto *SC = dyn_cast(C)) - V.push_back(*SC->Header); - return V; + DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header); } static SectionChunk *findByName(std::vector &Sections, @@ -95,10 +94,11 @@ }); } -// 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 @@ // 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 Data = getDebugSection(File, ".debug$T"); if (Data.empty()) continue; @@ -202,17 +216,15 @@ 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 Contribs = - pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab)); - DbiBuilder.setSectionContribs(Contribs); + addSectionContribs(Symtab, DbiBuilder); // Add Section Map stream. ArrayRef Sections = { Index: lld/trunk/test/COFF/pdb-lib.s =================================================================== --- lld/trunk/test/COFF/pdb-lib.s +++ lld/trunk/test/COFF/pdb-lib.s @@ -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 + Index: lld/trunk/test/COFF/pdb-options.test =================================================================== --- lld/trunk/test/COFF/pdb-options.test +++ lld/trunk/test/COFF/pdb-options.test @@ -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 Index: lld/trunk/test/COFF/pdb.test =================================================================== --- lld/trunk/test/COFF/pdb.test +++ lld/trunk/test/COFF/pdb.test @@ -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 Index: llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -56,6 +56,8 @@ StringRef getModuleName() const { return ModuleName; } StringRef getObjFileName() const { return ObjFileName; } + unsigned getModuleIndex() const { return Layout.Mod; } + ArrayRef source_files() const { return makeArrayRef(SourceFiles); } Index: llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -49,7 +49,6 @@ void setPdbDllRbld(uint16_t R); void setFlags(uint16_t F); void setMachineType(PDB_Machine M); - void setSectionContribs(ArrayRef SecMap); void setSectionMap(ArrayRef SecMap); // Add given bytes as a new stream. @@ -65,10 +64,8 @@ Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer); - // A helper function to create Section Contributions from COFF input - // section headers. - static std::vector - createSectionContribs(ArrayRef 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 @@ -112,7 +109,7 @@ WritableBinaryStreamRef NamesBuffer; MutableBinaryByteStream FileInfoBuffer; - ArrayRef SectionContribs; + std::vector SectionContribs; ArrayRef SectionMap; llvm::SmallVector DbgStreams; }; Index: llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -45,10 +45,6 @@ void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; } -void DbiStreamBuilder::setSectionContribs(ArrayRef Arr) { - SectionContribs = Arr; -} - void DbiStreamBuilder::setSectionMap(ArrayRef SecMap) { SectionMap = SecMap; } @@ -293,23 +289,17 @@ return Ret; } -// A utility function to create Section Contributions -// for a given input sections. -std::vector DbiStreamBuilder::createSectionContribs( - ArrayRef SecHdrs) { - std::vector 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 @@ 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; }