PDBFileBuilder.cpp 11 KB

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