1 //===- CodeViewYAMLSymbols.cpp - CodeView YAMLIO Symbol implementation ----===// 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 14 #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/DebugInfo/CodeView/CodeView.h" 18 #include "llvm/DebugInfo/CodeView/CodeViewError.h" 19 #include "llvm/DebugInfo/CodeView/EnumTables.h" 20 #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 21 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 22 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 23 #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" 24 #include "llvm/DebugInfo/CodeView/TypeIndex.h" 25 #include "llvm/ObjectYAML/YAML.h" 26 #include "llvm/Support/Allocator.h" 27 #include "llvm/Support/Error.h" 28 #include "llvm/Support/ScopedPrinter.h" 29 #include "llvm/Support/YAMLTraits.h" 30 #include <algorithm> 31 #include <cstdint> 32 #include <cstring> 33 #include <optional> 34 #include <string> 35 #include <vector> 36 37 using namespace llvm; 38 using namespace llvm::codeview; 39 using namespace llvm::CodeViewYAML; 40 using namespace llvm::CodeViewYAML::detail; 41 using namespace llvm::yaml; 42 43 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex) 44 LLVM_YAML_IS_SEQUENCE_VECTOR(LocalVariableAddrGap) 45 46 // We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp 47 LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None) 48 LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None) 49 50 LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind) 51 LLVM_YAML_DECLARE_ENUM_TRAITS(FrameCookieKind) 52 53 LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags) 54 LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags) 55 LLVM_YAML_DECLARE_BITSET_TRAITS(ExportFlags) 56 LLVM_YAML_DECLARE_BITSET_TRAITS(PublicSymFlags) 57 LLVM_YAML_DECLARE_BITSET_TRAITS(LocalSymFlags) 58 LLVM_YAML_DECLARE_BITSET_TRAITS(ProcSymFlags) 59 LLVM_YAML_DECLARE_BITSET_TRAITS(FrameProcedureOptions) 60 LLVM_YAML_DECLARE_ENUM_TRAITS(CPUType) 61 LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId) 62 LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType) 63 LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal) 64 LLVM_YAML_DECLARE_ENUM_TRAITS(JumpTableEntrySize) 65 66 LLVM_YAML_STRONG_TYPEDEF(StringRef, TypeName) 67 68 LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeName, QuotingType::Single) 69 70 StringRef ScalarTraits<TypeName>::input(StringRef S, void *V, TypeName &T) { 71 return ScalarTraits<StringRef>::input(S, V, T.value); 72 } 73 74 void ScalarTraits<TypeName>::output(const TypeName &T, void *V, 75 raw_ostream &R) { 76 ScalarTraits<StringRef>::output(T.value, V, R); 77 } 78 79 void ScalarEnumerationTraits<SymbolKind>::enumeration(IO &io, 80 SymbolKind &Value) { 81 auto SymbolNames = getSymbolTypeNames(); 82 for (const auto &E : SymbolNames) 83 io.enumCase(Value, E.Name.str().c_str(), E.Value); 84 } 85 86 void ScalarBitSetTraits<CompileSym2Flags>::bitset(IO &io, 87 CompileSym2Flags &Flags) { 88 auto FlagNames = getCompileSym2FlagNames(); 89 for (const auto &E : FlagNames) { 90 io.bitSetCase(Flags, E.Name.str().c_str(), 91 static_cast<CompileSym2Flags>(E.Value)); 92 } 93 } 94 95 void ScalarBitSetTraits<CompileSym3Flags>::bitset(IO &io, 96 CompileSym3Flags &Flags) { 97 auto FlagNames = getCompileSym3FlagNames(); 98 for (const auto &E : FlagNames) { 99 io.bitSetCase(Flags, E.Name.str().c_str(), 100 static_cast<CompileSym3Flags>(E.Value)); 101 } 102 } 103 104 void ScalarBitSetTraits<ExportFlags>::bitset(IO &io, ExportFlags &Flags) { 105 auto FlagNames = getExportSymFlagNames(); 106 for (const auto &E : FlagNames) { 107 io.bitSetCase(Flags, E.Name.str().c_str(), 108 static_cast<ExportFlags>(E.Value)); 109 } 110 } 111 112 void ScalarBitSetTraits<PublicSymFlags>::bitset(IO &io, PublicSymFlags &Flags) { 113 auto FlagNames = getPublicSymFlagNames(); 114 for (const auto &E : FlagNames) { 115 io.bitSetCase(Flags, E.Name.str().c_str(), 116 static_cast<PublicSymFlags>(E.Value)); 117 } 118 } 119 120 void ScalarBitSetTraits<LocalSymFlags>::bitset(IO &io, LocalSymFlags &Flags) { 121 auto FlagNames = getLocalFlagNames(); 122 for (const auto &E : FlagNames) { 123 io.bitSetCase(Flags, E.Name.str().c_str(), 124 static_cast<LocalSymFlags>(E.Value)); 125 } 126 } 127 128 void ScalarBitSetTraits<ProcSymFlags>::bitset(IO &io, ProcSymFlags &Flags) { 129 auto FlagNames = getProcSymFlagNames(); 130 for (const auto &E : FlagNames) { 131 io.bitSetCase(Flags, E.Name.str().c_str(), 132 static_cast<ProcSymFlags>(E.Value)); 133 } 134 } 135 136 void ScalarBitSetTraits<FrameProcedureOptions>::bitset( 137 IO &io, FrameProcedureOptions &Flags) { 138 auto FlagNames = getFrameProcSymFlagNames(); 139 for (const auto &E : FlagNames) { 140 io.bitSetCase(Flags, E.Name.str().c_str(), 141 static_cast<FrameProcedureOptions>(E.Value)); 142 } 143 } 144 145 void ScalarEnumerationTraits<CPUType>::enumeration(IO &io, CPUType &Cpu) { 146 auto CpuNames = getCPUTypeNames(); 147 for (const auto &E : CpuNames) { 148 io.enumCase(Cpu, E.Name.str().c_str(), static_cast<CPUType>(E.Value)); 149 } 150 } 151 152 void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) { 153 const auto *Header = static_cast<COFF::header *>(io.getContext()); 154 assert(Header && "The IO context is not initialized"); 155 156 std::optional<CPUType> CpuType; 157 ArrayRef<EnumEntry<uint16_t>> RegNames; 158 159 switch (Header->Machine) { 160 case COFF::IMAGE_FILE_MACHINE_I386: 161 CpuType = CPUType::Pentium3; 162 break; 163 case COFF::IMAGE_FILE_MACHINE_AMD64: 164 CpuType = CPUType::X64; 165 break; 166 case COFF::IMAGE_FILE_MACHINE_ARMNT: 167 CpuType = CPUType::ARMNT; 168 break; 169 case COFF::IMAGE_FILE_MACHINE_ARM64: 170 case COFF::IMAGE_FILE_MACHINE_ARM64EC: 171 case COFF::IMAGE_FILE_MACHINE_ARM64X: 172 CpuType = CPUType::ARM64; 173 break; 174 } 175 176 if (CpuType) 177 RegNames = getRegisterNames(*CpuType); 178 179 for (const auto &E : RegNames) { 180 io.enumCase(Reg, E.Name.str().c_str(), static_cast<RegisterId>(E.Value)); 181 } 182 io.enumFallback<Hex16>(Reg); 183 } 184 185 void ScalarEnumerationTraits<TrampolineType>::enumeration( 186 IO &io, TrampolineType &Tramp) { 187 auto TrampNames = getTrampolineNames(); 188 for (const auto &E : TrampNames) { 189 io.enumCase(Tramp, E.Name.str().c_str(), 190 static_cast<TrampolineType>(E.Value)); 191 } 192 } 193 194 void ScalarEnumerationTraits<ThunkOrdinal>::enumeration(IO &io, 195 ThunkOrdinal &Ord) { 196 auto ThunkNames = getThunkOrdinalNames(); 197 for (const auto &E : ThunkNames) { 198 io.enumCase(Ord, E.Name.str().c_str(), static_cast<ThunkOrdinal>(E.Value)); 199 } 200 } 201 202 void ScalarEnumerationTraits<FrameCookieKind>::enumeration( 203 IO &io, FrameCookieKind &FC) { 204 auto ThunkNames = getFrameCookieKindNames(); 205 for (const auto &E : ThunkNames) { 206 io.enumCase(FC, E.Name.str().c_str(), 207 static_cast<FrameCookieKind>(E.Value)); 208 } 209 } 210 211 void ScalarEnumerationTraits<JumpTableEntrySize>::enumeration( 212 IO &io, JumpTableEntrySize &FC) { 213 auto ThunkNames = getJumpTableEntrySizeNames(); 214 for (const auto &E : ThunkNames) { 215 io.enumCase(FC, E.Name.str().c_str(), 216 static_cast<JumpTableEntrySize>(E.Value)); 217 } 218 } 219 220 namespace llvm { 221 namespace yaml { 222 template <> struct MappingTraits<LocalVariableAddrRange> { 223 static void mapping(IO &io, LocalVariableAddrRange &Range) { 224 io.mapRequired("OffsetStart", Range.OffsetStart); 225 io.mapRequired("ISectStart", Range.ISectStart); 226 io.mapRequired("Range", Range.Range); 227 } 228 }; 229 template <> struct MappingTraits<LocalVariableAddrGap> { 230 static void mapping(IO &io, LocalVariableAddrGap &Gap) { 231 io.mapRequired("GapStartOffset", Gap.GapStartOffset); 232 io.mapRequired("Range", Gap.Range); 233 } 234 }; 235 } // namespace yaml 236 } // namespace llvm 237 238 namespace llvm { 239 namespace CodeViewYAML { 240 namespace detail { 241 242 struct SymbolRecordBase { 243 codeview::SymbolKind Kind; 244 245 explicit SymbolRecordBase(codeview::SymbolKind K) : Kind(K) {} 246 virtual ~SymbolRecordBase() = default; 247 248 virtual void map(yaml::IO &io) = 0; 249 virtual codeview::CVSymbol 250 toCodeViewSymbol(BumpPtrAllocator &Allocator, 251 CodeViewContainer Container) const = 0; 252 virtual Error fromCodeViewSymbol(codeview::CVSymbol Type) = 0; 253 }; 254 255 template <typename T> struct SymbolRecordImpl : public SymbolRecordBase { 256 explicit SymbolRecordImpl(codeview::SymbolKind K) 257 : SymbolRecordBase(K), Symbol(static_cast<SymbolRecordKind>(K)) {} 258 259 void map(yaml::IO &io) override; 260 261 codeview::CVSymbol 262 toCodeViewSymbol(BumpPtrAllocator &Allocator, 263 CodeViewContainer Container) const override { 264 return SymbolSerializer::writeOneSymbol(Symbol, Allocator, Container); 265 } 266 267 Error fromCodeViewSymbol(codeview::CVSymbol CVS) override { 268 return SymbolDeserializer::deserializeAs<T>(CVS, Symbol); 269 } 270 271 mutable T Symbol; 272 }; 273 274 struct UnknownSymbolRecord : public SymbolRecordBase { 275 explicit UnknownSymbolRecord(codeview::SymbolKind K) : SymbolRecordBase(K) {} 276 277 void map(yaml::IO &io) override; 278 279 CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator, 280 CodeViewContainer Container) const override { 281 RecordPrefix Prefix; 282 uint32_t TotalLen = sizeof(RecordPrefix) + Data.size(); 283 Prefix.RecordKind = Kind; 284 Prefix.RecordLen = TotalLen - 2; 285 uint8_t *Buffer = Allocator.Allocate<uint8_t>(TotalLen); 286 ::memcpy(Buffer, &Prefix, sizeof(RecordPrefix)); 287 ::memcpy(Buffer + sizeof(RecordPrefix), Data.data(), Data.size()); 288 return CVSymbol(ArrayRef<uint8_t>(Buffer, TotalLen)); 289 } 290 291 Error fromCodeViewSymbol(CVSymbol CVS) override { 292 this->Kind = CVS.kind(); 293 Data = CVS.RecordData.drop_front(sizeof(RecordPrefix)); 294 return Error::success(); 295 } 296 297 std::vector<uint8_t> Data; 298 }; 299 300 template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {} 301 302 void UnknownSymbolRecord::map(yaml::IO &io) { 303 yaml::BinaryRef Binary; 304 if (io.outputting()) 305 Binary = yaml::BinaryRef(Data); 306 io.mapRequired("Data", Binary); 307 if (!io.outputting()) { 308 std::string Str; 309 raw_string_ostream OS(Str); 310 Binary.writeAsBinary(OS); 311 OS.flush(); 312 Data.assign(Str.begin(), Str.end()); 313 } 314 } 315 316 template <> void SymbolRecordImpl<Thunk32Sym>::map(IO &IO) { 317 IO.mapRequired("Parent", Symbol.Parent); 318 IO.mapRequired("End", Symbol.End); 319 IO.mapRequired("Next", Symbol.Next); 320 IO.mapRequired("Off", Symbol.Offset); 321 IO.mapRequired("Seg", Symbol.Segment); 322 IO.mapRequired("Len", Symbol.Length); 323 IO.mapRequired("Ordinal", Symbol.Thunk); 324 } 325 326 template <> void SymbolRecordImpl<TrampolineSym>::map(IO &IO) { 327 IO.mapRequired("Type", Symbol.Type); 328 IO.mapRequired("Size", Symbol.Size); 329 IO.mapRequired("ThunkOff", Symbol.ThunkOffset); 330 IO.mapRequired("TargetOff", Symbol.TargetOffset); 331 IO.mapRequired("ThunkSection", Symbol.ThunkSection); 332 IO.mapRequired("TargetSection", Symbol.TargetSection); 333 } 334 335 template <> void SymbolRecordImpl<SectionSym>::map(IO &IO) { 336 IO.mapRequired("SectionNumber", Symbol.SectionNumber); 337 IO.mapRequired("Alignment", Symbol.Alignment); 338 IO.mapRequired("Rva", Symbol.Rva); 339 IO.mapRequired("Length", Symbol.Length); 340 IO.mapRequired("Characteristics", Symbol.Characteristics); 341 IO.mapRequired("Name", Symbol.Name); 342 } 343 344 template <> void SymbolRecordImpl<CoffGroupSym>::map(IO &IO) { 345 IO.mapRequired("Size", Symbol.Size); 346 IO.mapRequired("Characteristics", Symbol.Characteristics); 347 IO.mapRequired("Offset", Symbol.Offset); 348 IO.mapRequired("Segment", Symbol.Segment); 349 IO.mapRequired("Name", Symbol.Name); 350 } 351 352 template <> void SymbolRecordImpl<ExportSym>::map(IO &IO) { 353 IO.mapRequired("Ordinal", Symbol.Ordinal); 354 IO.mapRequired("Flags", Symbol.Flags); 355 IO.mapRequired("Name", Symbol.Name); 356 } 357 358 template <> void SymbolRecordImpl<ProcSym>::map(IO &IO) { 359 IO.mapOptional("PtrParent", Symbol.Parent, 0U); 360 IO.mapOptional("PtrEnd", Symbol.End, 0U); 361 IO.mapOptional("PtrNext", Symbol.Next, 0U); 362 IO.mapRequired("CodeSize", Symbol.CodeSize); 363 IO.mapRequired("DbgStart", Symbol.DbgStart); 364 IO.mapRequired("DbgEnd", Symbol.DbgEnd); 365 IO.mapRequired("FunctionType", Symbol.FunctionType); 366 IO.mapOptional("Offset", Symbol.CodeOffset, 0U); 367 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); 368 IO.mapRequired("Flags", Symbol.Flags); 369 IO.mapRequired("DisplayName", Symbol.Name); 370 } 371 372 template <> void SymbolRecordImpl<RegisterSym>::map(IO &IO) { 373 IO.mapRequired("Type", Symbol.Index); 374 IO.mapRequired("Seg", Symbol.Register); 375 IO.mapRequired("Name", Symbol.Name); 376 } 377 378 template <> void SymbolRecordImpl<PublicSym32>::map(IO &IO) { 379 IO.mapRequired("Flags", Symbol.Flags); 380 IO.mapOptional("Offset", Symbol.Offset, 0U); 381 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); 382 IO.mapRequired("Name", Symbol.Name); 383 } 384 385 template <> void SymbolRecordImpl<ProcRefSym>::map(IO &IO) { 386 IO.mapRequired("SumName", Symbol.SumName); 387 IO.mapRequired("SymOffset", Symbol.SymOffset); 388 IO.mapRequired("Mod", Symbol.Module); 389 IO.mapRequired("Name", Symbol.Name); 390 } 391 392 template <> void SymbolRecordImpl<EnvBlockSym>::map(IO &IO) { 393 IO.mapRequired("Entries", Symbol.Fields); 394 } 395 396 template <> void SymbolRecordImpl<InlineSiteSym>::map(IO &IO) { 397 IO.mapOptional("PtrParent", Symbol.Parent, 0U); 398 IO.mapOptional("PtrEnd", Symbol.End, 0U); 399 IO.mapRequired("Inlinee", Symbol.Inlinee); 400 // TODO: The binary annotations 401 } 402 403 template <> void SymbolRecordImpl<LocalSym>::map(IO &IO) { 404 IO.mapRequired("Type", Symbol.Type); 405 IO.mapRequired("Flags", Symbol.Flags); 406 407 IO.mapRequired("VarName", Symbol.Name); 408 } 409 410 template <> void SymbolRecordImpl<DefRangeSym>::map(IO &IO) { 411 IO.mapRequired("Program", Symbol.Program); 412 IO.mapRequired("Range", Symbol.Range); 413 IO.mapRequired("Gaps", Symbol.Gaps); 414 } 415 416 template <> void SymbolRecordImpl<DefRangeSubfieldSym>::map(IO &IO) { 417 IO.mapRequired("Program", Symbol.Program); 418 IO.mapRequired("OffsetInParent", Symbol.OffsetInParent); 419 IO.mapRequired("Range", Symbol.Range); 420 IO.mapRequired("Gaps", Symbol.Gaps); 421 } 422 423 template <> void SymbolRecordImpl<DefRangeRegisterSym>::map(IO &IO) { 424 IO.mapRequired("Register", Symbol.Hdr.Register); 425 IO.mapRequired("MayHaveNoName", Symbol.Hdr.MayHaveNoName); 426 IO.mapRequired("Range", Symbol.Range); 427 IO.mapRequired("Gaps", Symbol.Gaps); 428 } 429 430 template <> void SymbolRecordImpl<DefRangeFramePointerRelSym>::map(IO &IO) { 431 IO.mapRequired("Offset", Symbol.Hdr.Offset); 432 IO.mapRequired("Range", Symbol.Range); 433 IO.mapRequired("Gaps", Symbol.Gaps); 434 } 435 436 template <> void SymbolRecordImpl<DefRangeSubfieldRegisterSym>::map(IO &IO) { 437 IO.mapRequired("Register", Symbol.Hdr.Register); 438 IO.mapRequired("MayHaveNoName", Symbol.Hdr.MayHaveNoName); 439 IO.mapRequired("OffsetInParent", Symbol.Hdr.OffsetInParent); 440 IO.mapRequired("Range", Symbol.Range); 441 IO.mapRequired("Gaps", Symbol.Gaps); 442 } 443 444 template <> 445 void SymbolRecordImpl<DefRangeFramePointerRelFullScopeSym>::map(IO &IO) { 446 IO.mapRequired("Register", Symbol.Offset); 447 } 448 449 template <> void SymbolRecordImpl<DefRangeRegisterRelSym>::map(IO &IO) { 450 IO.mapRequired("Register", Symbol.Hdr.Register); 451 IO.mapRequired("Flags", Symbol.Hdr.Flags); 452 IO.mapRequired("BasePointerOffset", Symbol.Hdr.BasePointerOffset); 453 IO.mapRequired("Range", Symbol.Range); 454 IO.mapRequired("Gaps", Symbol.Gaps); 455 } 456 457 template <> void SymbolRecordImpl<BlockSym>::map(IO &IO) { 458 IO.mapOptional("PtrParent", Symbol.Parent, 0U); 459 IO.mapOptional("PtrEnd", Symbol.End, 0U); 460 IO.mapRequired("CodeSize", Symbol.CodeSize); 461 IO.mapOptional("Offset", Symbol.CodeOffset, 0U); 462 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); 463 IO.mapRequired("BlockName", Symbol.Name); 464 } 465 466 template <> void SymbolRecordImpl<LabelSym>::map(IO &IO) { 467 IO.mapOptional("Offset", Symbol.CodeOffset, 0U); 468 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); 469 IO.mapRequired("Flags", Symbol.Flags); 470 IO.mapRequired("DisplayName", Symbol.Name); 471 } 472 473 template <> void SymbolRecordImpl<ObjNameSym>::map(IO &IO) { 474 IO.mapRequired("Signature", Symbol.Signature); 475 IO.mapRequired("ObjectName", Symbol.Name); 476 } 477 478 template <> void SymbolRecordImpl<Compile2Sym>::map(IO &IO) { 479 IO.mapRequired("Flags", Symbol.Flags); 480 IO.mapRequired("Machine", Symbol.Machine); 481 IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor); 482 IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor); 483 IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild); 484 IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor); 485 IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor); 486 IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild); 487 IO.mapRequired("Version", Symbol.Version); 488 } 489 490 template <> void SymbolRecordImpl<Compile3Sym>::map(IO &IO) { 491 IO.mapRequired("Flags", Symbol.Flags); 492 IO.mapRequired("Machine", Symbol.Machine); 493 IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor); 494 IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor); 495 IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild); 496 IO.mapRequired("FrontendQFE", Symbol.VersionFrontendQFE); 497 IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor); 498 IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor); 499 IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild); 500 IO.mapRequired("BackendQFE", Symbol.VersionBackendQFE); 501 IO.mapRequired("Version", Symbol.Version); 502 } 503 504 template <> void SymbolRecordImpl<FrameProcSym>::map(IO &IO) { 505 IO.mapRequired("TotalFrameBytes", Symbol.TotalFrameBytes); 506 IO.mapRequired("PaddingFrameBytes", Symbol.PaddingFrameBytes); 507 IO.mapRequired("OffsetToPadding", Symbol.OffsetToPadding); 508 IO.mapRequired("BytesOfCalleeSavedRegisters", 509 Symbol.BytesOfCalleeSavedRegisters); 510 IO.mapRequired("OffsetOfExceptionHandler", Symbol.OffsetOfExceptionHandler); 511 IO.mapRequired("SectionIdOfExceptionHandler", 512 Symbol.SectionIdOfExceptionHandler); 513 IO.mapRequired("Flags", Symbol.Flags); 514 } 515 516 template <> void SymbolRecordImpl<CallSiteInfoSym>::map(IO &IO) { 517 IO.mapOptional("Offset", Symbol.CodeOffset, 0U); 518 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); 519 IO.mapRequired("Type", Symbol.Type); 520 } 521 522 template <> void SymbolRecordImpl<FileStaticSym>::map(IO &IO) { 523 IO.mapRequired("Index", Symbol.Index); 524 IO.mapRequired("ModFilenameOffset", Symbol.ModFilenameOffset); 525 IO.mapRequired("Flags", Symbol.Flags); 526 IO.mapRequired("Name", Symbol.Name); 527 } 528 529 template <> void SymbolRecordImpl<HeapAllocationSiteSym>::map(IO &IO) { 530 IO.mapOptional("Offset", Symbol.CodeOffset, 0U); 531 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); 532 IO.mapRequired("CallInstructionSize", Symbol.CallInstructionSize); 533 IO.mapRequired("Type", Symbol.Type); 534 } 535 536 template <> void SymbolRecordImpl<FrameCookieSym>::map(IO &IO) { 537 IO.mapRequired("Register", Symbol.Register); 538 IO.mapRequired("CookieKind", Symbol.CookieKind); 539 IO.mapRequired("Flags", Symbol.Flags); 540 } 541 542 template <> void SymbolRecordImpl<CallerSym>::map(IO &IO) { 543 IO.mapRequired("FuncID", Symbol.Indices); 544 } 545 546 template <> void SymbolRecordImpl<UDTSym>::map(IO &IO) { 547 IO.mapRequired("Type", Symbol.Type); 548 IO.mapRequired("UDTName", Symbol.Name); 549 } 550 551 template <> void SymbolRecordImpl<BuildInfoSym>::map(IO &IO) { 552 IO.mapRequired("BuildId", Symbol.BuildId); 553 } 554 555 template <> void SymbolRecordImpl<BPRelativeSym>::map(IO &IO) { 556 IO.mapRequired("Offset", Symbol.Offset); 557 IO.mapRequired("Type", Symbol.Type); 558 IO.mapRequired("VarName", Symbol.Name); 559 } 560 561 template <> void SymbolRecordImpl<RegRelativeSym>::map(IO &IO) { 562 IO.mapRequired("Offset", Symbol.Offset); 563 IO.mapRequired("Type", Symbol.Type); 564 IO.mapRequired("Register", Symbol.Register); 565 IO.mapRequired("VarName", Symbol.Name); 566 } 567 568 template <> void SymbolRecordImpl<ConstantSym>::map(IO &IO) { 569 IO.mapRequired("Type", Symbol.Type); 570 IO.mapRequired("Value", Symbol.Value); 571 IO.mapRequired("Name", Symbol.Name); 572 } 573 574 template <> void SymbolRecordImpl<DataSym>::map(IO &IO) { 575 IO.mapRequired("Type", Symbol.Type); 576 IO.mapOptional("Offset", Symbol.DataOffset, 0U); 577 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); 578 IO.mapRequired("DisplayName", Symbol.Name); 579 } 580 581 template <> void SymbolRecordImpl<ThreadLocalDataSym>::map(IO &IO) { 582 IO.mapRequired("Type", Symbol.Type); 583 IO.mapOptional("Offset", Symbol.DataOffset, 0U); 584 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); 585 IO.mapRequired("DisplayName", Symbol.Name); 586 } 587 588 template <> void SymbolRecordImpl<UsingNamespaceSym>::map(IO &IO) { 589 IO.mapRequired("Namespace", Symbol.Name); 590 } 591 592 template <> void SymbolRecordImpl<AnnotationSym>::map(IO &IO) { 593 IO.mapOptional("Offset", Symbol.CodeOffset, 0U); 594 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0)); 595 IO.mapRequired("Strings", Symbol.Strings); 596 } 597 598 template <> void SymbolRecordImpl<JumpTableSym>::map(IO &IO) { 599 IO.mapRequired("BaseOffset", Symbol.BaseOffset); 600 IO.mapRequired("BaseSegment", Symbol.BaseSegment); 601 IO.mapRequired("SwitchType", Symbol.SwitchType); 602 IO.mapRequired("BranchOffset", Symbol.BranchOffset); 603 IO.mapRequired("TableOffset", Symbol.TableOffset); 604 IO.mapRequired("BranchSegment", Symbol.BranchSegment); 605 IO.mapRequired("TableSegment", Symbol.TableSegment); 606 IO.mapRequired("EntriesCount", Symbol.EntriesCount); 607 } 608 609 } // end namespace detail 610 } // end namespace CodeViewYAML 611 } // end namespace llvm 612 613 CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol( 614 BumpPtrAllocator &Allocator, CodeViewContainer Container) const { 615 return Symbol->toCodeViewSymbol(Allocator, Container); 616 } 617 618 namespace llvm { 619 namespace yaml { 620 621 template <> struct MappingTraits<SymbolRecordBase> { 622 static void mapping(IO &io, SymbolRecordBase &Record) { Record.map(io); } 623 }; 624 625 } // end namespace yaml 626 } // end namespace llvm 627 628 template <typename SymbolType> 629 static inline Expected<CodeViewYAML::SymbolRecord> 630 fromCodeViewSymbolImpl(CVSymbol Symbol) { 631 CodeViewYAML::SymbolRecord Result; 632 633 auto Impl = std::make_shared<SymbolType>(Symbol.kind()); 634 if (auto EC = Impl->fromCodeViewSymbol(Symbol)) 635 return std::move(EC); 636 Result.Symbol = Impl; 637 return Result; 638 } 639 640 Expected<CodeViewYAML::SymbolRecord> 641 CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) { 642 #define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \ 643 case EnumName: \ 644 return fromCodeViewSymbolImpl<SymbolRecordImpl<ClassName>>(Symbol); 645 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \ 646 SYMBOL_RECORD(EnumName, EnumVal, ClassName) 647 switch (Symbol.kind()) { 648 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 649 default: 650 return fromCodeViewSymbolImpl<UnknownSymbolRecord>(Symbol); 651 } 652 return make_error<CodeViewError>(cv_error_code::corrupt_record); 653 } 654 655 template <typename ConcreteType> 656 static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind, 657 CodeViewYAML::SymbolRecord &Obj) { 658 if (!IO.outputting()) 659 Obj.Symbol = std::make_shared<ConcreteType>(Kind); 660 661 IO.mapRequired(Class, *Obj.Symbol); 662 } 663 664 void MappingTraits<CodeViewYAML::SymbolRecord>::mapping( 665 IO &IO, CodeViewYAML::SymbolRecord &Obj) { 666 SymbolKind Kind; 667 if (IO.outputting()) 668 Kind = Obj.Symbol->Kind; 669 IO.mapRequired("Kind", Kind); 670 671 #define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \ 672 case EnumName: \ 673 mapSymbolRecordImpl<SymbolRecordImpl<ClassName>>(IO, #ClassName, Kind, \ 674 Obj); \ 675 break; 676 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \ 677 SYMBOL_RECORD(EnumName, EnumVal, ClassName) 678 switch (Kind) { 679 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 680 default: 681 mapSymbolRecordImpl<UnknownSymbolRecord>(IO, "UnknownSym", Kind, Obj); 682 } 683 } 684