1 //===- CodeViewYAMLDebugSections.cpp - CodeView YAMLIO debug sections -----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines classes for handling the YAML representation of CodeView 11 // Debug Info. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" 16 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/ADT/StringSwitch.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/DebugInlineeLinesSubsection.h" 24 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 25 #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" 26 #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" 27 #include "llvm/DebugInfo/CodeView/EnumTables.h" 28 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 29 30 using namespace llvm; 31 using namespace llvm::codeview; 32 using namespace llvm::CodeViewYAML; 33 using namespace llvm::CodeViewYAML::detail; 34 using namespace llvm::yaml; 35 36 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceFileChecksumEntry) 37 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineEntry) 38 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceColumnEntry) 39 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineBlock) 40 LLVM_YAML_IS_SEQUENCE_VECTOR(SourceLineInfo) 41 LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeSite) 42 LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo) 43 LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport) 44 LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport) 45 LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef) 46 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t) 47 48 LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false) 49 LLVM_YAML_DECLARE_ENUM_TRAITS(DebugSubsectionKind) 50 LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind) 51 LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags) 52 53 LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport) 54 LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport) 55 LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem) 56 LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry) 57 LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceColumnEntry) 58 LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceFileChecksumEntry) 59 LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineBlock) 60 LLVM_YAML_DECLARE_MAPPING_TRAITS(InlineeSite) 61 62 namespace llvm { 63 namespace CodeViewYAML { 64 namespace detail { 65 struct YAMLSubsectionBase { 66 explicit YAMLSubsectionBase(DebugSubsectionKind Kind) : Kind(Kind) {} 67 DebugSubsectionKind Kind; 68 virtual ~YAMLSubsectionBase() {} 69 70 virtual void map(IO &IO) = 0; 71 virtual std::unique_ptr<DebugSubsection> 72 toCodeViewSubsection(DebugStringTableSubsection *UseStrings, 73 DebugChecksumsSubsection *UseChecksums) const = 0; 74 }; 75 } 76 } 77 } 78 79 namespace { 80 struct YAMLChecksumsSubsection : public YAMLSubsectionBase { 81 YAMLChecksumsSubsection() 82 : YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {} 83 84 void map(IO &IO) override; 85 std::unique_ptr<DebugSubsection> 86 toCodeViewSubsection(DebugStringTableSubsection *Strings, 87 DebugChecksumsSubsection *Checksums) const override; 88 static Expected<std::shared_ptr<YAMLChecksumsSubsection>> 89 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, 90 const DebugChecksumsSubsectionRef &FC); 91 92 std::vector<SourceFileChecksumEntry> Checksums; 93 }; 94 95 struct YAMLLinesSubsection : public YAMLSubsectionBase { 96 YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {} 97 98 void map(IO &IO) override; 99 std::unique_ptr<DebugSubsection> 100 toCodeViewSubsection(DebugStringTableSubsection *Strings, 101 DebugChecksumsSubsection *Checksums) const override; 102 static Expected<std::shared_ptr<YAMLLinesSubsection>> 103 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, 104 const DebugChecksumsSubsectionRef &Checksums, 105 const DebugLinesSubsectionRef &Lines); 106 107 SourceLineInfo Lines; 108 }; 109 110 struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase { 111 YAMLInlineeLinesSubsection() 112 : YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {} 113 114 void map(IO &IO) override; 115 std::unique_ptr<DebugSubsection> 116 toCodeViewSubsection(DebugStringTableSubsection *Strings, 117 DebugChecksumsSubsection *Checksums) const override; 118 static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>> 119 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, 120 const DebugChecksumsSubsectionRef &Checksums, 121 const DebugInlineeLinesSubsectionRef &Lines); 122 123 InlineeInfo InlineeLines; 124 }; 125 126 struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase { 127 YAMLCrossModuleExportsSubsection() 128 : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {} 129 130 void map(IO &IO) override; 131 std::unique_ptr<DebugSubsection> 132 toCodeViewSubsection(DebugStringTableSubsection *Strings, 133 DebugChecksumsSubsection *Checksums) const override; 134 static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>> 135 fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports); 136 137 std::vector<CrossModuleExport> Exports; 138 }; 139 140 struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase { 141 YAMLCrossModuleImportsSubsection() 142 : YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {} 143 144 void map(IO &IO) override; 145 std::unique_ptr<DebugSubsection> 146 toCodeViewSubsection(DebugStringTableSubsection *Strings, 147 DebugChecksumsSubsection *Checksums) const override; 148 static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>> 149 fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, 150 const DebugCrossModuleImportsSubsectionRef &Imports); 151 152 std::vector<YAMLCrossModuleImport> Imports; 153 }; 154 } 155 156 void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) { 157 io.bitSetCase(Flags, "HasColumnInfo", LF_HaveColumns); 158 io.enumFallback<Hex16>(Flags); 159 } 160 161 void ScalarEnumerationTraits<FileChecksumKind>::enumeration( 162 IO &io, FileChecksumKind &Kind) { 163 io.enumCase(Kind, "None", FileChecksumKind::None); 164 io.enumCase(Kind, "MD5", FileChecksumKind::MD5); 165 io.enumCase(Kind, "SHA1", FileChecksumKind::SHA1); 166 io.enumCase(Kind, "SHA256", FileChecksumKind::SHA256); 167 } 168 169 void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value, 170 void *ctx, raw_ostream &Out) { 171 StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()), 172 Value.Bytes.size()); 173 Out << toHex(Bytes); 174 } 175 176 StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt, 177 HexFormattedString &Value) { 178 std::string H = fromHex(Scalar); 179 Value.Bytes.assign(H.begin(), H.end()); 180 return StringRef(); 181 } 182 183 void MappingTraits<SourceLineEntry>::mapping(IO &IO, SourceLineEntry &Obj) { 184 IO.mapRequired("Offset", Obj.Offset); 185 IO.mapRequired("LineStart", Obj.LineStart); 186 IO.mapRequired("IsStatement", Obj.IsStatement); 187 IO.mapRequired("EndDelta", Obj.EndDelta); 188 } 189 190 void MappingTraits<SourceColumnEntry>::mapping(IO &IO, SourceColumnEntry &Obj) { 191 IO.mapRequired("StartColumn", Obj.StartColumn); 192 IO.mapRequired("EndColumn", Obj.EndColumn); 193 } 194 195 void MappingTraits<SourceLineBlock>::mapping(IO &IO, SourceLineBlock &Obj) { 196 IO.mapRequired("FileName", Obj.FileName); 197 IO.mapRequired("Lines", Obj.Lines); 198 IO.mapRequired("Columns", Obj.Columns); 199 } 200 201 void MappingTraits<CrossModuleExport>::mapping(IO &IO, CrossModuleExport &Obj) { 202 IO.mapRequired("LocalId", Obj.Local); 203 IO.mapRequired("GlobalId", Obj.Global); 204 } 205 206 void MappingTraits<YAMLCrossModuleImport>::mapping(IO &IO, 207 YAMLCrossModuleImport &Obj) { 208 IO.mapRequired("Module", Obj.ModuleName); 209 IO.mapRequired("Imports", Obj.ImportIds); 210 } 211 212 void MappingTraits<SourceFileChecksumEntry>::mapping( 213 IO &IO, SourceFileChecksumEntry &Obj) { 214 IO.mapRequired("FileName", Obj.FileName); 215 IO.mapRequired("Kind", Obj.Kind); 216 IO.mapRequired("Checksum", Obj.ChecksumBytes); 217 } 218 219 void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) { 220 IO.mapRequired("FileName", Obj.FileName); 221 IO.mapRequired("LineNum", Obj.SourceLineNum); 222 IO.mapRequired("Inlinee", Obj.Inlinee); 223 IO.mapOptional("ExtraFiles", Obj.ExtraFiles); 224 } 225 226 void YAMLChecksumsSubsection::map(IO &IO) { 227 IO.mapTag("!FileChecksums", true); 228 IO.mapRequired("Checksums", Checksums); 229 } 230 231 void YAMLLinesSubsection::map(IO &IO) { 232 IO.mapTag("!Lines", true); 233 IO.mapRequired("CodeSize", Lines.CodeSize); 234 235 IO.mapRequired("Flags", Lines.Flags); 236 IO.mapRequired("RelocOffset", Lines.RelocOffset); 237 IO.mapRequired("RelocSegment", Lines.RelocSegment); 238 IO.mapRequired("Blocks", Lines.Blocks); 239 } 240 241 void YAMLInlineeLinesSubsection::map(IO &IO) { 242 IO.mapTag("!InlineeLines", true); 243 IO.mapRequired("HasExtraFiles", InlineeLines.HasExtraFiles); 244 IO.mapRequired("Sites", InlineeLines.Sites); 245 } 246 247 void YAMLCrossModuleExportsSubsection::map(IO &IO) { 248 IO.mapTag("!CrossModuleExports", true); 249 IO.mapOptional("Exports", Exports); 250 } 251 252 void YAMLCrossModuleImportsSubsection::map(IO &IO) { 253 IO.mapTag("!CrossModuleImports", true); 254 IO.mapOptional("Imports", Imports); 255 } 256 257 void MappingTraits<YAMLDebugSubsection>::mapping( 258 IO &IO, YAMLDebugSubsection &Subsection) { 259 if (!IO.outputting()) { 260 if (IO.mapTag("!FileChecksums")) { 261 auto SS = std::make_shared<YAMLChecksumsSubsection>(); 262 Subsection.Subsection = SS; 263 } else if (IO.mapTag("!Lines")) { 264 Subsection.Subsection = std::make_shared<YAMLLinesSubsection>(); 265 } else if (IO.mapTag("!InlineeLines")) { 266 Subsection.Subsection = std::make_shared<YAMLInlineeLinesSubsection>(); 267 } else if (IO.mapTag("!CrossModuleExports")) { 268 Subsection.Subsection = 269 std::make_shared<YAMLCrossModuleExportsSubsection>(); 270 } else if (IO.mapTag("!CrossModuleImports")) { 271 Subsection.Subsection = 272 std::make_shared<YAMLCrossModuleImportsSubsection>(); 273 } else { 274 llvm_unreachable("Unexpected subsection tag!"); 275 } 276 } 277 Subsection.Subsection->map(IO); 278 } 279 280 static std::shared_ptr<YAMLChecksumsSubsection> 281 findChecksums(ArrayRef<YAMLDebugSubsection> Subsections) { 282 for (const auto &SS : Subsections) { 283 if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) { 284 return std::static_pointer_cast<YAMLChecksumsSubsection>(SS.Subsection); 285 } 286 } 287 288 return nullptr; 289 } 290 291 std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection( 292 DebugStringTableSubsection *UseStrings, 293 DebugChecksumsSubsection *UseChecksums) const { 294 assert(UseStrings && !UseChecksums); 295 auto Result = llvm::make_unique<DebugChecksumsSubsection>(*UseStrings); 296 for (const auto &CS : Checksums) { 297 Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes); 298 } 299 return std::move(Result); 300 } 301 302 std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection( 303 DebugStringTableSubsection *UseStrings, 304 DebugChecksumsSubsection *UseChecksums) const { 305 assert(UseStrings && UseChecksums); 306 auto Result = 307 llvm::make_unique<DebugLinesSubsection>(*UseChecksums, *UseStrings); 308 Result->setCodeSize(Lines.CodeSize); 309 Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset); 310 Result->setFlags(Lines.Flags); 311 for (const auto &LC : Lines.Blocks) { 312 Result->createBlock(LC.FileName); 313 if (Result->hasColumnInfo()) { 314 for (const auto &Item : zip(LC.Lines, LC.Columns)) { 315 auto &L = std::get<0>(Item); 316 auto &C = std::get<1>(Item); 317 uint32_t LE = L.LineStart + L.EndDelta; 318 Result->addLineAndColumnInfo(L.Offset, 319 LineInfo(L.LineStart, LE, L.IsStatement), 320 C.StartColumn, C.EndColumn); 321 } 322 } else { 323 for (const auto &L : LC.Lines) { 324 uint32_t LE = L.LineStart + L.EndDelta; 325 Result->addLineInfo(L.Offset, LineInfo(L.LineStart, LE, L.IsStatement)); 326 } 327 } 328 } 329 return llvm::cast<DebugSubsection>(std::move(Result)); 330 } 331 332 std::unique_ptr<DebugSubsection> 333 YAMLInlineeLinesSubsection::toCodeViewSubsection( 334 DebugStringTableSubsection *UseStrings, 335 DebugChecksumsSubsection *UseChecksums) const { 336 assert(UseChecksums); 337 auto Result = llvm::make_unique<DebugInlineeLinesSubsection>( 338 *UseChecksums, InlineeLines.HasExtraFiles); 339 340 for (const auto &Site : InlineeLines.Sites) { 341 Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName, 342 Site.SourceLineNum); 343 if (!InlineeLines.HasExtraFiles) 344 continue; 345 346 for (auto EF : Site.ExtraFiles) { 347 Result->addExtraFile(EF); 348 } 349 } 350 return llvm::cast<DebugSubsection>(std::move(Result)); 351 } 352 353 std::unique_ptr<DebugSubsection> 354 YAMLCrossModuleExportsSubsection::toCodeViewSubsection( 355 DebugStringTableSubsection *Strings, 356 DebugChecksumsSubsection *Checksums) const { 357 auto Result = llvm::make_unique<DebugCrossModuleExportsSubsection>(); 358 for (const auto &M : Exports) 359 Result->addMapping(M.Local, M.Global); 360 return llvm::cast<DebugSubsection>(std::move(Result)); 361 } 362 363 std::unique_ptr<DebugSubsection> 364 YAMLCrossModuleImportsSubsection::toCodeViewSubsection( 365 DebugStringTableSubsection *Strings, 366 DebugChecksumsSubsection *Checksums) const { 367 auto Result = llvm::make_unique<DebugCrossModuleImportsSubsection>(*Strings); 368 for (const auto &M : Imports) { 369 for (const auto Id : M.ImportIds) 370 Result->addImport(M.ModuleName, Id); 371 } 372 return llvm::cast<DebugSubsection>(std::move(Result)); 373 } 374 375 static Expected<SourceFileChecksumEntry> 376 convertOneChecksum(const DebugStringTableSubsectionRef &Strings, 377 const FileChecksumEntry &CS) { 378 auto ExpectedString = Strings.getString(CS.FileNameOffset); 379 if (!ExpectedString) 380 return ExpectedString.takeError(); 381 382 SourceFileChecksumEntry Result; 383 Result.ChecksumBytes.Bytes = CS.Checksum; 384 Result.Kind = CS.Kind; 385 Result.FileName = *ExpectedString; 386 return Result; 387 } 388 389 static Expected<StringRef> 390 getFileName(const DebugStringTableSubsectionRef &Strings, 391 const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) { 392 auto Iter = Checksums.getArray().at(FileID); 393 if (Iter == Checksums.getArray().end()) 394 return make_error<CodeViewError>(cv_error_code::no_records); 395 uint32_t Offset = Iter->FileNameOffset; 396 return Strings.getString(Offset); 397 } 398 399 Expected<std::shared_ptr<YAMLChecksumsSubsection>> 400 YAMLChecksumsSubsection::fromCodeViewSubsection( 401 const DebugStringTableSubsectionRef &Strings, 402 const DebugChecksumsSubsectionRef &FC) { 403 auto Result = std::make_shared<YAMLChecksumsSubsection>(); 404 405 for (const auto &CS : FC) { 406 auto ConvertedCS = convertOneChecksum(Strings, CS); 407 if (!ConvertedCS) 408 return ConvertedCS.takeError(); 409 Result->Checksums.push_back(*ConvertedCS); 410 } 411 return Result; 412 } 413 414 Expected<std::shared_ptr<YAMLLinesSubsection>> 415 YAMLLinesSubsection::fromCodeViewSubsection( 416 const DebugStringTableSubsectionRef &Strings, 417 const DebugChecksumsSubsectionRef &Checksums, 418 const DebugLinesSubsectionRef &Lines) { 419 auto Result = std::make_shared<YAMLLinesSubsection>(); 420 Result->Lines.CodeSize = Lines.header()->CodeSize; 421 Result->Lines.RelocOffset = Lines.header()->RelocOffset; 422 Result->Lines.RelocSegment = Lines.header()->RelocSegment; 423 Result->Lines.Flags = static_cast<LineFlags>(uint16_t(Lines.header()->Flags)); 424 for (const auto &L : Lines) { 425 SourceLineBlock Block; 426 auto EF = getFileName(Strings, Checksums, L.NameIndex); 427 if (!EF) 428 return EF.takeError(); 429 Block.FileName = *EF; 430 if (Lines.hasColumnInfo()) { 431 for (const auto &C : L.Columns) { 432 SourceColumnEntry SCE; 433 SCE.EndColumn = C.EndColumn; 434 SCE.StartColumn = C.StartColumn; 435 Block.Columns.push_back(SCE); 436 } 437 } 438 for (const auto &LN : L.LineNumbers) { 439 SourceLineEntry SLE; 440 LineInfo LI(LN.Flags); 441 SLE.Offset = LN.Offset; 442 SLE.LineStart = LI.getStartLine(); 443 SLE.EndDelta = LI.getLineDelta(); 444 SLE.IsStatement = LI.isStatement(); 445 Block.Lines.push_back(SLE); 446 } 447 Result->Lines.Blocks.push_back(Block); 448 } 449 return Result; 450 } 451 452 Expected<std::shared_ptr<YAMLInlineeLinesSubsection>> 453 YAMLInlineeLinesSubsection::fromCodeViewSubsection( 454 const DebugStringTableSubsectionRef &Strings, 455 const DebugChecksumsSubsectionRef &Checksums, 456 const DebugInlineeLinesSubsectionRef &Lines) { 457 auto Result = std::make_shared<YAMLInlineeLinesSubsection>(); 458 459 Result->InlineeLines.HasExtraFiles = Lines.hasExtraFiles(); 460 for (const auto &IL : Lines) { 461 InlineeSite Site; 462 auto ExpF = getFileName(Strings, Checksums, IL.Header->FileID); 463 if (!ExpF) 464 return ExpF.takeError(); 465 Site.FileName = *ExpF; 466 Site.Inlinee = IL.Header->Inlinee.getIndex(); 467 Site.SourceLineNum = IL.Header->SourceLineNum; 468 if (Lines.hasExtraFiles()) { 469 for (const auto EF : IL.ExtraFiles) { 470 auto ExpF2 = getFileName(Strings, Checksums, EF); 471 if (!ExpF2) 472 return ExpF2.takeError(); 473 Site.ExtraFiles.push_back(*ExpF2); 474 } 475 } 476 Result->InlineeLines.Sites.push_back(Site); 477 } 478 return Result; 479 } 480 481 Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>> 482 YAMLCrossModuleExportsSubsection::fromCodeViewSubsection( 483 const DebugCrossModuleExportsSubsectionRef &Exports) { 484 auto Result = std::make_shared<YAMLCrossModuleExportsSubsection>(); 485 Result->Exports.assign(Exports.begin(), Exports.end()); 486 return Result; 487 } 488 489 Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>> 490 YAMLCrossModuleImportsSubsection::fromCodeViewSubsection( 491 const DebugStringTableSubsectionRef &Strings, 492 const DebugCrossModuleImportsSubsectionRef &Imports) { 493 auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>(); 494 for (const auto &CMI : Imports) { 495 YAMLCrossModuleImport YCMI; 496 auto ExpectedStr = Strings.getString(CMI.Header->ModuleNameOffset); 497 if (!ExpectedStr) 498 return ExpectedStr.takeError(); 499 YCMI.ModuleName = *ExpectedStr; 500 YCMI.ImportIds.assign(CMI.Imports.begin(), CMI.Imports.end()); 501 Result->Imports.push_back(YCMI); 502 } 503 return Result; 504 } 505 506 Expected<std::vector<std::unique_ptr<DebugSubsection>>> 507 llvm::CodeViewYAML::convertSubsectionList( 508 ArrayRef<YAMLDebugSubsection> Subsections, 509 DebugStringTableSubsection &Strings) { 510 std::vector<std::unique_ptr<DebugSubsection>> Result; 511 if (Subsections.empty()) 512 return std::move(Result); 513 514 auto Checksums = findChecksums(Subsections); 515 std::unique_ptr<DebugSubsection> ChecksumsBase; 516 if (Checksums) 517 ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr); 518 DebugChecksumsSubsection *CS = 519 static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get()); 520 for (const auto &SS : Subsections) { 521 // We've already converted the checksums subsection, don't do it 522 // twice. 523 std::unique_ptr<DebugSubsection> CVS; 524 if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) 525 CVS = std::move(ChecksumsBase); 526 else 527 CVS = SS.Subsection->toCodeViewSubsection(&Strings, CS); 528 assert(CVS != nullptr); 529 Result.push_back(std::move(CVS)); 530 } 531 return std::move(Result); 532 } 533 534 namespace { 535 struct SubsectionConversionVisitor : public DebugSubsectionVisitor { 536 SubsectionConversionVisitor() {} 537 538 Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override; 539 Error visitLines(DebugLinesSubsectionRef &Lines, 540 const DebugSubsectionState &State) override; 541 Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, 542 const DebugSubsectionState &State) override; 543 Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, 544 const DebugSubsectionState &State) override; 545 Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums, 546 const DebugSubsectionState &State) override; 547 Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees, 548 const DebugSubsectionState &State) override; 549 550 YAMLDebugSubsection Subsection; 551 }; 552 553 Error SubsectionConversionVisitor::visitUnknown( 554 DebugUnknownSubsectionRef &Unknown) { 555 return make_error<CodeViewError>(cv_error_code::operation_unsupported); 556 } 557 558 Error SubsectionConversionVisitor::visitLines( 559 DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) { 560 auto Result = YAMLLinesSubsection::fromCodeViewSubsection( 561 State.strings(), State.checksums(), Lines); 562 if (!Result) 563 return Result.takeError(); 564 Subsection.Subsection = *Result; 565 return Error::success(); 566 } 567 568 Error SubsectionConversionVisitor::visitFileChecksums( 569 DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionState &State) { 570 auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(), 571 Checksums); 572 if (!Result) 573 return Result.takeError(); 574 Subsection.Subsection = *Result; 575 return Error::success(); 576 } 577 578 Error SubsectionConversionVisitor::visitInlineeLines( 579 DebugInlineeLinesSubsectionRef &Inlinees, 580 const DebugSubsectionState &State) { 581 auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection( 582 State.strings(), State.checksums(), Inlinees); 583 if (!Result) 584 return Result.takeError(); 585 Subsection.Subsection = *Result; 586 return Error::success(); 587 } 588 589 Error SubsectionConversionVisitor::visitCrossModuleExports( 590 DebugCrossModuleExportsSubsectionRef &Exports, 591 const DebugSubsectionState &State) { 592 auto Result = 593 YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports); 594 if (!Result) 595 return Result.takeError(); 596 Subsection.Subsection = *Result; 597 return Error::success(); 598 } 599 600 Error SubsectionConversionVisitor::visitCrossModuleImports( 601 DebugCrossModuleImportsSubsectionRef &Imports, 602 const DebugSubsectionState &State) { 603 auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection( 604 State.strings(), Imports); 605 if (!Result) 606 return Result.takeError(); 607 Subsection.Subsection = *Result; 608 return Error::success(); 609 } 610 } 611 612 Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection( 613 const DebugStringTableSubsectionRef &Strings, 614 const DebugChecksumsSubsectionRef &Checksums, 615 const DebugSubsectionRecord &SS) { 616 DebugSubsectionState State(Strings, Checksums); 617 SubsectionConversionVisitor V; 618 if (auto EC = visitDebugSubsection(SS, V, State)) 619 return std::move(EC); 620 621 return V.Subsection; 622 } 623