PDBFileBuilder.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. //===- PDBFileBuilder.cpp - PDB File Creation -------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
  9. #include "llvm/DebugInfo/MSF/MSFBuilder.h"
  10. #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
  11. #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
  12. #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
  13. #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
  14. #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
  15. #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
  16. #include "llvm/DebugInfo/PDB/Native/RawError.h"
  17. #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
  18. #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
  19. #include "llvm/Support/BinaryStream.h"
  20. #include "llvm/Support/BinaryStreamWriter.h"
  21. #include "llvm/Support/CRC.h"
  22. #include "llvm/Support/Chrono.h"
  23. #include "llvm/Support/Path.h"
  24. #include "llvm/Support/xxhash.h"
  25. using namespace llvm;
  26. using namespace llvm::codeview;
  27. using namespace llvm::msf;
  28. using namespace llvm::pdb;
  29. using namespace llvm::support;
  30. PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
  31. : Allocator(Allocator), InjectedSourceHashTraits(Strings),
  32. InjectedSourceTable(2) {}
  33. PDBFileBuilder::~PDBFileBuilder() {}
  34. Error PDBFileBuilder::initialize(uint32_t BlockSize) {
  35. auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
  36. if (!ExpectedMsf)
  37. return ExpectedMsf.takeError();
  38. Msf = std::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
  39. return Error::success();
  40. }
  41. MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
  42. InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
  43. if (!Info)
  44. Info = std::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
  45. return *Info;
  46. }
  47. DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
  48. if (!Dbi)
  49. Dbi = std::make_unique<DbiStreamBuilder>(*Msf);
  50. return *Dbi;
  51. }
  52. TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
  53. if (!Tpi)
  54. Tpi = std::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
  55. return *Tpi;
  56. }
  57. TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
  58. if (!Ipi)
  59. Ipi = std::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
  60. return *Ipi;
  61. }
  62. PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
  63. return Strings;
  64. }
  65. GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
  66. if (!Gsi)
  67. Gsi = std::make_unique<GSIStreamBuilder>(*Msf);
  68. return *Gsi;
  69. }
  70. Expected<uint32_t> PDBFileBuilder::allocateNamedStream(StringRef Name,
  71. uint32_t Size) {
  72. auto ExpectedStream = Msf->addStream(Size);
  73. if (ExpectedStream)
  74. NamedStreams.set(Name, *ExpectedStream);
  75. return ExpectedStream;
  76. }
  77. Error PDBFileBuilder::addNamedStream(StringRef Name, StringRef Data) {
  78. Expected<uint32_t> ExpectedIndex = allocateNamedStream(Name, Data.size());
  79. if (!ExpectedIndex)
  80. return ExpectedIndex.takeError();
  81. assert(NamedStreamData.count(*ExpectedIndex) == 0);
  82. NamedStreamData[*ExpectedIndex] = std::string(Data);
  83. return Error::success();
  84. }
  85. void PDBFileBuilder::addInjectedSource(StringRef Name,
  86. std::unique_ptr<MemoryBuffer> Buffer) {
  87. // Stream names must be exact matches, since they get looked up in a hash
  88. // table and the hash value is dependent on the exact contents of the string.
  89. // link.exe lowercases a path and converts / to \, so we must do the same.
  90. SmallString<64> VName;
  91. sys::path::native(Name.lower(), VName, sys::path::Style::windows_backslash);
  92. uint32_t NI = getStringTableBuilder().insert(Name);
  93. uint32_t VNI = getStringTableBuilder().insert(VName);
  94. InjectedSourceDescriptor Desc;
  95. Desc.Content = std::move(Buffer);
  96. Desc.NameIndex = NI;
  97. Desc.VNameIndex = VNI;
  98. Desc.StreamName = "/src/files/";
  99. Desc.StreamName += VName;
  100. InjectedSources.push_back(std::move(Desc));
  101. }
  102. Error PDBFileBuilder::finalizeMsfLayout() {
  103. if (Ipi && Ipi->getRecordCount() > 0) {
  104. // In theory newer PDBs always have an ID stream, but by saying that we're
  105. // only going to *really* have an ID stream if there is at least one ID
  106. // record, we leave open the opportunity to test older PDBs such as those
  107. // that don't have an ID stream.
  108. auto &Info = getInfoBuilder();
  109. Info.addFeature(PdbRaw_FeatureSig::VC140);
  110. }
  111. uint32_t StringsLen = Strings.calculateSerializedSize();
  112. Expected<uint32_t> SN = allocateNamedStream("/LinkInfo", 0);
  113. if (!SN)
  114. return SN.takeError();
  115. if (Gsi) {
  116. if (auto EC = Gsi->finalizeMsfLayout())
  117. return EC;
  118. if (Dbi) {
  119. Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
  120. Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
  121. Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIndex());
  122. }
  123. }
  124. if (Tpi) {
  125. if (auto EC = Tpi->finalizeMsfLayout())
  126. return EC;
  127. }
  128. if (Dbi) {
  129. if (auto EC = Dbi->finalizeMsfLayout())
  130. return EC;
  131. }
  132. SN = allocateNamedStream("/names", StringsLen);
  133. if (!SN)
  134. return SN.takeError();
  135. if (Ipi) {
  136. if (auto EC = Ipi->finalizeMsfLayout())
  137. return EC;
  138. }
  139. // Do this last, since it relies on the named stream map being complete, and
  140. // that can be updated by previous steps in the finalization.
  141. if (Info) {
  142. if (auto EC = Info->finalizeMsfLayout())
  143. return EC;
  144. }
  145. if (!InjectedSources.empty()) {
  146. for (const auto &IS : InjectedSources) {
  147. JamCRC CRC(0);
  148. CRC.update(arrayRefFromStringRef(IS.Content->getBuffer()));
  149. SrcHeaderBlockEntry Entry;
  150. ::memset(&Entry, 0, sizeof(SrcHeaderBlockEntry));
  151. Entry.Size = sizeof(SrcHeaderBlockEntry);
  152. Entry.FileSize = IS.Content->getBufferSize();
  153. Entry.FileNI = IS.NameIndex;
  154. Entry.VFileNI = IS.VNameIndex;
  155. Entry.ObjNI = 1;
  156. Entry.IsVirtual = 0;
  157. Entry.Version =
  158. static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
  159. Entry.CRC = CRC.getCRC();
  160. StringRef VName = getStringTableBuilder().getStringForId(IS.VNameIndex);
  161. InjectedSourceTable.set_as(VName, std::move(Entry),
  162. InjectedSourceHashTraits);
  163. }
  164. uint32_t SrcHeaderBlockSize =
  165. sizeof(SrcHeaderBlockHeader) +
  166. InjectedSourceTable.calculateSerializedLength();
  167. SN = allocateNamedStream("/src/headerblock", SrcHeaderBlockSize);
  168. if (!SN)
  169. return SN.takeError();
  170. for (const auto &IS : InjectedSources) {
  171. SN = allocateNamedStream(IS.StreamName, IS.Content->getBufferSize());
  172. if (!SN)
  173. return SN.takeError();
  174. }
  175. }
  176. // Do this last, since it relies on the named stream map being complete, and
  177. // that can be updated by previous steps in the finalization.
  178. if (Info) {
  179. if (auto EC = Info->finalizeMsfLayout())
  180. return EC;
  181. }
  182. return Error::success();
  183. }
  184. Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
  185. uint32_t SN = 0;
  186. if (!NamedStreams.get(Name, SN))
  187. return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
  188. return SN;
  189. }
  190. void PDBFileBuilder::commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
  191. const msf::MSFLayout &Layout) {
  192. assert(!InjectedSourceTable.empty());
  193. uint32_t SN = cantFail(getNamedStreamIndex("/src/headerblock"));
  194. auto Stream = WritableMappedBlockStream::createIndexedStream(
  195. Layout, MsfBuffer, SN, Allocator);
  196. BinaryStreamWriter Writer(*Stream);
  197. SrcHeaderBlockHeader Header;
  198. ::memset(&Header, 0, sizeof(Header));
  199. Header.Version = static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
  200. Header.Size = Writer.bytesRemaining();
  201. cantFail(Writer.writeObject(Header));
  202. cantFail(InjectedSourceTable.commit(Writer));
  203. assert(Writer.bytesRemaining() == 0);
  204. }
  205. void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer,
  206. const msf::MSFLayout &Layout) {
  207. if (InjectedSourceTable.empty())
  208. return;
  209. commitSrcHeaderBlock(MsfBuffer, Layout);
  210. for (const auto &IS : InjectedSources) {
  211. uint32_t SN = cantFail(getNamedStreamIndex(IS.StreamName));
  212. auto SourceStream = WritableMappedBlockStream::createIndexedStream(
  213. Layout, MsfBuffer, SN, Allocator);
  214. BinaryStreamWriter SourceWriter(*SourceStream);
  215. assert(SourceWriter.bytesRemaining() == IS.Content->getBufferSize());
  216. cantFail(SourceWriter.writeBytes(
  217. arrayRefFromStringRef(IS.Content->getBuffer())));
  218. }
  219. }
  220. Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) {
  221. assert(!Filename.empty());
  222. if (auto EC = finalizeMsfLayout())
  223. return EC;
  224. MSFLayout Layout;
  225. Expected<FileBufferByteStream> ExpectedMsfBuffer =
  226. Msf->commit(Filename, Layout);
  227. if (!ExpectedMsfBuffer)
  228. return ExpectedMsfBuffer.takeError();
  229. FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
  230. auto ExpectedSN = getNamedStreamIndex("/names");
  231. if (!ExpectedSN)
  232. return ExpectedSN.takeError();
  233. auto NS = WritableMappedBlockStream::createIndexedStream(
  234. Layout, Buffer, *ExpectedSN, Allocator);
  235. BinaryStreamWriter NSWriter(*NS);
  236. if (auto EC = Strings.commit(NSWriter))
  237. return EC;
  238. for (const auto &NSE : NamedStreamData) {
  239. if (NSE.second.empty())
  240. continue;
  241. auto NS = WritableMappedBlockStream::createIndexedStream(
  242. Layout, Buffer, NSE.first, Allocator);
  243. BinaryStreamWriter NSW(*NS);
  244. if (auto EC = NSW.writeBytes(arrayRefFromStringRef(NSE.second)))
  245. return EC;
  246. }
  247. if (Info) {
  248. if (auto EC = Info->commit(Layout, Buffer))
  249. return EC;
  250. }
  251. if (Dbi) {
  252. if (auto EC = Dbi->commit(Layout, Buffer))
  253. return EC;
  254. }
  255. if (Tpi) {
  256. if (auto EC = Tpi->commit(Layout, Buffer))
  257. return EC;
  258. }
  259. if (Ipi) {
  260. if (auto EC = Ipi->commit(Layout, Buffer))
  261. return EC;
  262. }
  263. if (Gsi) {
  264. if (auto EC = Gsi->commit(Layout, Buffer))
  265. return EC;
  266. }
  267. auto InfoStreamBlocks = Layout.StreamMap[StreamPDB];
  268. assert(!InfoStreamBlocks.empty());
  269. uint64_t InfoStreamFileOffset =
  270. blockToOffset(InfoStreamBlocks.front(), Layout.SB->BlockSize);
  271. InfoStreamHeader *H = reinterpret_cast<InfoStreamHeader *>(
  272. Buffer.getBufferStart() + InfoStreamFileOffset);
  273. commitInjectedSources(Buffer, Layout);
  274. // Set the build id at the very end, after every other byte of the PDB
  275. // has been written.
  276. if (Info->hashPDBContentsToGUID()) {
  277. // Compute a hash of all sections of the output file.
  278. uint64_t Digest =
  279. xxHash64({Buffer.getBufferStart(), Buffer.getBufferEnd()});
  280. H->Age = 1;
  281. memcpy(H->Guid.Guid, &Digest, 8);
  282. // xxhash only gives us 8 bytes, so put some fixed data in the other half.
  283. memcpy(H->Guid.Guid + 8, "LLD PDB.", 8);
  284. // Put the hash in the Signature field too.
  285. H->Signature = static_cast<uint32_t>(Digest);
  286. // Return GUID to caller.
  287. memcpy(Guid, H->Guid.Guid, 16);
  288. } else {
  289. H->Age = Info->getAge();
  290. H->Guid = Info->getGuid();
  291. Optional<uint32_t> Sig = Info->getSignature();
  292. H->Signature = Sig.hasValue() ? *Sig : time(nullptr);
  293. }
  294. return Buffer.commit();
  295. }