| 1 | //===-- PdbYaml.cpp ------------------------------------------- *- C++ --*-===// |
| 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 | #include "PdbYaml.h" |
| 10 | |
| 11 | #include "llvm/ADT/StringExtras.h" |
| 12 | #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" |
| 13 | #include "llvm/DebugInfo/PDB/Native/PDBFile.h" |
| 14 | #include "llvm/DebugInfo/PDB/Native/RawTypes.h" |
| 15 | #include "llvm/DebugInfo/PDB/Native/TpiHashing.h" |
| 16 | #include "llvm/DebugInfo/PDB/PDBTypes.h" |
| 17 | #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" |
| 18 | #include "llvm/ObjectYAML/CodeViewYAMLTypes.h" |
| 19 | |
| 20 | using namespace llvm; |
| 21 | using namespace llvm::pdb; |
| 22 | using namespace llvm::pdb::yaml; |
| 23 | using namespace llvm::yaml; |
| 24 | |
| 25 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping) |
| 26 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo) |
| 27 | LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) |
| 28 | LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::pdb::PdbRaw_FeatureSig) |
| 29 | |
| 30 | namespace llvm { |
| 31 | namespace yaml { |
| 32 | |
| 33 | template <> struct ScalarEnumerationTraits<llvm::pdb::PDB_Machine> { |
| 34 | static void enumeration(IO &io, llvm::pdb::PDB_Machine &Value) { |
| 35 | io.enumCase(Val&: Value, Str: "Invalid" , ConstVal: PDB_Machine::Invalid); |
| 36 | io.enumCase(Val&: Value, Str: "Am33" , ConstVal: PDB_Machine::Am33); |
| 37 | io.enumCase(Val&: Value, Str: "Amd64" , ConstVal: PDB_Machine::Amd64); |
| 38 | io.enumCase(Val&: Value, Str: "Arm" , ConstVal: PDB_Machine::Arm); |
| 39 | io.enumCase(Val&: Value, Str: "ArmNT" , ConstVal: PDB_Machine::ArmNT); |
| 40 | io.enumCase(Val&: Value, Str: "Ebc" , ConstVal: PDB_Machine::Ebc); |
| 41 | io.enumCase(Val&: Value, Str: "x86" , ConstVal: PDB_Machine::x86); |
| 42 | io.enumCase(Val&: Value, Str: "Ia64" , ConstVal: PDB_Machine::Ia64); |
| 43 | io.enumCase(Val&: Value, Str: "M32R" , ConstVal: PDB_Machine::M32R); |
| 44 | io.enumCase(Val&: Value, Str: "Mips16" , ConstVal: PDB_Machine::Mips16); |
| 45 | io.enumCase(Val&: Value, Str: "MipsFpu" , ConstVal: PDB_Machine::MipsFpu); |
| 46 | io.enumCase(Val&: Value, Str: "MipsFpu16" , ConstVal: PDB_Machine::MipsFpu16); |
| 47 | io.enumCase(Val&: Value, Str: "PowerPCFP" , ConstVal: PDB_Machine::PowerPCFP); |
| 48 | io.enumCase(Val&: Value, Str: "R4000" , ConstVal: PDB_Machine::R4000); |
| 49 | io.enumCase(Val&: Value, Str: "SH3" , ConstVal: PDB_Machine::SH3); |
| 50 | io.enumCase(Val&: Value, Str: "SH3DSP" , ConstVal: PDB_Machine::SH3DSP); |
| 51 | io.enumCase(Val&: Value, Str: "Thumb" , ConstVal: PDB_Machine::Thumb); |
| 52 | io.enumCase(Val&: Value, Str: "WceMipsV2" , ConstVal: PDB_Machine::WceMipsV2); |
| 53 | io.enumCase(Val&: Value, Str: "Arm64" , ConstVal: PDB_Machine::Arm64); |
| 54 | } |
| 55 | }; |
| 56 | |
| 57 | template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_DbiVer> { |
| 58 | static void enumeration(IO &io, llvm::pdb::PdbRaw_DbiVer &Value) { |
| 59 | io.enumCase(Val&: Value, Str: "V41" , ConstVal: llvm::pdb::PdbRaw_DbiVer::PdbDbiVC41); |
| 60 | io.enumCase(Val&: Value, Str: "V50" , ConstVal: llvm::pdb::PdbRaw_DbiVer::PdbDbiV50); |
| 61 | io.enumCase(Val&: Value, Str: "V60" , ConstVal: llvm::pdb::PdbRaw_DbiVer::PdbDbiV60); |
| 62 | io.enumCase(Val&: Value, Str: "V70" , ConstVal: llvm::pdb::PdbRaw_DbiVer::PdbDbiV70); |
| 63 | io.enumCase(Val&: Value, Str: "V110" , ConstVal: llvm::pdb::PdbRaw_DbiVer::PdbDbiV110); |
| 64 | } |
| 65 | }; |
| 66 | |
| 67 | template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_ImplVer> { |
| 68 | static void enumeration(IO &io, llvm::pdb::PdbRaw_ImplVer &Value) { |
| 69 | io.enumCase(Val&: Value, Str: "VC2" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC2); |
| 70 | io.enumCase(Val&: Value, Str: "VC4" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC4); |
| 71 | io.enumCase(Val&: Value, Str: "VC41" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC41); |
| 72 | io.enumCase(Val&: Value, Str: "VC50" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC50); |
| 73 | io.enumCase(Val&: Value, Str: "VC98" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC98); |
| 74 | io.enumCase(Val&: Value, Str: "VC70Dep" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC70Dep); |
| 75 | io.enumCase(Val&: Value, Str: "VC70" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC70); |
| 76 | io.enumCase(Val&: Value, Str: "VC80" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC80); |
| 77 | io.enumCase(Val&: Value, Str: "VC110" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC110); |
| 78 | io.enumCase(Val&: Value, Str: "VC140" , ConstVal: llvm::pdb::PdbRaw_ImplVer::PdbImplVC140); |
| 79 | } |
| 80 | }; |
| 81 | |
| 82 | template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_TpiVer> { |
| 83 | static void enumeration(IO &io, llvm::pdb::PdbRaw_TpiVer &Value) { |
| 84 | io.enumCase(Val&: Value, Str: "VC40" , ConstVal: llvm::pdb::PdbRaw_TpiVer::PdbTpiV40); |
| 85 | io.enumCase(Val&: Value, Str: "VC41" , ConstVal: llvm::pdb::PdbRaw_TpiVer::PdbTpiV41); |
| 86 | io.enumCase(Val&: Value, Str: "VC50" , ConstVal: llvm::pdb::PdbRaw_TpiVer::PdbTpiV50); |
| 87 | io.enumCase(Val&: Value, Str: "VC70" , ConstVal: llvm::pdb::PdbRaw_TpiVer::PdbTpiV70); |
| 88 | io.enumCase(Val&: Value, Str: "VC80" , ConstVal: llvm::pdb::PdbRaw_TpiVer::PdbTpiV80); |
| 89 | } |
| 90 | }; |
| 91 | |
| 92 | template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_FeatureSig> { |
| 93 | static void enumeration(IO &io, PdbRaw_FeatureSig &Features) { |
| 94 | io.enumCase(Val&: Features, Str: "MinimalDebugInfo" , |
| 95 | ConstVal: PdbRaw_FeatureSig::MinimalDebugInfo); |
| 96 | io.enumCase(Val&: Features, Str: "NoTypeMerge" , ConstVal: PdbRaw_FeatureSig::NoTypeMerge); |
| 97 | io.enumCase(Val&: Features, Str: "VC110" , ConstVal: PdbRaw_FeatureSig::VC110); |
| 98 | io.enumCase(Val&: Features, Str: "VC140" , ConstVal: PdbRaw_FeatureSig::VC140); |
| 99 | } |
| 100 | }; |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) { |
| 105 | IO.mapOptional(Key: "MSF" , Val&: Obj.Headers); |
| 106 | IO.mapOptional(Key: "StreamSizes" , Val&: Obj.StreamSizes); |
| 107 | IO.mapOptional(Key: "StreamMap" , Val&: Obj.StreamMap); |
| 108 | IO.mapOptional(Key: "StringTable" , Val&: Obj.StringTable); |
| 109 | IO.mapOptional(Key: "PdbStream" , Val&: Obj.PdbStream); |
| 110 | IO.mapOptional(Key: "DbiStream" , Val&: Obj.DbiStream); |
| 111 | IO.mapOptional(Key: "TpiStream" , Val&: Obj.TpiStream); |
| 112 | IO.mapOptional(Key: "IpiStream" , Val&: Obj.IpiStream); |
| 113 | IO.mapOptional(Key: "PublicsStream" , Val&: Obj.PublicsStream); |
| 114 | } |
| 115 | |
| 116 | void MappingTraits<MSFHeaders>::(IO &IO, MSFHeaders &Obj) { |
| 117 | IO.mapOptional(Key: "SuperBlock" , Val&: Obj.SuperBlock); |
| 118 | IO.mapOptional(Key: "NumDirectoryBlocks" , Val&: Obj.NumDirectoryBlocks); |
| 119 | IO.mapOptional(Key: "DirectoryBlocks" , Val&: Obj.DirectoryBlocks); |
| 120 | IO.mapOptional(Key: "NumStreams" , Val&: Obj.NumStreams); |
| 121 | IO.mapOptional(Key: "FileSize" , Val&: Obj.FileSize); |
| 122 | } |
| 123 | |
| 124 | void MappingTraits<msf::SuperBlock>::mapping(IO &IO, msf::SuperBlock &SB) { |
| 125 | if (!IO.outputting()) { |
| 126 | ::memcpy(dest: SB.MagicBytes, src: msf::Magic, n: sizeof(msf::Magic)); |
| 127 | } |
| 128 | |
| 129 | using u32 = support::ulittle32_t; |
| 130 | IO.mapOptional(Key: "BlockSize" , Val&: SB.BlockSize, Default: u32(4096U)); |
| 131 | IO.mapOptional(Key: "FreeBlockMap" , Val&: SB.FreeBlockMapBlock, Default: u32(0U)); |
| 132 | IO.mapOptional(Key: "NumBlocks" , Val&: SB.NumBlocks, Default: u32(0U)); |
| 133 | IO.mapOptional(Key: "NumDirectoryBytes" , Val&: SB.NumDirectoryBytes, Default: u32(0U)); |
| 134 | IO.mapOptional(Key: "Unknown1" , Val&: SB.Unknown1, Default: u32(0U)); |
| 135 | IO.mapOptional(Key: "BlockMapAddr" , Val&: SB.BlockMapAddr, Default: u32(0U)); |
| 136 | } |
| 137 | |
| 138 | void MappingTraits<StreamBlockList>::mapping(IO &IO, StreamBlockList &SB) { |
| 139 | IO.mapRequired(Key: "Stream" , Val&: SB.Blocks); |
| 140 | } |
| 141 | |
| 142 | void MappingTraits<PdbInfoStream>::mapping(IO &IO, PdbInfoStream &Obj) { |
| 143 | IO.mapOptional(Key: "Age" , Val&: Obj.Age, Default: 1U); |
| 144 | IO.mapOptional(Key: "Guid" , Val&: Obj.Guid); |
| 145 | IO.mapOptional(Key: "Signature" , Val&: Obj.Signature, Default: 0U); |
| 146 | IO.mapOptional(Key: "Features" , Val&: Obj.Features); |
| 147 | IO.mapOptional(Key: "Version" , Val&: Obj.Version, Default: PdbImplVC70); |
| 148 | } |
| 149 | |
| 150 | void MappingTraits<PdbDbiStream>::mapping(IO &IO, PdbDbiStream &Obj) { |
| 151 | IO.mapOptional(Key: "VerHeader" , Val&: Obj.VerHeader, Default: PdbDbiV70); |
| 152 | IO.mapOptional(Key: "Age" , Val&: Obj.Age, Default: 1U); |
| 153 | IO.mapOptional(Key: "BuildNumber" , Val&: Obj.BuildNumber, Default: uint16_t(0U)); |
| 154 | IO.mapOptional(Key: "PdbDllVersion" , Val&: Obj.PdbDllVersion, Default: 0U); |
| 155 | IO.mapOptional(Key: "PdbDllRbld" , Val&: Obj.PdbDllRbld, Default: uint16_t(0U)); |
| 156 | IO.mapOptional(Key: "Flags" , Val&: Obj.Flags, Default: uint16_t(1U)); |
| 157 | IO.mapOptional(Key: "MachineType" , Val&: Obj.MachineType, Default: PDB_Machine::x86); |
| 158 | // This is a workaround for IO not having document context with the |
| 159 | // machine type. The machine type is needed to properly parse Register enums |
| 160 | // in the PDB. |
| 161 | if (!IO.getContext()) { |
| 162 | Obj.FakeHeader.Machine = static_cast<uint16_t>(Obj.MachineType); |
| 163 | IO.setContext(&Obj.FakeHeader); |
| 164 | } |
| 165 | IO.mapOptional(Key: "Modules" , Val&: Obj.ModInfos); |
| 166 | } |
| 167 | |
| 168 | void MappingTraits<PdbTpiStream>::mapping(IO &IO, |
| 169 | pdb::yaml::PdbTpiStream &Obj) { |
| 170 | IO.mapOptional(Key: "Version" , Val&: Obj.Version, Default: PdbTpiV80); |
| 171 | IO.mapRequired(Key: "Records" , Val&: Obj.Records); |
| 172 | } |
| 173 | |
| 174 | void MappingTraits<PdbPublicsStream>::mapping( |
| 175 | IO &IO, pdb::yaml::PdbPublicsStream &Obj) { |
| 176 | IO.mapRequired(Key: "Records" , Val&: Obj.PubSyms); |
| 177 | } |
| 178 | |
| 179 | void MappingTraits<NamedStreamMapping>::mapping(IO &IO, |
| 180 | NamedStreamMapping &Obj) { |
| 181 | IO.mapRequired(Key: "Name" , Val&: Obj.StreamName); |
| 182 | IO.mapRequired(Key: "StreamNum" , Val&: Obj.StreamNumber); |
| 183 | } |
| 184 | |
| 185 | void MappingTraits<PdbModiStream>::mapping(IO &IO, PdbModiStream &Obj) { |
| 186 | IO.mapOptional(Key: "Signature" , Val&: Obj.Signature, Default: 4U); |
| 187 | IO.mapRequired(Key: "Records" , Val&: Obj.Symbols); |
| 188 | } |
| 189 | |
| 190 | void MappingTraits<PdbDbiModuleInfo>::mapping(IO &IO, PdbDbiModuleInfo &Obj) { |
| 191 | IO.mapRequired(Key: "Module" , Val&: Obj.Mod); |
| 192 | IO.mapOptional(Key: "ObjFile" , Val&: Obj.Obj, Default: Obj.Mod); |
| 193 | IO.mapOptional(Key: "SourceFiles" , Val&: Obj.SourceFiles); |
| 194 | IO.mapOptional(Key: "Subsections" , Val&: Obj.Subsections); |
| 195 | IO.mapOptional(Key: "Modi" , Val&: Obj.Modi); |
| 196 | } |
| 197 | |