CodeViewYAMLDebugSections.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  1. //===- CodeViewYAMLDebugSections.cpp - CodeView YAMLIO debug sections -----===//
  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. //
  9. // This file defines classes for handling the YAML representation of CodeView
  10. // Debug Info.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
  14. #include "llvm/ADT/STLExtras.h"
  15. #include "llvm/ADT/StringExtras.h"
  16. #include "llvm/ADT/StringRef.h"
  17. #include "llvm/BinaryFormat/COFF.h"
  18. #include "llvm/DebugInfo/CodeView/CodeView.h"
  19. #include "llvm/DebugInfo/CodeView/CodeViewError.h"
  20. #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
  21. #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
  22. #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
  23. #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
  24. #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
  25. #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
  26. #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
  27. #include "llvm/DebugInfo/CodeView/DebugSubsection.h"
  28. #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
  29. #include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h"
  30. #include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
  31. #include "llvm/DebugInfo/CodeView/Line.h"
  32. #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
  33. #include "llvm/DebugInfo/CodeView/TypeIndex.h"
  34. #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
  35. #include "llvm/Support/Allocator.h"
  36. #include "llvm/Support/BinaryStreamReader.h"
  37. #include "llvm/Support/Endian.h"
  38. #include "llvm/Support/Error.h"
  39. #include "llvm/Support/ErrorHandling.h"
  40. #include "llvm/Support/YAMLTraits.h"
  41. #include "llvm/Support/raw_ostream.h"
  42. #include <algorithm>
  43. #include <cassert>
  44. #include <cstdint>
  45. #include <memory>
  46. #include <string>
  47. #include <tuple>
  48. #include <vector>
  49. using namespace llvm;
  50. using namespace llvm::codeview;
  51. using namespace llvm::CodeViewYAML;
  52. using namespace llvm::CodeViewYAML::detail;
  53. using namespace llvm::yaml;
  54. LLVM_YAML_IS_SEQUENCE_VECTOR(SourceFileChecksumEntry)
  55. LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineEntry)
  56. LLVM_YAML_IS_SEQUENCE_VECTOR(SourceColumnEntry)
  57. LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock)
  58. LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo)
  59. LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite)
  60. LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo)
  61. LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport)
  62. LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport)
  63. LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLFrameData)
  64. LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, QuotingType::None)
  65. LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind)
  66. LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind)
  67. LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags)
  68. LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport)
  69. LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLFrameData)
  70. LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport)
  71. LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem)
  72. LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry)
  73. LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry)
  74. LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry)
  75. LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock)
  76. LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite)
  77. namespace llvm {
  78. namespace CodeViewYAML {
  79. namespace detail {
  80. struct YAMLSubsectionBase {
  81. explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {}
  82. virtual ~YAMLSubsectionBase() = default;
  83. virtual void map(IO &IO) = 0;
  84. virtual std::shared_ptr<DebugSubsection>
  85. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  86. const codeview::StringsAndChecksums &SC) const = 0;
  87. DebugSubsectionKind Kind;
  88. };
  89. } // end namespace detail
  90. } // end namespace CodeViewYAML
  91. } // end namespace llvm
  92. namespace {
  93. struct YAMLChecksumsSubsection : public YAMLSubsectionBase {
  94. YAMLChecksumsSubsection()
  95. : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {}
  96. void map(IO &IO) override;
  97. std::shared_ptr<DebugSubsection>
  98. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  99. const codeview::StringsAndChecksums &SC) const override;
  100. static Expected<std::shared_ptr<YAMLChecksumsSubsection>>
  101. fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
  102. const DebugChecksumsSubsectionRef &FC);
  103. std::vector<SourceFileChecksumEntry> Checksums;
  104. };
  105. struct YAMLLinesSubsection : public YAMLSubsectionBase {
  106. YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {}
  107. void map(IO &IO) override;
  108. std::shared_ptr<DebugSubsection>
  109. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  110. const codeview::StringsAndChecksums &SC) const override;
  111. static Expected<std::shared_ptr<YAMLLinesSubsection>>
  112. fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
  113. const DebugChecksumsSubsectionRef &Checksums,
  114. const DebugLinesSubsectionRef &Lines);
  115. SourceLineInfo Lines;
  116. };
  117. struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase {
  118. YAMLInlineeLinesSubsection()
  119. : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {}
  120. void map(IO &IO) override;
  121. std::shared_ptr<DebugSubsection>
  122. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  123. const codeview::StringsAndChecksums &SC) const override;
  124. static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
  125. fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
  126. const DebugChecksumsSubsectionRef &Checksums,
  127. const DebugInlineeLinesSubsectionRef &Lines);
  128. InlineeInfo InlineeLines;
  129. };
  130. struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase {
  131. YAMLCrossModuleExportsSubsection()
  132. : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {}
  133. void map(IO &IO) override;
  134. std::shared_ptr<DebugSubsection>
  135. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  136. const codeview::StringsAndChecksums &SC) const override;
  137. static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
  138. fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
  139. std::vector<CrossModuleExport> Exports;
  140. };
  141. struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase {
  142. YAMLCrossModuleImportsSubsection()
  143. : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {}
  144. void map(IO &IO) override;
  145. std::shared_ptr<DebugSubsection>
  146. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  147. const codeview::StringsAndChecksums &SC) const override;
  148. static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
  149. fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
  150. const DebugCrossModuleImportsSubsectionRef &Imports);
  151. std::vector<YAMLCrossModuleImport> Imports;
  152. };
  153. struct YAMLSymbolsSubsection : public YAMLSubsectionBase {
  154. YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {}
  155. void map(IO &IO) override;
  156. std::shared_ptr<DebugSubsection>
  157. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  158. const codeview::StringsAndChecksums &SC) const override;
  159. static Expected<std::shared_ptr<YAMLSymbolsSubsection>>
  160. fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols);
  161. std::vector<CodeViewYAML::SymbolRecord> Symbols;
  162. };
  163. struct YAMLStringTableSubsection : public YAMLSubsectionBase {
  164. YAMLStringTableSubsection()
  165. : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {}
  166. void map(IO &IO) override;
  167. std::shared_ptr<DebugSubsection>
  168. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  169. const codeview::StringsAndChecksums &SC) const override;
  170. static Expected<std::shared_ptr<YAMLStringTableSubsection>>
  171. fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings);
  172. std::vector<StringRef> Strings;
  173. };
  174. struct YAMLFrameDataSubsection : public YAMLSubsectionBase {
  175. YAMLFrameDataSubsection()
  176. : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {}
  177. void map(IO &IO) override;
  178. std::shared_ptr<DebugSubsection>
  179. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  180. const codeview::StringsAndChecksums &SC) const override;
  181. static Expected<std::shared_ptr<YAMLFrameDataSubsection>>
  182. fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
  183. const DebugFrameDataSubsectionRef &Frames);
  184. std::vector<YAMLFrameData> Frames;
  185. };
  186. struct YAMLCoffSymbolRVASubsection : public YAMLSubsectionBase {
  187. YAMLCoffSymbolRVASubsection()
  188. : YAMLSubsectionBase(DebugSubsectionKind::CoffSymbolRVA) {}
  189. void map(IO &IO) override;
  190. std::shared_ptr<DebugSubsection>
  191. toCodeViewSubsection(BumpPtrAllocator &Allocator,
  192. const codeview::StringsAndChecksums &SC) const override;
  193. static Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>>
  194. fromCodeViewSubsection(const DebugSymbolRVASubsectionRef &RVAs);
  195. std::vector<uint32_t> RVAs;
  196. };
  197. } // end anonymous namespace
  198. void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) {
  199. io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns);
  200. io.enumFallback<Hex16>(Flags);
  201. }
  202. void ScalarEnumerationTraits<FileChecksumKind>::enumeration(
  203. IO &io, FileChecksumKind &Kind) {
  204. io.enumCase(Kind, "None", FileChecksumKind::None);
  205. io.enumCase(Kind, "MD5", FileChecksumKind::MD5);
  206. io.enumCase(Kind, "SHA1", FileChecksumKind::SHA1);
  207. io.enumCase(Kind, "SHA256", FileChecksumKind::SHA256);
  208. }
  209. void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value,
  210. void *ctx, raw_ostream &Out) {
  211. StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()),
  212. Value.Bytes.size());
  213. Out << toHex(Bytes);
  214. }
  215. StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt,
  216. HexFormattedString &Value) {
  217. std::string H = fromHex(Scalar);
  218. Value.Bytes.assign(H.begin(), H.end());
  219. return StringRef();
  220. }
  221. void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) {
  222. IO.mapRequired("Offset", Obj.Offset);
  223. IO.mapRequired("LineStart", Obj.LineStart);
  224. IO.mapRequired("IsStatement", Obj.IsStatement);
  225. IO.mapRequired("EndDelta", Obj.EndDelta);
  226. }
  227. void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) {
  228. IO.mapRequired("StartColumn", Obj.StartColumn);
  229. IO.mapRequired("EndColumn", Obj.EndColumn);
  230. }
  231. void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) {
  232. IO.mapRequired("FileName", Obj.FileName);
  233. IO.mapRequired("Lines", Obj.Lines);
  234. IO.mapRequired("Columns", Obj.Columns);
  235. }
  236. void MappingTraits<CrossModuleExport>::mapping(IO &IO, CrossModuleExport &Obj) {
  237. IO.mapRequired("LocalId", Obj.Local);
  238. IO.mapRequired("GlobalId", Obj.Global);
  239. }
  240. void MappingTraits<YAMLCrossModuleImport>::mapping(IO &IO,
  241. YAMLCrossModuleImport &Obj) {
  242. IO.mapRequired("Module", Obj.ModuleName);
  243. IO.mapRequired("Imports", Obj.ImportIds);
  244. }
  245. void MappingTraits<SourceFileChecksumEntry>::mapping(
  246. IO &IO, SourceFileChecksumEntry &Obj) {
  247. IO.mapRequired("FileName", Obj.FileName);
  248. IO.mapRequired("Kind", Obj.Kind);
  249. IO.mapRequired("Checksum", Obj.ChecksumBytes);
  250. }
  251. void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) {
  252. IO.mapRequired("FileName", Obj.FileName);
  253. IO.mapRequired("LineNum", Obj.SourceLineNum);
  254. IO.mapRequired("Inlinee", Obj.Inlinee);
  255. IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
  256. }
  257. void MappingTraits<YAMLFrameData>::mapping(IO &IO, YAMLFrameData &Obj) {
  258. IO.mapRequired("CodeSize", Obj.CodeSize);
  259. IO.mapRequired("FrameFunc", Obj.FrameFunc);
  260. IO.mapRequired("LocalSize", Obj.LocalSize);
  261. IO.mapOptional("MaxStackSize", Obj.MaxStackSize);
  262. IO.mapOptional("ParamsSize", Obj.ParamsSize);
  263. IO.mapOptional("PrologSize", Obj.PrologSize);
  264. IO.mapOptional("RvaStart", Obj.RvaStart);
  265. IO.mapOptional("SavedRegsSize", Obj.SavedRegsSize);
  266. }
  267. void YAMLChecksumsSubsection::map(IO &IO) {
  268. IO.mapTag("!FileChecksums", true);
  269. IO.mapRequired("Checksums", Checksums);
  270. }
  271. void YAMLLinesSubsection::map(IO &IO) {
  272. IO.mapTag("!Lines", true);
  273. IO.mapRequired("CodeSize", Lines.CodeSize);
  274. IO.mapRequired("Flags", Lines.Flags);
  275. IO.mapRequired("RelocOffset", Lines.RelocOffset);
  276. IO.mapRequired("RelocSegment", Lines.RelocSegment);
  277. IO.mapRequired("Blocks", Lines.Blocks);
  278. }
  279. void YAMLInlineeLinesSubsection::map(IO &IO) {
  280. IO.mapTag("!InlineeLines", true);
  281. IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles);
  282. IO.mapRequired("Sites", InlineeLines.Sites);
  283. }
  284. void YAMLCrossModuleExportsSubsection::map(IO &IO) {
  285. IO.mapTag("!CrossModuleExports", true);
  286. IO.mapOptional("Exports", Exports);
  287. }
  288. void YAMLCrossModuleImportsSubsection::map(IO &IO) {
  289. IO.mapTag("!CrossModuleImports", true);
  290. IO.mapOptional("Imports", Imports);
  291. }
  292. void YAMLSymbolsSubsection::map(IO &IO) {
  293. IO.mapTag("!Symbols", true);
  294. IO.mapRequired("Records", Symbols);
  295. }
  296. void YAMLStringTableSubsection::map(IO &IO) {
  297. IO.mapTag("!StringTable", true);
  298. IO.mapRequired("Strings", Strings);
  299. }
  300. void YAMLFrameDataSubsection::map(IO &IO) {
  301. IO.mapTag("!FrameData", true);
  302. IO.mapRequired("Frames", Frames);
  303. }
  304. void YAMLCoffSymbolRVASubsection::map(IO &IO) {
  305. IO.mapTag("!COFFSymbolRVAs", true);
  306. IO.mapRequired("RVAs", RVAs);
  307. }
  308. void MappingTraits<YAMLDebugSubsection>::mapping(
  309. IO &IO, YAMLDebugSubsection &Subsection) {
  310. if (!IO.outputting()) {
  311. if (IO.mapTag("!FileChecksums")) {
  312. auto SS = std::make_shared<YAMLChecksumsSubsection>();
  313. Subsection.Subsection = SS;
  314. } else if (IO.mapTag("!Lines")) {
  315. Subsection.Subsection = std::make_shared<YAMLLinesSubsection>();
  316. } else if (IO.mapTag("!InlineeLines")) {
  317. Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>();
  318. } else if (IO.mapTag("!CrossModuleExports")) {
  319. Subsection.Subsection =
  320. std::make_shared<YAMLCrossModuleExportsSubsection>();
  321. } else if (IO.mapTag("!CrossModuleImports")) {
  322. Subsection.Subsection =
  323. std::make_shared<YAMLCrossModuleImportsSubsection>();
  324. } else if (IO.mapTag("!Symbols")) {
  325. Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>();
  326. } else if (IO.mapTag("!StringTable")) {
  327. Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>();
  328. } else if (IO.mapTag("!FrameData")) {
  329. Subsection.Subsection = std::make_shared<YAMLFrameDataSubsection>();
  330. } else if (IO.mapTag("!COFFSymbolRVAs")) {
  331. Subsection.Subsection = std::make_shared<YAMLCoffSymbolRVASubsection>();
  332. } else {
  333. llvm_unreachable("Unexpected subsection tag!");
  334. }
  335. }
  336. Subsection.Subsection->map(IO);
  337. }
  338. std::shared_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
  339. BumpPtrAllocator &Allocator,
  340. const codeview::StringsAndChecksums &SC) const {
  341. assert(SC.hasStrings());
  342. auto Result = std::make_shared<DebugChecksumsSubsection>(*SC.strings());
  343. for (const auto &CS : Checksums) {
  344. Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
  345. }
  346. return Result;
  347. }
  348. std::shared_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
  349. BumpPtrAllocator &Allocator,
  350. const codeview::StringsAndChecksums &SC) const {
  351. assert(SC.hasStrings() && SC.hasChecksums());
  352. auto Result =
  353. std::make_shared<DebugLinesSubsection>(*SC.checksums(), *SC.strings());
  354. Result->setCodeSize(Lines.CodeSize);
  355. Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
  356. Result->setFlags(Lines.Flags);
  357. for (const auto &LC : Lines.Blocks) {
  358. Result->createBlock(LC.FileName);
  359. if (Result->hasColumnInfo()) {
  360. for (auto Item : zip(LC.Lines, LC.Columns)) {
  361. auto &L = std::get<0>(Item);
  362. auto &C = std::get<1>(Item);
  363. uint32_t LE = L.LineStart + L.EndDelta;
  364. Result->addLineAndColumnInfo(L.Offset,
  365. LineInfo(L.LineStart, LE, L.IsStatement),
  366. C.StartColumn, C.EndColumn);
  367. }
  368. } else {
  369. for (const auto &L : LC.Lines) {
  370. uint32_t LE = L.LineStart + L.EndDelta;
  371. Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement));
  372. }
  373. }
  374. }
  375. return Result;
  376. }
  377. std::shared_ptr<DebugSubsection>
  378. YAMLInlineeLinesSubsection::toCodeViewSubsection(
  379. BumpPtrAllocator &Allocator,
  380. const codeview::StringsAndChecksums &SC) const {
  381. assert(SC.hasChecksums());
  382. auto Result = std::make_shared<DebugInlineeLinesSubsection>(
  383. *SC.checksums(), InlineeLines.HasExtraFiles);
  384. for (const auto &Site : InlineeLines.Sites) {
  385. Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
  386. Site.SourceLineNum);
  387. if (!InlineeLines.HasExtraFiles)
  388. continue;
  389. for (auto EF : Site.ExtraFiles) {
  390. Result->addExtraFile(EF);
  391. }
  392. }
  393. return Result;
  394. }
  395. std::shared_ptr<DebugSubsection>
  396. YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
  397. BumpPtrAllocator &Allocator,
  398. const codeview::StringsAndChecksums &SC) const {
  399. auto Result = std::make_shared<DebugCrossModuleExportsSubsection>();
  400. for (const auto &M : Exports)
  401. Result->addMapping(M.Local, M.Global);
  402. return Result;
  403. }
  404. std::shared_ptr<DebugSubsection>
  405. YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
  406. BumpPtrAllocator &Allocator,
  407. const codeview::StringsAndChecksums &SC) const {
  408. assert(SC.hasStrings());
  409. auto Result =
  410. std::make_shared<DebugCrossModuleImportsSubsection>(*SC.strings());
  411. for (const auto &M : Imports) {
  412. for (const auto Id : M.ImportIds)
  413. Result->addImport(M.ModuleName, Id);
  414. }
  415. return Result;
  416. }
  417. std::shared_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection(
  418. BumpPtrAllocator &Allocator,
  419. const codeview::StringsAndChecksums &SC) const {
  420. auto Result = std::make_shared<DebugSymbolsSubsection>();
  421. for (const auto &Sym : Symbols)
  422. Result->addSymbol(
  423. Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
  424. return Result;
  425. }
  426. std::shared_ptr<DebugSubsection>
  427. YAMLStringTableSubsection::toCodeViewSubsection(
  428. BumpPtrAllocator &Allocator,
  429. const codeview::StringsAndChecksums &SC) const {
  430. auto Result = std::make_shared<DebugStringTableSubsection>();
  431. for (const auto &Str : this->Strings)
  432. Result->insert(Str);
  433. return Result;
  434. }
  435. std::shared_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
  436. BumpPtrAllocator &Allocator,
  437. const codeview::StringsAndChecksums &SC) const {
  438. assert(SC.hasStrings());
  439. auto Result = std::make_shared<DebugFrameDataSubsection>(true);
  440. for (const auto &YF : Frames) {
  441. codeview::FrameData F;
  442. F.CodeSize = YF.CodeSize;
  443. F.Flags = YF.Flags;
  444. F.LocalSize = YF.LocalSize;
  445. F.MaxStackSize = YF.MaxStackSize;
  446. F.ParamsSize = YF.ParamsSize;
  447. F.PrologSize = YF.PrologSize;
  448. F.RvaStart = YF.RvaStart;
  449. F.SavedRegsSize = YF.SavedRegsSize;
  450. F.FrameFunc = SC.strings()->insert(YF.FrameFunc);
  451. Result->addFrameData(F);
  452. }
  453. return Result;
  454. }
  455. std::shared_ptr<DebugSubsection>
  456. YAMLCoffSymbolRVASubsection::toCodeViewSubsection(
  457. BumpPtrAllocator &Allocator,
  458. const codeview::StringsAndChecksums &SC) const {
  459. auto Result = std::make_shared<DebugSymbolRVASubsection>();
  460. for (const auto &RVA : RVAs)
  461. Result->addRVA(RVA);
  462. return Result;
  463. }
  464. static Expected<SourceFileChecksumEntry>
  465. convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
  466. const FileChecksumEntry &CS) {
  467. auto ExpectedString = Strings.getString(CS.FileNameOffset);
  468. if (!ExpectedString)
  469. return ExpectedString.takeError();
  470. SourceFileChecksumEntry Result;
  471. Result.ChecksumBytes.Bytes = CS.Checksum;
  472. Result.Kind = CS.Kind;
  473. Result.FileName = *ExpectedString;
  474. return Result;
  475. }
  476. static Expected<StringRef>
  477. getFileName(const DebugStringTableSubsectionRef &Strings,
  478. const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
  479. auto Iter = Checksums.getArray().at(FileID);
  480. if (Iter == Checksums.getArray().end())
  481. return make_error<CodeViewError>(cv_error_code::no_records);
  482. uint32_t Offset = Iter->FileNameOffset;
  483. return Strings.getString(Offset);
  484. }
  485. Expected<std::shared_ptr<YAMLChecksumsSubsection>>
  486. YAMLChecksumsSubsection::fromCodeViewSubsection(
  487. const DebugStringTableSubsectionRef &Strings,
  488. const DebugChecksumsSubsectionRef &FC) {
  489. auto Result = std::make_shared<YAMLChecksumsSubsection>();
  490. for (const auto &CS : FC) {
  491. auto ConvertedCS = convertOneChecksum(Strings, CS);
  492. if (!ConvertedCS)
  493. return ConvertedCS.takeError();
  494. Result->Checksums.push_back(*ConvertedCS);
  495. }
  496. return Result;
  497. }
  498. Expected<std::shared_ptr<YAMLLinesSubsection>>
  499. YAMLLinesSubsection::fromCodeViewSubsection(
  500. const DebugStringTableSubsectionRef &Strings,
  501. const DebugChecksumsSubsectionRef &Checksums,
  502. const DebugLinesSubsectionRef &Lines) {
  503. auto Result = std::make_shared<YAMLLinesSubsection>();
  504. Result->Lines.CodeSize = Lines.header()->CodeSize;
  505. Result->Lines.RelocOffset = Lines.header()->RelocOffset;
  506. Result->Lines.RelocSegment = Lines.header()->RelocSegment;
  507. Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags));
  508. for (const auto &L : Lines) {
  509. SourceLineBlock Block;
  510. auto EF = getFileName(Strings, Checksums, L.NameIndex);
  511. if (!EF)
  512. return EF.takeError();
  513. Block.FileName = *EF;
  514. if (Lines.hasColumnInfo()) {
  515. for (const auto &C : L.Columns) {
  516. SourceColumnEntry SCE;
  517. SCE.EndColumn = C.EndColumn;
  518. SCE.StartColumn = C.StartColumn;
  519. Block.Columns.push_back(SCE);
  520. }
  521. }
  522. for (const auto &LN : L.LineNumbers) {
  523. SourceLineEntry SLE;
  524. LineInfo LI(LN.Flags);
  525. SLE.Offset = LN.Offset;
  526. SLE.LineStart = LI.getStartLine();
  527. SLE.EndDelta = LI.getLineDelta();
  528. SLE.IsStatement = LI.isStatement();
  529. Block.Lines.push_back(SLE);
  530. }
  531. Result->Lines.Blocks.push_back(Block);
  532. }
  533. return Result;
  534. }
  535. Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
  536. YAMLInlineeLinesSubsection::fromCodeViewSubsection(
  537. const DebugStringTableSubsectionRef &Strings,
  538. const DebugChecksumsSubsectionRef &Checksums,
  539. const DebugInlineeLinesSubsectionRef &Lines) {
  540. auto Result = std::make_shared<YAMLInlineeLinesSubsection>();
  541. Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles();
  542. for (const auto &IL : Lines) {
  543. InlineeSite Site;
  544. auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID);
  545. if (!ExpF)
  546. return ExpF.takeError();
  547. Site.FileName = *ExpF;
  548. Site.Inlinee = IL.Header->Inlinee.getIndex();
  549. Site.SourceLineNum = IL.Header->SourceLineNum;
  550. if (Lines.hasExtraFiles()) {
  551. for (const auto EF : IL.ExtraFiles) {
  552. auto ExpF2 = getFileName(Strings, Checksums, EF);
  553. if (!ExpF2)
  554. return ExpF2.takeError();
  555. Site.ExtraFiles.push_back(*ExpF2);
  556. }
  557. }
  558. Result->InlineeLines.Sites.push_back(Site);
  559. }
  560. return Result;
  561. }
  562. Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
  563. YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(
  564. const DebugCrossModuleExportsSubsectionRef &Exports) {
  565. auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>();
  566. Result->Exports.assign(Exports.begin(), Exports.end());
  567. return Result;
  568. }
  569. Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
  570. YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
  571. const DebugStringTableSubsectionRef &Strings,
  572. const DebugCrossModuleImportsSubsectionRef &Imports) {
  573. auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>();
  574. for (const auto &CMI : Imports) {
  575. YAMLCrossModuleImport YCMI;
  576. auto ExpectedStr = Strings.getString(CMI.Header->ModuleNameOffset);
  577. if (!ExpectedStr)
  578. return ExpectedStr.takeError();
  579. YCMI.ModuleName = *ExpectedStr;
  580. YCMI.ImportIds.assign(CMI.Imports.begin(), CMI.Imports.end());
  581. Result->Imports.push_back(YCMI);
  582. }
  583. return Result;
  584. }
  585. Expected<std::shared_ptr<YAMLSymbolsSubsection>>
  586. YAMLSymbolsSubsection::fromCodeViewSubsection(
  587. const DebugSymbolsSubsectionRef &Symbols) {
  588. auto Result = std::make_shared<YAMLSymbolsSubsection>();
  589. for (const auto &Sym : Symbols) {
  590. auto S = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym);
  591. if (!S)
  592. return joinErrors(make_error<CodeViewError>(
  593. cv_error_code::corrupt_record,
  594. "Invalid CodeView Symbol Record in SymbolRecord "
  595. "subsection of .debug$S while converting to YAML!"),
  596. S.takeError());
  597. Result->Symbols.push_back(*S);
  598. }
  599. return Result;
  600. }
  601. Expected<std::shared_ptr<YAMLStringTableSubsection>>
  602. YAMLStringTableSubsection::fromCodeViewSubsection(
  603. const DebugStringTableSubsectionRef &Strings) {
  604. auto Result = std::make_shared<YAMLStringTableSubsection>();
  605. BinaryStreamReader Reader(Strings.getBuffer());
  606. StringRef S;
  607. // First item is a single null string, skip it.
  608. if (auto EC = Reader.readCString(S))
  609. return std::move(EC);
  610. assert(S.empty());
  611. while (Reader.bytesRemaining() > 0) {
  612. if (auto EC = Reader.readCString(S))
  613. return std::move(EC);
  614. Result->Strings.push_back(S);
  615. }
  616. return Result;
  617. }
  618. Expected<std::shared_ptr<YAMLFrameDataSubsection>>
  619. YAMLFrameDataSubsection::fromCodeViewSubsection(
  620. const DebugStringTableSubsectionRef &Strings,
  621. const DebugFrameDataSubsectionRef &Frames) {
  622. auto Result = std::make_shared<YAMLFrameDataSubsection>();
  623. for (const auto &F : Frames) {
  624. YAMLFrameData YF;
  625. YF.CodeSize = F.CodeSize;
  626. YF.Flags = F.Flags;
  627. YF.LocalSize = F.LocalSize;
  628. YF.MaxStackSize = F.MaxStackSize;
  629. YF.ParamsSize = F.ParamsSize;
  630. YF.PrologSize = F.PrologSize;
  631. YF.RvaStart = F.RvaStart;
  632. YF.SavedRegsSize = F.SavedRegsSize;
  633. auto ES = Strings.getString(F.FrameFunc);
  634. if (!ES)
  635. return joinErrors(
  636. make_error<CodeViewError>(
  637. cv_error_code::no_records,
  638. "Could not find string for string id while mapping FrameData!"),
  639. ES.takeError());
  640. YF.FrameFunc = *ES;
  641. Result->Frames.push_back(YF);
  642. }
  643. return Result;
  644. }
  645. Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>>
  646. YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(
  647. const DebugSymbolRVASubsectionRef &Section) {
  648. auto Result = std::make_shared<YAMLCoffSymbolRVASubsection>();
  649. for (const auto &RVA : Section) {
  650. Result->RVAs.push_back(RVA);
  651. }
  652. return Result;
  653. }
  654. Expected<std::vector<std::shared_ptr<DebugSubsection>>>
  655. llvm::CodeViewYAML::toCodeViewSubsectionList(
  656. BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
  657. const codeview::StringsAndChecksums &SC) {
  658. std::vector<std::shared_ptr<DebugSubsection>> Result;
  659. if (Subsections.empty())
  660. return std::move(Result);
  661. for (const auto &SS : Subsections) {
  662. std::shared_ptr<DebugSubsection> CVS;
  663. CVS = SS.Subsection->toCodeViewSubsection(Allocator, SC);
  664. assert(CVS != nullptr);
  665. Result.push_back(std::move(CVS));
  666. }
  667. return std::move(Result);
  668. }
  669. namespace {
  670. struct SubsectionConversionVisitor : public DebugSubsectionVisitor {
  671. SubsectionConversionVisitor() = default;
  672. Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
  673. Error visitLines(DebugLinesSubsectionRef &Lines,
  674. const StringsAndChecksumsRef &State) override;
  675. Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
  676. const StringsAndChecksumsRef &State) override;
  677. Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
  678. const StringsAndChecksumsRef &State) override;
  679. Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums,
  680. const StringsAndChecksumsRef &State) override;
  681. Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
  682. const StringsAndChecksumsRef &State) override;
  683. Error visitStringTable(DebugStringTableSubsectionRef &ST,
  684. const StringsAndChecksumsRef &State) override;
  685. Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
  686. const StringsAndChecksumsRef &State) override;
  687. Error visitFrameData(DebugFrameDataSubsectionRef &Symbols,
  688. const StringsAndChecksumsRef &State) override;
  689. Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &Symbols,
  690. const StringsAndChecksumsRef &State) override;
  691. YAMLDebugSubsection Subsection;
  692. };
  693. } // end anonymous namespace
  694. Error SubsectionConversionVisitor::visitUnknown(
  695. DebugUnknownSubsectionRef &Unknown) {
  696. return make_error<CodeViewError>(cv_error_code::operation_unsupported);
  697. }
  698. Error SubsectionConversionVisitor::visitLines(
  699. DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State) {
  700. auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
  701. State.strings(), State.checksums(), Lines);
  702. if (!Result)
  703. return Result.takeError();
  704. Subsection.Subsection = *Result;
  705. return Error::success();
  706. }
  707. Error SubsectionConversionVisitor::visitFileChecksums(
  708. DebugChecksumsSubsectionRef &Checksums,
  709. const StringsAndChecksumsRef &State) {
  710. auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
  711. Checksums);
  712. if (!Result)
  713. return Result.takeError();
  714. Subsection.Subsection = *Result;
  715. return Error::success();
  716. }
  717. Error SubsectionConversionVisitor::visitInlineeLines(
  718. DebugInlineeLinesSubsectionRef &Inlinees,
  719. const StringsAndChecksumsRef &State) {
  720. auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
  721. State.strings(), State.checksums(), Inlinees);
  722. if (!Result)
  723. return Result.takeError();
  724. Subsection.Subsection = *Result;
  725. return Error::success();
  726. }
  727. Error SubsectionConversionVisitor::visitCrossModuleExports(
  728. DebugCrossModuleExportsSubsectionRef &Exports,
  729. const StringsAndChecksumsRef &State) {
  730. auto Result =
  731. YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
  732. if (!Result)
  733. return Result.takeError();
  734. Subsection.Subsection = *Result;
  735. return Error::success();
  736. }
  737. Error SubsectionConversionVisitor::visitCrossModuleImports(
  738. DebugCrossModuleImportsSubsectionRef &Imports,
  739. const StringsAndChecksumsRef &State) {
  740. auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
  741. State.strings(), Imports);
  742. if (!Result)
  743. return Result.takeError();
  744. Subsection.Subsection = *Result;
  745. return Error::success();
  746. }
  747. Error SubsectionConversionVisitor::visitStringTable(
  748. DebugStringTableSubsectionRef &Strings,
  749. const StringsAndChecksumsRef &State) {
  750. auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
  751. if (!Result)
  752. return Result.takeError();
  753. Subsection.Subsection = *Result;
  754. return Error::success();
  755. }
  756. Error SubsectionConversionVisitor::visitSymbols(
  757. DebugSymbolsSubsectionRef &Symbols, const StringsAndChecksumsRef &State) {
  758. auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
  759. if (!Result)
  760. return Result.takeError();
  761. Subsection.Subsection = *Result;
  762. return Error::success();
  763. }
  764. Error SubsectionConversionVisitor::visitFrameData(
  765. DebugFrameDataSubsectionRef &Frames, const StringsAndChecksumsRef &State) {
  766. auto Result =
  767. YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
  768. if (!Result)
  769. return Result.takeError();
  770. Subsection.Subsection = *Result;
  771. return Error::success();
  772. }
  773. Error SubsectionConversionVisitor::visitCOFFSymbolRVAs(
  774. DebugSymbolRVASubsectionRef &RVAs, const StringsAndChecksumsRef &State) {
  775. auto Result = YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(RVAs);
  776. if (!Result)
  777. return Result.takeError();
  778. Subsection.Subsection = *Result;
  779. return Error::success();
  780. }
  781. Expected<YAMLDebugSubsection>
  782. YAMLDebugSubsection::fromCodeViewSubection(const StringsAndChecksumsRef &SC,
  783. const DebugSubsectionRecord &SS) {
  784. SubsectionConversionVisitor V;
  785. if (auto EC = visitDebugSubsection(SS, V, SC))
  786. return std::move(EC);
  787. return V.Subsection;
  788. }
  789. std::vector<YAMLDebugSubsection>
  790. llvm::CodeViewYAML::fromDebugS(ArrayRef<uint8_t> Data,
  791. const StringsAndChecksumsRef &SC) {
  792. BinaryStreamReader Reader(Data, support::little);
  793. uint32_t Magic;
  794. ExitOnError Err("Invalid .debug$S section!");
  795. Err(Reader.readInteger(Magic));
  796. assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!");
  797. DebugSubsectionArray Subsections;
  798. Err(Reader.readArray(Subsections, Reader.bytesRemaining()));
  799. std::vector<YAMLDebugSubsection> Result;
  800. for (const auto &SS : Subsections) {
  801. auto YamlSS = Err(YAMLDebugSubsection::fromCodeViewSubection(SC, SS));
  802. Result.push_back(YamlSS);
  803. }
  804. return Result;
  805. }
  806. void llvm::CodeViewYAML::initializeStringsAndChecksums(
  807. ArrayRef<YAMLDebugSubsection> Sections, codeview::StringsAndChecksums &SC) {
  808. // String Table and Checksums subsections don't use the allocator.
  809. BumpPtrAllocator Allocator;
  810. // It's possible for checksums and strings to even appear in different debug$S
  811. // sections, so we have to make this a stateful function that can build up
  812. // the strings and checksums field over multiple iterations.
  813. // File Checksums require the string table, but may become before it, so we
  814. // have to scan for strings first, then scan for checksums again from the
  815. // beginning.
  816. if (!SC.hasStrings()) {
  817. for (const auto &SS : Sections) {
  818. if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
  819. continue;
  820. auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
  821. SC.setStrings(
  822. std::static_pointer_cast<DebugStringTableSubsection>(Result));
  823. break;
  824. }
  825. }
  826. if (SC.hasStrings() && !SC.hasChecksums()) {
  827. for (const auto &SS : Sections) {
  828. if (SS.Subsection->Kind != DebugSubsectionKind::FileChecksums)
  829. continue;
  830. auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
  831. SC.setChecksums(
  832. std::static_pointer_cast<DebugChecksumsSubsection>(Result));
  833. break;
  834. }
  835. }
  836. }