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