1 //===- MachOYAML.h - Mach-O YAMLIO implementation ---------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief This file declares classes for handling the YAML representation 12 /// of Mach-O. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_OBJECTYAML_MACHOYAML_H 17 #define LLVM_OBJECTYAML_MACHOYAML_H 18 19 #include "llvm/BinaryFormat/MachO.h" 20 #include "llvm/ObjectYAML/DWARFYAML.h" 21 #include "llvm/ObjectYAML/YAML.h" 22 23 namespace llvm { 24 namespace MachOYAML { 25 26 struct Section { 27 char sectname[16]; 28 char segname[16]; 29 llvm::yaml::Hex64 addr; 30 uint64_t size; 31 llvm::yaml::Hex32 offset; 32 uint32_t align; 33 llvm::yaml::Hex32 reloff; 34 uint32_t nreloc; 35 llvm::yaml::Hex32 flags; 36 llvm::yaml::Hex32 reserved1; 37 llvm::yaml::Hex32 reserved2; 38 llvm::yaml::Hex32 reserved3; 39 }; 40 41 struct FileHeader { 42 llvm::yaml::Hex32 magic; 43 llvm::yaml::Hex32 cputype; 44 llvm::yaml::Hex32 cpusubtype; 45 llvm::yaml::Hex32 filetype; 46 uint32_t ncmds; 47 uint32_t sizeofcmds; 48 llvm::yaml::Hex32 flags; 49 llvm::yaml::Hex32 reserved; 50 }; 51 52 struct LoadCommand { 53 virtual ~LoadCommand(); 54 llvm::MachO::macho_load_command Data; 55 std::vector<Section> Sections; 56 std::vector<MachO::build_tool_version> Tools; 57 std::vector<llvm::yaml::Hex8> PayloadBytes; 58 std::string PayloadString; 59 uint64_t ZeroPadBytes; 60 }; 61 62 struct NListEntry { 63 uint32_t n_strx; 64 llvm::yaml::Hex8 n_type; 65 uint8_t n_sect; 66 uint16_t n_desc; 67 uint64_t n_value; 68 }; 69 struct RebaseOpcode { 70 MachO::RebaseOpcode Opcode; 71 uint8_t Imm; 72 std::vector<yaml::Hex64> ExtraData; 73 }; 74 75 struct BindOpcode { 76 MachO::BindOpcode Opcode; 77 uint8_t Imm; 78 std::vector<yaml::Hex64> ULEBExtraData; 79 std::vector<int64_t> SLEBExtraData; 80 StringRef Symbol; 81 }; 82 83 struct ExportEntry { 84 ExportEntry() 85 : TerminalSize(0), NodeOffset(0), Name(), Flags(0), Address(0), Other(0), 86 ImportName(), Children() {} 87 uint64_t TerminalSize; 88 uint64_t NodeOffset; 89 std::string Name; 90 llvm::yaml::Hex64 Flags; 91 llvm::yaml::Hex64 Address; 92 llvm::yaml::Hex64 Other; 93 std::string ImportName; 94 std::vector<MachOYAML::ExportEntry> Children; 95 }; 96 97 struct LinkEditData { 98 std::vector<MachOYAML::RebaseOpcode> RebaseOpcodes; 99 std::vector<MachOYAML::BindOpcode> BindOpcodes; 100 std::vector<MachOYAML::BindOpcode> WeakBindOpcodes; 101 std::vector<MachOYAML::BindOpcode> LazyBindOpcodes; 102 MachOYAML::ExportEntry ExportTrie; 103 std::vector<NListEntry> NameList; 104 std::vector<StringRef> StringTable; 105 106 bool isEmpty() const; 107 }; 108 109 struct Object { 110 bool IsLittleEndian; 111 FileHeader Header; 112 std::vector<LoadCommand> LoadCommands; 113 std::vector<Section> Sections; 114 LinkEditData LinkEdit; 115 DWARFYAML::Data DWARF; 116 }; 117 118 struct FatHeader { 119 llvm::yaml::Hex32 magic; 120 uint32_t nfat_arch; 121 }; 122 123 struct FatArch { 124 llvm::yaml::Hex32 cputype; 125 llvm::yaml::Hex32 cpusubtype; 126 llvm::yaml::Hex64 offset; 127 uint64_t size; 128 uint32_t align; 129 llvm::yaml::Hex32 reserved; 130 }; 131 132 struct UniversalBinary { 133 FatHeader Header; 134 std::vector<FatArch> FatArchs; 135 std::vector<Object> Slices; 136 }; 137 138 } // namespace llvm::MachOYAML 139 } // namespace llvm 140 141 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::LoadCommand) 142 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Section) 143 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(int64_t) 144 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::RebaseOpcode) 145 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::BindOpcode) 146 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::ExportEntry) 147 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::NListEntry) 148 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Object) 149 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::FatArch) 150 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachO::build_tool_version) 151 152 namespace llvm { 153 namespace yaml { 154 155 template <> struct MappingTraits<MachOYAML::FileHeader> { 156 static void mapping(IO &IO, MachOYAML::FileHeader &FileHeader); 157 }; 158 159 template <> struct MappingTraits<MachOYAML::Object> { 160 static void mapping(IO &IO, MachOYAML::Object &Object); 161 }; 162 163 template <> struct MappingTraits<MachOYAML::FatHeader> { 164 static void mapping(IO &IO, MachOYAML::FatHeader &FatHeader); 165 }; 166 167 template <> struct MappingTraits<MachOYAML::FatArch> { 168 static void mapping(IO &IO, MachOYAML::FatArch &FatArch); 169 }; 170 171 template <> struct MappingTraits<MachOYAML::UniversalBinary> { 172 static void mapping(IO &IO, MachOYAML::UniversalBinary &UniversalBinary); 173 }; 174 175 template <> struct MappingTraits<MachOYAML::LoadCommand> { 176 static void mapping(IO &IO, MachOYAML::LoadCommand &LoadCommand); 177 }; 178 179 template <> struct MappingTraits<MachOYAML::LinkEditData> { 180 static void mapping(IO &IO, MachOYAML::LinkEditData &LinkEditData); 181 }; 182 183 template <> struct MappingTraits<MachOYAML::RebaseOpcode> { 184 static void mapping(IO &IO, MachOYAML::RebaseOpcode &RebaseOpcode); 185 }; 186 187 template <> struct MappingTraits<MachOYAML::BindOpcode> { 188 static void mapping(IO &IO, MachOYAML::BindOpcode &BindOpcode); 189 }; 190 191 template <> struct MappingTraits<MachOYAML::ExportEntry> { 192 static void mapping(IO &IO, MachOYAML::ExportEntry &ExportEntry); 193 }; 194 195 template <> struct MappingTraits<MachOYAML::Section> { 196 static void mapping(IO &IO, MachOYAML::Section &Section); 197 }; 198 199 template <> struct MappingTraits<MachOYAML::NListEntry> { 200 static void mapping(IO &IO, MachOYAML::NListEntry &NListEntry); 201 }; 202 203 template <> struct MappingTraits<MachO::build_tool_version> { 204 static void mapping(IO &IO, MachO::build_tool_version &tool); 205 }; 206 207 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ 208 io.enumCase(value, #LCName, MachO::LCName); 209 210 template <> struct ScalarEnumerationTraits<MachO::LoadCommandType> { 211 static void enumeration(IO &io, MachO::LoadCommandType &value) { 212 #include "llvm/BinaryFormat/MachO.def" 213 io.enumFallback<Hex32>(value); 214 } 215 }; 216 217 #define ENUM_CASE(Enum) io.enumCase(value, #Enum, MachO::Enum); 218 219 template <> struct ScalarEnumerationTraits<MachO::RebaseOpcode> { 220 static void enumeration(IO &io, MachO::RebaseOpcode &value) { 221 ENUM_CASE(REBASE_OPCODE_DONE) 222 ENUM_CASE(REBASE_OPCODE_SET_TYPE_IMM) 223 ENUM_CASE(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB) 224 ENUM_CASE(REBASE_OPCODE_ADD_ADDR_ULEB) 225 ENUM_CASE(REBASE_OPCODE_ADD_ADDR_IMM_SCALED) 226 ENUM_CASE(REBASE_OPCODE_DO_REBASE_IMM_TIMES) 227 ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES) 228 ENUM_CASE(REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB) 229 ENUM_CASE(REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB) 230 io.enumFallback<Hex8>(value); 231 } 232 }; 233 234 template <> struct ScalarEnumerationTraits<MachO::BindOpcode> { 235 static void enumeration(IO &io, MachO::BindOpcode &value) { 236 ENUM_CASE(BIND_OPCODE_DONE) 237 ENUM_CASE(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM) 238 ENUM_CASE(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB) 239 ENUM_CASE(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM) 240 ENUM_CASE(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM) 241 ENUM_CASE(BIND_OPCODE_SET_TYPE_IMM) 242 ENUM_CASE(BIND_OPCODE_SET_ADDEND_SLEB) 243 ENUM_CASE(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB) 244 ENUM_CASE(BIND_OPCODE_ADD_ADDR_ULEB) 245 ENUM_CASE(BIND_OPCODE_DO_BIND) 246 ENUM_CASE(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) 247 ENUM_CASE(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED) 248 ENUM_CASE(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB) 249 io.enumFallback<Hex8>(value); 250 } 251 }; 252 253 // This trait is used for 16-byte chars in Mach structures used for strings 254 typedef char char_16[16]; 255 256 template <> struct ScalarTraits<char_16> { 257 static void output(const char_16 &Val, void *, llvm::raw_ostream &Out); 258 259 static StringRef input(StringRef Scalar, void *, char_16 &Val); 260 static bool mustQuote(StringRef S); 261 }; 262 263 // This trait is used for UUIDs. It reads and writes them matching otool's 264 // formatting style. 265 typedef uint8_t uuid_t[16]; 266 267 template <> struct ScalarTraits<uuid_t> { 268 static void output(const uuid_t &Val, void *, llvm::raw_ostream &Out); 269 270 static StringRef input(StringRef Scalar, void *, uuid_t &Val); 271 static bool mustQuote(StringRef S); 272 }; 273 274 // Load Command struct mapping traits 275 276 #define LOAD_COMMAND_STRUCT(LCStruct) \ 277 template <> struct MappingTraits<MachO::LCStruct> { \ 278 static void mapping(IO &IO, MachO::LCStruct &LoadCommand); \ 279 }; 280 281 #include "llvm/BinaryFormat/MachO.def" 282 283 // Extra structures used by load commands 284 template <> struct MappingTraits<MachO::dylib> { 285 static void mapping(IO &IO, MachO::dylib &LoadCommand); 286 }; 287 288 template <> struct MappingTraits<MachO::fvmlib> { 289 static void mapping(IO &IO, MachO::fvmlib &LoadCommand); 290 }; 291 292 template <> struct MappingTraits<MachO::section> { 293 static void mapping(IO &IO, MachO::section &LoadCommand); 294 }; 295 296 template <> struct MappingTraits<MachO::section_64> { 297 static void mapping(IO &IO, MachO::section_64 &LoadCommand); 298 }; 299 300 } // namespace llvm::yaml 301 302 } // namespace llvm 303 304 #endif 305