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