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