diff options
Diffstat (limited to 'lld/COFF/PDB.cpp')
| -rw-r--r-- | lld/COFF/PDB.cpp | 148 |
1 files changed, 136 insertions, 12 deletions
diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp index bf1438e7407..b69eac8aac6 100644 --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -109,6 +109,9 @@ public: /// Link CodeView from each object file in the symbol table into the PDB. void addObjectsToPDB(); + /// Link info for each import file in the symbol table into the PDB. + void addImportFilesToPDB(ArrayRef<OutputSection *> OutputSections); + /// Link CodeView from a single object file into the target (output) PDB. /// When a precompiled headers object is linked, its TPI map might be provided /// externally. @@ -878,7 +881,7 @@ static void scopeStackOpen(SmallVectorImpl<SymbolScope> &Stack, } static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack, - uint32_t CurOffset, ObjFile *File) { + uint32_t CurOffset, InputFile *File) { if (Stack.empty()) { warn("symbol scopes are not balanced in " + File->getName()); return; @@ -1104,7 +1107,6 @@ static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) { SC.DataCrc = CRC.getCRC(); } else { SC.Characteristics = OS ? OS->Header.Characteristics : 0; - // FIXME: When we start creating DBI for import libraries, use those here. SC.Imod = Modi; } SC.RelocCrc = 0; // FIXME @@ -1454,16 +1456,7 @@ static std::string quote(ArrayRef<StringRef> Args) { return R; } -static void addCommonLinkerModuleSymbols(StringRef Path, - pdb::DbiModuleDescriptorBuilder &Mod, - BumpPtrAllocator &Allocator) { - ObjNameSym ONS(SymbolRecordKind::ObjNameSym); - Compile3Sym CS(SymbolRecordKind::Compile3Sym); - EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); - - ONS.Name = "* Linker *"; - ONS.Signature = 0; - +static void fillLinkerVerRecord(Compile3Sym &CS) { CS.Machine = toCodeViewMachine(Config->Machine); // Interestingly, if we set the string to 0.0.0.0, then when trying to view // local variables WinDbg emits an error that private symbols are not present. @@ -1487,6 +1480,18 @@ static void addCommonLinkerModuleSymbols(StringRef Path, CS.VersionFrontendQFE = 0; CS.Version = "LLVM Linker"; CS.setLanguage(SourceLanguage::Link); +} + +static void addCommonLinkerModuleSymbols(StringRef Path, + pdb::DbiModuleDescriptorBuilder &Mod, + BumpPtrAllocator &Allocator) { + ObjNameSym ONS(SymbolRecordKind::ObjNameSym); + EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); + Compile3Sym CS(SymbolRecordKind::Compile3Sym); + fillLinkerVerRecord(CS); + + ONS.Name = "* Linker *"; + ONS.Signature = 0; ArrayRef<StringRef> Args = makeArrayRef(Config->Argv).drop_front(); std::string ArgStr = quote(Args); @@ -1513,6 +1518,33 @@ static void addCommonLinkerModuleSymbols(StringRef Path, EBS, Allocator, CodeViewContainer::Pdb)); } +static void addLinkerModuleCoffGroup(PartialSection *Sec, + pdb::DbiModuleDescriptorBuilder &Mod, + OutputSection &OS, + BumpPtrAllocator &Allocator) { + // If there's a section, there's at least one chunk + assert(!Sec->Chunks.empty()); + const Chunk *firstChunk = *Sec->Chunks.begin(); + const Chunk *lastChunk = *Sec->Chunks.rbegin(); + + // Emit COFF group + CoffGroupSym CGS(SymbolRecordKind::CoffGroupSym); + CGS.Name = Sec->Name; + CGS.Segment = OS.SectionIndex; + CGS.Offset = firstChunk->getRVA() - OS.getRVA(); + CGS.Size = lastChunk->getRVA() + lastChunk->getSize() - firstChunk->getRVA(); + CGS.Characteristics = Sec->Characteristics; + + // Somehow .idata sections & sections groups in the debug symbol stream have + // the "write" flag set. However the section header for the corresponding + // .idata section doesn't have it. + if (CGS.Name.startswith(".idata")) + CGS.Characteristics |= llvm::COFF::IMAGE_SCN_MEM_WRITE; + + Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( + CGS, Allocator, CodeViewContainer::Pdb)); +} + static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod, OutputSection &OS, BumpPtrAllocator &Allocator) { @@ -1525,6 +1557,97 @@ static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod, Sym.SectionNumber = OS.SectionIndex; Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( Sym, Allocator, CodeViewContainer::Pdb)); + + // Skip COFF groups in MinGW because it adds a significant footprint to the + // PDB, due to each function being in its own section + if (Config->MinGW) + return; + + // Output COFF groups for individual chunks of this section. + for (PartialSection *Sec : OS.ContribSections) { + addLinkerModuleCoffGroup(Sec, Mod, OS, Allocator); + } +} + +// Add all import files as modules to the PDB. +void PDBLinker::addImportFilesToPDB(ArrayRef<OutputSection *> OutputSections) { + if (ImportFile::Instances.empty()) + return; + + std::map<std::string, llvm::pdb::DbiModuleDescriptorBuilder *> DllToModuleDbi; + + for (ImportFile *File : ImportFile::Instances) { + if (!File->Live) + continue; + + if (!File->ThunkSym) + continue; + + std::string DLL = StringRef(File->DLLName).lower(); + llvm::pdb::DbiModuleDescriptorBuilder *&Mod = DllToModuleDbi[DLL]; + if (!Mod) { + pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); + SmallString<128> LibPath = File->ParentName; + pdbMakeAbsolute(LibPath); + sys::path::native(LibPath); + + // Name modules similar to MSVC's link.exe. + // The first module is the simple dll filename + llvm::pdb::DbiModuleDescriptorBuilder &FirstMod = + ExitOnErr(DbiBuilder.addModuleInfo(File->DLLName)); + FirstMod.setObjFileName(LibPath); + pdb::SectionContrib SC = + createSectionContrib(nullptr, llvm::pdb::kInvalidStreamIndex); + FirstMod.setFirstSectionContrib(SC); + + // The second module is where the import stream goes. + Mod = &ExitOnErr(DbiBuilder.addModuleInfo("Import:" + File->DLLName)); + Mod->setObjFileName(LibPath); + } + + DefinedImportThunk *Thunk = cast<DefinedImportThunk>(File->ThunkSym); + + ObjNameSym ONS(SymbolRecordKind::ObjNameSym); + Compile3Sym CS(SymbolRecordKind::Compile3Sym); + Thunk32Sym TS(SymbolRecordKind::Thunk32Sym); + ScopeEndSym ES(SymbolRecordKind::ScopeEndSym); + + ONS.Name = File->DLLName; + ONS.Signature = 0; + + fillLinkerVerRecord(CS); + + TS.Name = Thunk->getName(); + TS.Parent = 0; + TS.End = 0; + TS.Next = 0; + TS.Thunk = ThunkOrdinal::Standard; + TS.Length = Thunk->getChunk()->getSize(); + TS.Segment = Thunk->getChunk()->getOutputSection()->SectionIndex; + TS.Offset = Thunk->getChunk()->OutputSectionOff; + + Mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol( + ONS, Alloc, CodeViewContainer::Pdb)); + Mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol( + CS, Alloc, CodeViewContainer::Pdb)); + + SmallVector<SymbolScope, 4> Scopes; + CVSymbol NewSym = codeview::SymbolSerializer::writeOneSymbol( + TS, Alloc, CodeViewContainer::Pdb); + scopeStackOpen(Scopes, Mod->getNextSymbolOffset(), NewSym); + + Mod->addSymbol(NewSym); + + NewSym = codeview::SymbolSerializer::writeOneSymbol(ES, Alloc, + CodeViewContainer::Pdb); + scopeStackClose(Scopes, Mod->getNextSymbolOffset(), File); + + Mod->addSymbol(NewSym); + + pdb::SectionContrib SC = + createSectionContrib(Thunk->getChunk(), Mod->getModuleIndex()); + Mod->setFirstSectionContrib(SC); + } } // Creates a PDB file. @@ -1537,6 +1660,7 @@ void coff::createPDB(SymbolTable *Symtab, PDB.initialize(BuildId); PDB.addObjectsToPDB(); + PDB.addImportFilesToPDB(OutputSections); PDB.addSections(OutputSections, SectionTable); PDB.addNatvisFiles(); |

