DbiStream.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
  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/DbiStream.h"
  9. #include "llvm/ADT/StringRef.h"
  10. #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
  11. #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
  12. #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
  13. #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
  14. #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
  15. #include "llvm/DebugInfo/PDB/Native/RawError.h"
  16. #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
  17. #include "llvm/DebugInfo/PDB/PDBTypes.h"
  18. #include "llvm/Object/COFF.h"
  19. #include "llvm/Support/BinaryStreamArray.h"
  20. #include "llvm/Support/BinaryStreamReader.h"
  21. #include "llvm/Support/Error.h"
  22. #include <algorithm>
  23. #include <cstddef>
  24. #include <cstdint>
  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. template <typename ContribType>
  31. static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
  32. BinaryStreamReader &Reader) {
  33. if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
  34. return make_error<RawError>(
  35. raw_error_code::corrupt_file,
  36. "Invalid number of bytes of section contributions");
  37. uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
  38. if (auto EC = Reader.readArray(Output, Count))
  39. return EC;
  40. return Error::success();
  41. }
  42. DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
  43. : Stream(std::move(Stream)), Header(nullptr) {}
  44. DbiStream::~DbiStream() = default;
  45. Error DbiStream::reload(PDBFile *Pdb) {
  46. BinaryStreamReader Reader(*Stream);
  47. if (Stream->getLength() < sizeof(DbiStreamHeader))
  48. return make_error<RawError>(raw_error_code::corrupt_file,
  49. "DBI Stream does not contain a header.");
  50. if (auto EC = Reader.readObject(Header))
  51. return make_error<RawError>(raw_error_code::corrupt_file,
  52. "DBI Stream does not contain a header.");
  53. if (Header->VersionSignature != -1)
  54. return make_error<RawError>(raw_error_code::corrupt_file,
  55. "Invalid DBI version signature.");
  56. // Require at least version 7, which should be present in all PDBs
  57. // produced in the last decade and allows us to avoid having to
  58. // special case all kinds of complicated arcane formats.
  59. if (Header->VersionHeader < PdbDbiV70)
  60. return make_error<RawError>(raw_error_code::feature_unsupported,
  61. "Unsupported DBI version.");
  62. if (Stream->getLength() !=
  63. sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
  64. Header->SecContrSubstreamSize + Header->SectionMapSize +
  65. Header->FileInfoSize + Header->TypeServerSize +
  66. Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
  67. return make_error<RawError>(raw_error_code::corrupt_file,
  68. "DBI Length does not equal sum of substreams.");
  69. // Only certain substreams are guaranteed to be aligned. Validate
  70. // them here.
  71. if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
  72. return make_error<RawError>(raw_error_code::corrupt_file,
  73. "DBI MODI substream not aligned.");
  74. if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
  75. return make_error<RawError>(
  76. raw_error_code::corrupt_file,
  77. "DBI section contribution substream not aligned.");
  78. if (Header->SectionMapSize % sizeof(uint32_t) != 0)
  79. return make_error<RawError>(raw_error_code::corrupt_file,
  80. "DBI section map substream not aligned.");
  81. if (Header->FileInfoSize % sizeof(uint32_t) != 0)
  82. return make_error<RawError>(raw_error_code::corrupt_file,
  83. "DBI file info substream not aligned.");
  84. if (Header->TypeServerSize % sizeof(uint32_t) != 0)
  85. return make_error<RawError>(raw_error_code::corrupt_file,
  86. "DBI type server substream not aligned.");
  87. if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
  88. return EC;
  89. if (auto EC = Reader.readSubstream(SecContrSubstream,
  90. Header->SecContrSubstreamSize))
  91. return EC;
  92. if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
  93. return EC;
  94. if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
  95. return EC;
  96. if (auto EC =
  97. Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
  98. return EC;
  99. if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
  100. return EC;
  101. if (auto EC = Reader.readArray(
  102. DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
  103. return EC;
  104. if (auto EC = Modules.initialize(ModiSubstream.StreamData,
  105. FileInfoSubstream.StreamData))
  106. return EC;
  107. if (auto EC = initializeSectionContributionData())
  108. return EC;
  109. if (auto EC = initializeSectionHeadersData(Pdb))
  110. return EC;
  111. if (auto EC = initializeSectionMapData())
  112. return EC;
  113. if (auto EC = initializeOldFpoRecords(Pdb))
  114. return EC;
  115. if (auto EC = initializeNewFpoRecords(Pdb))
  116. return EC;
  117. if (Reader.bytesRemaining() > 0)
  118. return make_error<RawError>(raw_error_code::corrupt_file,
  119. "Found unexpected bytes in DBI Stream.");
  120. if (!ECSubstream.empty()) {
  121. BinaryStreamReader ECReader(ECSubstream.StreamData);
  122. if (auto EC = ECNames.reload(ECReader))
  123. return EC;
  124. }
  125. return Error::success();
  126. }
  127. PdbRaw_DbiVer DbiStream::getDbiVersion() const {
  128. uint32_t Value = Header->VersionHeader;
  129. return static_cast<PdbRaw_DbiVer>(Value);
  130. }
  131. uint32_t DbiStream::getAge() const { return Header->Age; }
  132. uint16_t DbiStream::getPublicSymbolStreamIndex() const {
  133. return Header->PublicSymbolStreamIndex;
  134. }
  135. uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
  136. return Header->GlobalSymbolStreamIndex;
  137. }
  138. uint16_t DbiStream::getFlags() const { return Header->Flags; }
  139. bool DbiStream::isIncrementallyLinked() const {
  140. return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
  141. }
  142. bool DbiStream::hasCTypes() const {
  143. return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
  144. }
  145. bool DbiStream::isStripped() const {
  146. return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
  147. }
  148. uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
  149. uint16_t DbiStream::getBuildMajorVersion() const {
  150. return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
  151. DbiBuildNo::BuildMajorShift;
  152. }
  153. uint16_t DbiStream::getBuildMinorVersion() const {
  154. return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
  155. DbiBuildNo::BuildMinorShift;
  156. }
  157. uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
  158. uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
  159. uint32_t DbiStream::getSymRecordStreamIndex() const {
  160. return Header->SymRecordStreamIndex;
  161. }
  162. PDB_Machine DbiStream::getMachineType() const {
  163. uint16_t Machine = Header->MachineType;
  164. return static_cast<PDB_Machine>(Machine);
  165. }
  166. FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {
  167. return SectionHeaders;
  168. }
  169. bool DbiStream::hasOldFpoRecords() const { return OldFpoStream != nullptr; }
  170. FixedStreamArray<object::FpoData> DbiStream::getOldFpoRecords() const {
  171. return OldFpoRecords;
  172. }
  173. bool DbiStream::hasNewFpoRecords() const { return NewFpoStream != nullptr; }
  174. const DebugFrameDataSubsectionRef &DbiStream::getNewFpoRecords() const {
  175. return NewFpoRecords;
  176. }
  177. const DbiModuleList &DbiStream::modules() const { return Modules; }
  178. FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
  179. return SectionMap;
  180. }
  181. void DbiStream::visitSectionContributions(
  182. ISectionContribVisitor &Visitor) const {
  183. if (!SectionContribs.empty()) {
  184. assert(SectionContribVersion == DbiSecContribVer60);
  185. for (auto &SC : SectionContribs)
  186. Visitor.visit(SC);
  187. } else if (!SectionContribs2.empty()) {
  188. assert(SectionContribVersion == DbiSecContribV2);
  189. for (auto &SC : SectionContribs2)
  190. Visitor.visit(SC);
  191. }
  192. }
  193. Expected<StringRef> DbiStream::getECName(uint32_t NI) const {
  194. return ECNames.getStringForID(NI);
  195. }
  196. Error DbiStream::initializeSectionContributionData() {
  197. if (SecContrSubstream.empty())
  198. return Error::success();
  199. BinaryStreamReader SCReader(SecContrSubstream.StreamData);
  200. if (auto EC = SCReader.readEnum(SectionContribVersion))
  201. return EC;
  202. if (SectionContribVersion == DbiSecContribVer60)
  203. return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
  204. if (SectionContribVersion == DbiSecContribV2)
  205. return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
  206. return make_error<RawError>(raw_error_code::feature_unsupported,
  207. "Unsupported DBI Section Contribution version");
  208. }
  209. // Initializes this->SectionHeaders.
  210. Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
  211. Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
  212. createIndexedStreamForHeaderType(Pdb, DbgHeaderType::SectionHdr);
  213. if (auto EC = ExpectedStream.takeError())
  214. return EC;
  215. auto &SHS = *ExpectedStream;
  216. if (!SHS)
  217. return Error::success();
  218. size_t StreamLen = SHS->getLength();
  219. if (StreamLen % sizeof(object::coff_section))
  220. return make_error<RawError>(raw_error_code::corrupt_file,
  221. "Corrupted section header stream.");
  222. size_t NumSections = StreamLen / sizeof(object::coff_section);
  223. BinaryStreamReader Reader(*SHS);
  224. if (auto EC = Reader.readArray(SectionHeaders, NumSections))
  225. return make_error<RawError>(raw_error_code::corrupt_file,
  226. "Could not read a bitmap.");
  227. SectionHeaderStream = std::move(SHS);
  228. return Error::success();
  229. }
  230. // Initializes this->Fpos.
  231. Error DbiStream::initializeOldFpoRecords(PDBFile *Pdb) {
  232. Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
  233. createIndexedStreamForHeaderType(Pdb, DbgHeaderType::FPO);
  234. if (auto EC = ExpectedStream.takeError())
  235. return EC;
  236. auto &FS = *ExpectedStream;
  237. if (!FS)
  238. return Error::success();
  239. size_t StreamLen = FS->getLength();
  240. if (StreamLen % sizeof(object::FpoData))
  241. return make_error<RawError>(raw_error_code::corrupt_file,
  242. "Corrupted Old FPO stream.");
  243. size_t NumRecords = StreamLen / sizeof(object::FpoData);
  244. BinaryStreamReader Reader(*FS);
  245. if (auto EC = Reader.readArray(OldFpoRecords, NumRecords))
  246. return make_error<RawError>(raw_error_code::corrupt_file,
  247. "Corrupted Old FPO stream.");
  248. OldFpoStream = std::move(FS);
  249. return Error::success();
  250. }
  251. Error DbiStream::initializeNewFpoRecords(PDBFile *Pdb) {
  252. Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
  253. createIndexedStreamForHeaderType(Pdb, DbgHeaderType::NewFPO);
  254. if (auto EC = ExpectedStream.takeError())
  255. return EC;
  256. auto &FS = *ExpectedStream;
  257. if (!FS)
  258. return Error::success();
  259. if (auto EC = NewFpoRecords.initialize(*FS))
  260. return EC;
  261. NewFpoStream = std::move(FS);
  262. return Error::success();
  263. }
  264. Expected<std::unique_ptr<msf::MappedBlockStream>>
  265. DbiStream::createIndexedStreamForHeaderType(PDBFile *Pdb,
  266. DbgHeaderType Type) const {
  267. if (!Pdb)
  268. return nullptr;
  269. if (DbgStreams.empty())
  270. return nullptr;
  271. uint32_t StreamNum = getDebugStreamIndex(Type);
  272. // This means there is no such stream.
  273. if (StreamNum == kInvalidStreamIndex)
  274. return nullptr;
  275. return Pdb->safelyCreateIndexedStream(StreamNum);
  276. }
  277. BinarySubstreamRef DbiStream::getSectionContributionData() const {
  278. return SecContrSubstream;
  279. }
  280. BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {
  281. return SecMapSubstream;
  282. }
  283. BinarySubstreamRef DbiStream::getModiSubstreamData() const {
  284. return ModiSubstream;
  285. }
  286. BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {
  287. return FileInfoSubstream;
  288. }
  289. BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {
  290. return TypeServerMapSubstream;
  291. }
  292. BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
  293. Error DbiStream::initializeSectionMapData() {
  294. if (SecMapSubstream.empty())
  295. return Error::success();
  296. BinaryStreamReader SMReader(SecMapSubstream.StreamData);
  297. const SecMapHeader *Header;
  298. if (auto EC = SMReader.readObject(Header))
  299. return EC;
  300. if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
  301. return EC;
  302. return Error::success();
  303. }
  304. uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
  305. uint16_t T = static_cast<uint16_t>(Type);
  306. if (T >= DbgStreams.size())
  307. return kInvalidStreamIndex;
  308. return DbgStreams[T];
  309. }