678 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines classes for handling the YAML representation of CodeView10// 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 37using namespace llvm;38using namespace llvm::codeview;39using namespace llvm::CodeViewYAML;40using namespace llvm::CodeViewYAML::detail;41using namespace llvm::yaml;42 43LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)44LLVM_YAML_IS_SEQUENCE_VECTOR(LocalVariableAddrGap)45 46// We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp47LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None)48LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None)49 50LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)51LLVM_YAML_DECLARE_ENUM_TRAITS(FrameCookieKind)52 53LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags)54LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags)55LLVM_YAML_DECLARE_BITSET_TRAITS(ExportFlags)56LLVM_YAML_DECLARE_BITSET_TRAITS(PublicSymFlags)57LLVM_YAML_DECLARE_BITSET_TRAITS(LocalSymFlags)58LLVM_YAML_DECLARE_BITSET_TRAITS(ProcSymFlags)59LLVM_YAML_DECLARE_BITSET_TRAITS(FrameProcedureOptions)60LLVM_YAML_DECLARE_ENUM_TRAITS(CPUType)61LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId)62LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType)63LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)64LLVM_YAML_DECLARE_ENUM_TRAITS(JumpTableEntrySize)65 66LLVM_YAML_STRONG_TYPEDEF(StringRef, TypeName)67 68LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeName, QuotingType::Single)69 70StringRef ScalarTraits<TypeName>::input(StringRef S, void *V, TypeName &T) {71 return ScalarTraits<StringRef>::input(S, V, T.value);72}73 74void ScalarTraits<TypeName>::output(const TypeName &T, void *V,75 raw_ostream &R) {76 ScalarTraits<StringRef>::output(T.value, V, R);77}78 79void ScalarEnumerationTraits<SymbolKind>::enumeration(IO &io,80 SymbolKind &Value) {81 auto SymbolNames = getSymbolTypeNames();82 for (const auto &E : SymbolNames)83 io.enumCase(Value, E.Name, E.Value);84}85 86void ScalarBitSetTraits<CompileSym2Flags>::bitset(IO &io,87 CompileSym2Flags &Flags) {88 auto FlagNames = getCompileSym2FlagNames();89 for (const auto &E : FlagNames) {90 io.bitSetCase(Flags, E.Name, static_cast<CompileSym2Flags>(E.Value));91 }92}93 94void ScalarBitSetTraits<CompileSym3Flags>::bitset(IO &io,95 CompileSym3Flags &Flags) {96 auto FlagNames = getCompileSym3FlagNames();97 for (const auto &E : FlagNames) {98 io.bitSetCase(Flags, E.Name, static_cast<CompileSym3Flags>(E.Value));99 }100}101 102void ScalarBitSetTraits<ExportFlags>::bitset(IO &io, ExportFlags &Flags) {103 auto FlagNames = getExportSymFlagNames();104 for (const auto &E : FlagNames) {105 io.bitSetCase(Flags, E.Name, 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, static_cast<PublicSymFlags>(E.Value));113 }114}115 116void ScalarBitSetTraits<LocalSymFlags>::bitset(IO &io, LocalSymFlags &Flags) {117 auto FlagNames = getLocalFlagNames();118 for (const auto &E : FlagNames) {119 io.bitSetCase(Flags, E.Name, static_cast<LocalSymFlags>(E.Value));120 }121}122 123void ScalarBitSetTraits<ProcSymFlags>::bitset(IO &io, ProcSymFlags &Flags) {124 auto FlagNames = getProcSymFlagNames();125 for (const auto &E : FlagNames) {126 io.bitSetCase(Flags, E.Name, static_cast<ProcSymFlags>(E.Value));127 }128}129 130void ScalarBitSetTraits<FrameProcedureOptions>::bitset(131 IO &io, FrameProcedureOptions &Flags) {132 auto FlagNames = getFrameProcSymFlagNames();133 for (const auto &E : FlagNames) {134 io.bitSetCase(Flags, E.Name, static_cast<FrameProcedureOptions>(E.Value));135 }136}137 138void ScalarEnumerationTraits<CPUType>::enumeration(IO &io, CPUType &Cpu) {139 auto CpuNames = getCPUTypeNames();140 for (const auto &E : CpuNames) {141 io.enumCase(Cpu, E.Name, static_cast<CPUType>(E.Value));142 }143}144 145void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) {146 const auto *Header = static_cast<COFF::header *>(io.getContext());147 assert(Header && "The IO context is not initialized");148 149 std::optional<CPUType> CpuType;150 ArrayRef<EnumEntry<uint16_t>> RegNames;151 152 switch (Header->Machine) {153 case COFF::IMAGE_FILE_MACHINE_I386:154 CpuType = CPUType::Pentium3;155 break;156 case COFF::IMAGE_FILE_MACHINE_AMD64:157 CpuType = CPUType::X64;158 break;159 case COFF::IMAGE_FILE_MACHINE_ARMNT:160 CpuType = CPUType::ARMNT;161 break;162 case COFF::IMAGE_FILE_MACHINE_ARM64:163 case COFF::IMAGE_FILE_MACHINE_ARM64EC:164 case COFF::IMAGE_FILE_MACHINE_ARM64X:165 CpuType = CPUType::ARM64;166 break;167 }168 169 if (CpuType)170 RegNames = getRegisterNames(*CpuType);171 172 for (const auto &E : RegNames) {173 io.enumCase(Reg, E.Name, static_cast<RegisterId>(E.Value));174 }175 io.enumFallback<Hex16>(Reg);176}177 178void ScalarEnumerationTraits<TrampolineType>::enumeration(179 IO &io, TrampolineType &Tramp) {180 auto TrampNames = getTrampolineNames();181 for (const auto &E : TrampNames) {182 io.enumCase(Tramp, E.Name, static_cast<TrampolineType>(E.Value));183 }184}185 186void ScalarEnumerationTraits<ThunkOrdinal>::enumeration(IO &io,187 ThunkOrdinal &Ord) {188 auto ThunkNames = getThunkOrdinalNames();189 for (const auto &E : ThunkNames) {190 io.enumCase(Ord, E.Name, static_cast<ThunkOrdinal>(E.Value));191 }192}193 194void ScalarEnumerationTraits<FrameCookieKind>::enumeration(195 IO &io, FrameCookieKind &FC) {196 auto ThunkNames = getFrameCookieKindNames();197 for (const auto &E : ThunkNames) {198 io.enumCase(FC, E.Name, static_cast<FrameCookieKind>(E.Value));199 }200}201 202void ScalarEnumerationTraits<JumpTableEntrySize>::enumeration(203 IO &io, JumpTableEntrySize &FC) {204 auto ThunkNames = getJumpTableEntrySizeNames();205 for (const auto &E : ThunkNames) {206 io.enumCase(FC, E.Name, static_cast<JumpTableEntrySize>(E.Value));207 }208}209 210namespace llvm {211namespace yaml {212template <> struct MappingTraits<LocalVariableAddrRange> {213 static void mapping(IO &io, LocalVariableAddrRange &Range) {214 io.mapRequired("OffsetStart", Range.OffsetStart);215 io.mapRequired("ISectStart", Range.ISectStart);216 io.mapRequired("Range", Range.Range);217 }218};219template <> struct MappingTraits<LocalVariableAddrGap> {220 static void mapping(IO &io, LocalVariableAddrGap &Gap) {221 io.mapRequired("GapStartOffset", Gap.GapStartOffset);222 io.mapRequired("Range", Gap.Range);223 }224};225} // namespace yaml226} // namespace llvm227 228namespace llvm {229namespace CodeViewYAML {230namespace detail {231 232struct SymbolRecordBase {233 codeview::SymbolKind Kind;234 235 explicit SymbolRecordBase(codeview::SymbolKind K) : Kind(K) {}236 virtual ~SymbolRecordBase() = default;237 238 virtual void map(yaml::IO &io) = 0;239 virtual codeview::CVSymbol240 toCodeViewSymbol(BumpPtrAllocator &Allocator,241 CodeViewContainer Container) const = 0;242 virtual Error fromCodeViewSymbol(codeview::CVSymbol Type) = 0;243};244 245template <typename T> struct SymbolRecordImpl : public SymbolRecordBase {246 explicit SymbolRecordImpl(codeview::SymbolKind K)247 : SymbolRecordBase(K), Symbol(static_cast<SymbolRecordKind>(K)) {}248 249 void map(yaml::IO &io) override;250 251 codeview::CVSymbol252 toCodeViewSymbol(BumpPtrAllocator &Allocator,253 CodeViewContainer Container) const override {254 return SymbolSerializer::writeOneSymbol(Symbol, Allocator, Container);255 }256 257 Error fromCodeViewSymbol(codeview::CVSymbol CVS) override {258 return SymbolDeserializer::deserializeAs<T>(CVS, Symbol);259 }260 261 mutable T Symbol;262};263 264struct UnknownSymbolRecord : public SymbolRecordBase {265 explicit UnknownSymbolRecord(codeview::SymbolKind K) : SymbolRecordBase(K) {}266 267 void map(yaml::IO &io) override;268 269 CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator,270 CodeViewContainer Container) const override {271 RecordPrefix Prefix;272 uint32_t TotalLen = sizeof(RecordPrefix) + Data.size();273 Prefix.RecordKind = Kind;274 Prefix.RecordLen = TotalLen - 2;275 uint8_t *Buffer = Allocator.Allocate<uint8_t>(TotalLen);276 ::memcpy(Buffer, &Prefix, sizeof(RecordPrefix));277 ::memcpy(Buffer + sizeof(RecordPrefix), Data.data(), Data.size());278 return CVSymbol(ArrayRef<uint8_t>(Buffer, TotalLen));279 }280 281 Error fromCodeViewSymbol(CVSymbol CVS) override {282 this->Kind = CVS.kind();283 Data = CVS.RecordData.drop_front(sizeof(RecordPrefix));284 return Error::success();285 }286 287 std::vector<uint8_t> Data;288};289 290template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {}291 292void UnknownSymbolRecord::map(yaml::IO &io) {293 yaml::BinaryRef Binary;294 if (io.outputting())295 Binary = yaml::BinaryRef(Data);296 io.mapRequired("Data", Binary);297 if (!io.outputting()) {298 std::string Str;299 raw_string_ostream OS(Str);300 Binary.writeAsBinary(OS);301 Data.assign(Str.begin(), Str.end());302 }303}304 305template <> 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 315template <> 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 324template <> 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 333template <> 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 341template <> 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 347template <> 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 361template <> 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 367template <> 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 374template <> 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 381template <> void SymbolRecordImpl<EnvBlockSym>::map(IO &IO) {382 IO.mapRequired("Entries", Symbol.Fields);383}384 385template <> 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 IO.mapOptional("AnnotationData", Symbol.AnnotationData);390}391 392template <> 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 399template <> 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 405template <> 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 412template <> 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 419template <> 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 425template <> 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 433template <>434void SymbolRecordImpl<DefRangeFramePointerRelFullScopeSym>::map(IO &IO) {435 IO.mapRequired("Register", Symbol.Offset);436}437 438template <> 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 446template <> 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 455template <> 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("DisplayName", Symbol.Name);460}461 462template <> void SymbolRecordImpl<ObjNameSym>::map(IO &IO) {463 IO.mapRequired("Signature", Symbol.Signature);464 IO.mapRequired("ObjectName", Symbol.Name);465}466 467template <> void SymbolRecordImpl<Compile2Sym>::map(IO &IO) {468 IO.mapRequired("Flags", Symbol.Flags);469 IO.mapRequired("Machine", Symbol.Machine);470 IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);471 IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);472 IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);473 IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);474 IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);475 IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);476 IO.mapRequired("Version", Symbol.Version);477}478 479template <> void SymbolRecordImpl<Compile3Sym>::map(IO &IO) {480 IO.mapRequired("Flags", Symbol.Flags);481 IO.mapRequired("Machine", Symbol.Machine);482 IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);483 IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);484 IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);485 IO.mapRequired("FrontendQFE", Symbol.VersionFrontendQFE);486 IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);487 IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);488 IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);489 IO.mapRequired("BackendQFE", Symbol.VersionBackendQFE);490 IO.mapRequired("Version", Symbol.Version);491}492 493template <> void SymbolRecordImpl<FrameProcSym>::map(IO &IO) {494 IO.mapRequired("TotalFrameBytes", Symbol.TotalFrameBytes);495 IO.mapRequired("PaddingFrameBytes", Symbol.PaddingFrameBytes);496 IO.mapRequired("OffsetToPadding", Symbol.OffsetToPadding);497 IO.mapRequired("BytesOfCalleeSavedRegisters",498 Symbol.BytesOfCalleeSavedRegisters);499 IO.mapRequired("OffsetOfExceptionHandler", Symbol.OffsetOfExceptionHandler);500 IO.mapRequired("SectionIdOfExceptionHandler",501 Symbol.SectionIdOfExceptionHandler);502 IO.mapRequired("Flags", Symbol.Flags);503}504 505template <> void SymbolRecordImpl<CallSiteInfoSym>::map(IO &IO) {506 IO.mapOptional("Offset", Symbol.CodeOffset, 0U);507 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));508 IO.mapRequired("Type", Symbol.Type);509}510 511template <> void SymbolRecordImpl<FileStaticSym>::map(IO &IO) {512 IO.mapRequired("Index", Symbol.Index);513 IO.mapRequired("ModFilenameOffset", Symbol.ModFilenameOffset);514 IO.mapRequired("Flags", Symbol.Flags);515 IO.mapRequired("Name", Symbol.Name);516}517 518template <> void SymbolRecordImpl<HeapAllocationSiteSym>::map(IO &IO) {519 IO.mapOptional("Offset", Symbol.CodeOffset, 0U);520 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));521 IO.mapRequired("CallInstructionSize", Symbol.CallInstructionSize);522 IO.mapRequired("Type", Symbol.Type);523}524 525template <> void SymbolRecordImpl<FrameCookieSym>::map(IO &IO) {526 IO.mapRequired("Register", Symbol.Register);527 IO.mapRequired("CookieKind", Symbol.CookieKind);528 IO.mapRequired("Flags", Symbol.Flags);529}530 531template <> void SymbolRecordImpl<CallerSym>::map(IO &IO) {532 IO.mapRequired("FuncID", Symbol.Indices);533}534 535template <> void SymbolRecordImpl<UDTSym>::map(IO &IO) {536 IO.mapRequired("Type", Symbol.Type);537 IO.mapRequired("UDTName", Symbol.Name);538}539 540template <> void SymbolRecordImpl<BuildInfoSym>::map(IO &IO) {541 IO.mapRequired("BuildId", Symbol.BuildId);542}543 544template <> void SymbolRecordImpl<BPRelativeSym>::map(IO &IO) {545 IO.mapRequired("Offset", Symbol.Offset);546 IO.mapRequired("Type", Symbol.Type);547 IO.mapRequired("VarName", Symbol.Name);548}549 550template <> void SymbolRecordImpl<RegRelativeSym>::map(IO &IO) {551 IO.mapRequired("Offset", Symbol.Offset);552 IO.mapRequired("Type", Symbol.Type);553 IO.mapRequired("Register", Symbol.Register);554 IO.mapRequired("VarName", Symbol.Name);555}556 557template <> void SymbolRecordImpl<ConstantSym>::map(IO &IO) {558 IO.mapRequired("Type", Symbol.Type);559 IO.mapRequired("Value", Symbol.Value);560 IO.mapRequired("Name", Symbol.Name);561}562 563template <> void SymbolRecordImpl<DataSym>::map(IO &IO) {564 IO.mapRequired("Type", Symbol.Type);565 IO.mapOptional("Offset", Symbol.DataOffset, 0U);566 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));567 IO.mapRequired("DisplayName", Symbol.Name);568}569 570template <> void SymbolRecordImpl<ThreadLocalDataSym>::map(IO &IO) {571 IO.mapRequired("Type", Symbol.Type);572 IO.mapOptional("Offset", Symbol.DataOffset, 0U);573 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));574 IO.mapRequired("DisplayName", Symbol.Name);575}576 577template <> void SymbolRecordImpl<UsingNamespaceSym>::map(IO &IO) {578 IO.mapRequired("Namespace", Symbol.Name);579}580 581template <> void SymbolRecordImpl<AnnotationSym>::map(IO &IO) {582 IO.mapOptional("Offset", Symbol.CodeOffset, 0U);583 IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));584 IO.mapRequired("Strings", Symbol.Strings);585}586 587template <> void SymbolRecordImpl<JumpTableSym>::map(IO &IO) {588 IO.mapRequired("BaseOffset", Symbol.BaseOffset);589 IO.mapRequired("BaseSegment", Symbol.BaseSegment);590 IO.mapRequired("SwitchType", Symbol.SwitchType);591 IO.mapRequired("BranchOffset", Symbol.BranchOffset);592 IO.mapRequired("TableOffset", Symbol.TableOffset);593 IO.mapRequired("BranchSegment", Symbol.BranchSegment);594 IO.mapRequired("TableSegment", Symbol.TableSegment);595 IO.mapRequired("EntriesCount", Symbol.EntriesCount);596}597 598template <> void SymbolRecordImpl<HotPatchFuncSym>::map(IO &IO) {599 IO.mapRequired("Function", Symbol.Function);600 IO.mapRequired("Name", Symbol.Name);601}602 603} // end namespace detail604} // end namespace CodeViewYAML605} // end namespace llvm606 607CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol(608 BumpPtrAllocator &Allocator, CodeViewContainer Container) const {609 return Symbol->toCodeViewSymbol(Allocator, Container);610}611 612namespace llvm {613namespace yaml {614 615template <> struct MappingTraits<SymbolRecordBase> {616 static void mapping(IO &io, SymbolRecordBase &Record) { Record.map(io); }617};618 619} // end namespace yaml620} // end namespace llvm621 622template <typename SymbolType>623static inline Expected<CodeViewYAML::SymbolRecord>624fromCodeViewSymbolImpl(CVSymbol Symbol) {625 CodeViewYAML::SymbolRecord Result;626 627 auto Impl = std::make_shared<SymbolType>(Symbol.kind());628 if (auto EC = Impl->fromCodeViewSymbol(Symbol))629 return std::move(EC);630 Result.Symbol = Impl;631 return Result;632}633 634Expected<CodeViewYAML::SymbolRecord>635CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) {636#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \637 case EnumName: \638 return fromCodeViewSymbolImpl<SymbolRecordImpl<ClassName>>(Symbol);639#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \640 SYMBOL_RECORD(EnumName, EnumVal, ClassName)641 switch (Symbol.kind()) {642#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"643 default:644 return fromCodeViewSymbolImpl<UnknownSymbolRecord>(Symbol);645 }646 return make_error<CodeViewError>(cv_error_code::corrupt_record);647}648 649template <typename ConcreteType>650static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind,651 CodeViewYAML::SymbolRecord &Obj) {652 if (!IO.outputting())653 Obj.Symbol = std::make_shared<ConcreteType>(Kind);654 655 IO.mapRequired(Class, *Obj.Symbol);656}657 658void MappingTraits<CodeViewYAML::SymbolRecord>::mapping(659 IO &IO, CodeViewYAML::SymbolRecord &Obj) {660 SymbolKind Kind;661 if (IO.outputting())662 Kind = Obj.Symbol->Kind;663 IO.mapRequired("Kind", Kind);664 665#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \666 case EnumName: \667 mapSymbolRecordImpl<SymbolRecordImpl<ClassName>>(IO, #ClassName, Kind, \668 Obj); \669 break;670#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \671 SYMBOL_RECORD(EnumName, EnumVal, ClassName)672 switch (Kind) {673#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"674 default:675 mapSymbolRecordImpl<UnknownSymbolRecord>(IO, "UnknownSym", Kind, Obj);676 }677}678