PDB.cpp revision 314564
1//===- PDB.cpp ------------------------------------------------------------===// 2// 3// The LLVM Linker 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "PDB.h" 11#include "Chunks.h" 12#include "Config.h" 13#include "Error.h" 14#include "SymbolTable.h" 15#include "Symbols.h" 16#include "llvm/DebugInfo/CodeView/CVDebugRecord.h" 17#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" 18#include "llvm/DebugInfo/CodeView/SymbolDumper.h" 19#include "llvm/DebugInfo/CodeView/TypeDatabase.h" 20#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" 21#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" 22#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" 23#include "llvm/DebugInfo/MSF/ByteStream.h" 24#include "llvm/DebugInfo/MSF/MSFBuilder.h" 25#include "llvm/DebugInfo/MSF/MSFCommon.h" 26#include "llvm/DebugInfo/PDB/Raw/DbiStream.h" 27#include "llvm/DebugInfo/PDB/Raw/DbiStreamBuilder.h" 28#include "llvm/DebugInfo/PDB/Raw/InfoStream.h" 29#include "llvm/DebugInfo/PDB/Raw/InfoStreamBuilder.h" 30#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" 31#include "llvm/DebugInfo/PDB/Raw/PDBFileBuilder.h" 32#include "llvm/DebugInfo/PDB/Raw/TpiStream.h" 33#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h" 34#include "llvm/Object/COFF.h" 35#include "llvm/Support/Endian.h" 36#include "llvm/Support/FileOutputBuffer.h" 37#include "llvm/Support/ScopedPrinter.h" 38#include <memory> 39 40using namespace lld; 41using namespace lld::coff; 42using namespace llvm; 43using namespace llvm::codeview; 44using namespace llvm::support; 45using namespace llvm::support::endian; 46 47using llvm::object::coff_section; 48 49static ExitOnError ExitOnErr; 50 51// Returns a list of all SectionChunks. 52static std::vector<coff_section> getInputSections(SymbolTable *Symtab) { 53 std::vector<coff_section> V; 54 for (Chunk *C : Symtab->getChunks()) 55 if (auto *SC = dyn_cast<SectionChunk>(C)) 56 V.push_back(*SC->Header); 57 return V; 58} 59 60static SectionChunk *findByName(std::vector<SectionChunk *> &Sections, 61 StringRef Name) { 62 for (SectionChunk *C : Sections) 63 if (C->getSectionName() == Name) 64 return C; 65 return nullptr; 66} 67 68static ArrayRef<uint8_t> getDebugSection(ObjectFile *File, StringRef SecName) { 69 SectionChunk *Sec = findByName(File->getDebugChunks(), SecName); 70 if (!Sec) 71 return {}; 72 73 // First 4 bytes are section magic. 74 ArrayRef<uint8_t> Data = Sec->getContents(); 75 if (Data.size() < 4) 76 fatal(SecName + " too short"); 77 if (read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC) 78 fatal(SecName + " has an invalid magic"); 79 return Data.slice(4); 80} 81 82// Merge .debug$T sections and returns it. 83static std::vector<uint8_t> mergeDebugT(SymbolTable *Symtab) { 84 ScopedPrinter W(outs()); 85 86 // Visit all .debug$T sections to add them to Builder. 87 codeview::TypeTableBuilder Builder(BAlloc); 88 for (ObjectFile *File : Symtab->ObjectFiles) { 89 ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); 90 if (Data.empty()) 91 continue; 92 93 msf::ByteStream Stream(Data); 94 codeview::CVTypeArray Types; 95 msf::StreamReader Reader(Stream); 96 if (auto EC = Reader.readArray(Types, Reader.getLength())) 97 fatal(EC, "Reader::readArray failed"); 98 if (!codeview::mergeTypeStreams(Builder, Types)) 99 fatal("codeview::mergeTypeStreams failed"); 100 } 101 102 // Construct section contents. 103 std::vector<uint8_t> V; 104 Builder.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Rec) { 105 V.insert(V.end(), Rec.begin(), Rec.end()); 106 }); 107 return V; 108} 109 110static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) { 111 ListScope LS(W, "DebugT"); 112 ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); 113 if (Data.empty()) 114 return; 115 116 TypeDatabase TDB; 117 TypeDumpVisitor TDV(TDB, &W, false); 118 CVTypeDumper TypeDumper(TDB); 119 if (auto EC = TypeDumper.dump(Data, TDV)) 120 fatal(EC, "CVTypeDumper::dump failed"); 121} 122 123static void dumpDebugS(ScopedPrinter &W, ObjectFile *File) { 124 ListScope LS(W, "DebugS"); 125 ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$S"); 126 if (Data.empty()) 127 return; 128 129 msf::ByteStream Stream(Data); 130 CVSymbolArray Symbols; 131 msf::StreamReader Reader(Stream); 132 if (auto EC = Reader.readArray(Symbols, Reader.getLength())) 133 fatal(EC, "StreamReader.readArray<CVSymbolArray> failed"); 134 135 TypeDatabase TDB; 136 CVSymbolDumper SymbolDumper(W, TDB, nullptr, false); 137 if (auto EC = SymbolDumper.dump(Symbols)) 138 fatal(EC, "CVSymbolDumper::dump failed"); 139} 140 141// Dump CodeView debug info. This is for debugging. 142static void dumpCodeView(SymbolTable *Symtab) { 143 ScopedPrinter W(outs()); 144 145 for (ObjectFile *File : Symtab->ObjectFiles) { 146 dumpDebugT(W, File); 147 dumpDebugS(W, File); 148 } 149} 150 151static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, 152 ArrayRef<uint8_t> Data) { 153 msf::ByteStream Stream(Data); 154 codeview::CVTypeArray Records; 155 msf::StreamReader Reader(Stream); 156 if (auto EC = Reader.readArray(Records, Reader.getLength())) 157 fatal(EC, "Reader.readArray failed"); 158 for (const codeview::CVType &Rec : Records) 159 TpiBuilder.addTypeRecord(Rec); 160} 161 162// Creates a PDB file. 163void coff::createPDB(StringRef Path, SymbolTable *Symtab, 164 ArrayRef<uint8_t> SectionTable, 165 const llvm::codeview::DebugInfo *DI) { 166 if (Config->DumpPdb) 167 dumpCodeView(Symtab); 168 169 BumpPtrAllocator Alloc; 170 pdb::PDBFileBuilder Builder(Alloc); 171 ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize 172 173 // Create streams in MSF for predefined streams, namely 174 // PDB, TPI, DBI and IPI. 175 for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I) 176 ExitOnErr(Builder.getMsfBuilder().addStream(0)); 177 178 // Add an Info stream. 179 auto &InfoBuilder = Builder.getInfoBuilder(); 180 InfoBuilder.setAge(DI->PDB70.Age); 181 InfoBuilder.setGuid( 182 *reinterpret_cast<const pdb::PDB_UniqueId *>(&DI->PDB70.Signature)); 183 // Should be the current time, but set 0 for reproducibilty. 184 InfoBuilder.setSignature(0); 185 InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70); 186 187 // Add an empty DPI stream. 188 auto &DbiBuilder = Builder.getDbiBuilder(); 189 DbiBuilder.setVersionHeader(pdb::PdbDbiV110); 190 191 // Add an empty TPI stream. 192 auto &TpiBuilder = Builder.getTpiBuilder(); 193 TpiBuilder.setVersionHeader(pdb::PdbTpiV80); 194 std::vector<uint8_t> TpiData; 195 if (Config->DebugPdb) { 196 TpiData = mergeDebugT(Symtab); 197 addTypeInfo(TpiBuilder, TpiData); 198 } 199 200 // Add an empty IPI stream. 201 auto &IpiBuilder = Builder.getIpiBuilder(); 202 IpiBuilder.setVersionHeader(pdb::PdbTpiV80); 203 204 // Add Section Contributions. 205 std::vector<pdb::SectionContrib> Contribs = 206 pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab)); 207 DbiBuilder.setSectionContribs(Contribs); 208 209 // Add Section Map stream. 210 ArrayRef<object::coff_section> Sections = { 211 (const object::coff_section *)SectionTable.data(), 212 SectionTable.size() / sizeof(object::coff_section)}; 213 std::vector<pdb::SecMapEntry> SectionMap = 214 pdb::DbiStreamBuilder::createSectionMap(Sections); 215 DbiBuilder.setSectionMap(SectionMap); 216 217 ExitOnErr(DbiBuilder.addModuleInfo("", "* Linker *")); 218 219 // Add COFF section header stream. 220 ExitOnErr( 221 DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable)); 222 223 // Write to a file. 224 ExitOnErr(Builder.commit(Path)); 225} 226