diff --git a/macho/types.cpp b/macho/types.cpp new file mode 100644 index 000000000..b243716e8 --- /dev/null +++ b/macho/types.cpp @@ -0,0 +1,869 @@ +#include "macho/types.h" + +#include +#include + +using namespace BinaryNinja; + +namespace BinaryNinja::MachO { + +namespace { + Ref BuildEnum(Ref view, const std::string& name, size_t width, + std::initializer_list> values) + { + EnumerationBuilder builder; + for (const auto& value : values) + builder.AddMemberWithValue(std::string(value.first), value.second); + Ref type = Type::EnumerationType(nullptr, builder.Finalize(), width, false); + QualifiedName qualName(name); + std::string typeId = Type::GenerateAutoTypeId("macho", qualName); + return Type::NamedType(view, view->DefineType(typeId, qualName, type)); + } + + Ref BuildStruct(Ref view, const std::string& name, bool packed, + std::initializer_list>> members) + { + StructureBuilder builder; + builder.SetPacked(packed); + for (const auto& member : members) + builder.AddMember(member.second, std::string(member.first)); + Ref type = Type::StructureType(builder.Finalize()); + QualifiedName qualName(name); + std::string typeId = Type::GenerateAutoTypeId("macho", qualName); + return Type::NamedType(view, view->DefineType(typeId, qualName, type)); + } + +} // namespace + +void CreateHeaderTypes(Ref view) +{ + auto cpuTypeEnum = BuildEnum(view, "cpu_type_t", 4, + { + // clang-format off + {"CPU_TYPE_ANY", MACHO_CPU_TYPE_ANY}, + {"CPU_TYPE_VAX", MACHO_CPU_TYPE_VAX}, + {"CPU_TYPE_MC680x0", MACHO_CPU_TYPE_MC680x0}, + {"CPU_TYPE_X86", MACHO_CPU_TYPE_X86}, + {"CPU_TYPE_X86_64", MACHO_CPU_TYPE_X86_64}, + {"CPU_TYPE_MIPS", MACHO_CPU_TYPE_MIPS}, + {"CPU_TYPE_MC98000", MACHO_CPU_TYPE_MC98000}, + {"CPU_TYPE_HPPA", MACHO_CPU_TYPE_HPPA}, + {"CPU_TYPE_ARM", MACHO_CPU_TYPE_ARM}, + {"CPU_TYPE_ARM64", MACHO_CPU_TYPE_ARM64}, + {"CPU_TYPE_ARM64_32", MACHO_CPU_TYPE_ARM64_32}, + {"CPU_TYPE_MC88000", MACHO_CPU_TYPE_MC88000}, + {"CPU_TYPE_SPARC", MACHO_CPU_TYPE_SPARC}, + {"CPU_TYPE_I860", MACHO_CPU_TYPE_I860}, + {"CPU_TYPE_ALPHA", MACHO_CPU_TYPE_ALPHA}, + {"CPU_TYPE_POWERPC", MACHO_CPU_TYPE_POWERPC}, + {"CPU_TYPE_POWERPC64", MACHO_CPU_TYPE_POWERPC64} + // clang-format on + }); + + auto cpuSubTypeEnum = BuildEnum(view, "cpu_subtype_t", 4, + { + // clang-format off + {"CPU_SUBTYPE_MASK", MACHO_CPU_SUBTYPE_MASK}, + {"CPU_SUBTYPE_LIB64", MACHO_CPU_SUBTYPE_LIB64}, + {"CPU_SUBTYPE_INTEL_ALL", MACHO_CPU_SUBTYPE_I386_ALL}, + {"CPU_SUBTYPE_X86_ALL", MACHO_CPU_SUBTYPE_X86_ALL}, + {"CPU_SUBTYPE_X86_ARCH1", MACHO_CPU_SUBTYPE_X86_ARCH1}, + {"CPU_SUBTYPE_X86_64_ALL", MACHO_CPU_SUBTYPE_X86_64_ALL}, + {"CPU_SUBTYPE_X86_64_H", MACHO_CPU_SUBTYPE_X86_64_H}, + {"CPU_SUBTYPE_ARM_ALL", MACHO_CPU_SUBTYPE_ARM_ALL}, + {"CPU_SUBTYPE_ARM_V4T", MACHO_CPU_SUBTYPE_ARM_V4T}, + {"CPU_SUBTYPE_ARM_V6", MACHO_CPU_SUBTYPE_ARM_V6}, + {"CPU_SUBTYPE_ARM_V5TEJ", MACHO_CPU_SUBTYPE_ARM_V5TEJ}, + {"CPU_SUBTYPE_ARM_XSCALE", MACHO_CPU_SUBTYPE_ARM_XSCALE}, + {"CPU_SUBTYPE_ARM_V7", MACHO_CPU_SUBTYPE_ARM_V7}, + {"CPU_SUBTYPE_ARM_V7F", MACHO_CPU_SUBTYPE_ARM_V7F}, + {"CPU_SUBTYPE_ARM_V7S", MACHO_CPU_SUBTYPE_ARM_V7S}, + {"CPU_SUBTYPE_ARM_V7K", MACHO_CPU_SUBTYPE_ARM_V7K}, + {"CPU_SUBTYPE_ARM_V8", MACHO_CPU_SUBTYPE_ARM_V8}, + {"CPU_SUBTYPE_ARM_V6M", MACHO_CPU_SUBTYPE_ARM_V6M}, + {"CPU_SUBTYPE_ARM_V7M", MACHO_CPU_SUBTYPE_ARM_V7M}, + {"CPU_SUBTYPE_ARM_V7EM", MACHO_CPU_SUBTYPE_ARM_V7EM}, + {"CPU_SUBTYPE_ARM64_ALL", MACHO_CPU_SUBTYPE_ARM64_ALL}, + {"CPU_SUBTYPE_ARM64_V8", MACHO_CPU_SUBTYPE_ARM64_V8}, + {"CPU_SUBTYPE_ARM64E", MACHO_CPU_SUBTYPE_ARM64E}, + {"CPU_SUBTYPE_ARM64_32_ALL", MACHO_CPU_SUBTYPE_ARM64_32_ALL}, + {"CPU_SUBTYPE_ARM64_32_V8", MACHO_CPU_SUBTYPE_ARM64_32_V8}, + {"CPU_SUBTYPE_POWERPC_ALL", MACHO_CPU_SUBTYPE_POWERPC_ALL}, + {"CPU_SUBTYPE_POWERPC_601", MACHO_CPU_SUBTYPE_POWERPC_601}, + {"CPU_SUBTYPE_POWERPC_602", MACHO_CPU_SUBTYPE_POWERPC_602}, + {"CPU_SUBTYPE_POWERPC_603", MACHO_CPU_SUBTYPE_POWERPC_603}, + {"CPU_SUBTYPE_POWERPC_603e", MACHO_CPU_SUBTYPE_POWERPC_603e}, + {"CPU_SUBTYPE_POWERPC_603ev", MACHO_CPU_SUBTYPE_POWERPC_603ev}, + {"CPU_SUBTYPE_POWERPC_604", MACHO_CPU_SUBTYPE_POWERPC_604}, + {"CPU_SUBTYPE_POWERPC_604e", MACHO_CPU_SUBTYPE_POWERPC_604e}, + {"CPU_SUBTYPE_POWERPC_620", MACHO_CPU_SUBTYPE_POWERPC_620}, + {"CPU_SUBTYPE_POWERPC_750", MACHO_CPU_SUBTYPE_POWERPC_750}, + {"CPU_SUBTYPE_POWERPC_7400", MACHO_CPU_SUBTYPE_POWERPC_7400}, + {"CPU_SUBTYPE_POWERPC_7450", MACHO_CPU_SUBTYPE_POWERPC_7450}, + {"CPU_SUBTYPE_POWERPC_970", MACHO_CPU_SUBTYPE_POWERPC_970} + // clang-format on + }); + + auto fileTypeEnum = BuildEnum(view, "file_type_t", 4, + { + // clang-format off + {"MH_OBJECT", MH_OBJECT}, + {"MH_EXECUTE", MH_EXECUTE}, + {"MH_FVMLIB", MH_FVMLIB}, + {"MH_CORE", MH_CORE}, + {"MH_PRELOAD", MH_PRELOAD}, + {"MH_DYLIB", MH_DYLIB}, + {"MH_DYLINKER", MH_DYLINKER}, + {"MH_BUNDLE", MH_BUNDLE}, + {"MH_DYLIB_STUB", MH_DYLIB_STUB}, + {"MH_DSYM", MH_DSYM}, + {"MH_KEXT_BUNDLE", MH_KEXT_BUNDLE}, + {"MH_FILESET", MH_FILESET} + // clang-format on + }); + + auto flagsTypeEnum = BuildEnum(view, "flags_type_t", 4, + { + // clang-format off + {"MH_NOUNDEFS", MH_NOUNDEFS}, + {"MH_INCRLINK", MH_INCRLINK}, + {"MH_DYLDLINK", MH_DYLDLINK}, + {"MH_BINDATLOAD", MH_BINDATLOAD}, + {"MH_PREBOUND", MH_PREBOUND}, + {"MH_SPLIT_SEGS", MH_SPLIT_SEGS}, + {"MH_LAZY_INIT", MH_LAZY_INIT}, + {"MH_TWOLEVEL", MH_TWOLEVEL}, + {"MH_FORCE_FLAT", MH_FORCE_FLAT}, + {"MH_NOMULTIDEFS", MH_NOMULTIDEFS}, + {"MH_NOFIXPREBINDING", MH_NOFIXPREBINDING}, + {"MH_PREBINDABLE", MH_PREBINDABLE}, + {"MH_ALLMODSBOUND", MH_ALLMODSBOUND}, + {"MH_SUBSECTIONS_VIA_SYMBOLS", MH_SUBSECTIONS_VIA_SYMBOLS}, + {"MH_CANONICAL", MH_CANONICAL}, + {"MH_WEAK_DEFINES", MH_WEAK_DEFINES}, + {"MH_BINDS_TO_WEAK", MH_BINDS_TO_WEAK}, + {"MH_ALLOW_STACK_EXECUTION", MH_ALLOW_STACK_EXECUTION}, + {"MH_ROOT_SAFE", MH_ROOT_SAFE}, + {"MH_SETUID_SAFE", MH_SETUID_SAFE}, + {"MH_NO_REEXPORTED_DYLIBS", MH_NO_REEXPORTED_DYLIBS}, + {"MH_PIE", MH_PIE}, + {"MH_DEAD_STRIPPABLE_DYLIB", MH_DEAD_STRIPPABLE_DYLIB}, + {"MH_HAS_TLV_DESCRIPTORS", MH_HAS_TLV_DESCRIPTORS}, + {"MH_NO_HEAP_EXECUTION", MH_NO_HEAP_EXECUTION}, + {"MH_APP_EXTENSION_SAFE", _MH_APP_EXTENSION_SAFE}, + {"MH_NLIST_OUTOFSYNC_WITH_DYLDINFO", _MH_NLIST_OUTOFSYNC_WITH_DYLDINFO}, + {"MH_SIM_SUPPORT", _MH_SIM_SUPPORT}, + {"MH_DYLIB_IN_CACHE", _MH_DYLIB_IN_CACHE} + // clang-format on + }); + + Ref headerType; + if (view->GetAddressSize() == 8) + { + headerType = BuildStruct(view, "mach_header_64", false, + { + // clang-format off + {"magic", Type::IntegerType(4, false)}, + {"cputype", cpuTypeEnum}, + {"cpusubtype", cpuSubTypeEnum}, + {"filetype", fileTypeEnum}, + {"ncmds", Type::IntegerType(4, false)}, + {"sizeofcmds", Type::IntegerType(4, false)}, + {"flags", flagsTypeEnum}, + {"reserved", Type::IntegerType(4, false)} + // clang-format on + }); + } + else + { + headerType = BuildStruct(view, "mach_header", false, + { + // clang-format off + {"magic", Type::IntegerType(4, false)}, + {"cputype", cpuTypeEnum}, + {"cpusubtype", cpuSubTypeEnum}, + {"filetype", fileTypeEnum}, + {"ncmds", Type::IntegerType(4, false)}, + {"sizeofcmds", Type::IntegerType(4, false)}, + {"flags", flagsTypeEnum} + // clang-format on + }); + } + + auto cmdTypeEnum = BuildEnum(view, "load_command_type_t", 4, + { + // clang-format off + {"LC_REQ_DYLD", LC_REQ_DYLD}, + {"LC_SEGMENT", LC_SEGMENT}, + {"LC_SYMTAB", LC_SYMTAB}, + {"LC_SYMSEG", LC_SYMSEG}, + {"LC_THREAD", LC_THREAD}, + {"LC_UNIXTHREAD", LC_UNIXTHREAD}, + {"LC_LOADFVMLIB", LC_LOADFVMLIB}, + {"LC_IDFVMLIB", LC_IDFVMLIB}, + {"LC_IDENT", LC_IDENT}, + {"LC_FVMFILE", LC_FVMFILE}, + {"LC_PREPAGE", LC_PREPAGE}, + {"LC_DYSYMTAB", LC_DYSYMTAB}, + {"LC_LOAD_DYLIB", LC_LOAD_DYLIB}, + {"LC_ID_DYLIB", LC_ID_DYLIB}, + {"LC_LOAD_DYLINKER", LC_LOAD_DYLINKER}, + {"LC_ID_DYLINKER", LC_ID_DYLINKER}, + {"LC_PREBOUND_DYLIB", LC_PREBOUND_DYLIB}, + {"LC_ROUTINES", LC_ROUTINES}, + {"LC_SUB_FRAMEWORK", LC_SUB_FRAMEWORK}, + {"LC_SUB_UMBRELLA", LC_SUB_UMBRELLA}, + {"LC_SUB_CLIENT", LC_SUB_CLIENT}, + {"LC_SUB_LIBRARY", LC_SUB_LIBRARY}, + {"LC_TWOLEVEL_HINTS", LC_TWOLEVEL_HINTS}, + {"LC_PREBIND_CKSUM", LC_PREBIND_CKSUM}, + {"LC_LOAD_WEAK_DYLIB", LC_LOAD_WEAK_DYLIB}, + {"LC_SEGMENT_64", LC_SEGMENT_64}, + {"LC_ROUTINES_64", LC_ROUTINES_64}, + {"LC_UUID", LC_UUID}, + {"LC_RPATH", LC_RPATH}, + {"LC_CODE_SIGNATURE", LC_CODE_SIGNATURE}, + {"LC_SEGMENT_SPLIT_INFO", LC_SEGMENT_SPLIT_INFO}, + {"LC_REEXPORT_DYLIB", LC_REEXPORT_DYLIB}, + {"LC_LAZY_LOAD_DYLIB", LC_LAZY_LOAD_DYLIB}, + {"LC_ENCRYPTION_INFO", LC_ENCRYPTION_INFO}, + {"LC_DYLD_INFO", LC_DYLD_INFO}, + {"LC_DYLD_INFO_ONLY", LC_DYLD_INFO_ONLY}, + {"LC_LOAD_UPWARD_DYLIB", LC_LOAD_UPWARD_DYLIB}, + {"LC_VERSION_MIN_MACOSX", LC_VERSION_MIN_MACOSX}, + {"LC_VERSION_MIN_IPHONEOS", LC_VERSION_MIN_IPHONEOS}, + {"LC_FUNCTION_STARTS", LC_FUNCTION_STARTS}, + {"LC_DYLD_ENVIRONMENT", LC_DYLD_ENVIRONMENT}, + {"LC_MAIN", LC_MAIN}, + {"LC_DATA_IN_CODE", LC_DATA_IN_CODE}, + {"LC_SOURCE_VERSION", LC_SOURCE_VERSION}, + {"LC_DYLIB_CODE_SIGN_DRS", LC_DYLIB_CODE_SIGN_DRS}, + {"LC_ENCRYPTION_INFO_64", _LC_ENCRYPTION_INFO_64}, + {"LC_LINKER_OPTION", _LC_LINKER_OPTION}, + {"LC_LINKER_OPTIMIZATION_HINT", _LC_LINKER_OPTIMIZATION_HINT}, + {"LC_VERSION_MIN_TVOS", _LC_VERSION_MIN_TVOS}, + {"LC_VERSION_MIN_WATCHOS", LC_VERSION_MIN_WATCHOS}, + {"LC_NOTE", LC_NOTE}, + {"LC_BUILD_VERSION", LC_BUILD_VERSION}, + {"LC_DYLD_EXPORTS_TRIE", LC_DYLD_EXPORTS_TRIE}, + {"LC_DYLD_CHAINED_FIXUPS", LC_DYLD_CHAINED_FIXUPS}, + {"LC_FILESET_ENTRY", LC_FILESET_ENTRY} + // clang-format on + }); + + auto loadCommandType = BuildStruct(view, "load_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)} + // clang-format on + }); + + auto protTypeEnum = BuildEnum(view, "vm_prot_t", 4, + { + {"VM_PROT_NONE", MACHO_VM_PROT_NONE}, {"VM_PROT_READ", MACHO_VM_PROT_READ}, + {"VM_PROT_WRITE", MACHO_VM_PROT_WRITE}, {"VM_PROT_EXECUTE", MACHO_VM_PROT_EXECUTE}, + // {"VM_PROT_DEFAULT", MACHO_VM_PROT_DEFAULT}, + // {"VM_PROT_ALL", MACHO_VM_PROT_ALL}, + {"VM_PROT_NO_CHANGE", MACHO_VM_PROT_NO_CHANGE}, {"VM_PROT_COPY_OR_WANTS_COPY", MACHO_VM_PROT_COPY} + // {"VM_PROT_WANTS_COPY", MACHO_VM_PROT_WANTS_COPY}, + }); + + auto segFlagsTypeEnum = BuildEnum(view, "sg_flags_t", 4, + { + // clang-format off + {"SG_HIGHVM", SG_HIGHVM}, + {"SG_FVMLIB", SG_FVMLIB}, + {"SG_NORELOC", SG_NORELOC}, + {"SG_PROTECTED_VERSION_1", SG_PROTECTED_VERSION_1}, + {"SG_READ_ONLY_DATA", SG_READ_ONLY_DATA}, + // clang-format on + }); + + auto segmentCommandType = BuildStruct(view, "segment_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"segname", Type::ArrayType(Type::IntegerType(1, true), 16)}, + {"vmaddr", Type::IntegerType(4, false)}, + {"vmsize", Type::IntegerType(4, false)}, + {"fileoff", Type::IntegerType(4, false)}, + {"filesize", Type::IntegerType(4, false)}, + {"maxprot", protTypeEnum}, + {"initprot", protTypeEnum}, + {"nsects", Type::IntegerType(4, false)}, + {"flags", segFlagsTypeEnum} + // clang-format on + }); + + auto segmentCommand64Type = BuildStruct(view, "segment_command_64", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"segname", Type::ArrayType(Type::IntegerType(1, true), 16)}, + {"vmaddr", Type::IntegerType(8, false)}, + {"vmsize", Type::IntegerType(8, false)}, + {"fileoff", Type::IntegerType(8, false)}, + {"filesize", Type::IntegerType(8, false)}, + {"maxprot", protTypeEnum}, + {"initprot", protTypeEnum}, + {"nsects", Type::IntegerType(4, false)}, + {"flags", segFlagsTypeEnum} + // clang-format on + }); + + // TODO: These three enums are technically a single field 32-bit field in the struct. The upper 24 bits are bit + // flags while the lower 8 bits are mutually exclusive. This prevents Binary Ninja from rendering them in an ORd + // form. The upper 24 bits are split into two enums because a 24 bit enum field isn't handle correctly either. + auto sectionTypeEnum = BuildEnum(view, "section_type_t", 1, + { + {"S_REGULAR", S_REGULAR}, + {"S_ZEROFILL", S_ZEROFILL}, + {"S_CSTRING_LITERALS", S_CSTRING_LITERALS}, + {"S_4BYTE_LITERALS", S_4BYTE_LITERALS}, + {"S_8BYTE_LITERALS", S_8BYTE_LITERALS}, + {"S_LITERAL_POINTERS", S_LITERAL_POINTERS}, + {"S_NON_LAZY_SYMBOL_POINTERS", S_NON_LAZY_SYMBOL_POINTERS}, + {"S_LAZY_SYMBOL_POINTERS", S_LAZY_SYMBOL_POINTERS}, + {"S_SYMBOL_STUBS", S_SYMBOL_STUBS}, + {"S_MOD_INIT_FUNC_POINTERS", S_MOD_INIT_FUNC_POINTERS}, + {"S_MOD_TERM_FUNC_POINTERS", S_MOD_TERM_FUNC_POINTERS}, + {"S_COALESCED", S_COALESCED}, + {"S_GB_ZEROFILL", S_GB_ZEROFILL}, + {"S_INTERPOSING", S_INTERPOSING}, + {"S_16BYTE_LITERALS", S_16BYTE_LITERALS}, + {"S_DTRACE_DOF", S_DTRACE_DOF}, + {"S_LAZY_DYLIB_SYMBOL_POINTERS", S_LAZY_DYLIB_SYMBOL_POINTERS}, + {"S_THREAD_LOCAL_REGULAR", S_THREAD_LOCAL_REGULAR}, + {"S_THREAD_LOCAL_ZEROFILL", S_THREAD_LOCAL_ZEROFILL}, + {"S_THREAD_LOCAL_VARIABLES", S_THREAD_LOCAL_VARIABLES}, + {"S_THREAD_LOCAL_VARIABLE_POINTERS", S_THREAD_LOCAL_VARIABLE_POINTERS}, + {"S_THREAD_LOCAL_INIT_FUNCTION_POINTERS", S_THREAD_LOCAL_INIT_FUNCTION_POINTERS}, + {"S_INIT_FUNC_OFFSETS", S_INIT_FUNC_OFFSETS}, + }); + + auto sectionAttributesSysEnum = BuildEnum(view, "section_attr_sys_t", 1, + { + {"S_ATTR_DEBUG", (S_ATTR_DEBUG >> 24) & 0xff}, + {"S_ATTR_SELF_MODIFYING_CODE", (S_ATTR_SELF_MODIFYING_CODE >> 24) & 0xff}, + {"S_ATTR_LIVE_SUPPORT", (S_ATTR_LIVE_SUPPORT >> 24) & 0xff}, + {"S_ATTR_NO_DEAD_STRIP", (S_ATTR_NO_DEAD_STRIP >> 24) & 0xff}, + {"S_ATTR_STRIP_STATIC_SYMS", (S_ATTR_STRIP_STATIC_SYMS >> 24) & 0xff}, + {"S_ATTR_NO_TOC", (S_ATTR_NO_TOC >> 24) & 0xff}, + {"S_ATTR_PURE_INSTRUCTIONS", (S_ATTR_PURE_INSTRUCTIONS >> 24) & 0xff}, + }); + + auto sectionAttributesUserEnum = BuildEnum(view, "section_attr_user_t", 2, + { + {"S_ATTR_LOC_RELOC", (S_ATTR_LOC_RELOC >> 8) & 0xffff}, + {"S_ATTR_EXT_RELOC", (S_ATTR_EXT_RELOC >> 8) & 0xffff}, + {"S_ATTR_SOME_INSTRUCTIONS", (S_ATTR_SOME_INSTRUCTIONS >> 8) & 0xffff}, + }); + + auto sectionType = BuildStruct(view, "section", true, + { + // clang-format off + {"sectname", Type::ArrayType(Type::IntegerType(1, true), 16)}, + {"segname", Type::ArrayType(Type::IntegerType(1, true), 16)}, + {"addr", Type::IntegerType(4, false)}, + {"size", Type::IntegerType(4, false)}, + {"offset", Type::IntegerType(4, false)}, + {"align", Type::IntegerType(4, false)}, + {"reloff", Type::IntegerType(4, false)}, + {"nreloc", Type::IntegerType(4, false)}, + {"type", sectionTypeEnum}, + {"attrs_user", sectionAttributesUserEnum}, + {"attrs_sys", sectionAttributesSysEnum}, + {"reserved1", Type::IntegerType(4, false)}, + {"reserved2", Type::IntegerType(4, false)} + // clang-format on + }); + + auto section64Type = BuildStruct(view, "section_64", true, + { + // clang-format off + {"sectname", Type::ArrayType(Type::IntegerType(1, true), 16)}, + {"segname", Type::ArrayType(Type::IntegerType(1, true), 16)}, + {"addr", Type::IntegerType(8, false)}, + {"size", Type::IntegerType(8, false)}, + {"offset", Type::IntegerType(4, false)}, + {"align", Type::IntegerType(4, false)}, + {"reloff", Type::IntegerType(4, false)}, + {"nreloc", Type::IntegerType(4, false)}, + {"type", sectionTypeEnum}, + {"attrs_user", sectionAttributesUserEnum}, + {"attrs_sys", sectionAttributesSysEnum}, + {"reserved1", Type::IntegerType(4, false)}, + {"reserved2", Type::IntegerType(4, false)}, + {"reserved3", Type::IntegerType(4, false)} + // clang-format on + }); + + auto symtabCommandType = BuildStruct(view, "symtab_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"symoff", Type::IntegerType(4, false)}, + {"nsyms", Type::IntegerType(4, false)}, + {"stroff", Type::IntegerType(4, false)}, + {"strsize", Type::IntegerType(4, false)} + // clang-format on + }); + + auto dysymtabCommandType = BuildStruct(view, "dysymtab_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"ilocalsym", Type::IntegerType(4, false)}, + {"nlocalsym", Type::IntegerType(4, false)}, + {"iextdefsym", Type::IntegerType(4, false)}, + {"nextdefsym", Type::IntegerType(4, false)}, + {"iundefsym", Type::IntegerType(4, false)}, + {"nundefsym", Type::IntegerType(4, false)}, + {"tocoff", Type::IntegerType(4, false)}, + {"ntoc", Type::IntegerType(4, false)}, + {"modtaboff", Type::IntegerType(4, false)}, + {"nmodtab", Type::IntegerType(4, false)}, + {"extrefsymoff", Type::IntegerType(4, false)}, + {"nextrefsyms", Type::IntegerType(4, false)}, + {"indirectsymoff", Type::IntegerType(4, false)}, + {"nindirectsyms", Type::IntegerType(4, false)}, + {"extreloff", Type::IntegerType(4, false)}, + {"nextrel", Type::IntegerType(4, false)}, + {"locreloff", Type::IntegerType(4, false)}, + {"nlocrel", Type::IntegerType(4, false)} + // clang-format on + }); + + auto uuidCommandType = BuildStruct(view, "uuid_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"uuid", Type::ArrayType(Type::IntegerType(1, true), 16)} + // clang-format on + }); + + auto linkeditDataCommandType = BuildStruct(view, "linkedit_data_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"dataoff", Type::IntegerType(4, false)}, + {"datasize", Type::IntegerType(4, false)} + // clang-format on + }); + + auto encryptionInfoCommandType = BuildStruct(view, "encryption_info_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"cryptoff", Type::IntegerType(4, false)}, + {"cryptsize", Type::IntegerType(4, false)}, + {"cryptid", Type::IntegerType(4, false)} + // clang-format on + }); + + auto versionMinCommandType = BuildStruct(view, "version_min_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"version", Type::IntegerType(4, false)}, + {"sdk", Type::IntegerType(4, false)} + // clang-format on + }); + + auto dyldInfoCommandType = BuildStruct(view, "dyld_info_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"rebase_off", Type::IntegerType(4, false)}, + {"rebase_size", Type::IntegerType(4, false)}, + {"bind_off", Type::IntegerType(4, false)}, + {"bind_size", Type::IntegerType(4, false)}, + {"weak_bind_off", Type::IntegerType(4, false)}, + {"weak_bind_size", Type::IntegerType(4, false)}, + {"lazy_bind_off", Type::IntegerType(4, false)}, + {"lazy_bind_size", Type::IntegerType(4, false)}, + {"export_off", Type::IntegerType(4, false)}, + {"export_size", Type::IntegerType(4, false)} + // clang-format on + }); + + QualifiedName lcStringName("lc_str"); + std::string lcStringTypeId = Type::GenerateAutoTypeId("macho", lcStringName); + auto lcStringType = Type::NamedType(view, + view->DefineType(lcStringTypeId, lcStringName, + TypeBuilder::PointerType(4, Type::IntegerType(1, true)) + .SetPointerBase(RelativeToVariableAddressPointerBaseType, -8) + .Finalize())); + + auto dylibType = BuildStruct(view, "dylib", false, + { + // clang-format off + {"name", lcStringType}, + {"timestamp", Type::IntegerType(4, false)}, + {"current_version", Type::IntegerType(4, false)}, + {"compatibility_version", Type::IntegerType(4, false)} + // clang-format on + }); + + auto dylibCommandType = BuildStruct(view, "dylib_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"dylib", dylibType} + // clang-format on + }); + + auto dylibUseMarkerEnum = BuildEnum(view, "dylib_use_marker_t", 4, + { + {"DYLIB_USE_MARKER", DYLIB_USE_MARKER}, + }); + + auto dylibUseFlagsEnum = BuildEnum(view, "dylib_use_flags_t", 4, + { + // clang-format off + {"DYLIB_USE_WEAK_LINK", DYLIB_USE_WEAK_LINK}, + {"DYLIB_USE_REEXPORT", DYLIB_USE_REEXPORT}, + {"DYLIB_USE_UPWARD", DYLIB_USE_UPWARD}, + {"DYLIB_USE_DELAYED_INIT", DYLIB_USE_DELAYED_INIT} + // clang-format on + }); + + auto dylibUseCommandType = BuildStruct(view, "dylib_use_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"nameoff", lcStringType}, + {"marker", dylibUseMarkerEnum}, + {"current_version", Type::IntegerType(4, false)}, + {"compat_version", Type::IntegerType(4, false)}, + {"flags", dylibUseFlagsEnum} + // clang-format on + }); + + QualifiedName filesetEntryIdName("fileset_entry_id"); + std::string filesetEntryIdId = Type::GenerateAutoTypeId("macho", filesetEntryIdName); + auto filesetEntryIdType = Type::NamedType(view, + view->DefineType(filesetEntryIdId, filesetEntryIdName, + TypeBuilder::PointerType(4, Type::IntegerType(1, true)) + .SetPointerBase(RelativeToVariableAddressPointerBaseType, -24) + .Finalize())); + + auto filesetEntryCommandType = BuildStruct(view, "fileset_entry_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"vmaddr", Type::IntegerType(8, false)}, + {"fileoff", Type::IntegerType(8, false)}, + {"entry_id", filesetEntryIdType}, + {"reserved", Type::IntegerType(4, false)} + // clang-format on + }); + + auto unixThreadCommandType = BuildStruct(view, "unix_thread_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"flavor", Type::IntegerType(4, false)}, + {"count", Type::IntegerType(4, false)}, + // The 'state' field is intentionally ignored. + // clang-format off + }); + + auto platformTypeEnum = BuildEnum(view, "macho_platform_t", 4, + { + // clang-format off + {"MACHO_PLATFORM_MACOS", MACHO_PLATFORM_MACOS}, + {"MACHO_PLATFORM_IOS", MACHO_PLATFORM_IOS}, + {"MACHO_PLATFORM_TVOS", MACHO_PLATFORM_TVOS}, + {"MACHO_PLATFORM_WATCHOS", MACHO_PLATFORM_WATCHOS}, + {"MACHO_PLATFORM_BRIDGEOS", MACHO_PLATFORM_BRIDGEOS}, + {"MACHO_PLATFORM_MACCATALYST", MACHO_PLATFORM_MACCATALYST}, + {"MACHO_PLATFORM_IOSSIMULATOR", MACHO_PLATFORM_IOSSIMULATOR}, + {"MACHO_PLATFORM_TVOSSIMULATOR", MACHO_PLATFORM_TVOSSIMULATOR}, + {"MACHO_PLATFORM_WATCHOSSIMULATOR", MACHO_PLATFORM_WATCHOSSIMULATOR}, + {"MACHO_PLATFORM_DRIVERKIT", MACHO_PLATFORM_DRIVERKIT}, + {"MACHO_PLATFORM_VISIONOS", MACHO_PLATFORM_VISIONOS}, + {"MACHO_PLATFORM_VISIONOSSIMULATOR", MACHO_PLATFORM_VISIONOSSIMULATOR}, + {"MACHO_PLATFORM_FIRMWARE", MACHO_PLATFORM_FIRMWARE}, + {"MACHO_PLATFORM_SEPOS", MACHO_PLATFORM_SEPOS}, + {"MACHO_PLATFORM_MACOS_EXCLAVECORE", MACHO_PLATFORM_MACOS_EXCLAVECORE}, + {"MACHO_PLATFORM_MACOS_EXCLAVEKIT", MACHO_PLATFORM_MACOS_EXCLAVEKIT}, + {"MACHO_PLATFORM_IOS_EXCLAVECORE", MACHO_PLATFORM_IOS_EXCLAVECORE}, + {"MACHO_PLATFORM_IOS_EXCLAVEKIT", MACHO_PLATFORM_IOS_EXCLAVEKIT}, + {"MACHO_PLATFORM_TVOS_EXCLAVECORE", MACHO_PLATFORM_TVOS_EXCLAVECORE}, + {"MACHO_PLATFORM_TVOS_EXCLAVEKIT", MACHO_PLATFORM_TVOS_EXCLAVEKIT}, + {"MACHO_PLATFORM_WATCHOS_EXCLAVECORE", MACHO_PLATFORM_WATCHOS_EXCLAVECORE}, + {"MACHO_PLATFORM_WATCHOS_EXCLAVEKIT", MACHO_PLATFORM_WATCHOS_EXCLAVEKIT}, + {"MACHO_PLATFORM_VISIONOS_EXCLAVECORE", MACHO_PLATFORM_VISIONOS_EXCLAVECORE}, + {"MACHO_PLATFORM_VISIONOS_EXCLAVEKIT", MACHO_PLATFORM_VISIONOS_EXCLAVEKIT} + // clang-format on + }); + + auto buildToolEnum = BuildEnum(view, "macho_build_tool_t", 4, + { + // clang-format off + {"MACHO_TOOL_CLANG", MACHO_TOOL_CLANG}, + {"MACHO_TOOL_SWIFT", MACHO_TOOL_SWIFT}, + {"MACHO_TOOL_LD", MACHO_TOOL_LD}, + {"MACHO_TOOL_LLD", MACHO_TOOL_LLD}, + {"MACHO_TOOL_METAL", MACHO_TOOL_METAL}, + {"MACHO_TOOL_AIRLLD", MACHO_TOOL_AIRLLD}, + {"MACHO_TOOL_AIRNT", MACHO_TOOL_AIRNT}, + {"MACHO_TOOL_AIRNT_PLUGIN", MACHO_TOOL_AIRNT_PLUGIN}, + {"MACHO_TOOL_AIRPACK", MACHO_TOOL_AIRPACK}, + {"MACHO_TOOL_GPUARCHIVER", MACHO_TOOL_GPUARCHIVER}, + {"MACHO_TOOL_METAL_FRAMEWORK", MACHO_TOOL_METAL_FRAMEWORK}, + // clang-format on + }); + + auto buildToolVersionType = BuildStruct(view, "build_tool_version", false, + { + // clang-format off + {"tool", buildToolEnum}, + {"version", Type::IntegerType(4, false)} + // clang-format on + }); + + auto buildVersionCommandType = BuildStruct(view, "build_version_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"platform", platformTypeEnum}, + {"minos", Type::IntegerType(4, false)}, + {"sdk", Type::IntegerType(4, false)}, + {"ntools", Type::IntegerType(4, false)}, + {"tools", Type::ArrayType(buildToolVersionType, 0)} + // clang-format on + }); + + auto sourceVersionCommandType = BuildStruct(view, "source_version_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"version", Type::IntegerType(8, false)} + // clang-format on + }); + + auto entryPointCommandType = BuildStruct(view, "entry_point_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"entryoff", Type::IntegerType(8, false)}, + {"stacksize", Type::IntegerType(8, false)} + // clang-format on + }); + + // Used for the various LC_LOAD_* commands that have only a single string field. + auto stringCommandType = BuildStruct(view, "string_command", false, + { + // clang-format off + {"cmd", cmdTypeEnum}, + {"cmdsize", Type::IntegerType(4, false)}, + {"value", lcStringType} + // clang-format on + }); +} + +void ApplyHeaderTypes(Ref view, Ref logger, const BinaryReader& incomingReader, + std::string_view imageName, uint64_t headerAddress, size_t loadCommandCount) +{ + BinaryReader reader(view, incomingReader.GetEndianness()); + std::string symbolSuffix = imageName.empty() ? "" : fmt::format("::{}", imageName); + + auto headerType = + Type::NamedType(view, QualifiedName(view->GetAddressSize() == 8 ? "mach_header_64" : "mach_header")); + reader.Seek(headerAddress + headerType->GetWidth()); + + view->DefineDataVariable(headerAddress, headerType); + view->DefineAutoSymbol( + new Symbol(DataSymbol, fmt::format("__macho_header{}", symbolSuffix), headerAddress, LocalBinding)); + + auto applyLoadCommand = [&](uint64_t cmdAddr, const load_command& load) { + switch (load.cmd) + { + case LC_SEGMENT: + { + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("segment_command"))); + reader.SeekRelative(5 * 8); + size_t numSections = reader.Read32(); + reader.SeekRelative(4); + for (size_t j = 0; j < numSections; j++) + { + view->DefineDataVariable(reader.GetOffset(), Type::NamedType(view, QualifiedName("section"))); + auto sectionSymName = fmt::format("__macho_section{}_[{}]", symbolSuffix, j); + auto sectionSym = new Symbol(DataSymbol, sectionSymName, reader.GetOffset(), LocalBinding); + view->DefineAutoSymbol(sectionSym); + reader.SeekRelative((8 * 8) + 4); + } + break; + } + case LC_SEGMENT_64: + { + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("segment_command_64"))); + reader.SeekRelative(7 * 8); + size_t numSections = reader.Read32(); + reader.SeekRelative(4); + for (size_t j = 0; j < numSections; j++) + { + view->DefineDataVariable(reader.GetOffset(), Type::NamedType(view, QualifiedName("section_64"))); + auto sectionSymName = fmt::format("__macho_section_64{}_[{}]", symbolSuffix, j); + auto sectionSym = new Symbol(DataSymbol, sectionSymName, reader.GetOffset(), LocalBinding); + view->DefineAutoSymbol(sectionSym); + reader.SeekRelative(10 * 8); + } + break; + } + case LC_SYMTAB: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("symtab_command"))); + break; + case LC_DYSYMTAB: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("dysymtab_command"))); + break; + case LC_UUID: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("uuid_command"))); + break; + case LC_ID_DYLIB: + case LC_LOAD_DYLIB: + case LC_REEXPORT_DYLIB: + case LC_LOAD_WEAK_DYLIB: + case LC_LOAD_UPWARD_DYLIB: + { + reader.SeekRelative(4); + uint32_t timestamp = reader.Read32(); + Ref type = Type::NamedType(view, QualifiedName("dylib_command")); + // A timestamp of `DYLIB_USE_MARKER` indicates this is a `dylib_use_command`. + if (timestamp == DYLIB_USE_MARKER) + { + type = Type::NamedType(view, QualifiedName("dylib_use_command")); + } + view->DefineDataVariable(cmdAddr, type); + + if (load.cmdsize - type->GetWidth() <= 150) + view->DefineDataVariable(cmdAddr + type->GetWidth(), + Type::ArrayType(Type::IntegerType(1, true), load.cmdsize - type->GetWidth())); + break; + } + case LC_CODE_SIGNATURE: + case LC_SEGMENT_SPLIT_INFO: + case LC_FUNCTION_STARTS: + case LC_DATA_IN_CODE: + case LC_DYLIB_CODE_SIGN_DRS: + case LC_DYLD_EXPORTS_TRIE: + case LC_DYLD_CHAINED_FIXUPS: + case LC_ATOM_INFO: + case LC_FUNCTION_VARIANTS: + case LC_FUNCTION_VARIANT_FIXUPS: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("linkedit_data_command"))); + break; + case LC_ENCRYPTION_INFO: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("encryption_info_command"))); + break; + case LC_VERSION_MIN_MACOSX: + case LC_VERSION_MIN_IPHONEOS: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("version_min_command"))); + break; + case LC_DYLD_INFO: + case LC_DYLD_INFO_ONLY: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("dyld_info_command"))); + break; + case LC_FILESET_ENTRY: + { + auto type = Type::NamedType(view, QualifiedName("fileset_entry_command")); + view->DefineDataVariable(cmdAddr, type); + if (load.cmdsize - type->GetWidth() <= 150) + view->DefineDataVariable(cmdAddr + type->GetWidth(), + Type::ArrayType(Type::IntegerType(1, true), load.cmdsize - type->GetWidth())); + break; + } + case LC_UNIXTHREAD: + { + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("unix_thread_command"))); + reader.SeekRelative(4); + uint32_t count = reader.Read32(); + view->DefineDataVariable(reader.GetOffset(), Type::ArrayType(Type::IntegerType(8, true), count)); + break; + } + case LC_BUILD_VERSION: + { + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("build_version_command"))); + reader.SeekRelative(12); + uint32_t count = reader.Read32(); + view->DefineDataVariable( + reader.GetOffset(), Type::ArrayType(Type::NamedType(view, QualifiedName("build_tool_version")), count)); + break; + } + case LC_SOURCE_VERSION: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("source_version_command"))); + break; + case LC_MAIN: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("entry_point_command"))); + break; + case LC_DYLD_ENVIRONMENT: + case LC_ID_DYLINKER: + case LC_LOAD_DYLINKER: + case LC_RPATH: + case LC_SUB_CLIENT: + case LC_SUB_FRAMEWORK: + case LC_SUB_LIBRARY: + case LC_SUB_UMBRELLA: + case LC_TARGET_TRIPLE: + { + Ref type = Type::NamedType(view, QualifiedName("string_command")); + view->DefineDataVariable(cmdAddr, type); + + if (load.cmdsize - type->GetWidth() <= 150) + view->DefineDataVariable(cmdAddr + type->GetWidth(), + Type::ArrayType(Type::IntegerType(1, true), load.cmdsize - type->GetWidth())); + + break; + } + default: + view->DefineDataVariable(cmdAddr, Type::NamedType(view, QualifiedName("load_command"))); + break; + } + }; + + try + { + for (size_t i = 0; i < loadCommandCount; i++) + { + load_command load {}; + uint64_t curOffset = reader.GetOffset(); + load.cmd = reader.Read32(); + load.cmdsize = reader.Read32(); + + applyLoadCommand(curOffset, load); + view->DefineAutoSymbol(new Symbol( + DataSymbol, fmt::format("__macho_load_command{}_[{}]", symbolSuffix, i), curOffset, LocalBinding)); + + uint64_t nextOffset = curOffset + load.cmdsize; + reader.Seek(nextOffset); + } + } + catch (ReadException&) + { + if (logger) + logger->LogError("Error when applying Mach-O header types at %llx", headerAddress); + else + LogError("Error when applying Mach-O header types at %llx", headerAddress); + } +} + +} // namespace BinaryNinja::MachO diff --git a/macho/types.h b/macho/types.h new file mode 100644 index 000000000..e67963449 --- /dev/null +++ b/macho/types.h @@ -0,0 +1,1455 @@ +#pragma once + +#include "binaryninjaapi.h" + +// These are already defined in one of the osx headers we want to override +#undef CPU_SUBTYPE_INTEL +#undef CPU_SUBTYPE_I386_ALL +#undef CPU_SUBTYPE_POWERPC_ALL +#undef LC_MAIN +#undef LC_SOURCE_VERSION +#undef LC_DYLIB_CODE_SIGN_DRS +#undef LC_DYLD_INFO_ONLY + +#define MH_MAGIC 0xfeedface +#define MH_MAGIC_64 0xfeedfacf +#define MH_CIGAM 0xcefaedfe +#define MH_CIGAM_64 0xcffaedfe +#define FAT_MAGIC 0xcafebabe +#define FAT_MAGIC_64 0xcafebabf + +typedef int32_t cpu_type_t; +typedef int32_t cpu_subtype_t; +typedef int vm_prot_t; + +// Cpu types +#define MACHO_CPU_ARCH_ABI64 0x01000000 +#define MACHO_CPU_ARCH_ABI64_32 0x02000000 + +#define MACHO_CPU_TYPE_ANY ((cpu_type_t) - 1) +#define MACHO_CPU_TYPE_VAX ((cpu_type_t)1) +#define MACHO_CPU_TYPE_MC680x0 ((cpu_type_t)6) +#define MACHO_CPU_TYPE_X86 ((cpu_type_t)7) +#define MACHO_CPU_TYPE_X86_64 (MACHO_CPU_TYPE_X86 | MACHO_CPU_ARCH_ABI64) +#define MACHO_CPU_TYPE_MIPS ((cpu_type_t)8) +#define MACHO_CPU_TYPE_MC98000 ((cpu_type_t)10) +#define MACHO_CPU_TYPE_HPPA ((cpu_type_t)11) +#define MACHO_CPU_TYPE_ARM ((cpu_type_t)12) +#define MACHO_CPU_TYPE_ARM64 (MACHO_CPU_TYPE_ARM | MACHO_CPU_ARCH_ABI64) +#define MACHO_CPU_TYPE_ARM64_32 (MACHO_CPU_TYPE_ARM | MACHO_CPU_ARCH_ABI64_32) +#define MACHO_CPU_TYPE_MC88000 ((cpu_type_t)13) +#define MACHO_CPU_TYPE_SPARC ((cpu_type_t)14) +#define MACHO_CPU_TYPE_I860 ((cpu_type_t)15) +#define MACHO_CPU_TYPE_ALPHA ((cpu_type_t)16) +#define MACHO_CPU_TYPE_POWERPC ((cpu_type_t)18) +#define MACHO_CPU_TYPE_POWERPC64 (MACHO_CPU_TYPE_POWERPC | MACHO_CPU_ARCH_ABI64) + +// Cpu subtype capability bits +#define MACHO_CPU_SUBTYPE_MASK ((cpu_subtype_t)0xff000000) +#define MACHO_CPU_SUBTYPE_LIB64 ((cpu_subtype_t)0x80000000) + +// Cpu subtypes +#define MACHO_CPU_SUBTYPE_INTEL(f, m) ((cpu_subtype_t)(f) + ((m) << 4)) +#define MACHO_CPU_SUBTYPE_I386_ALL MACHO_CPU_SUBTYPE_INTEL(3, 0) +#define MACHO_CPU_SUBTYPE_X86_ALL ((cpu_subtype_t)3) +#define MACHO_CPU_SUBTYPE_X86_ARCH1 ((cpu_subtype_t)4) +#define MACHO_CPU_SUBTYPE_X86_64_ALL ((cpu_subtype_t)3) +#define MACHO_CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) + +#define MACHO_CPU_SUBTYPE_ARM_ALL ((cpu_subtype_t)0) +#define MACHO_CPU_SUBTYPE_ARM_V4T ((cpu_subtype_t)5) +#define MACHO_CPU_SUBTYPE_ARM_V6 ((cpu_subtype_t)6) +#define MACHO_CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t)7) +#define MACHO_CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t)8) +#define MACHO_CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t)9) +#define MACHO_CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t)10) +#define MACHO_CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t)11) +#define MACHO_CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t)12) +#define MACHO_CPU_SUBTYPE_ARM_V8 ((cpu_subtype_t)13) +#define MACHO_CPU_SUBTYPE_ARM_V6M ((cpu_subtype_t)14) +#define MACHO_CPU_SUBTYPE_ARM_V7M ((cpu_subtype_t)15) +#define MACHO_CPU_SUBTYPE_ARM_V7EM ((cpu_subtype_t)16) + +#define MACHO_CPU_SUBTYPE_ARM64_ALL ((cpu_subtype_t)0) +#define MACHO_CPU_SUBTYPE_ARM64_V8 ((cpu_subtype_t)1) +#define MACHO_CPU_SUBTYPE_ARM64E ((cpu_subtype_t)2) + +#define MACHO_CPU_SUBTYPE_ARM64_32_ALL ((cpu_subtype_t)0) +#define MACHO_CPU_SUBTYPE_ARM64_32_V8 ((cpu_subtype_t)1) + +#define MACHO_CPU_SUBTYPE_POWERPC_ALL ((cpu_subtype_t)0) +#define MACHO_CPU_SUBTYPE_POWERPC_601 ((cpu_subtype_t)1) +#define MACHO_CPU_SUBTYPE_POWERPC_602 ((cpu_subtype_t)2) +#define MACHO_CPU_SUBTYPE_POWERPC_603 ((cpu_subtype_t)3) +#define MACHO_CPU_SUBTYPE_POWERPC_603e ((cpu_subtype_t)4) +#define MACHO_CPU_SUBTYPE_POWERPC_603ev ((cpu_subtype_t)5) +#define MACHO_CPU_SUBTYPE_POWERPC_604 ((cpu_subtype_t)6) +#define MACHO_CPU_SUBTYPE_POWERPC_604e ((cpu_subtype_t)7) +#define MACHO_CPU_SUBTYPE_POWERPC_620 ((cpu_subtype_t)8) +#define MACHO_CPU_SUBTYPE_POWERPC_750 ((cpu_subtype_t)9) +#define MACHO_CPU_SUBTYPE_POWERPC_7400 ((cpu_subtype_t)10) +#define MACHO_CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t)11) +#define MACHO_CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t)100) + +// Page protections +#define MACHO_VM_PROT_NONE ((vm_prot_t)0x00) +#define MACHO_VM_PROT_READ ((vm_prot_t)0x01) +#define MACHO_VM_PROT_WRITE ((vm_prot_t)0x02) +#define MACHO_VM_PROT_EXECUTE ((vm_prot_t)0x04) +#define MACHO_VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE) +#define MACHO_VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE) +#define MACHO_VM_PROT_NO_CHANGE ((vm_prot_t)0x08) +#define MACHO_VM_PROT_COPY ((vm_prot_t)0x10) +#define MACHO_VM_PROT_WANTS_COPY ((vm_prot_t)0x10) + +// Segment flags +#define SG_HIGHVM 0x1 +#define SG_FVMLIB 0x2 +#define SG_NORELOC 0x4 +#define SG_PROTECTED_VERSION_1 0x8 +#define SG_READ_ONLY_DATA 0x10 + +// Section flags +#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 +#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 // section contains only true machine instructions +#define S_ATTR_NO_TOC 0x40000000 // section contains coalesced symbols that are not to be in a ranlib table of contents +#define S_ATTR_STRIP_STATIC_SYMS \ + 0x20000000 // ok to strip static symbols in this section in files with the MH_DYLDLINK flag +#define S_ATTR_NO_DEAD_STRIP 0x10000000 // no dead stripping +#define S_ATTR_LIVE_SUPPORT 0x08000000 // blocks are live if they reference live blocks +#define S_ATTR_SELF_MODIFYING_CODE 0x04000000 // Used with i386 code stubs written on by dyld +#define S_ATTR_DEBUG 0x02000000 // a debug section */ +#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 // section contains some machine instructions +#define S_ATTR_EXT_RELOC 0x00000200 // section has external relocation entries +#define S_ATTR_LOC_RELOC 0x00000100 // section has local relocation entries + +#define S_REGULAR 0x0 +#define S_ZEROFILL 0x1 +#define S_CSTRING_LITERALS 0x2 +#define S_4BYTE_LITERALS 0x3 +#define S_8BYTE_LITERALS 0x4 +#define S_LITERAL_POINTERS 0x5 +#define S_NON_LAZY_SYMBOL_POINTERS 0x6 +#define S_LAZY_SYMBOL_POINTERS 0x7 +#define S_SYMBOL_STUBS 0x8 +#define S_MOD_INIT_FUNC_POINTERS 0x9 +#define S_MOD_TERM_FUNC_POINTERS 0xa +#define S_COALESCED 0xb +#define S_GB_ZEROFILL 0xc +#define S_INTERPOSING 0xd +#define S_16BYTE_LITERALS 0xe +#define S_DTRACE_DOF 0xf +#define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10 +#define S_THREAD_LOCAL_REGULAR 0x11 +#define S_THREAD_LOCAL_ZEROFILL 0x12 +#define S_THREAD_LOCAL_VARIABLES 0x13 +#define S_THREAD_LOCAL_VARIABLE_POINTERS 0x14 +#define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS 0x15 +#define S_INIT_FUNC_OFFSETS 0x16 + +// Mach-O Commands +#define LC_REQ_DYLD 0x80000000 +#define LC_SEGMENT 0x1 +#define LC_SYMTAB 0x2 +#define LC_SYMSEG 0x3 +#define LC_THREAD 0x4 +#define LC_UNIXTHREAD 0x5 +#define LC_LOADFVMLIB 0x6 +#define LC_IDFVMLIB 0x7 +#define LC_IDENT 0x8 +#define LC_FVMFILE 0x9 +#define LC_PREPAGE 0xa +#define LC_DYSYMTAB 0xb +#define LC_LOAD_DYLIB 0xc +#define LC_ID_DYLIB 0xd +#define LC_LOAD_DYLINKER 0xe +#define LC_ID_DYLINKER 0xf +#define LC_PREBOUND_DYLIB 0x10 +#define LC_ROUTINES 0x11 +#define LC_SUB_FRAMEWORK 0x12 +#define LC_SUB_UMBRELLA 0x13 +#define LC_SUB_CLIENT 0x14 +#define LC_SUB_LIBRARY 0x15 +#define LC_TWOLEVEL_HINTS 0x16 +#define LC_PREBIND_CKSUM 0x17 +#define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) +#define LC_SEGMENT_64 0x19 +#define LC_ROUTINES_64 0x1a +#define LC_UUID 0x1b +#define LC_RPATH (0x1c | LC_REQ_DYLD) +#define LC_CODE_SIGNATURE 0x1d +#define LC_SEGMENT_SPLIT_INFO 0x1e +#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) +#define LC_LAZY_LOAD_DYLIB 0x20 +#define LC_ENCRYPTION_INFO 0x21 +#define LC_DYLD_INFO 0x22 +#define LC_DYLD_INFO_ONLY (0x22 | LC_REQ_DYLD) +#define LC_LOAD_UPWARD_DYLIB (0x23 | LC_REQ_DYLD) +#define LC_VERSION_MIN_MACOSX 0x24 +#define LC_VERSION_MIN_IPHONEOS 0x25 +#define LC_FUNCTION_STARTS 0x26 +#define LC_DYLD_ENVIRONMENT 0x27 +#define LC_MAIN (0x28 | LC_REQ_DYLD) +#define LC_DATA_IN_CODE 0x29 +#define LC_SOURCE_VERSION 0x2a +#define LC_DYLIB_CODE_SIGN_DRS 0x2b +#define _LC_ENCRYPTION_INFO_64 \ + 0x2c /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h \ + */ +#define _LC_LINKER_OPTION 0x2d /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h */ +#define _LC_LINKER_OPTIMIZATION_HINT \ + 0x2e /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h */ +#define _LC_VERSION_MIN_TVOS 0x2f /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h */ +#define LC_VERSION_MIN_WATCHOS 0x30 +#define LC_NOTE 0x31 +#define LC_BUILD_VERSION 0x32 +#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) +#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) +#define LC_FILESET_ENTRY (0x35 | LC_REQ_DYLD) +#define LC_ATOM_INFO 0x36 +#define LC_FUNCTION_VARIANTS 0x37 +#define LC_FUNCTION_VARIANT_FIXUPS 0x38 +#define LC_TARGET_TRIPLE 0x39 + +// Mach-O File types +#define MH_OBJECT 0x1 +#define MH_EXECUTE 0x2 +#define MH_FVMLIB 0x3 +#define MH_CORE 0x4 +#define MH_PRELOAD 0x5 +#define MH_DYLIB 0x6 +#define MH_DYLINKER 0x7 +#define MH_BUNDLE 0x8 +#define MH_DYLIB_STUB 0x9 +#define MH_DSYM 0xa +#define MH_KEXT_BUNDLE 0xb +#define MH_FILESET 0xc + +#define MH_NOUNDEFS 0x1 +#define MH_INCRLINK 0x2 +#define MH_DYLDLINK 0x4 +#define MH_BINDATLOAD 0x8 +#define MH_PREBOUND 0x10 +#define MH_SPLIT_SEGS 0x20 +#define MH_LAZY_INIT 0x40 +#define MH_TWOLEVEL 0x80 +#define MH_FORCE_FLAT 0x100 +#define MH_NOMULTIDEFS 0x200 +#define MH_NOFIXPREBINDING 0x400 +#define MH_PREBINDABLE 0x800 +#define MH_ALLMODSBOUND 0x1000 +#define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000 +#define MH_CANONICAL 0x4000 +#define MH_WEAK_DEFINES 0x8000 +#define MH_BINDS_TO_WEAK 0x10000 +#define MH_ALLOW_STACK_EXECUTION 0x20000 +#define MH_ROOT_SAFE 0x40000 +#define MH_SETUID_SAFE 0x80000 +#define MH_NO_REEXPORTED_DYLIBS 0x100000 +#define MH_PIE 0x200000 +#define MH_DEAD_STRIPPABLE_DYLIB 0x400000 +#define MH_HAS_TLV_DESCRIPTORS 0x800000 +#define MH_NO_HEAP_EXECUTION 0x1000000 +#define _MH_APP_EXTENSION_SAFE \ + 0x2000000 /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h */ +#define _MH_NLIST_OUTOFSYNC_WITH_DYLDINFO 0x04000000u +#define _MH_SIM_SUPPORT 0x08000000u +#define _MH_DYLIB_IN_CACHE 0x80000000u + +#define DYLIB_USE_WEAK_LINK 0x01 +#define DYLIB_USE_REEXPORT 0x02 +#define DYLIB_USE_UPWARD 0x04 +#define DYLIB_USE_DELAYED_INIT 0x08 + +#define DYLIB_USE_MARKER 0x1a741800 + +// Segment Names +#define SEG_PAGEZERO "__PAGEZERO" +#define SEG_TEXT "__TEXT" +#define SECT_TEXT "__text" +#define SECT_FVMLIB_INIT0 "__fvmlib_init0" +#define SECT_FVMLIB_INIT1 "__fvmlib_init1" +#define SEG_DATA "__DATA" +#define SECT_DATA "__data" +#define SECT_BSS "__bss" +#define SECT_COMMON "__common" +#define SEG_OBJC "__OBJC" +#define SECT_OBJC_SYMBOLS "__symbol_table" +#define SECT_OBJC_MODULES "__module_info" +#define SECT_OBJC_STRINGS "__selector_strs" +#define SECT_OBJC_REFS "__selector_refs" +#define SEG_ICON "__ICON" +#define SECT_ICON_HEADER "__header" +#define SECT_ICON_TIFF "__tiff" +#define SEG_LINKEDIT "__LINKEDIT" +#define SEG_UNIXSTACK "__UNIXSTACK" +#define SEG_IMPORT "__IMPORT" + +/* + * Symbols with a index into the string table of zero (n_un.n_strx == 0) are + * defined to have a null, "", name. Therefore all string indexes to non null + * names must not have a zero string index. This is bit historical information + * that has never been well documented. + */ + +/* + * The n_type field really contains four fields: + * unsigned char N_STAB:3, + * N_PEXT:1, + * N_TYPE:3, + * N_EXT:1; + * which are used via the following masks. + */ +#define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */ +#define N_PEXT 0x10 /* private external symbol bit */ +#define N_TYPE 0x0e /* mask for the type bits */ +#define N_EXT 0x01 /* external symbol bit, set for external symbols */ + +/* + * Only symbolic debugging entries have some of the N_STAB bits set and if any + * of these bits are set then it is a symbolic debugging entry (a stab). In + * which case then the values of the n_type field (the entire field) are given + * in + */ + +/* + * Values for N_TYPE bits of the n_type field. + */ +#define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */ +#define N_ABS 0x2 /* absolute, n_sect == NO_SECT */ +#define N_SECT 0xe /* defined in section number n_sect */ +#define N_PBUD 0xc /* prebound undefined (defined in a dylib) */ +#define N_INDR 0xa /* indirect */ + +/* + * If the type is N_INDR then the symbol is defined to be the same as another + * symbol. In this case the n_value field is an index into the string table + * of the other symbol's name. When the other symbol is defined then they both + * take on the defined type and value. + */ + +/* + * If the type is N_SECT then the n_sect field contains an ordinal of the + * section the symbol is defined in. The sections are numbered from 1 and + * refer to sections in order they appear in the load commands for the file + * they are in. This means the same ordinal may very well refer to different + * sections in different files. + * + * The n_value field for all symbol table entries (including N_STAB's) gets + * updated by the link editor based on the value of it's n_sect field and where + * the section n_sect references gets relocated. If the value of the n_sect + * field is NO_SECT then it's n_value field is not changed by the link editor. + */ +#define NO_SECT 0 /* symbol is not in any section */ +#define MAX_SECT 255 /* 1 thru 255 inclusive */ + +/* + * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes + * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED. + */ + +/* + * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a + * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the + * static link editor it is never to dead strip the symbol. + */ +#define N_NO_DEAD_STRIP 0x0020 /* symbol is not to be dead stripped */ + +/* + * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image. + * But is used in very rare cases by the dynamic link editor to mark an in + * memory symbol as discared and longer used for linking. + */ +#define N_DESC_DISCARDED 0x0020 /* symbol is discarded */ + +/* + * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that + * the undefined symbol is allowed to be missing and is to have the address of + * zero when missing. + */ +#define N_WEAK_REF 0x0040 /* symbol is weak referenced */ + +/* + * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic + * linkers that the symbol definition is weak, allowing a non-weak symbol to + * also be used which causes the weak definition to be discared. Currently this + * is only supported for symbols in coalesed sections. + */ +#define N_WEAK_DEF 0x0080 /* coalesed symbol is a weak definition */ + +/* + * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker + * that the undefined symbol should be resolved using flat namespace searching. + */ +#define N_REF_TO_WEAK 0x0080 /* reference to a weak symbol */ + +/* + * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is + * a defintion of a Thumb function. + */ +#define N_ARM_THUMB_DEF 0x0008 /* symbol is a Thumb function (ARM) */ + +/* + * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the + * that the function is actually a resolver function and should + * be called to get the address of the real function to use. + * This bit is only available in .o files (MH_OBJECT filetype) + */ +#define N_SYMBOL_RESOLVER 0x0100 + +/* + * The N_ALT_ENTRY bit of the n_desc field indicates that the + * symbol is pinned to the previous content. + */ +#define N_ALT_ENTRY 0x0200 + +/* + * The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used + * infrequently and the linker should order it towards the end of the section. + */ +#define N_COLD_FUNC 0x0400 + +/* + * An indirect symbol table entry is simply a 32bit index into the symbol table + * to the symbol that the pointer or stub is referring to. Unless it is for a + * non-lazy symbol pointer section for a defined symbol which strip(1) as + * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the + * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that. + */ +#define INDIRECT_SYMBOL_ABS 0x40000000 +#define INDIRECT_SYMBOL_LOCAL 0x80000000 + +#define SECTION_TYPE 0x000000ff /* 256 section types */ +#define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes */ + +#define BINARYNINJA_MANUAL_RELOCATION ((uint64_t)-2) + +enum MachoRelocationType +{ + GENERIC_RELOC_VANILLA = 0, + GENERIC_RELOC_PAIR = 1, + GENERIC_RELOC_SECTDIFF = 2, + GENERIC_RELOC_PB_LA_PTR = 3, + GENERIC_RELOC_LOCAL_SECTDIFF = 4, + GENERIC_RELOC_TLV = 5 +}; + + +namespace BinaryNinja { + class MachoFormatException : public std::exception + { + std::string m_message; + + public: + MachoFormatException(const std::string& msg = "invalid format") : m_message(msg) {} + virtual const char* what() const NOEXCEPT { return m_message.c_str(); } + }; + + struct FatHeader + { + uint32_t magic; + uint32_t nfat_arch; + }; + + struct FatArch32 + { + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint32_t offset; + uint32_t size; + uint32_t align; + }; + + struct FatArch64 + { + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint64_t offset; + uint64_t size; + uint32_t align; + uint32_t reserved; + }; + + struct mach_header + { + uint32_t magic; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; + }; + + struct mach_header_64 + { + uint32_t magic; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; + uint32_t reserved; + }; + + struct load_command + { + uint32_t cmd; + uint32_t cmdsize; + }; + + struct segment_command + { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint32_t vmaddr; + uint32_t vmsize; + uint32_t fileoff; + uint32_t filesize; + vm_prot_t maxprot; + vm_prot_t initprot; + uint32_t nsects; + uint32_t flags; + }; + + struct section + { // for 32-bit architectures + char sectname[16]; // name of this section + char segname[16]; // segment this section goes in + uint32_t addr; // memory address of this section + uint32_t size; // size in bytes of this section + uint32_t offset; // file offset of this section + uint32_t align; // section alignment (power of 2) + uint32_t reloff; // file offset of relocation entries + uint32_t nreloc; // number of relocation entries + uint32_t flags; // flags (section type and attributes) + uint32_t reserved1; // reserved (for offset or index) + uint32_t reserved2; // reserved (for count or sizeof) + }; + + struct section_64 + { // for 64-bit architectures + char sectname[16]; // name of this section + char segname[16]; // segment this section goes in + uint64_t addr; // memory address of this section + uint64_t size; // size in bytes of this section + uint32_t offset; // file offset of this section + uint32_t align; // section alignment (power of 2) + uint32_t reloff; // file offset of relocation entries + uint32_t nreloc; // number of relocation entries + uint32_t flags; // flags (section type and attributes) + uint32_t reserved1; // reserved (for offset or index) + uint32_t reserved2; // reserved (for count or sizeof) + uint32_t reserved3; // reserved + }; + + struct segment_command_64 + { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint64_t vmaddr; + uint64_t vmsize; + uint64_t fileoff; + uint64_t filesize; + vm_prot_t maxprot; + vm_prot_t initprot; + uint32_t nsects; + uint32_t flags; + }; + + struct uuid_command + { + uint32_t cmd; + uint32_t cmdsize; + char uuid[16]; + }; + + struct fvmlib_command + { + uint32_t cmd; + uint32_t cmdsize; + char segname[16]; + uint32_t minor_version; + uint32_t header_addr; + }; + + struct dylib + { + uint32_t name; + uint32_t timestamp; + uint32_t current_version; + uint32_t compatibility_version; + }; + + struct dylib_command + { + uint32_t cmd; + uint32_t cmdsize; + struct dylib dylib; + }; + + struct sub_framework_command + { + uint32_t cmd; // LC_SUB_FRAMEWORK + uint32_t cmdsize; // includes umbrella string + uint32_t umbrella; // the umbrella framework name + }; + + struct sub_client_command + { + uint32_t cmd; // LC_SUB_CLIENT + uint32_t cmdsize; // includes client string + uint32_t client; // offset to the string + }; + + struct sub_umbrella_command + { + uint32_t cmd; // LC_SUB_UMBRELLA + uint32_t cmdsize; // includes sub_umbrella string + uint32_t sub_umbrella; // the sub_umbrella framework name + }; + + struct sub_library_command + { + uint32_t cmd; // LC_SUB_LIBRARY + uint32_t cmdsize; // includes sub_library string + uint32_t sub_library; // the sub_library name + }; + + struct prebound_dylib_command + { + uint32_t cmd; // LC_PREBOUND_DYLIB + uint32_t cmdsize; // includes strings + uint32_t name; // library's path name + uint32_t nmodules; // number of modules in library + uint32_t linked_modules; // bit vector of linked modules + }; + + struct dylinker_command + { + uint32_t cmd; // LC_ID_DYLINKER or LC_LOAD_DYLINKER + uint32_t cmdsize; // includes pathname string + uint32_t name; // dynamic linker's path name + }; + + struct x86_thread_state64 + { + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rsp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t rip; + uint64_t rflags; + uint64_t cs; + uint64_t fs; + uint64_t gs; + }; + + struct x86_thread_state32 + { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; + uint32_t ss; + uint32_t eflags; + uint32_t eip; + uint32_t cs; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + }; + + struct armv7_thread_state + { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t r13; + uint32_t r14; // SP + uint32_t r15; // PC + }; + + struct arm_thread_state64 + { + uint64_t x[29]; // GPR x0-x28 + uint64_t fp; // x29 + uint64_t lr; // x30 + uint64_t sp; // x31 + uint64_t pc; // Program Counter + uint32_t cpsr; // Current program status register + }; + + struct ppc_thread_state + { + uint32_t srr0; // Machine state register (PC) + uint32_t srr1; + uint32_t r0; + uint32_t r1; // Stack pointer + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t r13; + uint32_t r14; + uint32_t r15; + uint32_t r16; + uint32_t r17; + uint32_t r18; + uint32_t r19; + uint32_t r20; + uint32_t r21; + uint32_t r22; + uint32_t r23; + uint32_t r24; + uint32_t r25; + uint32_t r26; + uint32_t r27; + uint32_t r28; + uint32_t r29; + uint32_t r30; + uint32_t r31; + uint32_t cr; + uint32_t xer; + uint32_t lr; + uint32_t ctr; + uint32_t mq; + uint32_t vrsave; + }; + +#pragma pack(push, 4) + struct ppc_thread_state64 + { + uint64_t srr0; // Machine state register (PC) + uint64_t srr1; + uint64_t r0; // Stack pointer + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t r16; + uint64_t r17; + uint64_t r18; + uint64_t r19; + uint64_t r20; + uint64_t r21; + uint64_t r22; + uint64_t r23; + uint64_t r24; + uint64_t r25; + uint64_t r26; + uint64_t r27; + uint64_t r28; + uint64_t r29; + uint64_t r30; + uint64_t r31; + uint32_t cr; // Condition register + uint64_t xer; // User's integer exception register + uint64_t lr; // Link register + uint64_t ctr; // Count register + uint32_t vrsave; // Vector Save Register + }; +#pragma pack(pop) + + struct thread_command + { + uint32_t cmd; // LC_THREAD or LC_UNIXTHREAD + uint32_t cmdsize; // total size of this command + uint32_t flavor; // flavor of thread state + uint32_t count; // count of longs in thread state + union + { + x86_thread_state64 statex64; + x86_thread_state32 statex86; + armv7_thread_state statearmv7; + arm_thread_state64 stateaarch64; + ppc_thread_state stateppc; + ppc_thread_state64 stateppc64; + }; + }; + + struct linkedit_data_command + { + uint32_t cmd; + uint32_t cmdsize; + uint32_t dataoff; + uint32_t datasize; + }; + + + enum MachOArchitecture + { + MachOABIMask = 0xff000000, + MachOABI64 = 0x01000000, // 64 bit ABI + MachOABI6432 = 0x02000000, // "ABI for 64-bit hardware with 32-bit types; LP32" + + // Constants for the cputype field. + MachOx86 = 7, + MachOx64 = MachOx86 | MachOABI64, + MachOArm = 0xc, + MachOAarch64 = MachOABI64 | MachOArm, + MachOAarch6432 = MachOABI6432 | MachOArm, + MachOSPARC = 0xe, + MachOPPC = 0x12, + MachOPPC64 = MachOABI64 | MachOPPC, + }; + + enum RebaseType + { + RebaseTypeInvalid = 0, + RebaseTypePointer = 1, + RebaseTypeTextAbsolute32 = 2, + RebaseTypeTextPCRel32 = 3 + }; + + enum RebaseOpcode + { + RebaseOpcodeMask = 0xF0u, // REBASE_OPCODE_MASK + RebaseImmediateMask = 0x0Fu, // REBASE_IMMEDIATE_MASK + RebaseOpcodeDone = 0x00u, // REBASE_OPCODE_DONE + RebaseOpcodeSetTypeImmediate = 0x10u, // REBASE_OPCODE_SET_TYPE_IMM + RebaseOpcodeSetSegmentAndOffsetUleb = 0x20u, // REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + RebaseOpcodeAddAddressUleb = 0x30u, // REBASE_OPCODE_ADD_ADDR_ULEB + RebaseOpcodeAddAddressImmediateScaled = 0x40u, // REBASE_OPCODE_ADD_ADDR_IMM_SCALED + RebaseOpcodeDoRebaseImmediateTimes = 0x50u, // REBASE_OPCODE_DO_REBASE_IMM_TIMES + RebaseOpcodeDoRebaseUlebTimes = 0x60u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES + RebaseOpcodeDoRebaseAddAddressUleb = 0x70u, // REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + RebaseOpcodeDoRebaseUlebTimesSkippingUleb = 0x80u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + }; + + enum BindOpcode + { + BindOpcodeMask = 0xF0u, // BIND_OPCODE_MASK + BindImmediateMask = 0x0Fu, // BIND_IMMEDIATE_MASK + BindOpcodeDone = 0x00u, // BIND_OPCODE_DONE + BindOpcodeSetDylibOrdinalImmediate = 0x10u, // BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + BindOpcodeSetDylibOrdinalULEB = 0x20u, // BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB + BindOpcodeSetDylibSpecialImmediate = 0x30u, // BIND_OPCODE_SET_DYLIB_SPECIAL_IMM + BindOpcodeSetSymbolTrailingFlagsImmediate = 0x40u, // BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + BindOpcodeSetTypeImmediate = 0x50u, // BIND_OPCODE_SET_TYPE_IMM + BindOpcodeSetAddendSLEB = 0x60u, // BIND_OPCODE_SET_ADDEND_SLEB + BindOpcodeSetSegmentAndOffsetULEB = 0x70u, // BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + BindOpcodeAddAddressULEB = 0x80u, // BIND_OPCODE_ADD_ADDR_ULEB + BindOpcodeDoBind = 0x90u, // BIND_OPCODE_DO_BIND + BindOpcodeDoBindAddAddressULEB = 0xA0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB + BindOpcodeDoBindAddAddressImmediateScaled = 0xB0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED + BindOpcodeDoBindULEBTimesSkippingULEB = 0xC0u, // BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB + }; + + enum X86ThreadFlavor + { + X86_THREAD_STATE32 = 0x1, + X86_FLOAT_STATE32 = 0x2, + X86_EXCEPTION_STATE32 = 0x3, + X86_THREAD_STATE64 = 0x4, + X86_FLOAT_STATE64 = 0x5, + X86_EXCEPTION_STATE64 = 0x6, + X86_THREAD_STATE = 0x7, + X86_FLOAT_STATE = 0x8, + X86_EXCEPTION_STATE = 0x9, + X86_DEBUG_STATE32 = 0xA, + X86_DEBUG_STATE64 = 0xB, + X86_DEBUG_STATE = 0xC, + _THREAD_STATE_NONE = 0xD + }; + + enum PPCThreadFlavor + { + PPC_THREAD_STATE = 0x1, + PPC_FLOAT_STATE = 0x2, + PPC_EXCEPTION_STATE = 0x3, + PPC_VECTOR_STATE = 0x4, + PPC_THREAD_STATE64 = 0x5, + PPC_EXCEPTION_STATE64 = 0x6 + }; + + enum ARMThreadFlavor + { + _ARM_THREAD_STATE = 1, + _ARM_VFP_STATE = 2, + _ARM_EXCEPTION_STATE = 3, + _ARM_DEBUG_STATE = 4, /* pre-armv8 */ + _ARM_THREAD_STATE64 = 6, + _ARM_EXCEPTION_STATE64 = 7 + }; + + struct routines_command + { // for 32-bit architectures + uint32_t cmd; // LC_ROUTINES + uint32_t cmdsize; // total size of this command + uint32_t init_address; // address of initialization routine + uint32_t init_module; // index into the module table that the init routine is defined in + uint32_t reserved1; + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + uint32_t reserved5; + uint32_t reserved6; + }; + + struct routines_command_64 + { // for 64-bit architectures + uint32_t cmd; // LC_ROUTINES_64 + uint32_t cmdsize; // total size of this command + uint64_t init_address; // address of initialization routine + uint64_t init_module; // index into the module table that the init routine is defined in + uint64_t reserved1; + uint64_t reserved2; + uint64_t reserved3; + uint64_t reserved4; + uint64_t reserved5; + uint64_t reserved6; + }; + + struct symtab_command + { + uint32_t cmd; // LC_SYMTAB + uint32_t cmdsize; // sizeof(struct symtab_command) + uint32_t symoff; // symbol table offset + uint32_t nsyms; // number of symbol table entries + uint32_t stroff; // string table offset + uint32_t strsize; // string table size in bytes + }; + + // Lots of good information on how to use dysymtab for relocations + // https://opensource.apple.com/source/cctools/cctools-795/include/mach-o/loader.h + struct dysymtab_command + { + uint32_t cmd; // LC_DYSYMTAB + uint32_t cmdsize; // sizeof(struct dysymtab_command) + uint32_t ilocalsym; // index to local symbols + uint32_t nlocalsym; // number of local symbols + uint32_t iextdefsym; // index to externally defined symbols + uint32_t nextdefsym; // number of externally defined symbols + uint32_t iundefsym; // index to undefined symbols + uint32_t nundefsym; // number of undefined symbols + uint32_t tocoff; // file offset to table of contents + uint32_t ntoc; // number of entries in table of contents + uint32_t modtaboff; // file offset to module table + uint32_t nmodtab; // number of module table entries + uint32_t extrefsymoff; // offset to referenced symbol table + uint32_t nextrefsyms; // number of referenced symbol table entries + uint32_t indirectsymoff; // file offset to the indirect symbol table + uint32_t nindirectsyms; // number of indirect symbol table entries + uint32_t extreloff; // offset to external relocation entries + uint32_t nextrel; // number of external relocation entries + uint32_t locreloff; // offset to local relocation entries + uint32_t nlocrel; // number of local relocation entries + }; + + struct twolevel_hints_command + { + uint32_t cmd; // LC_TWOLEVEL_HINTS + uint32_t cmdsize; // sizeof(struct twolevel_hints_command) + uint32_t offset; // offset to the hint table + uint32_t nhints; // number of hints in the hint table + }; + + struct dyld_info_command + { + uint32_t cmd; // LC_DYLD_INFO or LC_DYLD_INFO_ONLY + uint32_t cmdsize; // sizeof(struct dyld_info_command) + uint32_t rebase_off; // file offset to rebase info + uint32_t rebase_size; // size of rebase info + uint32_t bind_off; // file offset to binding info + uint32_t bind_size; // size of binding info + uint32_t weak_bind_off; // file offset to weak binding info + uint32_t weak_bind_size; // size of weak binding info + uint32_t lazy_bind_off; // file offset to lazy binding info + uint32_t lazy_bind_size; // size of lazy binding infs + uint32_t export_off; // file offset to lazy binding info + uint32_t export_size; // size of lazy binding infs + }; + + struct function_starts_command + { + uint32_t cmd; // LC_FUNCTION_STARTS + uint32_t cmdsize; // sizeof(struct function_starts_command) + uint32_t funcoff; // offset to function starts list + uint32_t funcsize; // sizeof function starts list + }; + + enum MachoPlatform + { + MACHO_PLATFORM_MACOS = 1, + MACHO_PLATFORM_IOS = 2, + MACHO_PLATFORM_TVOS = 3, + MACHO_PLATFORM_WATCHOS = 4, + MACHO_PLATFORM_BRIDGEOS = 5, + MACHO_PLATFORM_MACCATALYST = 6, + MACHO_PLATFORM_IOSSIMULATOR = 7, + MACHO_PLATFORM_TVOSSIMULATOR = 8, + MACHO_PLATFORM_WATCHOSSIMULATOR = 9, + MACHO_PLATFORM_DRIVERKIT = 10, + MACHO_PLATFORM_VISIONOS = 11, + MACHO_PLATFORM_VISIONOSSIMULATOR = 12, + + MACHO_PLATFORM_FIRMWARE = 13, + MACHO_PLATFORM_SEPOS = 14, + + MACHO_PLATFORM_MACOS_EXCLAVECORE = 15, + MACHO_PLATFORM_MACOS_EXCLAVEKIT = 16, + MACHO_PLATFORM_IOS_EXCLAVECORE = 17, + MACHO_PLATFORM_IOS_EXCLAVEKIT = 18, + MACHO_PLATFORM_TVOS_EXCLAVECORE = 19, + MACHO_PLATFORM_TVOS_EXCLAVEKIT = 20, + MACHO_PLATFORM_WATCHOS_EXCLAVECORE = 21, + MACHO_PLATFORM_WATCHOS_EXCLAVEKIT = 22, + MACHO_PLATFORM_VISIONOS_EXCLAVECORE = 23, + MACHO_PLATFORM_VISIONOS_EXCLAVEKIT = 24, + }; + + enum MachoBuildTool + { + MACHO_TOOL_CLANG = 1, + MACHO_TOOL_SWIFT = 2, + MACHO_TOOL_LD = 3, + MACHO_TOOL_LLD = 4, + + MACHO_TOOL_METAL = 1024, + MACHO_TOOL_AIRLLD = 1025, + MACHO_TOOL_AIRNT = 1026, + MACHO_TOOL_AIRNT_PLUGIN = 1027, + MACHO_TOOL_AIRPACK = 1028, + MACHO_TOOL_GPUARCHIVER = 1031, + MACHO_TOOL_METAL_FRAMEWORK = 1032, + }; + + struct build_tool_version + { + uint32_t tool; + uint32_t version; + }; + + struct build_version_command + { + uint32_t cmd; // LC_BUILD_VERSION + uint32_t cmdsize; // sizeof(build_version_command) + (ntools * sizeof(build_tool_version) + uint32_t platform; // MachoPlatform + uint32_t minos; // X.Y.Z is encoded in nibbles xxxx.yy.zz + uint32_t sdk; // X.Y.Z is encoded in nibbles xxxx.yy.zz + uint32_t ntools; // number build_tool_version entries + }; + +#pragma pack(push, 1) + struct nlist + { + int32_t n_strx; + uint8_t n_type; + uint8_t n_sect; + int16_t n_desc; + uint32_t n_value; + }; + + struct nlist_64 + { + uint32_t n_strx; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + uint64_t n_value; + }; +#pragma pack(pop) + +#define R_ABS 0 + struct relocation_info + { + int32_t r_address; + uint32_t r_symbolnum : 24; + uint32_t r_pcrel : 1; + uint32_t r_length : 2; + uint32_t r_extern : 1; + uint32_t r_type : 4; + }; +#define R_SCATTERED 0x80000000 + struct scattered_relocation_info_be_64 + { + uint32_t r_scattered : 1; // 1=scattered, 0=non-scattered (see above) + uint32_t r_pcrel : 1; // was relocated pc relative already + uint32_t r_length : 2; // 0=byte, 1=word, 2=long + uint32_t r_type : 4; // if not 0, machine specific relocation type + uint32_t r_address : 24; // offset in the section to what is being relocated + int64_t r_value; // the value the item to be relocated is refering to (without any offset added) + }; + struct scattered_relocation_info_le_64 + { + uint32_t r_address : 24; // offset in the section to what is being relocated + uint32_t r_type : 4; // if not 0, machine specific relocation type + uint32_t r_length : 2; // 0=byte, 1=word, 2=long + uint32_t r_pcrel : 1; // was relocated pc relative already + uint32_t r_scattered : 1; // 1=scattered, 0=non-scattered (see above) + int64_t r_value; // the value the item to be relocated is refering to (without any offset added) + }; + struct scattered_relocation_info_be + { + uint32_t r_scattered : 1; // 1=scattered, 0=non-scattered (see above) + uint32_t r_pcrel : 1; // was relocated pc relative already + uint32_t r_length : 2; // 0=byte, 1=word, 2=long + uint32_t r_type : 4; // if not 0, machine specific relocation type + uint32_t r_address : 24; // offset in the section to what is being relocated + int32_t r_value; // the value the item to be relocated is refering to (without any offset added) + }; + struct scattered_relocation_info_le + { + uint32_t r_address : 24; // offset in the section to what is being relocated + uint32_t r_type : 4; // if not 0, machine specific relocation type + uint32_t r_length : 2; // 0=byte, 1=word, 2=long + uint32_t r_pcrel : 1; // was relocated pc relative already + uint32_t r_scattered : 1; // 1=scattered, 0=non-scattered (see above) + int32_t r_value; // the value the item to be relocated is refering to (without any offset added) + }; + + enum reloc_type_generic + { + GENERIC_RELOC_VANILLA, // generic relocation as discribed above + GENERIC_RELOC_PAIR, // Only follows a GENRIC_RELOC_SECTDIFF + GENERIC_RELOC_SECTDIFF, + GENERIC_RELOC_PB_LA_PTR // prebound lazy pointer + }; + + struct dyld_chained_fixups_header + { + uint32_t fixups_version; // 0 + uint32_t starts_offset; // offset of dyld_chained_starts_in_image in chain_data + uint32_t imports_offset; // offset of imports table in chain_data + uint32_t symbols_offset; // offset of symbol strings in chain_data + uint32_t imports_count; // number of imported symbol names + uint32_t imports_format; // DYLD_CHAINED_IMPORT* + uint32_t symbols_format; // 0 => uncompressed, 1 => zlib compressed + }; + + // This struct is embedded in LC_DYLD_CHAINED_FIXUPS payload + struct dyld_chained_starts_in_image + { + uint32_t seg_count; + uint32_t seg_info_offset[1]; // each entry is offset into this struct for that segment + // followed by pool of dyld_chain_starts_in_segment data + }; + + // This struct is embedded in dyld_chain_starts_in_image + // and passed down to the kernel for page-in linking + struct dyld_chained_starts_in_segment + { + uint32_t size; // size of this (amount kernel needs to copy) + uint16_t page_size; // 0x1000 or 0x4000 + uint16_t pointer_format; // DYLD_CHAINED_PTR_* + uint64_t segment_offset; // offset in memory to start of segment + uint32_t max_valid_pointer; // for 32-bit OS, any value beyond this is not a pointer + uint16_t page_count; // how many pages are in array + uint16_t page_start[1]; // each entry is offset in each page of first element in chain + // or DYLD_CHAINED_PTR_START_NONE if no fixups on page + + // uint16_t chain_starts[1]; // some 32-bit formats may require multiple starts per page. + // for those, if high bit is set in page_starts[], then it + // is index into chain_starts[] which is a list of starts + // the last of which has the high bit set + }; + + enum + { + DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups + DYLD_CHAINED_PTR_START_MULTI = 0x8000, // used in page_start[] to denote a page which has multiple starts + DYLD_CHAINED_PTR_START_LAST = 0x8000, // used in chain_starts[] to denote last start in list for page + }; + + // This struct is embedded in __TEXT,__chain_starts section in firmware + struct dyld_chained_starts_offsets + { + uint32_t pointer_format; // DYLD_CHAINED_PTR_32_FIRMWARE + uint32_t starts_count; // number of starts in array + uint32_t chain_starts[1]; // array chain start offsets + }; + + // values for dyld_chained_starts_in_segment.pointer_format + enum + { + DYLD_CHAINED_PTR_ARM64E = 1, // stride 8, unauth target is vmaddr + DYLD_CHAINED_PTR_64 = 2, // target is vmaddr + DYLD_CHAINED_PTR_32 = 3, + DYLD_CHAINED_PTR_32_CACHE = 4, + DYLD_CHAINED_PTR_32_FIRMWARE = 5, + DYLD_CHAINED_PTR_64_OFFSET = 6, // target is vm offset + DYLD_CHAINED_PTR_ARM64E_OFFSET = 7, // old name + DYLD_CHAINED_PTR_ARM64E_KERNEL = 7, // stride 4, unauth target is vm offset + DYLD_CHAINED_PTR_64_KERNEL_CACHE = 8, + DYLD_CHAINED_PTR_ARM64E_USERLAND = 9, // stride 8, unauth target is vm offset + DYLD_CHAINED_PTR_ARM64E_FIRMWARE = 10, // stride 4, unauth target is vmaddr + DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE = 11, // stride 1, x86_64 kernel caches + DYLD_CHAINED_PTR_ARM64E_USERLAND24 = 12, // stride 8, unauth target is vm offset, 24-bit bind + }; + + // DYLD_CHAINED_PTR_ARM64E + struct dyld_chained_ptr_arm64e_rebase + { + uint64_t target : 43, high8 : 8, + next : 11, // 4 or 8-byte stide + bind : 1, // == 0 + auth : 1; // == 0 + }; + + // DYLD_CHAINED_PTR_ARM64E + struct dyld_chained_ptr_arm64e_bind + { + uint64_t ordinal : 16, zero : 16, + addend : 19, // +/-256K + next : 11, // 4 or 8-byte stide + bind : 1, // == 1 + auth : 1; // == 0 + }; + + // DYLD_CHAINED_PTR_ARM64E + struct dyld_chained_ptr_arm64e_auth_rebase + { + uint64_t target : 32, // runtimeOffset + diversity : 16, addrDiv : 1, key : 2, + next : 11, // 4 or 8-byte stide + bind : 1, // == 0 + auth : 1; // == 1 + }; + + // DYLD_CHAINED_PTR_ARM64E + struct dyld_chained_ptr_arm64e_auth_bind + { + uint64_t ordinal : 16, zero : 16, diversity : 16, addrDiv : 1, key : 2, + next : 11, // 4 or 8-byte stide + bind : 1, // == 1 + auth : 1; // == 1 + }; + + // DYLD_CHAINED_PTR_64/DYLD_CHAINED_PTR_64_OFFSET + struct dyld_chained_ptr_64_rebase + { + uint64_t target : 36, // 64GB max image size (DYLD_CHAINED_PTR_64 => vmAddr, DYLD_CHAINED_PTR_64_OFFSET => + // runtimeOffset) + high8 : 8, // top 8 bits set to this (DYLD_CHAINED_PTR_64 => after slide added, DYLD_CHAINED_PTR_64_OFFSET + // => before slide added) + reserved : 7, // all zeros + next : 12, // 4-byte stride + bind : 1; // == 0 + }; + + + // DYLD_CHAINED_PTR_ARM64E_USERLAND24 + struct dyld_chained_ptr_arm64e_bind24 + { + uint64_t ordinal : 24, zero : 8, + addend : 19, // +/-256K + next : 11, // 8-byte stide + bind : 1, // == 1 + auth : 1; // == 0 + }; + + // DYLD_CHAINED_PTR_ARM64E_USERLAND24 + struct dyld_chained_ptr_arm64e_auth_bind24 + { + uint64_t ordinal : 24, zero : 8, diversity : 16, addrDiv : 1, key : 2, + next : 11, // 8-byte stide + bind : 1, // == 1 + auth : 1; // == 1 + }; + + + // DYLD_CHAINED_PTR_64 + struct dyld_chained_ptr_64_bind + { + uint64_t ordinal : 24, + addend : 8, // 0 thru 255 + reserved : 19, // all zeros + next : 12, // 4-byte stride + bind : 1; // == 1 + }; + + // DYLD_CHAINED_PTR_64_KERNEL_CACHE, DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE + struct dyld_chained_ptr_64_kernel_cache_rebase + { + uint64_t target : 30, // basePointers[cacheLevel] + target + cacheLevel : 2, // what level of cache to bind to (indexes a mach_header array) + diversity : 16, addrDiv : 1, key : 2, + next : 12, // 1 or 4-byte stide + isAuth : 1; // 0 -> not authenticated. 1 -> authenticated + }; + + // DYLD_CHAINED_PTR_32 + // Note: for DYLD_CHAINED_PTR_32 some non-pointer values are co-opted into the chain + // as out of range rebases. If an entry in the chain is > max_valid_pointer, then it + // is not a pointer. To restore the value, subtract off the bias, which is + // (64MB+max_valid_pointer)/2. + struct dyld_chained_ptr_32_rebase + { + uint32_t target : 26, // vmaddr, 64MB max image size + next : 5, // 4-byte stride + bind : 1; // == 0 + }; + + // DYLD_CHAINED_PTR_32 + struct dyld_chained_ptr_32_bind + { + uint32_t ordinal : 20, + addend : 6, // 0 thru 63 + next : 5, // 4-byte stride + bind : 1; // == 1 + }; + + // DYLD_CHAINED_PTR_32_CACHE + struct dyld_chained_ptr_32_cache_rebase + { + uint32_t target : 30, // 1GB max dyld cache TEXT and DATA + next : 2; // 4-byte stride + }; + + + // DYLD_CHAINED_PTR_32_FIRMWARE + struct dyld_chained_ptr_32_firmware_rebase + { + uint32_t target : 26, // 64MB max firmware TEXT and DATA + next : 6; // 4-byte stride + }; + + enum ChainedFixupPointerGeneric + { + GenericArm64eFixupFormat, + Generic64FixupFormat, + Generic32FixupFormat, + Firmware32FixupFormat, + Kernel64Format + }; + + union Arm64e + { + dyld_chained_ptr_arm64e_auth_rebase authRebase; + dyld_chained_ptr_arm64e_auth_bind authBind; + dyld_chained_ptr_arm64e_rebase rebase; + dyld_chained_ptr_arm64e_bind bind; + dyld_chained_ptr_arm64e_bind24 bind24; + dyld_chained_ptr_arm64e_auth_bind24 authBind24; + }; + + union Generic64 + { + dyld_chained_ptr_64_rebase rebase; + dyld_chained_ptr_64_bind bind; + }; + + union Generic32 + { + dyld_chained_ptr_32_rebase rebase; + dyld_chained_ptr_32_bind bind; + }; + + union ChainedFixupPointer + { + dyld_chained_ptr_64_kernel_cache_rebase kernel64; + dyld_chained_ptr_32_firmware_rebase firmware32; + + uint64_t raw64; + Arm64e arm64e; + Generic64 generic64; + + uint32_t raw32; + Generic32 generic32; + dyld_chained_ptr_32_cache_rebase cache32; + }; + + // values for dyld_chained_fixups_header.imports_format + enum + { + DYLD_CHAINED_IMPORT = 1, + DYLD_CHAINED_IMPORT_ADDEND = 2, + DYLD_CHAINED_IMPORT_ADDEND64 = 3, + }; + + // DYLD_CHAINED_IMPORT + struct dyld_chained_import + { + uint32_t lib_ordinal : 8, weak_import : 1, name_offset : 23; + }; + + // DYLD_CHAINED_IMPORT_ADDEND + struct dyld_chained_import_addend + { + uint32_t lib_ordinal : 8, weak_import : 1, name_offset : 23; + int32_t addend; + }; + + // DYLD_CHAINED_IMPORT_ADDEND64 + struct dyld_chained_import_addend64 + { + uint64_t lib_ordinal : 16, weak_import : 1, reserved : 15, name_offset : 32; + uint64_t addend; + }; + +#ifndef EXPORT_SYMBOL_FLAGS_KIND_MASK + enum EXPORT_SYMBOL_FLAGS + { + EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03u, ///< Mask to access to EXPORT_SYMBOL_KINDS + EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04u, + EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08u, + EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10u + }; + + enum EXPORT_SYMBOL_KINDS + { + EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00u, + EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01u, + EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE = 0x02u + }; +#endif + + namespace MachO { + // Create Mach-O header types in `view`. + void CreateHeaderTypes(Ref view); + + void ApplyHeaderTypes(Ref view, Ref logger, const BinaryReader& reader, + std::string_view imageName, uint64_t headerAddress, size_t loadCommandCount); + + } // namespace MachO + +} // namespace BinaryNinja diff --git a/view/kernelcache/api/kernelcacheapi.h b/view/kernelcache/api/kernelcacheapi.h index 35c53d78b..ee5aae2ce 100644 --- a/view/kernelcache/api/kernelcacheapi.h +++ b/view/kernelcache/api/kernelcacheapi.h @@ -2,7 +2,7 @@ #include #include "../core/MetadataSerializable.hpp" -#include "../api/view/macho/machoview.h" +#include "macho/types.h" #include "kernelcachecore.h" using namespace BinaryNinja; diff --git a/view/kernelcache/core/CMakeLists.txt b/view/kernelcache/core/CMakeLists.txt index d2b37443c..f1f8d30ce 100644 --- a/view/kernelcache/core/CMakeLists.txt +++ b/view/kernelcache/core/CMakeLists.txt @@ -14,6 +14,7 @@ file (GLOB_RECURSE COMMON_SOURCES CONFIGURE_DEPENDS *.hpp *.c *.cpp + ../../../macho/* ) set(SOURCES ${COMMON_SOURCES}) diff --git a/view/kernelcache/core/KCView.cpp b/view/kernelcache/core/KCView.cpp index f166eafdf..4a47f593a 100644 --- a/view/kernelcache/core/KCView.cpp +++ b/view/kernelcache/core/KCView.cpp @@ -7,7 +7,7 @@ * */ #include "KCView.h" -#include "view/macho/machoview.h" +#include "macho/types.h" #include "KernelCache.h" [[maybe_unused]] KCViewType* g_kcViewType; @@ -133,429 +133,7 @@ bool KCView::Init() return false; } - - // Add Mach-O file header type info - EnumerationBuilder cpuTypeBuilder; - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ANY", MACHO_CPU_TYPE_ANY); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_VAX", MACHO_CPU_TYPE_VAX); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC680x0", MACHO_CPU_TYPE_MC680x0); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_X86", MACHO_CPU_TYPE_X86); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_X86_64", MACHO_CPU_TYPE_X86_64); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MIPS", MACHO_CPU_TYPE_MIPS); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC98000", MACHO_CPU_TYPE_MC98000); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_HPPA", MACHO_CPU_TYPE_HPPA); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM", MACHO_CPU_TYPE_ARM); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM64", MACHO_CPU_TYPE_ARM64); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM64_32", MACHO_CPU_TYPE_ARM64_32); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC88000", MACHO_CPU_TYPE_MC88000); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_SPARC", MACHO_CPU_TYPE_SPARC); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_I860", MACHO_CPU_TYPE_I860); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ALPHA", MACHO_CPU_TYPE_ALPHA); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_POWERPC", MACHO_CPU_TYPE_POWERPC); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_POWERPC64", MACHO_CPU_TYPE_POWERPC64); - Ref cpuTypeEnum = cpuTypeBuilder.Finalize(); - - Ref cpuTypeEnumType = Type::EnumerationType(nullptr, cpuTypeEnum, 4, false); - std::string cpuTypeEnumName = "cpu_type_t"; - std::string cpuTypeEnumId = Type::GenerateAutoTypeId("macho", cpuTypeEnumName); - DefineType(cpuTypeEnumId, cpuTypeEnumName, cpuTypeEnumType); - - EnumerationBuilder fileTypeBuilder; - fileTypeBuilder.AddMemberWithValue("MH_OBJECT", MH_OBJECT); - fileTypeBuilder.AddMemberWithValue("MH_EXECUTE", MH_EXECUTE); - fileTypeBuilder.AddMemberWithValue("MH_FVMLIB", MH_FVMLIB); - fileTypeBuilder.AddMemberWithValue("MH_CORE", MH_CORE); - fileTypeBuilder.AddMemberWithValue("MH_PRELOAD", MH_PRELOAD); - fileTypeBuilder.AddMemberWithValue("MH_DYLIB", MH_DYLIB); - fileTypeBuilder.AddMemberWithValue("MH_DYLINKER", MH_DYLINKER); - fileTypeBuilder.AddMemberWithValue("MH_BUNDLE", MH_BUNDLE); - fileTypeBuilder.AddMemberWithValue("MH_DYLIB_STUB", MH_DYLIB_STUB); - fileTypeBuilder.AddMemberWithValue("MH_DSYM", MH_DSYM); - fileTypeBuilder.AddMemberWithValue("MH_KEXT_BUNDLE", MH_KEXT_BUNDLE); - fileTypeBuilder.AddMemberWithValue("MH_FILESET", MH_FILESET); - Ref fileTypeEnum = fileTypeBuilder.Finalize(); - - Ref fileTypeEnumType = Type::EnumerationType(nullptr, fileTypeEnum, 4, false); - std::string fileTypeEnumName = "file_type_t"; - std::string fileTypeEnumId = Type::GenerateAutoTypeId("macho", fileTypeEnumName); - DefineType(fileTypeEnumId, fileTypeEnumName, fileTypeEnumType); - - EnumerationBuilder flagsTypeBuilder; - flagsTypeBuilder.AddMemberWithValue("MH_NOUNDEFS", MH_NOUNDEFS); - flagsTypeBuilder.AddMemberWithValue("MH_INCRLINK", MH_INCRLINK); - flagsTypeBuilder.AddMemberWithValue("MH_DYLDLINK", MH_DYLDLINK); - flagsTypeBuilder.AddMemberWithValue("MH_BINDATLOAD", MH_BINDATLOAD); - flagsTypeBuilder.AddMemberWithValue("MH_PREBOUND", MH_PREBOUND); - flagsTypeBuilder.AddMemberWithValue("MH_SPLIT_SEGS", MH_SPLIT_SEGS); - flagsTypeBuilder.AddMemberWithValue("MH_LAZY_INIT", MH_LAZY_INIT); - flagsTypeBuilder.AddMemberWithValue("MH_TWOLEVEL", MH_TWOLEVEL); - flagsTypeBuilder.AddMemberWithValue("MH_FORCE_FLAT", MH_FORCE_FLAT); - flagsTypeBuilder.AddMemberWithValue("MH_NOMULTIDEFS", MH_NOMULTIDEFS); - flagsTypeBuilder.AddMemberWithValue("MH_NOFIXPREBINDING", MH_NOFIXPREBINDING); - flagsTypeBuilder.AddMemberWithValue("MH_PREBINDABLE", MH_PREBINDABLE); - flagsTypeBuilder.AddMemberWithValue("MH_ALLMODSBOUND", MH_ALLMODSBOUND); - flagsTypeBuilder.AddMemberWithValue("MH_SUBSECTIONS_VIA_SYMBOLS", MH_SUBSECTIONS_VIA_SYMBOLS); - flagsTypeBuilder.AddMemberWithValue("MH_CANONICAL", MH_CANONICAL); - flagsTypeBuilder.AddMemberWithValue("MH_WEAK_DEFINES", MH_WEAK_DEFINES); - flagsTypeBuilder.AddMemberWithValue("MH_BINDS_TO_WEAK", MH_BINDS_TO_WEAK); - flagsTypeBuilder.AddMemberWithValue("MH_ALLOW_STACK_EXECUTION", MH_ALLOW_STACK_EXECUTION); - flagsTypeBuilder.AddMemberWithValue("MH_ROOT_SAFE", MH_ROOT_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_SETUID_SAFE", MH_SETUID_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_NO_REEXPORTED_DYLIBS", MH_NO_REEXPORTED_DYLIBS); - flagsTypeBuilder.AddMemberWithValue("MH_PIE", MH_PIE); - flagsTypeBuilder.AddMemberWithValue("MH_DEAD_STRIPPABLE_DYLIB", MH_DEAD_STRIPPABLE_DYLIB); - flagsTypeBuilder.AddMemberWithValue("MH_HAS_TLV_DESCRIPTORS", MH_HAS_TLV_DESCRIPTORS); - flagsTypeBuilder.AddMemberWithValue("MH_NO_HEAP_EXECUTION", MH_NO_HEAP_EXECUTION); - flagsTypeBuilder.AddMemberWithValue("MH_APP_EXTENSION_SAFE", _MH_APP_EXTENSION_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_NLIST_OUTOFSYNC_WITH_DYLDINFO", _MH_NLIST_OUTOFSYNC_WITH_DYLDINFO); - flagsTypeBuilder.AddMemberWithValue("MH_SIM_SUPPORT", _MH_SIM_SUPPORT); - flagsTypeBuilder.AddMemberWithValue("MH_DYLIB_IN_CACHE", _MH_DYLIB_IN_CACHE); - Ref flagsTypeEnum = flagsTypeBuilder.Finalize(); - - Ref flagsTypeEnumType = Type::EnumerationType(nullptr, flagsTypeEnum, 4, false); - std::string flagsTypeEnumName = "flags_type_t"; - std::string flagsTypeEnumId = Type::GenerateAutoTypeId("macho", flagsTypeEnumName); - DefineType(flagsTypeEnumId, flagsTypeEnumName, flagsTypeEnumType); - - StructureBuilder machoHeaderBuilder; - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "magic"); - machoHeaderBuilder.AddMember(Type::NamedType(this, QualifiedName("cpu_type_t")), "cputype"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "cpusubtype"); - machoHeaderBuilder.AddMember(Type::NamedType(this, QualifiedName("file_type_t")), "filetype"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "ncmds"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "sizeofcmds"); - machoHeaderBuilder.AddMember(Type::NamedType(this, QualifiedName("flags_type_t")), "flags"); - if (GetAddressSize() == 8) - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "reserved"); - Ref machoHeaderStruct = machoHeaderBuilder.Finalize(); - QualifiedName headerName = (GetAddressSize() == 8) ? std::string("mach_header_64") : std::string("mach_header"); - - std::string headerTypeId = Type::GenerateAutoTypeId("macho", headerName); - Ref machoHeaderType = Type::StructureType(machoHeaderStruct); - DefineType(headerTypeId, headerName, machoHeaderType); - - EnumerationBuilder cmdTypeBuilder; - cmdTypeBuilder.AddMemberWithValue("LC_REQ_DYLD", LC_REQ_DYLD); - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT", LC_SEGMENT); - cmdTypeBuilder.AddMemberWithValue("LC_SYMTAB", LC_SYMTAB); - cmdTypeBuilder.AddMemberWithValue("LC_SYMSEG", LC_SYMSEG); - cmdTypeBuilder.AddMemberWithValue("LC_THREAD", LC_THREAD); - cmdTypeBuilder.AddMemberWithValue("LC_UNIXTHREAD", LC_UNIXTHREAD); - cmdTypeBuilder.AddMemberWithValue("LC_LOADFVMLIB", LC_LOADFVMLIB); - cmdTypeBuilder.AddMemberWithValue("LC_IDFVMLIB", LC_IDFVMLIB); - cmdTypeBuilder.AddMemberWithValue("LC_IDENT", LC_IDENT); - cmdTypeBuilder.AddMemberWithValue("LC_FVMFILE", LC_FVMFILE); - cmdTypeBuilder.AddMemberWithValue("LC_PREPAGE", LC_PREPAGE); - cmdTypeBuilder.AddMemberWithValue("LC_DYSYMTAB", LC_DYSYMTAB); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_DYLIB", LC_LOAD_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ID_DYLIB", LC_ID_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_DYLINKER", LC_LOAD_DYLINKER); - cmdTypeBuilder.AddMemberWithValue("LC_ID_DYLINKER", LC_ID_DYLINKER); - cmdTypeBuilder.AddMemberWithValue("LC_PREBOUND_DYLIB", LC_PREBOUND_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ROUTINES", LC_ROUTINES); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_FRAMEWORK", LC_SUB_FRAMEWORK); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_UMBRELLA", LC_SUB_UMBRELLA); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_CLIENT", LC_SUB_CLIENT); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_LIBRARY", LC_SUB_LIBRARY); - cmdTypeBuilder.AddMemberWithValue("LC_TWOLEVEL_HINTS", LC_TWOLEVEL_HINTS); - cmdTypeBuilder.AddMemberWithValue("LC_PREBIND_CKSUM", LC_PREBIND_CKSUM); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_WEAK_DYLIB", LC_LOAD_WEAK_DYLIB); // (0x18 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT_64", LC_SEGMENT_64); - cmdTypeBuilder.AddMemberWithValue("LC_ROUTINES_64", LC_ROUTINES_64); - cmdTypeBuilder.AddMemberWithValue("LC_UUID", LC_UUID); - cmdTypeBuilder.AddMemberWithValue("LC_RPATH", LC_RPATH); // (0x1c | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_CODE_SIGNATURE", LC_CODE_SIGNATURE); - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT_SPLIT_INFO", LC_SEGMENT_SPLIT_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_REEXPORT_DYLIB", LC_REEXPORT_DYLIB); // (0x1f | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_LAZY_LOAD_DYLIB", LC_LAZY_LOAD_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ENCRYPTION_INFO", LC_ENCRYPTION_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_INFO", LC_DYLD_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_INFO_ONLY", LC_DYLD_INFO_ONLY); // (0x22 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_UPWARD_DYLIB", LC_LOAD_UPWARD_DYLIB); // (0x23 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_MACOSX", LC_VERSION_MIN_MACOSX); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_IPHONEOS", LC_VERSION_MIN_IPHONEOS); - cmdTypeBuilder.AddMemberWithValue("LC_FUNCTION_STARTS", LC_FUNCTION_STARTS); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_ENVIRONMENT", LC_DYLD_ENVIRONMENT); - cmdTypeBuilder.AddMemberWithValue("LC_MAIN", LC_MAIN); // (0x28 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_DATA_IN_CODE", LC_DATA_IN_CODE); - cmdTypeBuilder.AddMemberWithValue("LC_SOURCE_VERSION", LC_SOURCE_VERSION); - cmdTypeBuilder.AddMemberWithValue("LC_DYLIB_CODE_SIGN_DRS", LC_DYLIB_CODE_SIGN_DRS); - cmdTypeBuilder.AddMemberWithValue("LC_ENCRYPTION_INFO_64", _LC_ENCRYPTION_INFO_64); - cmdTypeBuilder.AddMemberWithValue("LC_LINKER_OPTION", _LC_LINKER_OPTION); - cmdTypeBuilder.AddMemberWithValue("LC_LINKER_OPTIMIZATION_HINT", _LC_LINKER_OPTIMIZATION_HINT); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_TVOS", _LC_VERSION_MIN_TVOS); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_WATCHOS", LC_VERSION_MIN_WATCHOS); - cmdTypeBuilder.AddMemberWithValue("LC_NOTE", LC_NOTE); - cmdTypeBuilder.AddMemberWithValue("LC_BUILD_VERSION", LC_BUILD_VERSION); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_EXPORTS_TRIE", LC_DYLD_EXPORTS_TRIE); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_CHAINED_FIXUPS", LC_DYLD_CHAINED_FIXUPS); - cmdTypeBuilder.AddMemberWithValue("LC_FILESET_ENTRY", LC_FILESET_ENTRY); - Ref cmdTypeEnum = cmdTypeBuilder.Finalize(); - - Ref cmdTypeEnumType = Type::EnumerationType(nullptr, cmdTypeEnum, 4, false); - std::string cmdTypeEnumName = "load_command_type_t"; - std::string cmdTypeEnumId = Type::GenerateAutoTypeId("macho", cmdTypeEnumName); - DefineType(cmdTypeEnumId, cmdTypeEnumName, cmdTypeEnumType); - - StructureBuilder loadCommandBuilder; - loadCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - loadCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - Ref loadCommandStruct = loadCommandBuilder.Finalize(); - QualifiedName loadCommandName = std::string("load_command"); - std::string loadCommandTypeId = Type::GenerateAutoTypeId("macho", loadCommandName); - Ref loadCommandType = Type::StructureType(loadCommandStruct); - DefineType(loadCommandTypeId, loadCommandName, loadCommandType); - - EnumerationBuilder protTypeBuilder; - protTypeBuilder.AddMemberWithValue("VM_PROT_NONE", MACHO_VM_PROT_NONE); - protTypeBuilder.AddMemberWithValue("VM_PROT_READ", MACHO_VM_PROT_READ); - protTypeBuilder.AddMemberWithValue("VM_PROT_WRITE", MACHO_VM_PROT_WRITE); - protTypeBuilder.AddMemberWithValue("VM_PROT_EXECUTE", MACHO_VM_PROT_EXECUTE); - // protTypeBuilder.AddMemberWithValue("VM_PROT_DEFAULT", MACHO_VM_PROT_DEFAULT); - // protTypeBuilder.AddMemberWithValue("VM_PROT_ALL", MACHO_VM_PROT_ALL); - protTypeBuilder.AddMemberWithValue("VM_PROT_NO_CHANGE", MACHO_VM_PROT_NO_CHANGE); - protTypeBuilder.AddMemberWithValue("VM_PROT_COPY_OR_WANTS_COPY", MACHO_VM_PROT_COPY); - // protTypeBuilder.AddMemberWithValue("VM_PROT_WANTS_COPY", MACHO_VM_PROT_WANTS_COPY); - Ref protTypeEnum = protTypeBuilder.Finalize(); - - Ref protTypeEnumType = Type::EnumerationType(nullptr, protTypeEnum, 4, false); - std::string protTypeEnumName = "vm_prot_t"; - std::string protTypeEnumId = Type::GenerateAutoTypeId("macho", protTypeEnumName); - DefineType(protTypeEnumId, protTypeEnumName, protTypeEnumType); - - EnumerationBuilder segFlagsTypeBuilder; - segFlagsTypeBuilder.AddMemberWithValue("SG_HIGHVM", SG_HIGHVM); - segFlagsTypeBuilder.AddMemberWithValue("SG_FVMLIB", SG_FVMLIB); - segFlagsTypeBuilder.AddMemberWithValue("SG_NORELOC", SG_NORELOC); - segFlagsTypeBuilder.AddMemberWithValue("SG_PROTECTED_VERSION_1", SG_PROTECTED_VERSION_1); - Ref segFlagsTypeEnum = segFlagsTypeBuilder.Finalize(); - - Ref segFlagsTypeEnumType = Type::EnumerationType(nullptr, segFlagsTypeEnum, 4, false); - std::string segFlagsTypeEnumName = "sg_flags_t"; - std::string segFlagsTypeEnumId = Type::GenerateAutoTypeId("macho", segFlagsTypeEnumName); - DefineType(segFlagsTypeEnumId, segFlagsTypeEnumName, segFlagsTypeEnumType); - - StructureBuilder loadSegmentCommandBuilder; - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - loadSegmentCommandBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "vmaddr"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "vmsize"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "fileoff"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "filesize"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "maxprot"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "initprot"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "nsects"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("sg_flags_t")), "flags"); - Ref loadSegmentCommandStruct = loadSegmentCommandBuilder.Finalize(); - QualifiedName loadSegmentCommandName = std::string("segment_command"); - std::string loadSegmentCommandTypeId = Type::GenerateAutoTypeId("macho", loadSegmentCommandName); - Ref loadSegmentCommandType = Type::StructureType(loadSegmentCommandStruct); - DefineType(loadSegmentCommandTypeId, loadSegmentCommandName, loadSegmentCommandType); - - StructureBuilder loadSegmentCommand64Builder; - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(4, false), "cmdsize"); - loadSegmentCommand64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "vmaddr"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "vmsize"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "fileoff"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "filesize"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "maxprot"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "initprot"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(4, false), "nsects"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("sg_flags_t")), "flags"); - Ref loadSegmentCommand64Struct = loadSegmentCommand64Builder.Finalize(); - QualifiedName loadSegment64CommandName = std::string("segment_command_64"); - std::string loadSegment64CommandTypeId = Type::GenerateAutoTypeId("macho", loadSegment64CommandName); - Ref loadSegment64CommandType = Type::StructureType(loadSegmentCommand64Struct); - DefineType(loadSegment64CommandTypeId, loadSegment64CommandName, loadSegment64CommandType); - - StructureBuilder sectionBuilder; - sectionBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "sectname"); - sectionBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "addr"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "size"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "offset"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "align"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reloff"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "nreloc"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "flags"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reserved1"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reserved2"); - Ref sectionStruct = sectionBuilder.Finalize(); - QualifiedName sectionName = std::string("section"); - std::string sectionTypeId = Type::GenerateAutoTypeId("macho", sectionName); - Ref sectionType = Type::StructureType(sectionStruct); - DefineType(sectionTypeId, sectionName, sectionType); - - StructureBuilder section64Builder; - section64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "sectname"); - section64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - section64Builder.AddMember(Type::IntegerType(8, false), "addr"); - section64Builder.AddMember(Type::IntegerType(8, false), "size"); - section64Builder.AddMember(Type::IntegerType(4, false), "offset"); - section64Builder.AddMember(Type::IntegerType(4, false), "align"); - section64Builder.AddMember(Type::IntegerType(4, false), "reloff"); - section64Builder.AddMember(Type::IntegerType(4, false), "nreloc"); - section64Builder.AddMember(Type::IntegerType(4, false), "flags"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved1"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved2"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved3"); - Ref section64Struct = section64Builder.Finalize(); - QualifiedName section64Name = std::string("section_64"); - std::string section64TypeId = Type::GenerateAutoTypeId("macho", section64Name); - Ref section64Type = Type::StructureType(section64Struct); - DefineType(section64TypeId, section64Name, section64Type); - - StructureBuilder symtabBuilder; - symtabBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "symoff"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "nsyms"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "stroff"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "strsize"); - Ref symtabStruct = symtabBuilder.Finalize(); - QualifiedName symtabName = std::string("symtab"); - std::string symtabTypeId = Type::GenerateAutoTypeId("macho", symtabName); - Ref symtabType = Type::StructureType(symtabStruct); - DefineType(symtabTypeId, symtabName, symtabType); - - StructureBuilder dynsymtabBuilder; - dynsymtabBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "ilocalsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nlocalsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "iextdefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextdefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "iundefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nundefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "tocoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "ntoc"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "modtaboff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nmodtab"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "extrefsymoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextrefsyms"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "indirectsymoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nindirectsyms"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "extreloff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextrel"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "locreloff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nlocrel"); - Ref dynsymtabStruct = dynsymtabBuilder.Finalize(); - QualifiedName dynsymtabName = std::string("dysymtab"); - std::string dynsymtabTypeId = Type::GenerateAutoTypeId("macho", dynsymtabName); - Ref dynsymtabType = Type::StructureType(dynsymtabStruct); - DefineType(dynsymtabTypeId, dynsymtabName, dynsymtabType); - - StructureBuilder uuidBuilder; - uuidBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - uuidBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - uuidBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, false), 16), "uuid"); - Ref uuidStruct = uuidBuilder.Finalize(); - QualifiedName uuidName = std::string("uuid"); - std::string uuidTypeId = Type::GenerateAutoTypeId("macho", uuidName); - Ref uuidType = Type::StructureType(uuidStruct); - DefineType(uuidTypeId, uuidName, uuidType); - - StructureBuilder linkeditDataBuilder; - linkeditDataBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "dataoff"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "datasize"); - Ref linkeditDataStruct = linkeditDataBuilder.Finalize(); - QualifiedName linkeditDataName = std::string("linkedit_data"); - std::string linkeditDataTypeId = Type::GenerateAutoTypeId("macho", linkeditDataName); - Ref linkeditDataType = Type::StructureType(linkeditDataStruct); - DefineType(linkeditDataTypeId, linkeditDataName, linkeditDataType); - - StructureBuilder encryptionInfoBuilder; - encryptionInfoBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptoff"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptsize"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptid"); - Ref encryptionInfoStruct = encryptionInfoBuilder.Finalize(); - QualifiedName encryptionInfoName = std::string("encryption_info"); - std::string encryptionInfoTypeId = Type::GenerateAutoTypeId("macho", encryptionInfoName); - Ref encryptionInfoType = Type::StructureType(encryptionInfoStruct); - DefineType(encryptionInfoTypeId, encryptionInfoName, encryptionInfoType); - - StructureBuilder versionMinBuilder; - versionMinBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "version"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "sdk"); - Ref versionMinStruct = versionMinBuilder.Finalize(); - QualifiedName versionMinName = std::string("version_min"); - std::string versionMinTypeId = Type::GenerateAutoTypeId("macho", versionMinName); - Ref versionMinType = Type::StructureType(versionMinStruct); - DefineType(versionMinTypeId, versionMinName, versionMinType); - - StructureBuilder dyldInfoBuilder; - dyldInfoBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "rebase_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "rebase_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "weak_bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "weak_bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "lazy_bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "lazy_bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "export_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "export_size"); - Ref dyldInfoStruct = dyldInfoBuilder.Finalize(); - QualifiedName dyldInfoName = std::string("dyld_info"); - std::string dyldInfoTypeId = Type::GenerateAutoTypeId("macho", dyldInfoName); - Ref dyldInfoType = Type::StructureType(dyldInfoStruct); - DefineType(dyldInfoTypeId, dyldInfoName, dyldInfoType); - - StructureBuilder dylibBuilder; - dylibBuilder.AddMember(Type::IntegerType(4, false), "name"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "timestamp"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "current_version"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "compatibility_version"); - Ref dylibStruct = dylibBuilder.Finalize(); - QualifiedName dylibName = std::string("dylib"); - std::string dylibTypeId = Type::GenerateAutoTypeId("macho", dylibName); - Ref dylibType = Type::StructureType(dylibStruct); - DefineType(dylibTypeId, dylibName, dylibType); - - StructureBuilder dylibCommandBuilder; - dylibCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - dylibCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dylibCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("dylib")), "dylib"); - Ref dylibCommandStruct = dylibCommandBuilder.Finalize(); - QualifiedName dylibCommandName = std::string("dylib_command"); - std::string dylibCommandTypeId = Type::GenerateAutoTypeId("macho", dylibCommandName); - Ref dylibCommandType = Type::StructureType(dylibCommandStruct); - DefineType(dylibCommandTypeId, dylibCommandName, dylibCommandType); - - StructureBuilder filesetEntryCommandBuilder; - filesetEntryCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(8, false), "vmaddr"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(8, false), "fileoff"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "entry_id"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "reserved"); - Ref filesetEntryCommandStruct = filesetEntryCommandBuilder.Finalize(); - QualifiedName filesetEntryCommandName = std::string("fileset_entry_command"); - std::string filesetEntryCommandTypeId = Type::GenerateAutoTypeId("macho", filesetEntryCommandName); - Ref filesetEntryCommandType = Type::StructureType(filesetEntryCommandStruct); - DefineType(filesetEntryCommandTypeId, filesetEntryCommandName, filesetEntryCommandType); - - StructureBuilder unixThreadCommandBuilder; - unixThreadCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - unixThreadCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - unixThreadCommandBuilder.AddMember(Type::IntegerType(4, false), "flavor"); - unixThreadCommandBuilder.AddMember(Type::IntegerType(4, false), "count"); - // The 'state' field is intentionally ignored. - Ref unixThreadCommandStruct = unixThreadCommandBuilder.Finalize(); - QualifiedName unixThreadCommandName = std::string("unix_thread_command"); - std::string unixThreadCommandTypeId = Type::GenerateAutoTypeId("macho", unixThreadCommandName); - Ref unixThreadCommandType = Type::StructureType(unixThreadCommandStruct); - DefineType(unixThreadCommandTypeId, unixThreadCommandName, unixThreadCommandType); + MachO::CreateHeaderTypes(this); std::vector regionsMappedIntoMemory; if (auto metadata = KernelCacheCore::KernelCacheMetadata::LoadFromView(GetParentView())) @@ -588,119 +166,7 @@ bool KCView::Init() DefineAutoSymbol( new Symbol(DataSymbol, "kernelcache_header", textSegOffset, LocalBinding)); - try - { - reader.Seek(sizeof(mach_header_64)); - size_t sectionNum = 0; - for (size_t i = 0; i < ncmds; i++) - { - load_command load; - uint64_t curOffset = reader.GetOffset(); - load.cmd = reader.Read32(); - load.cmdsize = reader.Read32(); - uint64_t nextOffset = curOffset + load.cmdsize; - switch (load.cmd) - { - case LC_SEGMENT: - { - DefineDataVariable(reader.GetOffset() + textSegOffset, Type::NamedType(this, QualifiedName("segment_command"))); - reader.SeekRelative(5 * 8); - size_t numSections = reader.Read32(); - reader.SeekRelative(4); - for (size_t j = 0; j < numSections; j++) - { - DefineDataVariable( - reader.GetOffset() + textSegOffset, Type::NamedType(this, QualifiedName("section"))); - DefineAutoSymbol(new Symbol(DataSymbol, - "__macho_section::kernelcache[" + std::to_string(sectionNum++) + "]", - reader.GetOffset() + textSegOffset, LocalBinding)); - reader.SeekRelative((8 * 8) + 4); - } - break; - } - case LC_SEGMENT_64: - { - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("segment_command_64"))); - reader.SeekRelative(7 * 8); - size_t numSections = reader.Read32(); - reader.SeekRelative(4); - for (size_t j = 0; j < numSections; j++) - { - DefineDataVariable( - reader.GetOffset() + textSegOffset, Type::NamedType(this, QualifiedName("section_64"))); - DefineAutoSymbol(new Symbol(DataSymbol, - "__macho_section_64::kernelcache[" + std::to_string(sectionNum++) + "]", - reader.GetOffset() + textSegOffset, LocalBinding)); - reader.SeekRelative(10 * 8); - } - break; - } - case LC_SYMTAB: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("symtab"))); - break; - case LC_DYSYMTAB: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("dysymtab"))); - break; - case LC_UUID: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("uuid"))); - break; - case LC_ID_DYLIB: - case LC_LOAD_DYLIB: - case LC_REEXPORT_DYLIB: - case LC_LOAD_WEAK_DYLIB: - case LC_LOAD_UPWARD_DYLIB: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("dylib_command"))); - if (load.cmdsize - 24 <= 150) - DefineDataVariable( - curOffset + textSegOffset + 24, Type::ArrayType(Type::IntegerType(1, true), load.cmdsize - 24)); - break; - case LC_CODE_SIGNATURE: - case LC_SEGMENT_SPLIT_INFO: - case LC_FUNCTION_STARTS: - case LC_DATA_IN_CODE: - case LC_DYLIB_CODE_SIGN_DRS: - case LC_DYLD_EXPORTS_TRIE: - case LC_DYLD_CHAINED_FIXUPS: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("linkedit_data"))); - break; - case LC_ENCRYPTION_INFO: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("encryption_info"))); - break; - case LC_VERSION_MIN_MACOSX: - case LC_VERSION_MIN_IPHONEOS: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("version_min"))); - break; - case LC_DYLD_INFO: - case LC_DYLD_INFO_ONLY: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("dyld_info"))); - break; - case LC_FILESET_ENTRY: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("fileset_entry_command"))); - break; - case LC_UNIXTHREAD: - { - DefineDataVariable( - curOffset + textSegOffset, Type::NamedType(this, QualifiedName("unix_thread_command"))); - reader.SeekRelative(4); - uint32_t count = reader.Read32(); - DefineDataVariable(reader.GetOffset() + textSegOffset, Type::ArrayType(Type::IntegerType(8, true), count)); - break; - } - default: - DefineDataVariable(curOffset + textSegOffset, Type::NamedType(this, QualifiedName("load_command"))); - break; - } - - DefineAutoSymbol(new Symbol(DataSymbol, - "__macho_load_command::kernelcache[" + std::to_string(i) + "]", curOffset + textSegOffset, - LocalBinding)); - reader.Seek(nextOffset); - } - } - catch (ReadException&) - { - LogError("Error when applying Mach-O header types at %" PRIx64, textSegOffset); - } + MachO::ApplyHeaderTypes(this, nullptr, reader, "kernelcache", textSegOffset + sizeof(mach_header_64), ncmds); return true; } diff --git a/view/kernelcache/core/KernelCache.h b/view/kernelcache/core/KernelCache.h index e0e80cb63..b05c74369 100644 --- a/view/kernelcache/core/KernelCache.h +++ b/view/kernelcache/core/KernelCache.h @@ -4,7 +4,7 @@ #include #include "KCView.h" -#include "view/macho/machoview.h" +#include "macho/types.h" #include "MetadataSerializable.hpp" #include "../api/kernelcachecore.h" diff --git a/view/kernelcache/core/MetadataSerializable.hpp b/view/kernelcache/core/MetadataSerializable.hpp index 5397a56c1..5011e51fd 100644 --- a/view/kernelcache/core/MetadataSerializable.hpp +++ b/view/kernelcache/core/MetadataSerializable.hpp @@ -43,7 +43,7 @@ #include "rapidjson/stringbuffer.h" #include "rapidjson/prettywriter.h" #include "../api/kernelcachecore.h" -#include "view/macho/machoview.h" +#include "macho/types.h" using namespace BinaryNinja; diff --git a/view/macho/CMakeLists.txt b/view/macho/CMakeLists.txt index 6e628b1f2..22e533fe2 100644 --- a/view/macho/CMakeLists.txt +++ b/view/macho/CMakeLists.txt @@ -6,7 +6,7 @@ if(NOT BN_INTERNAL_BUILD) add_subdirectory(${PROJECT_SOURCE_DIR}/../.. ${PROJECT_BINARY_DIR}/api) endif() -file(GLOB SOURCES *.cpp *.h ../../objectivec/*) +file(GLOB SOURCES *.cpp *.h ../../objectivec/* ../../macho/*) if(DEMO) add_library(view_macho STATIC ${SOURCES}) diff --git a/view/macho/machoview.cpp b/view/macho/machoview.cpp index 26839c933..5b0f60609 100644 --- a/view/macho/machoview.cpp +++ b/view/macho/machoview.cpp @@ -1,3 +1,4 @@ +#include "macho/types.h" #include #include #include @@ -1112,6 +1113,8 @@ bool MachoView::Init() } } + MachO::CreateHeaderTypes(this); + m_imageBaseAdjustment = 0; if (!initialImageBase) m_imageBaseAdjustment = preferredImageBase; @@ -1120,417 +1123,6 @@ bool MachoView::Init() else m_imageBaseAdjustment = -(int64_t)(initialImageBase - preferredImageBase); - // Add Mach-O file header type info - EnumerationBuilder cpuTypeBuilder; - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ANY", MACHO_CPU_TYPE_ANY); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_VAX", MACHO_CPU_TYPE_VAX); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC680x0", MACHO_CPU_TYPE_MC680x0); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_X86", MACHO_CPU_TYPE_X86); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_X86_64", MACHO_CPU_TYPE_X86_64); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MIPS", MACHO_CPU_TYPE_MIPS); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC98000", MACHO_CPU_TYPE_MC98000); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_HPPA", MACHO_CPU_TYPE_HPPA); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM", MACHO_CPU_TYPE_ARM); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM64", MACHO_CPU_TYPE_ARM64); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM64_32", MACHO_CPU_TYPE_ARM64_32); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC88000", MACHO_CPU_TYPE_MC88000); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_SPARC", MACHO_CPU_TYPE_SPARC); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_I860", MACHO_CPU_TYPE_I860); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ALPHA", MACHO_CPU_TYPE_ALPHA); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_POWERPC", MACHO_CPU_TYPE_POWERPC); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_POWERPC64", MACHO_CPU_TYPE_POWERPC64); - Ref cpuTypeEnum = cpuTypeBuilder.Finalize(); - - Ref cpuTypeEnumType = Type::EnumerationType(nullptr, cpuTypeEnum, 4, false); - string cpuTypeEnumName = "cpu_type_t"; - string cpuTypeEnumId = Type::GenerateAutoTypeId("macho", cpuTypeEnumName); - m_typeNames.cpuTypeEnumQualName = DefineType(cpuTypeEnumId, cpuTypeEnumName, cpuTypeEnumType); - - EnumerationBuilder fileTypeBuilder; - fileTypeBuilder.AddMemberWithValue("MH_OBJECT", MH_OBJECT); - fileTypeBuilder.AddMemberWithValue("MH_EXECUTE", MH_EXECUTE); - fileTypeBuilder.AddMemberWithValue("MH_FVMLIB", MH_FVMLIB); - fileTypeBuilder.AddMemberWithValue("MH_CORE", MH_CORE); - fileTypeBuilder.AddMemberWithValue("MH_PRELOAD", MH_PRELOAD); - fileTypeBuilder.AddMemberWithValue("MH_DYLIB", MH_DYLIB); - fileTypeBuilder.AddMemberWithValue("MH_DYLINKER", MH_DYLINKER); - fileTypeBuilder.AddMemberWithValue("MH_BUNDLE", MH_BUNDLE); - fileTypeBuilder.AddMemberWithValue("MH_DYLIB_STUB", MH_DYLIB_STUB); - fileTypeBuilder.AddMemberWithValue("MH_DSYM", MH_DSYM); - fileTypeBuilder.AddMemberWithValue("MH_KEXT_BUNDLE", MH_KEXT_BUNDLE); - fileTypeBuilder.AddMemberWithValue("MH_FILESET", MH_FILESET); - Ref fileTypeEnum = fileTypeBuilder.Finalize(); - - Ref fileTypeEnumType = Type::EnumerationType(nullptr, fileTypeEnum, 4, false); - string fileTypeEnumName = "file_type_t"; - string fileTypeEnumId = Type::GenerateAutoTypeId("macho", fileTypeEnumName); - m_typeNames.fileTypeEnumQualName = DefineType(fileTypeEnumId, fileTypeEnumName, fileTypeEnumType); - - EnumerationBuilder flagsTypeBuilder; - flagsTypeBuilder.AddMemberWithValue("MH_NOUNDEFS", MH_NOUNDEFS); - flagsTypeBuilder.AddMemberWithValue("MH_INCRLINK", MH_INCRLINK); - flagsTypeBuilder.AddMemberWithValue("MH_DYLDLINK", MH_DYLDLINK); - flagsTypeBuilder.AddMemberWithValue("MH_BINDATLOAD", MH_BINDATLOAD); - flagsTypeBuilder.AddMemberWithValue("MH_PREBOUND", MH_PREBOUND); - flagsTypeBuilder.AddMemberWithValue("MH_SPLIT_SEGS", MH_SPLIT_SEGS); - flagsTypeBuilder.AddMemberWithValue("MH_LAZY_INIT", MH_LAZY_INIT); - flagsTypeBuilder.AddMemberWithValue("MH_TWOLEVEL", MH_TWOLEVEL); - flagsTypeBuilder.AddMemberWithValue("MH_FORCE_FLAT", MH_FORCE_FLAT); - flagsTypeBuilder.AddMemberWithValue("MH_NOMULTIDEFS", MH_NOMULTIDEFS); - flagsTypeBuilder.AddMemberWithValue("MH_NOFIXPREBINDING", MH_NOFIXPREBINDING); - flagsTypeBuilder.AddMemberWithValue("MH_PREBINDABLE", MH_PREBINDABLE); - flagsTypeBuilder.AddMemberWithValue("MH_ALLMODSBOUND", MH_ALLMODSBOUND); - flagsTypeBuilder.AddMemberWithValue("MH_SUBSECTIONS_VIA_SYMBOLS", MH_SUBSECTIONS_VIA_SYMBOLS); - flagsTypeBuilder.AddMemberWithValue("MH_CANONICAL", MH_CANONICAL); - flagsTypeBuilder.AddMemberWithValue("MH_WEAK_DEFINES", MH_WEAK_DEFINES); - flagsTypeBuilder.AddMemberWithValue("MH_BINDS_TO_WEAK", MH_BINDS_TO_WEAK); - flagsTypeBuilder.AddMemberWithValue("MH_ALLOW_STACK_EXECUTION", MH_ALLOW_STACK_EXECUTION); - flagsTypeBuilder.AddMemberWithValue("MH_ROOT_SAFE", MH_ROOT_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_SETUID_SAFE", MH_SETUID_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_NO_REEXPORTED_DYLIBS", MH_NO_REEXPORTED_DYLIBS); - flagsTypeBuilder.AddMemberWithValue("MH_PIE", MH_PIE); - flagsTypeBuilder.AddMemberWithValue("MH_DEAD_STRIPPABLE_DYLIB", MH_DEAD_STRIPPABLE_DYLIB); - flagsTypeBuilder.AddMemberWithValue("MH_HAS_TLV_DESCRIPTORS", MH_HAS_TLV_DESCRIPTORS); - flagsTypeBuilder.AddMemberWithValue("MH_NO_HEAP_EXECUTION", MH_NO_HEAP_EXECUTION); - flagsTypeBuilder.AddMemberWithValue("MH_APP_EXTENSION_SAFE", _MH_APP_EXTENSION_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_NLIST_OUTOFSYNC_WITH_DYLDINFO", _MH_NLIST_OUTOFSYNC_WITH_DYLDINFO); - flagsTypeBuilder.AddMemberWithValue("MH_SIM_SUPPORT", _MH_SIM_SUPPORT); - flagsTypeBuilder.AddMemberWithValue("MH_DYLIB_IN_CACHE", _MH_DYLIB_IN_CACHE); - Ref flagsTypeEnum = flagsTypeBuilder.Finalize(); - - Ref flagsTypeEnumType = Type::EnumerationType(nullptr, flagsTypeEnum, 4, false); - string flagsTypeEnumName = "flags_type_t"; - string flagsTypeEnumId = Type::GenerateAutoTypeId("macho", flagsTypeEnumName); - m_typeNames.flagsTypeEnumQualName = DefineType(flagsTypeEnumId, flagsTypeEnumName, flagsTypeEnumType); - - StructureBuilder machoHeaderBuilder; - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "magic"); - machoHeaderBuilder.AddMember(Type::NamedType(this, m_typeNames.cpuTypeEnumQualName), "cputype"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "cpusubtype"); - machoHeaderBuilder.AddMember(Type::NamedType(this, m_typeNames.fileTypeEnumQualName), "filetype"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "ncmds"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "sizeofcmds"); - machoHeaderBuilder.AddMember(Type::NamedType(this, m_typeNames.flagsTypeEnumQualName), "flags"); - if (m_addressSize == 8) - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "reserved"); - Ref machoHeaderStruct = machoHeaderBuilder.Finalize(); - QualifiedName headerName = (m_addressSize == 8) ? string("mach_header_64") : string("mach_header"); - - string headerTypeId = Type::GenerateAutoTypeId("macho", headerName); - Ref machoHeaderType = Type::StructureType(machoHeaderStruct); - m_typeNames.headerQualName = DefineType(headerTypeId, headerName, machoHeaderType); - - EnumerationBuilder cmdTypeBuilder; - cmdTypeBuilder.AddMemberWithValue("LC_REQ_DYLD", LC_REQ_DYLD); - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT", LC_SEGMENT); - cmdTypeBuilder.AddMemberWithValue("LC_SYMTAB", LC_SYMTAB); - cmdTypeBuilder.AddMemberWithValue("LC_SYMSEG",LC_SYMSEG); - cmdTypeBuilder.AddMemberWithValue("LC_THREAD", LC_THREAD); - cmdTypeBuilder.AddMemberWithValue("LC_UNIXTHREAD", LC_UNIXTHREAD); - cmdTypeBuilder.AddMemberWithValue("LC_LOADFVMLIB", LC_LOADFVMLIB); - cmdTypeBuilder.AddMemberWithValue("LC_IDFVMLIB", LC_IDFVMLIB); - cmdTypeBuilder.AddMemberWithValue("LC_IDENT", LC_IDENT); - cmdTypeBuilder.AddMemberWithValue("LC_FVMFILE", LC_FVMFILE); - cmdTypeBuilder.AddMemberWithValue("LC_PREPAGE", LC_PREPAGE); - cmdTypeBuilder.AddMemberWithValue("LC_DYSYMTAB", LC_DYSYMTAB); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_DYLIB", LC_LOAD_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ID_DYLIB", LC_ID_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_DYLINKER", LC_LOAD_DYLINKER); - cmdTypeBuilder.AddMemberWithValue("LC_ID_DYLINKER", LC_ID_DYLINKER); - cmdTypeBuilder.AddMemberWithValue("LC_PREBOUND_DYLIB", LC_PREBOUND_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ROUTINES", LC_ROUTINES); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_FRAMEWORK", LC_SUB_FRAMEWORK); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_UMBRELLA", LC_SUB_UMBRELLA); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_CLIENT", LC_SUB_CLIENT); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_LIBRARY", LC_SUB_LIBRARY); - cmdTypeBuilder.AddMemberWithValue("LC_TWOLEVEL_HINTS", LC_TWOLEVEL_HINTS); - cmdTypeBuilder.AddMemberWithValue("LC_PREBIND_CKSUM", LC_PREBIND_CKSUM); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_WEAK_DYLIB", LC_LOAD_WEAK_DYLIB);// (0x18 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT_64", LC_SEGMENT_64); - cmdTypeBuilder.AddMemberWithValue("LC_ROUTINES_64", LC_ROUTINES_64); - cmdTypeBuilder.AddMemberWithValue("LC_UUID", LC_UUID); - cmdTypeBuilder.AddMemberWithValue("LC_RPATH", LC_RPATH);// (0x1c | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_CODE_SIGNATURE", LC_CODE_SIGNATURE); - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT_SPLIT_INFO", LC_SEGMENT_SPLIT_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_REEXPORT_DYLIB", LC_REEXPORT_DYLIB);// (0x1f | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_LAZY_LOAD_DYLIB", LC_LAZY_LOAD_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ENCRYPTION_INFO", LC_ENCRYPTION_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_INFO", LC_DYLD_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_INFO_ONLY", LC_DYLD_INFO_ONLY);// (0x22 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_UPWARD_DYLIB", LC_LOAD_UPWARD_DYLIB);// (0x23 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_MACOSX", LC_VERSION_MIN_MACOSX); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_IPHONEOS", LC_VERSION_MIN_IPHONEOS); - cmdTypeBuilder.AddMemberWithValue("LC_FUNCTION_STARTS", LC_FUNCTION_STARTS); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_ENVIRONMENT", LC_DYLD_ENVIRONMENT); - cmdTypeBuilder.AddMemberWithValue("LC_MAIN", LC_MAIN);// (0x28 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_DATA_IN_CODE", LC_DATA_IN_CODE); - cmdTypeBuilder.AddMemberWithValue("LC_SOURCE_VERSION", LC_SOURCE_VERSION); - cmdTypeBuilder.AddMemberWithValue("LC_DYLIB_CODE_SIGN_DRS", LC_DYLIB_CODE_SIGN_DRS); - cmdTypeBuilder.AddMemberWithValue("LC_ENCRYPTION_INFO_64", _LC_ENCRYPTION_INFO_64); - cmdTypeBuilder.AddMemberWithValue("LC_LINKER_OPTION", _LC_LINKER_OPTION); - cmdTypeBuilder.AddMemberWithValue("LC_LINKER_OPTIMIZATION_HINT", _LC_LINKER_OPTIMIZATION_HINT); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_TVOS", _LC_VERSION_MIN_TVOS); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_WATCHOS", LC_VERSION_MIN_WATCHOS); - cmdTypeBuilder.AddMemberWithValue("LC_NOTE", LC_NOTE); - cmdTypeBuilder.AddMemberWithValue("LC_BUILD_VERSION", LC_BUILD_VERSION); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_EXPORTS_TRIE", LC_DYLD_EXPORTS_TRIE); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_CHAINED_FIXUPS", LC_DYLD_CHAINED_FIXUPS); - cmdTypeBuilder.AddMemberWithValue("LC_FILESET_ENTRY", LC_FILESET_ENTRY); - Ref cmdTypeEnum = cmdTypeBuilder.Finalize(); - - Ref cmdTypeEnumType = Type::EnumerationType(nullptr, cmdTypeEnum, 4, false); - string cmdTypeEnumName = "load_command_type_t"; - string cmdTypeEnumId = Type::GenerateAutoTypeId("macho", cmdTypeEnumName); - m_typeNames.cmdTypeEnumQualName = DefineType(cmdTypeEnumId, cmdTypeEnumName, cmdTypeEnumType); - - StructureBuilder loadCommandBuilder; - loadCommandBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - loadCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - Ref loadCommandStruct = loadCommandBuilder.Finalize(); - QualifiedName loadCommandName = string("load_command"); - string loadCommandTypeId = Type::GenerateAutoTypeId("macho", loadCommandName); - Ref loadCommandType = Type::StructureType(loadCommandStruct); - m_typeNames.loadCommandQualName = DefineType(loadCommandTypeId, loadCommandName, loadCommandType); - - EnumerationBuilder protTypeBuilder; - protTypeBuilder.AddMemberWithValue("VM_PROT_NONE", MACHO_VM_PROT_NONE); - protTypeBuilder.AddMemberWithValue("VM_PROT_READ", MACHO_VM_PROT_READ); - protTypeBuilder.AddMemberWithValue("VM_PROT_WRITE", MACHO_VM_PROT_WRITE); - protTypeBuilder.AddMemberWithValue("VM_PROT_EXECUTE", MACHO_VM_PROT_EXECUTE); - // protTypeBuilder.AddMemberWithValue("VM_PROT_DEFAULT", MACHO_VM_PROT_DEFAULT); - // protTypeBuilder.AddMemberWithValue("VM_PROT_ALL", MACHO_VM_PROT_ALL); - protTypeBuilder.AddMemberWithValue("VM_PROT_NO_CHANGE", MACHO_VM_PROT_NO_CHANGE); - protTypeBuilder.AddMemberWithValue("VM_PROT_COPY_OR_WANTS_COPY", MACHO_VM_PROT_COPY); - //protTypeBuilder.AddMemberWithValue("VM_PROT_WANTS_COPY", MACHO_VM_PROT_WANTS_COPY); - Ref protTypeEnum = protTypeBuilder.Finalize(); - - Ref protTypeEnumType = Type::EnumerationType(nullptr, protTypeEnum, 4, false); - string protTypeEnumName = "vm_prot_t"; - string protTypeEnumId = Type::GenerateAutoTypeId("macho", protTypeEnumName); - m_typeNames.protTypeEnumQualName = DefineType(protTypeEnumId, protTypeEnumName, protTypeEnumType); - - EnumerationBuilder segFlagsTypeBuilder; - segFlagsTypeBuilder.AddMemberWithValue("SG_HIGHVM", SG_HIGHVM); - segFlagsTypeBuilder.AddMemberWithValue("SG_FVMLIB", SG_FVMLIB); - segFlagsTypeBuilder.AddMemberWithValue("SG_NORELOC", SG_NORELOC); - segFlagsTypeBuilder.AddMemberWithValue("SG_PROTECTED_VERSION_1", SG_PROTECTED_VERSION_1); - Ref segFlagsTypeEnum = segFlagsTypeBuilder.Finalize(); - - Ref segFlagsTypeEnumType = Type::EnumerationType(nullptr, segFlagsTypeEnum, 4, false); - string segFlagsTypeEnumName = "sg_flags_t"; - string segFlagsTypeEnumId = Type::GenerateAutoTypeId("macho", segFlagsTypeEnumName); - m_typeNames.segFlagsTypeEnumQualName = DefineType(segFlagsTypeEnumId, segFlagsTypeEnumName, segFlagsTypeEnumType); - - StructureBuilder loadSegmentCommandBuilder; - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - loadSegmentCommandBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "vmaddr"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "vmsize"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "fileoff"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "filesize"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, m_typeNames.protTypeEnumQualName), "maxprot"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, m_typeNames.protTypeEnumQualName), "initprot"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "nsects"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, m_typeNames.segFlagsTypeEnumQualName), "flags"); - Ref loadSegmentCommandStruct = loadSegmentCommandBuilder.Finalize(); - QualifiedName loadSegmentCommandName = string("segment_command"); - string loadSegmentCommandTypeId = Type::GenerateAutoTypeId("macho", loadSegmentCommandName); - Ref loadSegmentCommandType = Type::StructureType(loadSegmentCommandStruct); - m_typeNames.loadSegmentCommandQualName = DefineType(loadSegmentCommandTypeId, loadSegmentCommandName, loadSegmentCommandType); - - StructureBuilder loadSegmentCommand64Builder; - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(4, false), "cmdsize"); - loadSegmentCommand64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "vmaddr"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "vmsize"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "fileoff"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "filesize"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, m_typeNames.protTypeEnumQualName), "maxprot"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, m_typeNames.protTypeEnumQualName), "initprot"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(4, false), "nsects"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, m_typeNames.segFlagsTypeEnumQualName), "flags"); - Ref loadSegmentCommand64Struct = loadSegmentCommand64Builder.Finalize(); - QualifiedName loadSegment64CommandName = string("segment_command_64"); - string loadSegment64CommandTypeId = Type::GenerateAutoTypeId("macho", loadSegment64CommandName); - Ref loadSegment64CommandType = Type::StructureType(loadSegmentCommand64Struct); - m_typeNames.loadSegment64CommandQualName = DefineType(loadSegment64CommandTypeId, loadSegment64CommandName, loadSegment64CommandType); - - StructureBuilder sectionBuilder; - sectionBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "sectname"); - sectionBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "addr"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "size"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "offset"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "align"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reloff"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "nreloc"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "flags"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reserved1"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reserved2"); - Ref sectionStruct = sectionBuilder.Finalize(); - QualifiedName sectionName = string("section"); - string sectionTypeId = Type::GenerateAutoTypeId("macho", sectionName); - Ref sectionType = Type::StructureType(sectionStruct); - m_typeNames.sectionQualName = DefineType(sectionTypeId, sectionName, sectionType); - - StructureBuilder section64Builder; - section64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "sectname"); - section64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - section64Builder.AddMember(Type::IntegerType(8, false), "addr"); - section64Builder.AddMember(Type::IntegerType(8, false), "size"); - section64Builder.AddMember(Type::IntegerType(4, false), "offset"); - section64Builder.AddMember(Type::IntegerType(4, false), "align"); - section64Builder.AddMember(Type::IntegerType(4, false), "reloff"); - section64Builder.AddMember(Type::IntegerType(4, false), "nreloc"); - section64Builder.AddMember(Type::IntegerType(4, false), "flags"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved1"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved2"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved3"); - Ref section64Struct = section64Builder.Finalize(); - QualifiedName section64Name = string("section_64"); - string section64TypeId = Type::GenerateAutoTypeId("macho", section64Name); - Ref section64Type = Type::StructureType(section64Struct); - m_typeNames.section64QualName = DefineType(section64TypeId, section64Name, section64Type); - - StructureBuilder symtabBuilder; - symtabBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "symoff"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "nsyms"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "stroff"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "strsize"); - Ref symtabStruct = symtabBuilder.Finalize(); - QualifiedName symtabName = string("symtab"); - string symtabTypeId = Type::GenerateAutoTypeId("macho", symtabName); - Ref symtabType = Type::StructureType(symtabStruct); - m_typeNames.symtabQualName = DefineType(symtabTypeId, symtabName, symtabType); - - StructureBuilder dynsymtabBuilder; - dynsymtabBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "ilocalsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nlocalsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "iextdefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextdefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "iundefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nundefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "tocoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "ntoc"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "modtaboff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nmodtab"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "extrefsymoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextrefsyms"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "indirectsymoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nindirectsyms"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "extreloff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextrel"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "locreloff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nlocrel"); - Ref dynsymtabStruct = dynsymtabBuilder.Finalize(); - QualifiedName dynsymtabName = string("dynsymtab"); - string dynsymtabTypeId = Type::GenerateAutoTypeId("macho", dynsymtabName); - Ref dynsymtabType = Type::StructureType(dynsymtabStruct); - m_typeNames.dynsymtabQualName = DefineType(dynsymtabTypeId, dynsymtabName, dynsymtabType); - - StructureBuilder uuidBuilder; - uuidBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - uuidBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - uuidBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, false), 16), "uuid"); - Ref uuidStruct = uuidBuilder.Finalize(); - QualifiedName uuidName = string("uuid"); - string uuidTypeId = Type::GenerateAutoTypeId("macho", uuidName); - Ref uuidType = Type::StructureType(uuidStruct); - m_typeNames.uuidQualName = DefineType(uuidTypeId, uuidName, uuidType); - - StructureBuilder linkeditDataBuilder; - linkeditDataBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "dataoff"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "datasize"); - Ref linkeditDataStruct = linkeditDataBuilder.Finalize(); - QualifiedName linkeditDataName = string("linkedit_data"); - string linkeditDataTypeId = Type::GenerateAutoTypeId("macho", linkeditDataName); - Ref linkeditDataType = Type::StructureType(linkeditDataStruct); - m_typeNames.linkeditDataQualName = DefineType(linkeditDataTypeId, linkeditDataName, linkeditDataType); - - StructureBuilder encryptionInfoBuilder; - encryptionInfoBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptoff"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptsize"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptid"); - Ref encryptionInfoStruct = encryptionInfoBuilder.Finalize(); - QualifiedName encryptionInfoName = string("encryption_info"); - string encryptionInfoTypeId = Type::GenerateAutoTypeId("macho", encryptionInfoName); - Ref encryptionInfoType = Type::StructureType(encryptionInfoStruct); - m_typeNames.encryptionInfoQualName = DefineType(encryptionInfoTypeId, encryptionInfoName, encryptionInfoType); - - StructureBuilder versionMinBuilder; - versionMinBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "version"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "sdk"); - Ref versionMinStruct = versionMinBuilder.Finalize(); - QualifiedName versionMinName = string("version_min"); - string versionMinTypeId = Type::GenerateAutoTypeId("macho", versionMinName); - Ref versionMinType = Type::StructureType(versionMinStruct); - m_typeNames.versionMinQualName = DefineType(versionMinTypeId, versionMinName, versionMinType); - - StructureBuilder dyldInfoBuilder; - dyldInfoBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "rebase_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "rebase_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "weak_bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "weak_bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "lazy_bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "lazy_bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "export_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "export_size"); - Ref dyldInfoStruct = dyldInfoBuilder.Finalize(); - QualifiedName dyldInfoName = string("dyld_info"); - string dyldInfoTypeId = Type::GenerateAutoTypeId("macho", dyldInfoName); - Ref dyldInfoType = Type::StructureType(dyldInfoStruct); - m_typeNames.dyldInfoQualName = DefineType(dyldInfoTypeId, dyldInfoName, dyldInfoType); - - StructureBuilder dylibBuilder; - dylibBuilder.AddMember(Type::IntegerType(4, false), "name"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "timestamp"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "current_version"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "compatibility_version"); - Ref dylibStruct = dylibBuilder.Finalize(); - QualifiedName dylibName = string("dylib"); - string dylibTypeId = Type::GenerateAutoTypeId("macho", dylibName); - Ref dylibType = Type::StructureType(dylibStruct); - m_typeNames.dylibQualName = DefineType(dylibTypeId, dylibName, dylibType); - - StructureBuilder dylibCommandBuilder; - dylibCommandBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - dylibCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dylibCommandBuilder.AddMember(Type::NamedType(this, m_typeNames.dylibQualName), "dylib"); - Ref dylibCommandStruct = dylibCommandBuilder.Finalize(); - QualifiedName dylibCommandName = string("dylib_command"); - string dylibCommandTypeId = Type::GenerateAutoTypeId("macho", dylibCommandName); - Ref dylibCommandType = Type::StructureType(dylibCommandStruct); - m_typeNames.dylibCommandQualName = DefineType(dylibCommandTypeId, dylibCommandName, dylibCommandType); - - StructureBuilder filesetEntryCommandBuilder; - filesetEntryCommandBuilder.AddMember(Type::NamedType(this, m_typeNames.cmdTypeEnumQualName), "cmd"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(8, false), "vmaddr"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(8, false), "fileoff"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "entry_id"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "reserved"); - Ref filesetEntryCommandStruct = filesetEntryCommandBuilder.Finalize(); - QualifiedName filesetEntryCommandName = string("fileset_entry_command"); - string filesetEntryCommandTypeId = Type::GenerateAutoTypeId("macho", filesetEntryCommandName); - Ref filesetEntryCommandType = Type::StructureType(filesetEntryCommandStruct); - m_typeNames.filesetEntryCommandQualName = DefineType(filesetEntryCommandTypeId, filesetEntryCommandName, filesetEntryCommandType); - if (!InitializeHeader(m_header, true, preferredImageBase, preferredImageBaseDesc, platformSetByUser)) return false; @@ -2260,106 +1852,7 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_ if (!loadCommandOffset) continue; - DefineDataVariable(imageBase, Type::NamedType(this, m_typeNames.headerQualName)); - DefineAutoSymbol(new Symbol(DataSymbol, "__macho_header" + imageDesc, imageBase, LocalBinding)); - - try - { - virtualReader.Seek(imageBase + loadCommandOffset); - size_t sectionNum = 0; - for (size_t i = 0; i < mappedIdent.ncmds; i++) - { - load_command load; - uint64_t curOffset = virtualReader.GetOffset(); - load.cmd = virtualReader.Read32(); - load.cmdsize = virtualReader.Read32(); - uint64_t nextOffset = curOffset + load.cmdsize; - switch (load.cmd) - { - case LC_SEGMENT: - { - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.loadSegmentCommandQualName)); - virtualReader.SeekRelative(5 * 8); - size_t numSections = virtualReader.Read32(); - virtualReader.SeekRelative(4); - for (size_t j = 0; j < numSections; j++) - { - DefineDataVariable(virtualReader.GetOffset(), Type::NamedType(this, m_typeNames.sectionQualName)); - DefineAutoSymbol(new Symbol(DataSymbol, "__macho_section" + imageDesc + "_[" + to_string(sectionNum++) + "]", virtualReader.GetOffset(), LocalBinding)); - virtualReader.SeekRelative((8 * 8) + 4); - } - break; - } - case LC_SEGMENT_64: - { - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.loadSegment64CommandQualName)); - virtualReader.SeekRelative(7 * 8); - size_t numSections = virtualReader.Read32(); - virtualReader.SeekRelative(4); - for (size_t j = 0; j < numSections; j++) - { - DefineDataVariable(virtualReader.GetOffset(), Type::NamedType(this, m_typeNames.section64QualName)); - DefineAutoSymbol(new Symbol(DataSymbol, "__macho_section_64" + imageDesc + "_[" + to_string(sectionNum++) + "]", virtualReader.GetOffset(), LocalBinding)); - virtualReader.SeekRelative(10 * 8); - } - break; - } - case LC_SYMTAB: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.symtabQualName)); - break; - case LC_DYSYMTAB: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.dynsymtabQualName)); - break; - case LC_UUID: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.uuidQualName)); - break; - case LC_ID_DYLIB: - case LC_LOAD_DYLIB: - case LC_REEXPORT_DYLIB: - case LC_LOAD_WEAK_DYLIB: - case LC_LOAD_UPWARD_DYLIB: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.dylibCommandQualName)); - if (load.cmdsize-24 <= 150) - DefineDataVariable(curOffset + 24, Type::ArrayType(Type::IntegerType(1, true), load.cmdsize-24)); - break; - case LC_CODE_SIGNATURE: - case LC_SEGMENT_SPLIT_INFO: - case LC_FUNCTION_STARTS: - case LC_DATA_IN_CODE: - case LC_DYLIB_CODE_SIGN_DRS: - case LC_DYLD_EXPORTS_TRIE: - case LC_DYLD_CHAINED_FIXUPS: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.linkeditDataQualName)); - break; - case LC_ENCRYPTION_INFO: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.encryptionInfoQualName)); - break; - case LC_VERSION_MIN_MACOSX: - case LC_VERSION_MIN_IPHONEOS: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.versionMinQualName)); - break; - case LC_DYLD_INFO: - case LC_DYLD_INFO_ONLY: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.dyldInfoQualName)); - break; - case LC_FILESET_ENTRY: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.filesetEntryCommandQualName)); - if (load.cmdsize-0x20 <= 150) - DefineDataVariable(curOffset + 0x20, Type::ArrayType(Type::IntegerType(1, true), load.cmdsize-0x20)); - break; - default: - DefineDataVariable(curOffset, Type::NamedType(this, m_typeNames.loadCommandQualName)); - break; - } - - DefineAutoSymbol(new Symbol(DataSymbol, "__macho_load_command" + imageDesc + "_[" + to_string(i) + "]", curOffset, LocalBinding)); - virtualReader.Seek(nextOffset); - } - } - catch (ReadException&) - { - LogError("Error when applying Mach-O header types at %" PRIx64, imageBase); - } + MachO::ApplyHeaderTypes(this, m_logger, virtualReader, imageDesc, imageBase, mappedIdent.ncmds); } if (parseCFStrings) diff --git a/view/macho/machoview.h b/view/macho/machoview.h index 1a7159919..137d8ec1e 100644 --- a/view/macho/machoview.h +++ b/view/macho/machoview.h @@ -6,1341 +6,14 @@ #include "binaryninjaapi.h" #include "objc.h" - -//These are laready defined in one of the osx headers we want to override -#undef CPU_SUBTYPE_INTEL -#undef CPU_SUBTYPE_I386_ALL -#undef CPU_SUBTYPE_POWERPC_ALL -#undef LC_MAIN -#undef LC_SOURCE_VERSION -#undef LC_DYLIB_CODE_SIGN_DRS -#undef LC_DYLD_INFO_ONLY - -#define MH_MAGIC 0xfeedface -#define MH_MAGIC_64 0xfeedfacf -#define MH_CIGAM 0xcefaedfe -#define MH_CIGAM_64 0xcffaedfe -#define FAT_MAGIC 0xcafebabe -#define FAT_MAGIC_64 0xcafebabf - -typedef int32_t cpu_type_t; -typedef int32_t cpu_subtype_t; -typedef int vm_prot_t; - -//Cpu types -#define MACHO_CPU_ARCH_ABI64 0x01000000 -#define MACHO_CPU_ARCH_ABI64_32 0x02000000 - -#define MACHO_CPU_TYPE_ANY ((cpu_type_t) -1) -#define MACHO_CPU_TYPE_VAX ((cpu_type_t) 1) -#define MACHO_CPU_TYPE_MC680x0 ((cpu_type_t) 6) -#define MACHO_CPU_TYPE_X86 ((cpu_type_t) 7) -#define MACHO_CPU_TYPE_X86_64 (MACHO_CPU_TYPE_X86 | MACHO_CPU_ARCH_ABI64) -#define MACHO_CPU_TYPE_MIPS ((cpu_type_t) 8) -#define MACHO_CPU_TYPE_MC98000 ((cpu_type_t) 10) -#define MACHO_CPU_TYPE_HPPA ((cpu_type_t) 11) -#define MACHO_CPU_TYPE_ARM ((cpu_type_t) 12) -#define MACHO_CPU_TYPE_ARM64 (MACHO_CPU_TYPE_ARM | MACHO_CPU_ARCH_ABI64) -#define MACHO_CPU_TYPE_ARM64_32 (MACHO_CPU_TYPE_ARM | MACHO_CPU_ARCH_ABI64_32) -#define MACHO_CPU_TYPE_MC88000 ((cpu_type_t) 13) -#define MACHO_CPU_TYPE_SPARC ((cpu_type_t) 14) -#define MACHO_CPU_TYPE_I860 ((cpu_type_t) 15) -#define MACHO_CPU_TYPE_ALPHA ((cpu_type_t) 16) -#define MACHO_CPU_TYPE_POWERPC ((cpu_type_t) 18) -#define MACHO_CPU_TYPE_POWERPC64 (MACHO_CPU_TYPE_POWERPC | MACHO_CPU_ARCH_ABI64) - -//Cpu subtype capability bits -#define MACHO_CPU_SUBTYPE_MASK ((cpu_subtype_t)0xff000000) -#define MACHO_CPU_SUBTYPE_LIB64 ((cpu_subtype_t)0x80000000) - -//Cpu subtypes -#define MACHO_CPU_SUBTYPE_INTEL(f,m) ((cpu_subtype_t) (f)+((m)<<4)) -#define MACHO_CPU_SUBTYPE_I386_ALL MACHO_CPU_SUBTYPE_INTEL(3,0) -#define MACHO_CPU_SUBTYPE_X86_ALL ((cpu_subtype_t) 3) -#define MACHO_CPU_SUBTYPE_X86_ARCH1 ((cpu_subtype_t) 4) -#define MACHO_CPU_SUBTYPE_X86_64_ALL ((cpu_subtype_t) 3) -#define MACHO_CPU_SUBTYPE_X86_64_H ((cpu_subtype_t) 8) - -#define MACHO_CPU_SUBTYPE_ARM_ALL ((cpu_subtype_t) 0) -#define MACHO_CPU_SUBTYPE_ARM_V4T ((cpu_subtype_t) 5) -#define MACHO_CPU_SUBTYPE_ARM_V6 ((cpu_subtype_t) 6) -#define MACHO_CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7) -#define MACHO_CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8) -#define MACHO_CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9) -#define MACHO_CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) -#define MACHO_CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) -#define MACHO_CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12) -#define MACHO_CPU_SUBTYPE_ARM_V8 ((cpu_subtype_t) 13) -#define MACHO_CPU_SUBTYPE_ARM_V6M ((cpu_subtype_t) 14) -#define MACHO_CPU_SUBTYPE_ARM_V7M ((cpu_subtype_t) 15) -#define MACHO_CPU_SUBTYPE_ARM_V7EM ((cpu_subtype_t) 16) - -#define MACHO_CPU_SUBTYPE_ARM64_ALL ((cpu_subtype_t) 0) -#define MACHO_CPU_SUBTYPE_ARM64_V8 ((cpu_subtype_t) 1) -#define MACHO_CPU_SUBTYPE_ARM64E ((cpu_subtype_t) 2) - -#define MACHO_CPU_SUBTYPE_ARM64_32_ALL ((cpu_subtype_t) 0) -#define MACHO_CPU_SUBTYPE_ARM64_32_V8 ((cpu_subtype_t) 1) - -#define MACHO_CPU_SUBTYPE_POWERPC_ALL ((cpu_subtype_t) 0) -#define MACHO_CPU_SUBTYPE_POWERPC_601 ((cpu_subtype_t) 1) -#define MACHO_CPU_SUBTYPE_POWERPC_602 ((cpu_subtype_t) 2) -#define MACHO_CPU_SUBTYPE_POWERPC_603 ((cpu_subtype_t) 3) -#define MACHO_CPU_SUBTYPE_POWERPC_603e ((cpu_subtype_t) 4) -#define MACHO_CPU_SUBTYPE_POWERPC_603ev ((cpu_subtype_t) 5) -#define MACHO_CPU_SUBTYPE_POWERPC_604 ((cpu_subtype_t) 6) -#define MACHO_CPU_SUBTYPE_POWERPC_604e ((cpu_subtype_t) 7) -#define MACHO_CPU_SUBTYPE_POWERPC_620 ((cpu_subtype_t) 8) -#define MACHO_CPU_SUBTYPE_POWERPC_750 ((cpu_subtype_t) 9) -#define MACHO_CPU_SUBTYPE_POWERPC_7400 ((cpu_subtype_t) 10) -#define MACHO_CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t) 11) -#define MACHO_CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) - -//Page protections -#define MACHO_VM_PROT_NONE ((vm_prot_t) 0x00) -#define MACHO_VM_PROT_READ ((vm_prot_t) 0x01) -#define MACHO_VM_PROT_WRITE ((vm_prot_t) 0x02) -#define MACHO_VM_PROT_EXECUTE ((vm_prot_t) 0x04) -#define MACHO_VM_PROT_DEFAULT (VM_PROT_READ|VM_PROT_WRITE) -#define MACHO_VM_PROT_ALL (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) -#define MACHO_VM_PROT_NO_CHANGE ((vm_prot_t) 0x08) -#define MACHO_VM_PROT_COPY ((vm_prot_t) 0x10) -#define MACHO_VM_PROT_WANTS_COPY ((vm_prot_t) 0x10) - -//Segment flags -#define SG_HIGHVM 0x1 -#define SG_FVMLIB 0x2 -#define SG_NORELOC 0x4 -#define SG_PROTECTED_VERSION_1 0x8 - -//Section flags -#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 -#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 // section contains only true machine instructions -#define S_ATTR_NO_TOC 0x40000000 // section contains coalesced symbols that are not to be in a ranlib table of contents -#define S_ATTR_STRIP_STATIC_SYMS 0x20000000 // ok to strip static symbols in this section in files with the MH_DYLDLINK flag -#define S_ATTR_NO_DEAD_STRIP 0x10000000 // no dead stripping -#define S_ATTR_LIVE_SUPPORT 0x08000000 // blocks are live if they reference live blocks -#define S_ATTR_SELF_MODIFYING_CODE 0x04000000 // Used with i386 code stubs written on by dyld - -#define S_REGULAR 0x0 -#define S_ZEROFILL 0x1 -#define S_CSTRING_LITERALS 0x2 -#define S_4BYTE_LITERALS 0x3 -#define S_8BYTE_LITERALS 0x4 -#define S_LITERAL_POINTERS 0x5 -#define S_NON_LAZY_SYMBOL_POINTERS 0x6 -#define S_LAZY_SYMBOL_POINTERS 0x7 -#define S_SYMBOL_STUBS 0x8 -#define S_MOD_INIT_FUNC_POINTERS 0x9 -#define S_MOD_TERM_FUNC_POINTERS 0xa -#define S_COALESCED 0xb -#define S_GB_ZEROFILL 0xc -#define S_INTERPOSING 0xd -#define S_16BYTE_LITERALS 0xe -#define S_DTRACE_DOF 0xf -#define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10 -#define S_THREAD_LOCAL_REGULAR 0x11 -#define S_THREAD_LOCAL_ZEROFILL 0x12 -#define S_THREAD_LOCAL_VARIABLES 0x13 -#define S_THREAD_LOCAL_VARIABLE_POINTERS 0x14 -#define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS 0x15 -#define S_INIT_FUNC_OFFSETS 0x16 - -//Mach-O Commands -#define LC_REQ_DYLD 0x80000000 -#define LC_SEGMENT 0x1 -#define LC_SYMTAB 0x2 -#define LC_SYMSEG 0x3 -#define LC_THREAD 0x4 -#define LC_UNIXTHREAD 0x5 -#define LC_LOADFVMLIB 0x6 -#define LC_IDFVMLIB 0x7 -#define LC_IDENT 0x8 -#define LC_FVMFILE 0x9 -#define LC_PREPAGE 0xa -#define LC_DYSYMTAB 0xb -#define LC_LOAD_DYLIB 0xc -#define LC_ID_DYLIB 0xd -#define LC_LOAD_DYLINKER 0xe -#define LC_ID_DYLINKER 0xf -#define LC_PREBOUND_DYLIB 0x10 -#define LC_ROUTINES 0x11 -#define LC_SUB_FRAMEWORK 0x12 -#define LC_SUB_UMBRELLA 0x13 -#define LC_SUB_CLIENT 0x14 -#define LC_SUB_LIBRARY 0x15 -#define LC_TWOLEVEL_HINTS 0x16 -#define LC_PREBIND_CKSUM 0x17 -#define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) -#define LC_SEGMENT_64 0x19 -#define LC_ROUTINES_64 0x1a -#define LC_UUID 0x1b -#define LC_RPATH (0x1c | LC_REQ_DYLD) -#define LC_CODE_SIGNATURE 0x1d -#define LC_SEGMENT_SPLIT_INFO 0x1e -#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) -#define LC_LAZY_LOAD_DYLIB 0x20 -#define LC_ENCRYPTION_INFO 0x21 -#define LC_DYLD_INFO 0x22 -#define LC_DYLD_INFO_ONLY (0x22 | LC_REQ_DYLD) -#define LC_LOAD_UPWARD_DYLIB (0x23 | LC_REQ_DYLD) -#define LC_VERSION_MIN_MACOSX 0x24 -#define LC_VERSION_MIN_IPHONEOS 0x25 -#define LC_FUNCTION_STARTS 0x26 -#define LC_DYLD_ENVIRONMENT 0x27 -#define LC_MAIN (0x28 | LC_REQ_DYLD) -#define LC_DATA_IN_CODE 0x29 -#define LC_SOURCE_VERSION 0x2a -#define LC_DYLIB_CODE_SIGN_DRS 0x2b -#define _LC_ENCRYPTION_INFO_64 0x2c /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h */ -#define _LC_LINKER_OPTION 0x2d /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h */ -#define _LC_LINKER_OPTIMIZATION_HINT 0x2e /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h */ -#define _LC_VERSION_MIN_TVOS 0x2f /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h */ -#define LC_VERSION_MIN_WATCHOS 0x30 -#define LC_NOTE 0x31 -#define LC_BUILD_VERSION 0x32 -#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) -#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) -#define LC_FILESET_ENTRY (0x35 | LC_REQ_DYLD) - -//Mach-O File types -#define MH_OBJECT 0x1 -#define MH_EXECUTE 0x2 -#define MH_FVMLIB 0x3 -#define MH_CORE 0x4 -#define MH_PRELOAD 0x5 -#define MH_DYLIB 0x6 -#define MH_DYLINKER 0x7 -#define MH_BUNDLE 0x8 -#define MH_DYLIB_STUB 0x9 -#define MH_DSYM 0xa -#define MH_KEXT_BUNDLE 0xb -#define MH_FILESET 0xc - -#define MH_NOUNDEFS 0x1 -#define MH_INCRLINK 0x2 -#define MH_DYLDLINK 0x4 -#define MH_BINDATLOAD 0x8 -#define MH_PREBOUND 0x10 -#define MH_SPLIT_SEGS 0x20 -#define MH_LAZY_INIT 0x40 -#define MH_TWOLEVEL 0x80 -#define MH_FORCE_FLAT 0x100 -#define MH_NOMULTIDEFS 0x200 -#define MH_NOFIXPREBINDING 0x400 -#define MH_PREBINDABLE 0x800 -#define MH_ALLMODSBOUND 0x1000 -#define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000 -#define MH_CANONICAL 0x4000 -#define MH_WEAK_DEFINES 0x8000 -#define MH_BINDS_TO_WEAK 0x10000 -#define MH_ALLOW_STACK_EXECUTION 0x20000 -#define MH_ROOT_SAFE 0x40000 -#define MH_SETUID_SAFE 0x80000 -#define MH_NO_REEXPORTED_DYLIBS 0x100000 -#define MH_PIE 0x200000 -#define MH_DEAD_STRIPPABLE_DYLIB 0x400000 -#define MH_HAS_TLV_DESCRIPTORS 0x800000 -#define MH_NO_HEAP_EXECUTION 0x1000000 -#define _MH_APP_EXTENSION_SAFE 0x2000000 /* FIXME: warning defined in .../SDKs/MacOSX10.15.sdk/usr/include/mach-o/loader.h */ -#define _MH_NLIST_OUTOFSYNC_WITH_DYLDINFO 0x04000000u -#define _MH_SIM_SUPPORT 0x08000000u -#define _MH_DYLIB_IN_CACHE 0x80000000u - -//Segment Names -#define SEG_PAGEZERO "__PAGEZERO" -#define SEG_TEXT "__TEXT" -#define SECT_TEXT "__text" -#define SECT_FVMLIB_INIT0 "__fvmlib_init0" -#define SECT_FVMLIB_INIT1 "__fvmlib_init1" -#define SEG_DATA "__DATA" -#define SECT_DATA "__data" -#define SECT_BSS "__bss" -#define SECT_COMMON "__common" -#define SEG_OBJC "__OBJC" -#define SECT_OBJC_SYMBOLS "__symbol_table" -#define SECT_OBJC_MODULES "__module_info" -#define SECT_OBJC_STRINGS "__selector_strs" -#define SECT_OBJC_REFS "__selector_refs" -#define SEG_ICON "__ICON" -#define SECT_ICON_HEADER "__header" -#define SECT_ICON_TIFF "__tiff" -#define SEG_LINKEDIT "__LINKEDIT" -#define SEG_UNIXSTACK "__UNIXSTACK" -#define SEG_IMPORT "__IMPORT" - -/* - * Symbols with a index into the string table of zero (n_un.n_strx == 0) are - * defined to have a null, "", name. Therefore all string indexes to non null - * names must not have a zero string index. This is bit historical information - * that has never been well documented. - */ - -/* - * The n_type field really contains four fields: - * unsigned char N_STAB:3, - * N_PEXT:1, - * N_TYPE:3, - * N_EXT:1; - * which are used via the following masks. - */ -#define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */ -#define N_PEXT 0x10 /* private external symbol bit */ -#define N_TYPE 0x0e /* mask for the type bits */ -#define N_EXT 0x01 /* external symbol bit, set for external symbols */ - -/* - * Only symbolic debugging entries have some of the N_STAB bits set and if any - * of these bits are set then it is a symbolic debugging entry (a stab). In - * which case then the values of the n_type field (the entire field) are given - * in - */ - -/* - * Values for N_TYPE bits of the n_type field. - */ -#define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */ -#define N_ABS 0x2 /* absolute, n_sect == NO_SECT */ -#define N_SECT 0xe /* defined in section number n_sect */ -#define N_PBUD 0xc /* prebound undefined (defined in a dylib) */ -#define N_INDR 0xa /* indirect */ - -/* - * If the type is N_INDR then the symbol is defined to be the same as another - * symbol. In this case the n_value field is an index into the string table - * of the other symbol's name. When the other symbol is defined then they both - * take on the defined type and value. - */ - -/* - * If the type is N_SECT then the n_sect field contains an ordinal of the - * section the symbol is defined in. The sections are numbered from 1 and - * refer to sections in order they appear in the load commands for the file - * they are in. This means the same ordinal may very well refer to different - * sections in different files. - * - * The n_value field for all symbol table entries (including N_STAB's) gets - * updated by the link editor based on the value of it's n_sect field and where - * the section n_sect references gets relocated. If the value of the n_sect - * field is NO_SECT then it's n_value field is not changed by the link editor. - */ -#define NO_SECT 0 /* symbol is not in any section */ -#define MAX_SECT 255 /* 1 thru 255 inclusive */ - -/* - * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes - * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED. - */ - -/* - * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a - * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the - * static link editor it is never to dead strip the symbol. - */ -#define N_NO_DEAD_STRIP 0x0020 /* symbol is not to be dead stripped */ - -/* - * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image. - * But is used in very rare cases by the dynamic link editor to mark an in - * memory symbol as discared and longer used for linking. - */ -#define N_DESC_DISCARDED 0x0020 /* symbol is discarded */ - -/* - * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that - * the undefined symbol is allowed to be missing and is to have the address of - * zero when missing. - */ -#define N_WEAK_REF 0x0040 /* symbol is weak referenced */ - -/* - * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic - * linkers that the symbol definition is weak, allowing a non-weak symbol to - * also be used which causes the weak definition to be discared. Currently this - * is only supported for symbols in coalesed sections. - */ -#define N_WEAK_DEF 0x0080 /* coalesed symbol is a weak definition */ - -/* - * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker - * that the undefined symbol should be resolved using flat namespace searching. - */ -#define N_REF_TO_WEAK 0x0080 /* reference to a weak symbol */ - -/* - * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is - * a defintion of a Thumb function. - */ -#define N_ARM_THUMB_DEF 0x0008 /* symbol is a Thumb function (ARM) */ - -/* - * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the - * that the function is actually a resolver function and should - * be called to get the address of the real function to use. - * This bit is only available in .o files (MH_OBJECT filetype) - */ -#define N_SYMBOL_RESOLVER 0x0100 - -/* - * The N_ALT_ENTRY bit of the n_desc field indicates that the - * symbol is pinned to the previous content. - */ -#define N_ALT_ENTRY 0x0200 - -/* - * The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used - * infrequently and the linker should order it towards the end of the section. - */ -#define N_COLD_FUNC 0x0400 - -/* - * An indirect symbol table entry is simply a 32bit index into the symbol table - * to the symbol that the pointer or stub is referring to. Unless it is for a - * non-lazy symbol pointer section for a defined symbol which strip(1) as - * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the - * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that. - */ -#define INDIRECT_SYMBOL_ABS 0x40000000 -#define INDIRECT_SYMBOL_LOCAL 0x80000000 +#include "macho/types.h" #define SECTION_TYPE 0x000000ff /* 256 section types */ #define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes */ #define BINARYNINJA_MANUAL_RELOCATION ((uint64_t)-2) -enum MachoRelocationType -{ - GENERIC_RELOC_VANILLA = 0, - GENERIC_RELOC_PAIR = 1, - GENERIC_RELOC_SECTDIFF = 2, - GENERIC_RELOC_PB_LA_PTR = 3, - GENERIC_RELOC_LOCAL_SECTDIFF = 4, - GENERIC_RELOC_TLV = 5 -}; - - -namespace BinaryNinja -{ - class MachoFormatException: public std::exception - { - std::string m_message; - - public: - MachoFormatException(const std::string& msg = "invalid format"): m_message(msg) {} - virtual const char* what() const NOEXCEPT { return m_message.c_str(); } - }; - - struct FatHeader { - uint32_t magic; - uint32_t nfat_arch; - }; - - struct FatArch32 { - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint32_t offset; - uint32_t size; - uint32_t align; - }; - - struct FatArch64 { - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint64_t offset; - uint64_t size; - uint32_t align; - uint32_t reserved; - }; - - struct mach_header { - uint32_t magic; - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint32_t filetype; - uint32_t ncmds; - uint32_t sizeofcmds; - uint32_t flags; - }; - - struct mach_header_64 { - uint32_t magic; - cpu_type_t cputype; - cpu_subtype_t cpusubtype; - uint32_t filetype; - uint32_t ncmds; - uint32_t sizeofcmds; - uint32_t flags; - uint32_t reserved; - }; - - struct load_command { - uint32_t cmd; - uint32_t cmdsize; - }; - - struct segment_command { - uint32_t cmd; - uint32_t cmdsize; - char segname[16]; - uint32_t vmaddr; - uint32_t vmsize; - uint32_t fileoff; - uint32_t filesize; - vm_prot_t maxprot; - vm_prot_t initprot; - uint32_t nsects; - uint32_t flags; - }; - - struct section { // for 32-bit architectures - char sectname[16]; // name of this section - char segname[16]; // segment this section goes in - uint32_t addr; // memory address of this section - uint32_t size; // size in bytes of this section - uint32_t offset; // file offset of this section - uint32_t align; // section alignment (power of 2) - uint32_t reloff; // file offset of relocation entries - uint32_t nreloc; // number of relocation entries - uint32_t flags; // flags (section type and attributes) - uint32_t reserved1; // reserved (for offset or index) - uint32_t reserved2; // reserved (for count or sizeof) - }; - - struct section_64 { // for 64-bit architectures - char sectname[16]; // name of this section - char segname[16]; // segment this section goes in - uint64_t addr; // memory address of this section - uint64_t size; // size in bytes of this section - uint32_t offset; // file offset of this section - uint32_t align; // section alignment (power of 2) - uint32_t reloff; // file offset of relocation entries - uint32_t nreloc; // number of relocation entries - uint32_t flags; // flags (section type and attributes) - uint32_t reserved1; // reserved (for offset or index) - uint32_t reserved2; // reserved (for count or sizeof) - uint32_t reserved3; // reserved - }; - - struct segment_command_64 { - uint32_t cmd; - uint32_t cmdsize; - char segname[16]; - uint64_t vmaddr; - uint64_t vmsize; - uint64_t fileoff; - uint64_t filesize; - vm_prot_t maxprot; - vm_prot_t initprot; - uint32_t nsects; - uint32_t flags; - }; - - struct uuid_command { - uint32_t cmd; - uint32_t cmdsize; - char uuid[16]; - }; - - struct fvmlib_command { - uint32_t cmd; - uint32_t cmdsize; - char segname[16]; - uint32_t minor_version; - uint32_t header_addr; - }; - - struct dylib { - uint32_t name; - uint32_t timestamp; - uint32_t current_version; - uint32_t compatibility_version; - }; - - struct dylib_command { - uint32_t cmd; - uint32_t cmdsize; - struct dylib dylib; - }; - - struct sub_framework_command { - uint32_t cmd; // LC_SUB_FRAMEWORK - uint32_t cmdsize; // includes umbrella string - uint32_t umbrella; // the umbrella framework name - }; - - struct sub_client_command { - uint32_t cmd; // LC_SUB_CLIENT - uint32_t cmdsize; // includes client string - uint32_t client; // offset to the string - }; - - struct sub_umbrella_command { - uint32_t cmd; // LC_SUB_UMBRELLA - uint32_t cmdsize; // includes sub_umbrella string - uint32_t sub_umbrella; // the sub_umbrella framework name - }; - - struct sub_library_command { - uint32_t cmd; // LC_SUB_LIBRARY - uint32_t cmdsize; // includes sub_library string - uint32_t sub_library; // the sub_library name - }; - - struct prebound_dylib_command { - uint32_t cmd; // LC_PREBOUND_DYLIB - uint32_t cmdsize; // includes strings - uint32_t name; // library's path name - uint32_t nmodules; // number of modules in library - uint32_t linked_modules; // bit vector of linked modules - }; - - struct dylinker_command { - uint32_t cmd; // LC_ID_DYLINKER or LC_LOAD_DYLINKER - uint32_t cmdsize; // includes pathname string - uint32_t name; // dynamic linker's path name - }; - - struct x86_thread_state64 { - uint64_t rax; - uint64_t rbx; - uint64_t rcx; - uint64_t rdx; - uint64_t rdi; - uint64_t rsi; - uint64_t rbp; - uint64_t rsp; - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t rip; - uint64_t rflags; - uint64_t cs; - uint64_t fs; - uint64_t gs; - }; - - struct x86_thread_state32 { - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t esp; - uint32_t ss; - uint32_t eflags; - uint32_t eip; - uint32_t cs; - uint32_t ds; - uint32_t es; - uint32_t fs; - uint32_t gs; - }; - - struct armv7_thread_state { - uint32_t r0; - uint32_t r1; - uint32_t r2; - uint32_t r3; - uint32_t r4; - uint32_t r5; - uint32_t r6; - uint32_t r7; - uint32_t r8; - uint32_t r9; - uint32_t r10; - uint32_t r11; - uint32_t r12; - uint32_t r13; - uint32_t r14; //SP - uint32_t r15; //PC - }; - - struct arm_thread_state64 { - uint64_t x[29]; // GPR x0-x28 - uint64_t fp; // x29 - uint64_t lr; // x30 - uint64_t sp; // x31 - uint64_t pc; // Program Counter - uint32_t cpsr; // Current program status register - }; - - struct ppc_thread_state { - uint32_t srr0; //Machine state register (PC) - uint32_t srr1; - uint32_t r0; - uint32_t r1; //Stack pointer - uint32_t r2; - uint32_t r3; - uint32_t r4; - uint32_t r5; - uint32_t r6; - uint32_t r7; - uint32_t r8; - uint32_t r9; - uint32_t r10; - uint32_t r11; - uint32_t r12; - uint32_t r13; - uint32_t r14; - uint32_t r15; - uint32_t r16; - uint32_t r17; - uint32_t r18; - uint32_t r19; - uint32_t r20; - uint32_t r21; - uint32_t r22; - uint32_t r23; - uint32_t r24; - uint32_t r25; - uint32_t r26; - uint32_t r27; - uint32_t r28; - uint32_t r29; - uint32_t r30; - uint32_t r31; - uint32_t cr; - uint32_t xer; - uint32_t lr; - uint32_t ctr; - uint32_t mq; - uint32_t vrsave; - }; - - #pragma pack(push, 4) - struct ppc_thread_state64 { - uint64_t srr0; //Machine state register (PC) - uint64_t srr1; - uint64_t r0; //Stack pointer - uint64_t r1; - uint64_t r2; - uint64_t r3; - uint64_t r4; - uint64_t r5; - uint64_t r6; - uint64_t r7; - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t r16; - uint64_t r17; - uint64_t r18; - uint64_t r19; - uint64_t r20; - uint64_t r21; - uint64_t r22; - uint64_t r23; - uint64_t r24; - uint64_t r25; - uint64_t r26; - uint64_t r27; - uint64_t r28; - uint64_t r29; - uint64_t r30; - uint64_t r31; - uint32_t cr; // Condition register - uint64_t xer; // User's integer exception register - uint64_t lr; // Link register - uint64_t ctr; // Count register - uint32_t vrsave; // Vector Save Register - }; - #pragma pack(pop) - - struct thread_command { - uint32_t cmd; // LC_THREAD or LC_UNIXTHREAD - uint32_t cmdsize; // total size of this command - uint32_t flavor; // flavor of thread state - uint32_t count; //count of longs in thread state - union { - x86_thread_state64 statex64; - x86_thread_state32 statex86; - armv7_thread_state statearmv7; - arm_thread_state64 stateaarch64; - ppc_thread_state stateppc; - ppc_thread_state64 stateppc64; - }; - }; - - struct linkedit_data_command { - uint32_t cmd; - uint32_t cmdsize; - uint32_t dataoff; - uint32_t datasize; - }; - - - enum MachOArchitecture { - MachOABIMask = 0xff000000, - MachOABI64 = 0x01000000, // 64 bit ABI - MachOABI6432 = 0x02000000, // "ABI for 64-bit hardware with 32-bit types; LP32" - - // Constants for the cputype field. - MachOx86 = 7, - MachOx64 = MachOx86 | MachOABI64, - MachOArm = 0xc, - MachOAarch64 = MachOABI64 | MachOArm, - MachOAarch6432 = MachOABI6432 | MachOArm, - MachOSPARC = 0xe, - MachOPPC = 0x12, - MachOPPC64 = MachOABI64 | MachOPPC, - }; - - enum RebaseType { - RebaseTypeInvalid = 0, - RebaseTypePointer = 1, - RebaseTypeTextAbsolute32 = 2, - RebaseTypeTextPCRel32 = 3 - }; - - enum RebaseOpcode { - RebaseOpcodeMask = 0xF0u, // REBASE_OPCODE_MASK - RebaseImmediateMask = 0x0Fu, // REBASE_IMMEDIATE_MASK - RebaseOpcodeDone = 0x00u, // REBASE_OPCODE_DONE - RebaseOpcodeSetTypeImmediate = 0x10u, // REBASE_OPCODE_SET_TYPE_IMM - RebaseOpcodeSetSegmentAndOffsetUleb = 0x20u, // REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB - RebaseOpcodeAddAddressUleb = 0x30u, // REBASE_OPCODE_ADD_ADDR_ULEB - RebaseOpcodeAddAddressImmediateScaled = 0x40u, // REBASE_OPCODE_ADD_ADDR_IMM_SCALED - RebaseOpcodeDoRebaseImmediateTimes = 0x50u, // REBASE_OPCODE_DO_REBASE_IMM_TIMES - RebaseOpcodeDoRebaseUlebTimes = 0x60u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES - RebaseOpcodeDoRebaseAddAddressUleb = 0x70u, // REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB - RebaseOpcodeDoRebaseUlebTimesSkippingUleb = 0x80u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB - }; - - enum BindOpcode { - BindOpcodeMask = 0xF0u, // BIND_OPCODE_MASK - BindImmediateMask = 0x0Fu, // BIND_IMMEDIATE_MASK - BindOpcodeDone = 0x00u, // BIND_OPCODE_DONE - BindOpcodeSetDylibOrdinalImmediate = 0x10u, // BIND_OPCODE_SET_DYLIB_ORDINAL_IMM - BindOpcodeSetDylibOrdinalULEB = 0x20u, // BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB - BindOpcodeSetDylibSpecialImmediate = 0x30u, // BIND_OPCODE_SET_DYLIB_SPECIAL_IMM - BindOpcodeSetSymbolTrailingFlagsImmediate = 0x40u, // BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM - BindOpcodeSetTypeImmediate = 0x50u, // BIND_OPCODE_SET_TYPE_IMM - BindOpcodeSetAddendSLEB = 0x60u, // BIND_OPCODE_SET_ADDEND_SLEB - BindOpcodeSetSegmentAndOffsetULEB = 0x70u, // BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB - BindOpcodeAddAddressULEB = 0x80u, // BIND_OPCODE_ADD_ADDR_ULEB - BindOpcodeDoBind = 0x90u, // BIND_OPCODE_DO_BIND - BindOpcodeDoBindAddAddressULEB = 0xA0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB - BindOpcodeDoBindAddAddressImmediateScaled = 0xB0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED - BindOpcodeDoBindULEBTimesSkippingULEB = 0xC0u, // BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB - }; - - enum X86ThreadFlavor { - X86_THREAD_STATE32 = 0x1, - X86_FLOAT_STATE32 = 0x2, - X86_EXCEPTION_STATE32 = 0x3, - X86_THREAD_STATE64 = 0x4, - X86_FLOAT_STATE64 = 0x5, - X86_EXCEPTION_STATE64 = 0x6, - X86_THREAD_STATE = 0x7, - X86_FLOAT_STATE = 0x8, - X86_EXCEPTION_STATE = 0x9, - X86_DEBUG_STATE32 = 0xA, - X86_DEBUG_STATE64 = 0xB, - X86_DEBUG_STATE = 0xC, - _THREAD_STATE_NONE = 0xD - }; - - enum PPCThreadFlavor { - PPC_THREAD_STATE = 0x1, - PPC_FLOAT_STATE = 0x2, - PPC_EXCEPTION_STATE = 0x3, - PPC_VECTOR_STATE = 0x4, - PPC_THREAD_STATE64 = 0x5, - PPC_EXCEPTION_STATE64 = 0x6 - }; - - enum ARMThreadFlavor - { - _ARM_THREAD_STATE = 1, - _ARM_VFP_STATE = 2, - _ARM_EXCEPTION_STATE = 3, - _ARM_DEBUG_STATE = 4, /* pre-armv8 */ - _ARM_THREAD_STATE64 = 6, - _ARM_EXCEPTION_STATE64 = 7 - }; - - struct routines_command { // for 32-bit architectures - uint32_t cmd; // LC_ROUTINES - uint32_t cmdsize; // total size of this command - uint32_t init_address; // address of initialization routine - uint32_t init_module; // index into the module table that the init routine is defined in - uint32_t reserved1; - uint32_t reserved2; - uint32_t reserved3; - uint32_t reserved4; - uint32_t reserved5; - uint32_t reserved6; - }; - - struct routines_command_64 { // for 64-bit architectures - uint32_t cmd; // LC_ROUTINES_64 - uint32_t cmdsize; // total size of this command - uint64_t init_address; // address of initialization routine - uint64_t init_module; // index into the module table that the init routine is defined in - uint64_t reserved1; - uint64_t reserved2; - uint64_t reserved3; - uint64_t reserved4; - uint64_t reserved5; - uint64_t reserved6; - }; - - struct symtab_command { - uint32_t cmd; // LC_SYMTAB - uint32_t cmdsize; // sizeof(struct symtab_command) - uint32_t symoff; // symbol table offset - uint32_t nsyms; // number of symbol table entries - uint32_t stroff; // string table offset - uint32_t strsize; // string table size in bytes - }; - - // Lots of good information on how to use dysymtab for relocations - // https://opensource.apple.com/source/cctools/cctools-795/include/mach-o/loader.h - struct dysymtab_command { - uint32_t cmd; // LC_DYSYMTAB - uint32_t cmdsize; // sizeof(struct dysymtab_command) - uint32_t ilocalsym; // index to local symbols - uint32_t nlocalsym; // number of local symbols - uint32_t iextdefsym; // index to externally defined symbols - uint32_t nextdefsym; // number of externally defined symbols - uint32_t iundefsym; // index to undefined symbols - uint32_t nundefsym; // number of undefined symbols - uint32_t tocoff; // file offset to table of contents - uint32_t ntoc; // number of entries in table of contents - uint32_t modtaboff; // file offset to module table - uint32_t nmodtab; // number of module table entries - uint32_t extrefsymoff; // offset to referenced symbol table - uint32_t nextrefsyms; // number of referenced symbol table entries - uint32_t indirectsymoff; // file offset to the indirect symbol table - uint32_t nindirectsyms; // number of indirect symbol table entries - uint32_t extreloff; // offset to external relocation entries - uint32_t nextrel; // number of external relocation entries - uint32_t locreloff; // offset to local relocation entries - uint32_t nlocrel; // number of local relocation entries - }; - - struct twolevel_hints_command { - uint32_t cmd; // LC_TWOLEVEL_HINTS - uint32_t cmdsize; // sizeof(struct twolevel_hints_command) - uint32_t offset; // offset to the hint table - uint32_t nhints; // number of hints in the hint table - }; - - struct dyld_info_command { - uint32_t cmd; // LC_DYLD_INFO or LC_DYLD_INFO_ONLY - uint32_t cmdsize; // sizeof(struct dyld_info_command) - uint32_t rebase_off; // file offset to rebase info - uint32_t rebase_size; // size of rebase info - uint32_t bind_off; // file offset to binding info - uint32_t bind_size; // size of binding info - uint32_t weak_bind_off; // file offset to weak binding info - uint32_t weak_bind_size; // size of weak binding info - uint32_t lazy_bind_off; // file offset to lazy binding info - uint32_t lazy_bind_size; // size of lazy binding infs - uint32_t export_off; // file offset to lazy binding info - uint32_t export_size; // size of lazy binding infs - }; - - struct function_starts_command { - uint32_t cmd; //LC_FUNCTION_STARTS - uint32_t cmdsize; //sizeof(struct function_starts_command) - uint32_t funcoff; //offset to function starts list - uint32_t funcsize; //sizeof function starts list - }; - - enum MachoPlatform { - MACHO_PLATFORM_MACOS = 1, - MACHO_PLATFORM_IOS = 2, - MACHO_PLATFORM_TVOS = 3, - MACHO_PLATFORM_WATCHOS = 4, - MACHO_PLATFORM_BRIDGEOS = 5 - }; - - enum MachoBuildTool { - MACHO_TOOL_CLANG = 1, - MACHO_TOOL_SWIFT = 2, - MACHO_TOOL_LD = 3 - }; - - struct build_tool_version { - uint32_t tool; - uint32_t version; - }; - - struct build_version_command { - uint32_t cmd; // LC_BUILD_VERSION - uint32_t cmdsize; // sizeof(build_version_command) + (ntools * sizeof(build_tool_version) - uint32_t platform; // MachoPlatform - uint32_t minos; // X.Y.Z is encoded in nibbles xxxx.yy.zz - uint32_t sdk; // X.Y.Z is encoded in nibbles xxxx.yy.zz - uint32_t ntools; // number build_tool_version entries - }; - -#pragma pack(push, 1) - struct nlist { - int32_t n_strx; - uint8_t n_type; - uint8_t n_sect; - int16_t n_desc; - uint32_t n_value; - }; - - struct nlist_64 { - uint32_t n_strx; - uint8_t n_type; - uint8_t n_sect; - uint16_t n_desc; - uint64_t n_value; - }; -#pragma pack(pop) - -#define R_ABS 0 - struct relocation_info - { - int32_t r_address; - uint32_t r_symbolnum:24; - uint32_t r_pcrel:1; - uint32_t r_length:2; - uint32_t r_extern:1; - uint32_t r_type:4; - }; -#define R_SCATTERED 0x80000000 - struct scattered_relocation_info_be_64 { - uint32_t r_scattered:1; // 1=scattered, 0=non-scattered (see above) - uint32_t r_pcrel:1; // was relocated pc relative already - uint32_t r_length:2; // 0=byte, 1=word, 2=long - uint32_t r_type:4; // if not 0, machine specific relocation type - uint32_t r_address:24; // offset in the section to what is being relocated - int64_t r_value; // the value the item to be relocated is refering to (without any offset added) - }; - struct scattered_relocation_info_le_64 { - uint32_t r_address:24; // offset in the section to what is being relocated - uint32_t r_type:4; // if not 0, machine specific relocation type - uint32_t r_length:2; // 0=byte, 1=word, 2=long - uint32_t r_pcrel:1; // was relocated pc relative already - uint32_t r_scattered:1; // 1=scattered, 0=non-scattered (see above) - int64_t r_value; // the value the item to be relocated is refering to (without any offset added) - }; - struct scattered_relocation_info_be { - uint32_t r_scattered:1; // 1=scattered, 0=non-scattered (see above) - uint32_t r_pcrel:1; // was relocated pc relative already - uint32_t r_length:2; // 0=byte, 1=word, 2=long - uint32_t r_type:4; // if not 0, machine specific relocation type - uint32_t r_address:24; // offset in the section to what is being relocated - int32_t r_value; // the value the item to be relocated is refering to (without any offset added) - }; - struct scattered_relocation_info_le { - uint32_t r_address:24; // offset in the section to what is being relocated - uint32_t r_type:4; // if not 0, machine specific relocation type - uint32_t r_length:2; // 0=byte, 1=word, 2=long - uint32_t r_pcrel:1; // was relocated pc relative already - uint32_t r_scattered:1; // 1=scattered, 0=non-scattered (see above) - int32_t r_value; // the value the item to be relocated is refering to (without any offset added) - }; - - enum reloc_type_generic - { - GENERIC_RELOC_VANILLA, // generic relocation as discribed above - GENERIC_RELOC_PAIR, // Only follows a GENRIC_RELOC_SECTDIFF - GENERIC_RELOC_SECTDIFF, - GENERIC_RELOC_PB_LA_PTR // prebound lazy pointer - }; - - struct dyld_chained_fixups_header - { - uint32_t fixups_version; // 0 - uint32_t starts_offset; // offset of dyld_chained_starts_in_image in chain_data - uint32_t imports_offset; // offset of imports table in chain_data - uint32_t symbols_offset; // offset of symbol strings in chain_data - uint32_t imports_count; // number of imported symbol names - uint32_t imports_format; // DYLD_CHAINED_IMPORT* - uint32_t symbols_format; // 0 => uncompressed, 1 => zlib compressed - }; - - // This struct is embedded in LC_DYLD_CHAINED_FIXUPS payload - struct dyld_chained_starts_in_image - { - uint32_t seg_count; - uint32_t seg_info_offset[1]; // each entry is offset into this struct for that segment - // followed by pool of dyld_chain_starts_in_segment data - }; - - // This struct is embedded in dyld_chain_starts_in_image - // and passed down to the kernel for page-in linking - struct dyld_chained_starts_in_segment - { - uint32_t size; // size of this (amount kernel needs to copy) - uint16_t page_size; // 0x1000 or 0x4000 - uint16_t pointer_format; // DYLD_CHAINED_PTR_* - uint64_t segment_offset; // offset in memory to start of segment - uint32_t max_valid_pointer; // for 32-bit OS, any value beyond this is not a pointer - uint16_t page_count; // how many pages are in array - uint16_t page_start[1]; // each entry is offset in each page of first element in chain - // or DYLD_CHAINED_PTR_START_NONE if no fixups on page - - // uint16_t chain_starts[1]; // some 32-bit formats may require multiple starts per page. - // for those, if high bit is set in page_starts[], then it - // is index into chain_starts[] which is a list of starts - // the last of which has the high bit set - }; - - enum { - DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups - DYLD_CHAINED_PTR_START_MULTI = 0x8000, // used in page_start[] to denote a page which has multiple starts - DYLD_CHAINED_PTR_START_LAST = 0x8000, // used in chain_starts[] to denote last start in list for page - }; - - // This struct is embedded in __TEXT,__chain_starts section in firmware - struct dyld_chained_starts_offsets - { - uint32_t pointer_format; // DYLD_CHAINED_PTR_32_FIRMWARE - uint32_t starts_count; // number of starts in array - uint32_t chain_starts[1]; // array chain start offsets - }; - - // values for dyld_chained_starts_in_segment.pointer_format - enum { - DYLD_CHAINED_PTR_ARM64E = 1, // stride 8, unauth target is vmaddr - DYLD_CHAINED_PTR_64 = 2, // target is vmaddr - DYLD_CHAINED_PTR_32 = 3, - DYLD_CHAINED_PTR_32_CACHE = 4, - DYLD_CHAINED_PTR_32_FIRMWARE = 5, - DYLD_CHAINED_PTR_64_OFFSET = 6, // target is vm offset - DYLD_CHAINED_PTR_ARM64E_OFFSET = 7, // old name - DYLD_CHAINED_PTR_ARM64E_KERNEL = 7, // stride 4, unauth target is vm offset - DYLD_CHAINED_PTR_64_KERNEL_CACHE = 8, - DYLD_CHAINED_PTR_ARM64E_USERLAND = 9, // stride 8, unauth target is vm offset - DYLD_CHAINED_PTR_ARM64E_FIRMWARE = 10, // stride 4, unauth target is vmaddr - DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE = 11, // stride 1, x86_64 kernel caches - DYLD_CHAINED_PTR_ARM64E_USERLAND24 = 12, // stride 8, unauth target is vm offset, 24-bit bind - }; - - // DYLD_CHAINED_PTR_ARM64E - struct dyld_chained_ptr_arm64e_rebase - { - uint64_t target : 43, - high8 : 8, - next : 11, // 4 or 8-byte stide - bind : 1, // == 0 - auth : 1; // == 0 - }; - - // DYLD_CHAINED_PTR_ARM64E - struct dyld_chained_ptr_arm64e_bind - { - uint64_t ordinal : 16, - zero : 16, - addend : 19, // +/-256K - next : 11, // 4 or 8-byte stide - bind : 1, // == 1 - auth : 1; // == 0 - }; - - // DYLD_CHAINED_PTR_ARM64E - struct dyld_chained_ptr_arm64e_auth_rebase - { - uint64_t target : 32, // runtimeOffset - diversity : 16, - addrDiv : 1, - key : 2, - next : 11, // 4 or 8-byte stide - bind : 1, // == 0 - auth : 1; // == 1 - }; - - // DYLD_CHAINED_PTR_ARM64E - struct dyld_chained_ptr_arm64e_auth_bind - { - uint64_t ordinal : 16, - zero : 16, - diversity : 16, - addrDiv : 1, - key : 2, - next : 11, // 4 or 8-byte stide - bind : 1, // == 1 - auth : 1; // == 1 - }; - - // DYLD_CHAINED_PTR_64/DYLD_CHAINED_PTR_64_OFFSET - struct dyld_chained_ptr_64_rebase - { - uint64_t target : 36, // 64GB max image size (DYLD_CHAINED_PTR_64 => vmAddr, DYLD_CHAINED_PTR_64_OFFSET => runtimeOffset) - high8 : 8, // top 8 bits set to this (DYLD_CHAINED_PTR_64 => after slide added, DYLD_CHAINED_PTR_64_OFFSET => before slide added) - reserved : 7, // all zeros - next : 12, // 4-byte stride - bind : 1; // == 0 - }; - - - // DYLD_CHAINED_PTR_ARM64E_USERLAND24 - struct dyld_chained_ptr_arm64e_bind24 - { - uint64_t ordinal : 24, - zero : 8, - addend : 19, // +/-256K - next : 11, // 8-byte stide - bind : 1, // == 1 - auth : 1; // == 0 - }; - - // DYLD_CHAINED_PTR_ARM64E_USERLAND24 - struct dyld_chained_ptr_arm64e_auth_bind24 - { - uint64_t ordinal : 24, - zero : 8, - diversity : 16, - addrDiv : 1, - key : 2, - next : 11, // 8-byte stide - bind : 1, // == 1 - auth : 1; // == 1 - }; - - - // DYLD_CHAINED_PTR_64 - struct dyld_chained_ptr_64_bind - { - uint64_t ordinal : 24, - addend : 8, // 0 thru 255 - reserved : 19, // all zeros - next : 12, // 4-byte stride - bind : 1; // == 1 - }; - - // DYLD_CHAINED_PTR_64_KERNEL_CACHE, DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE - struct dyld_chained_ptr_64_kernel_cache_rebase - { - uint64_t target : 30, // basePointers[cacheLevel] + target - cacheLevel : 2, // what level of cache to bind to (indexes a mach_header array) - diversity : 16, - addrDiv : 1, - key : 2, - next : 12, // 1 or 4-byte stide - isAuth : 1; // 0 -> not authenticated. 1 -> authenticated - }; - - // DYLD_CHAINED_PTR_32 - // Note: for DYLD_CHAINED_PTR_32 some non-pointer values are co-opted into the chain - // as out of range rebases. If an entry in the chain is > max_valid_pointer, then it - // is not a pointer. To restore the value, subtract off the bias, which is - // (64MB+max_valid_pointer)/2. - struct dyld_chained_ptr_32_rebase - { - uint32_t target : 26, // vmaddr, 64MB max image size - next : 5, // 4-byte stride - bind : 1; // == 0 - }; - - // DYLD_CHAINED_PTR_32 - struct dyld_chained_ptr_32_bind - { - uint32_t ordinal : 20, - addend : 6, // 0 thru 63 - next : 5, // 4-byte stride - bind : 1; // == 1 - }; - - // DYLD_CHAINED_PTR_32_CACHE - struct dyld_chained_ptr_32_cache_rebase - { - uint32_t target : 30, // 1GB max dyld cache TEXT and DATA - next : 2; // 4-byte stride - }; - - - // DYLD_CHAINED_PTR_32_FIRMWARE - struct dyld_chained_ptr_32_firmware_rebase - { - uint32_t target : 26, // 64MB max firmware TEXT and DATA - next : 6; // 4-byte stride - }; - - enum ChainedFixupPointerGeneric { - GenericArm64eFixupFormat, - Generic64FixupFormat, - Generic32FixupFormat, - Firmware32FixupFormat, - Kernel64Format - }; - - union Arm64e { - dyld_chained_ptr_arm64e_auth_rebase authRebase; - dyld_chained_ptr_arm64e_auth_bind authBind; - dyld_chained_ptr_arm64e_rebase rebase; - dyld_chained_ptr_arm64e_bind bind; - dyld_chained_ptr_arm64e_bind24 bind24; - dyld_chained_ptr_arm64e_auth_bind24 authBind24; - }; - - union Generic64 { - dyld_chained_ptr_64_rebase rebase; - dyld_chained_ptr_64_bind bind; - }; - - union Generic32 { - dyld_chained_ptr_32_rebase rebase; - dyld_chained_ptr_32_bind bind; - }; - - union ChainedFixupPointer - { - dyld_chained_ptr_64_kernel_cache_rebase kernel64; - dyld_chained_ptr_32_firmware_rebase firmware32; - - uint64_t raw64; - Arm64e arm64e; - Generic64 generic64; - - uint32_t raw32; - Generic32 generic32; - dyld_chained_ptr_32_cache_rebase cache32; - }; - - // values for dyld_chained_fixups_header.imports_format - enum { - DYLD_CHAINED_IMPORT = 1, - DYLD_CHAINED_IMPORT_ADDEND = 2, - DYLD_CHAINED_IMPORT_ADDEND64 = 3, - }; - - // DYLD_CHAINED_IMPORT - struct dyld_chained_import - { - uint32_t lib_ordinal : 8, - weak_import : 1, - name_offset : 23; - }; - - // DYLD_CHAINED_IMPORT_ADDEND - struct dyld_chained_import_addend - { - uint32_t lib_ordinal : 8, - weak_import : 1, - name_offset : 23; - int32_t addend; - }; - - // DYLD_CHAINED_IMPORT_ADDEND64 - struct dyld_chained_import_addend64 - { - uint64_t lib_ordinal : 16, - weak_import : 1, - reserved : 15, - name_offset : 32; - uint64_t addend; - }; +namespace BinaryNinja { // When we preload the table, we store them in this format. struct import_entry @@ -1351,21 +24,6 @@ namespace BinaryNinja std::string name; }; -#ifndef EXPORT_SYMBOL_FLAGS_KIND_MASK - enum EXPORT_SYMBOL_FLAGS { - EXPORT_SYMBOL_FLAGS_KIND_MASK = 0x03u, ///< Mask to access to EXPORT_SYMBOL_KINDS - EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION = 0x04u, - EXPORT_SYMBOL_FLAGS_REEXPORT = 0x08u, - EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER = 0x10u - }; - - enum EXPORT_SYMBOL_KINDS { - EXPORT_SYMBOL_FLAGS_KIND_REGULAR = 0x00u, - EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL = 0x01u, - EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE = 0x02u - }; -#endif - struct MachOHeader { bool isMainHeader = false; @@ -1422,31 +80,6 @@ namespace BinaryNinja MachOHeader m_header; std::map m_subHeaders; // Used for MH_FILESET entries. - struct HeaderQualifiedNames { - QualifiedName cpuTypeEnumQualName; - QualifiedName fileTypeEnumQualName; - QualifiedName flagsTypeEnumQualName; - QualifiedName headerQualName; - QualifiedName cmdTypeEnumQualName; - QualifiedName loadCommandQualName; - QualifiedName protTypeEnumQualName; - QualifiedName segFlagsTypeEnumQualName; - QualifiedName loadSegmentCommandQualName; - QualifiedName loadSegment64CommandQualName; - QualifiedName sectionQualName; - QualifiedName section64QualName; - QualifiedName symtabQualName; - QualifiedName dynsymtabQualName; - QualifiedName uuidQualName; - QualifiedName linkeditDataQualName; - QualifiedName encryptionInfoQualName; - QualifiedName versionMinQualName; - QualifiedName dyldInfoQualName; - QualifiedName dylibQualName; - QualifiedName dylibCommandQualName; - QualifiedName filesetEntryCommandQualName; - } m_typeNames; - MachoObjCProcessor* m_objcProcessor = nullptr; uint64_t m_universalImageOffset; @@ -1522,4 +155,4 @@ namespace BinaryNinja }; void InitMachoViewType(); -} +} // namespace BinaryNinja diff --git a/view/sharedcache/core/CMakeLists.txt b/view/sharedcache/core/CMakeLists.txt index a9aaa1bc8..e93478ffc 100644 --- a/view/sharedcache/core/CMakeLists.txt +++ b/view/sharedcache/core/CMakeLists.txt @@ -9,7 +9,7 @@ if((NOT BN_API_PATH) AND (NOT BN_INTERNAL_BUILD)) endif() endif() -file(GLOB_RECURSE SOURCES *.cpp *.h ../../../objectivec/*) +file(GLOB_RECURSE SOURCES *.cpp *.h ../../../objectivec/* ../../../macho/*) add_library(sharedcachecore OBJECT ${SOURCES}) diff --git a/view/sharedcache/core/MachO.h b/view/sharedcache/core/MachO.h index d3a720a91..a86c943f1 100644 --- a/view/sharedcache/core/MachO.h +++ b/view/sharedcache/core/MachO.h @@ -2,8 +2,7 @@ #include "VirtualMemory.h" -// TODO: Including this adds a bunch of binary ninja specific stuff :ugh: -#include "view/macho/machoview.h" +#include "macho/types.h" struct CacheSymbol; diff --git a/view/sharedcache/core/MachOProcessor.cpp b/view/sharedcache/core/MachOProcessor.cpp index c6e2c2880..d2a06aa3e 100644 --- a/view/sharedcache/core/MachOProcessor.cpp +++ b/view/sharedcache/core/MachOProcessor.cpp @@ -1,5 +1,6 @@ #include "MachOProcessor.h" #include "SharedCache.h" +#include "macho/types.h" using namespace BinaryNinja; @@ -267,116 +268,5 @@ void SharedCacheMachOProcessor::ApplyHeaderDataVariables(SharedCacheMachOHeader& // TODO: By using a binary reader we assume the sections have all been mapped. // TODO: Maybe we should just use the virtual memory reader... // TODO: We can define symbols and data variables even if there is no backing region FWIW - BinaryReader reader(m_view); - // TODO: Do we support non 64 bit header? - reader.Seek(header.textBase + sizeof(mach_header_64)); - - m_view->DefineDataVariable(header.textBase, Type::NamedType(m_view, QualifiedName("mach_header_64"))); - m_view->DefineAutoSymbol( - new Symbol(DataSymbol, "__macho_header::" + header.identifierPrefix, header.textBase, LocalBinding)); - - auto applyLoadCommand = [&](uint64_t cmdAddr, const load_command& load) { - switch (load.cmd) - { - case LC_SEGMENT: - { - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("segment_command"))); - reader.SeekRelative(5 * 8); - size_t numSections = reader.Read32(); - reader.SeekRelative(4); - for (size_t j = 0; j < numSections; j++) - { - m_view->DefineDataVariable(reader.GetOffset(), Type::NamedType(m_view, QualifiedName("section"))); - auto sectionSymName = - fmt::format("__macho_section::{}_[{}]", header.identifierPrefix, std::to_string(j)); - auto sectionSym = new Symbol(DataSymbol, sectionSymName, reader.GetOffset(), LocalBinding); - m_view->DefineAutoSymbol(sectionSym); - reader.SeekRelative((8 * 8) + 4); - } - break; - } - case LC_SEGMENT_64: - { - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("segment_command_64"))); - reader.SeekRelative(7 * 8); - size_t numSections = reader.Read32(); - reader.SeekRelative(4); - for (size_t j = 0; j < numSections; j++) - { - m_view->DefineDataVariable(reader.GetOffset(), Type::NamedType(m_view, QualifiedName("section_64"))); - auto sectionSymName = - fmt::format("__macho_section_64::{}_[{}]", header.identifierPrefix, std::to_string(j)); - auto sectionSym = new Symbol(DataSymbol, sectionSymName, reader.GetOffset(), LocalBinding); - m_view->DefineAutoSymbol(sectionSym); - reader.SeekRelative(10 * 8); - } - break; - } - case LC_SYMTAB: - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("symtab"))); - break; - case LC_DYSYMTAB: - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("dysymtab"))); - break; - case LC_UUID: - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("uuid"))); - break; - case LC_ID_DYLIB: - case LC_LOAD_DYLIB: - case LC_REEXPORT_DYLIB: - case LC_LOAD_WEAK_DYLIB: - case LC_LOAD_UPWARD_DYLIB: - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("dylib_command"))); - if (load.cmdsize - 24 <= 150) - m_view->DefineDataVariable( - cmdAddr + 24, Type::ArrayType(Type::IntegerType(1, true), load.cmdsize - 24)); - break; - case LC_CODE_SIGNATURE: - case LC_SEGMENT_SPLIT_INFO: - case LC_FUNCTION_STARTS: - case LC_DATA_IN_CODE: - case LC_DYLIB_CODE_SIGN_DRS: - case LC_DYLD_EXPORTS_TRIE: - case LC_DYLD_CHAINED_FIXUPS: - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("linkedit_data"))); - break; - case LC_ENCRYPTION_INFO: - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("encryption_info"))); - break; - case LC_VERSION_MIN_MACOSX: - case LC_VERSION_MIN_IPHONEOS: - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("version_min"))); - break; - case LC_DYLD_INFO: - case LC_DYLD_INFO_ONLY: - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("dyld_info"))); - break; - default: - m_view->DefineDataVariable(cmdAddr, Type::NamedType(m_view, QualifiedName("load_command"))); - break; - } - }; - - try - { - for (size_t i = 0; i < header.ident.ncmds; i++) - { - load_command load {}; - uint64_t curOffset = reader.GetOffset(); - load.cmd = reader.Read32(); - load.cmdsize = reader.Read32(); - - applyLoadCommand(curOffset, load); - m_view->DefineAutoSymbol(new Symbol(DataSymbol, - "__macho_load_command::" + header.identifierPrefix + "_[" + std::to_string(i) + "]", curOffset, - LocalBinding)); - - uint64_t nextOffset = curOffset + load.cmdsize; - reader.Seek(nextOffset); - } - } - catch (ReadException&) - { - m_logger->LogError("Error when applying Mach-O header types at %llx", header.textBase); - } + MachO::ApplyHeaderTypes(m_view, m_logger, BinaryReader(m_view), header.identifierPrefix, header.textBase, header.ident.ncmds); } diff --git a/view/sharedcache/core/SharedCacheView.cpp b/view/sharedcache/core/SharedCacheView.cpp index e9699ab10..dc350a741 100644 --- a/view/sharedcache/core/SharedCacheView.cpp +++ b/view/sharedcache/core/SharedCacheView.cpp @@ -6,6 +6,7 @@ #include "FileAccessorCache.h" #include "MappedFileAccessor.h" #include "SharedCacheBuilder.h" +#include "macho/types.h" using namespace BinaryNinja; using namespace BinaryNinja::DSC; @@ -357,416 +358,7 @@ bool SharedCacheView::Init() return false; } - // Add Mach-O file header type info - EnumerationBuilder cpuTypeBuilder; - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ANY", MACHO_CPU_TYPE_ANY); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_VAX", MACHO_CPU_TYPE_VAX); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC680x0", MACHO_CPU_TYPE_MC680x0); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_X86", MACHO_CPU_TYPE_X86); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_X86_64", MACHO_CPU_TYPE_X86_64); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MIPS", MACHO_CPU_TYPE_MIPS); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC98000", MACHO_CPU_TYPE_MC98000); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_HPPA", MACHO_CPU_TYPE_HPPA); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM", MACHO_CPU_TYPE_ARM); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM64", MACHO_CPU_TYPE_ARM64); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ARM64_32", MACHO_CPU_TYPE_ARM64_32); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_MC88000", MACHO_CPU_TYPE_MC88000); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_SPARC", MACHO_CPU_TYPE_SPARC); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_I860", MACHO_CPU_TYPE_I860); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_ALPHA", MACHO_CPU_TYPE_ALPHA); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_POWERPC", MACHO_CPU_TYPE_POWERPC); - cpuTypeBuilder.AddMemberWithValue("CPU_TYPE_POWERPC64", MACHO_CPU_TYPE_POWERPC64); - Ref cpuTypeEnum = cpuTypeBuilder.Finalize(); - - Ref cpuTypeEnumType = Type::EnumerationType(nullptr, cpuTypeEnum, 4, false); - std::string cpuTypeEnumName = "cpu_type_t"; - std::string cpuTypeEnumId = Type::GenerateAutoTypeId("macho", cpuTypeEnumName); - DefineType(cpuTypeEnumId, cpuTypeEnumName, cpuTypeEnumType); - - EnumerationBuilder fileTypeBuilder; - fileTypeBuilder.AddMemberWithValue("MH_OBJECT", MH_OBJECT); - fileTypeBuilder.AddMemberWithValue("MH_EXECUTE", MH_EXECUTE); - fileTypeBuilder.AddMemberWithValue("MH_FVMLIB", MH_FVMLIB); - fileTypeBuilder.AddMemberWithValue("MH_CORE", MH_CORE); - fileTypeBuilder.AddMemberWithValue("MH_PRELOAD", MH_PRELOAD); - fileTypeBuilder.AddMemberWithValue("MH_DYLIB", MH_DYLIB); - fileTypeBuilder.AddMemberWithValue("MH_DYLINKER", MH_DYLINKER); - fileTypeBuilder.AddMemberWithValue("MH_BUNDLE", MH_BUNDLE); - fileTypeBuilder.AddMemberWithValue("MH_DYLIB_STUB", MH_DYLIB_STUB); - fileTypeBuilder.AddMemberWithValue("MH_DSYM", MH_DSYM); - fileTypeBuilder.AddMemberWithValue("MH_KEXT_BUNDLE", MH_KEXT_BUNDLE); - fileTypeBuilder.AddMemberWithValue("MH_FILESET", MH_FILESET); - Ref fileTypeEnum = fileTypeBuilder.Finalize(); - - Ref fileTypeEnumType = Type::EnumerationType(nullptr, fileTypeEnum, 4, false); - std::string fileTypeEnumName = "file_type_t"; - std::string fileTypeEnumId = Type::GenerateAutoTypeId("macho", fileTypeEnumName); - DefineType(fileTypeEnumId, fileTypeEnumName, fileTypeEnumType); - - EnumerationBuilder flagsTypeBuilder; - flagsTypeBuilder.AddMemberWithValue("MH_NOUNDEFS", MH_NOUNDEFS); - flagsTypeBuilder.AddMemberWithValue("MH_INCRLINK", MH_INCRLINK); - flagsTypeBuilder.AddMemberWithValue("MH_DYLDLINK", MH_DYLDLINK); - flagsTypeBuilder.AddMemberWithValue("MH_BINDATLOAD", MH_BINDATLOAD); - flagsTypeBuilder.AddMemberWithValue("MH_PREBOUND", MH_PREBOUND); - flagsTypeBuilder.AddMemberWithValue("MH_SPLIT_SEGS", MH_SPLIT_SEGS); - flagsTypeBuilder.AddMemberWithValue("MH_LAZY_INIT", MH_LAZY_INIT); - flagsTypeBuilder.AddMemberWithValue("MH_TWOLEVEL", MH_TWOLEVEL); - flagsTypeBuilder.AddMemberWithValue("MH_FORCE_FLAT", MH_FORCE_FLAT); - flagsTypeBuilder.AddMemberWithValue("MH_NOMULTIDEFS", MH_NOMULTIDEFS); - flagsTypeBuilder.AddMemberWithValue("MH_NOFIXPREBINDING", MH_NOFIXPREBINDING); - flagsTypeBuilder.AddMemberWithValue("MH_PREBINDABLE", MH_PREBINDABLE); - flagsTypeBuilder.AddMemberWithValue("MH_ALLMODSBOUND", MH_ALLMODSBOUND); - flagsTypeBuilder.AddMemberWithValue("MH_SUBSECTIONS_VIA_SYMBOLS", MH_SUBSECTIONS_VIA_SYMBOLS); - flagsTypeBuilder.AddMemberWithValue("MH_CANONICAL", MH_CANONICAL); - flagsTypeBuilder.AddMemberWithValue("MH_WEAK_DEFINES", MH_WEAK_DEFINES); - flagsTypeBuilder.AddMemberWithValue("MH_BINDS_TO_WEAK", MH_BINDS_TO_WEAK); - flagsTypeBuilder.AddMemberWithValue("MH_ALLOW_STACK_EXECUTION", MH_ALLOW_STACK_EXECUTION); - flagsTypeBuilder.AddMemberWithValue("MH_ROOT_SAFE", MH_ROOT_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_SETUID_SAFE", MH_SETUID_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_NO_REEXPORTED_DYLIBS", MH_NO_REEXPORTED_DYLIBS); - flagsTypeBuilder.AddMemberWithValue("MH_PIE", MH_PIE); - flagsTypeBuilder.AddMemberWithValue("MH_DEAD_STRIPPABLE_DYLIB", MH_DEAD_STRIPPABLE_DYLIB); - flagsTypeBuilder.AddMemberWithValue("MH_HAS_TLV_DESCRIPTORS", MH_HAS_TLV_DESCRIPTORS); - flagsTypeBuilder.AddMemberWithValue("MH_NO_HEAP_EXECUTION", MH_NO_HEAP_EXECUTION); - flagsTypeBuilder.AddMemberWithValue("MH_APP_EXTENSION_SAFE", _MH_APP_EXTENSION_SAFE); - flagsTypeBuilder.AddMemberWithValue("MH_NLIST_OUTOFSYNC_WITH_DYLDINFO", _MH_NLIST_OUTOFSYNC_WITH_DYLDINFO); - flagsTypeBuilder.AddMemberWithValue("MH_SIM_SUPPORT", _MH_SIM_SUPPORT); - flagsTypeBuilder.AddMemberWithValue("MH_DYLIB_IN_CACHE", _MH_DYLIB_IN_CACHE); - Ref flagsTypeEnum = flagsTypeBuilder.Finalize(); - - Ref flagsTypeEnumType = Type::EnumerationType(nullptr, flagsTypeEnum, 4, false); - std::string flagsTypeEnumName = "flags_type_t"; - std::string flagsTypeEnumId = Type::GenerateAutoTypeId("macho", flagsTypeEnumName); - DefineType(flagsTypeEnumId, flagsTypeEnumName, flagsTypeEnumType); - - StructureBuilder machoHeaderBuilder; - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "magic"); - machoHeaderBuilder.AddMember(Type::NamedType(this, QualifiedName("cpu_type_t")), "cputype"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "cpusubtype"); - machoHeaderBuilder.AddMember(Type::NamedType(this, QualifiedName("file_type_t")), "filetype"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "ncmds"); - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "sizeofcmds"); - machoHeaderBuilder.AddMember(Type::NamedType(this, QualifiedName("flags_type_t")), "flags"); - if (GetAddressSize() == 8) - machoHeaderBuilder.AddMember(Type::IntegerType(4, false), "reserved"); - Ref machoHeaderStruct = machoHeaderBuilder.Finalize(); - QualifiedName headerName = (GetAddressSize() == 8) ? std::string("mach_header_64") : std::string("mach_header"); - - std::string headerTypeId = Type::GenerateAutoTypeId("macho", headerName); - Ref machoHeaderType = Type::StructureType(machoHeaderStruct); - DefineType(headerTypeId, headerName, machoHeaderType); - - EnumerationBuilder cmdTypeBuilder; - cmdTypeBuilder.AddMemberWithValue("LC_REQ_DYLD", LC_REQ_DYLD); - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT", LC_SEGMENT); - cmdTypeBuilder.AddMemberWithValue("LC_SYMTAB", LC_SYMTAB); - cmdTypeBuilder.AddMemberWithValue("LC_SYMSEG", LC_SYMSEG); - cmdTypeBuilder.AddMemberWithValue("LC_THREAD", LC_THREAD); - cmdTypeBuilder.AddMemberWithValue("LC_UNIXTHREAD", LC_UNIXTHREAD); - cmdTypeBuilder.AddMemberWithValue("LC_LOADFVMLIB", LC_LOADFVMLIB); - cmdTypeBuilder.AddMemberWithValue("LC_IDFVMLIB", LC_IDFVMLIB); - cmdTypeBuilder.AddMemberWithValue("LC_IDENT", LC_IDENT); - cmdTypeBuilder.AddMemberWithValue("LC_FVMFILE", LC_FVMFILE); - cmdTypeBuilder.AddMemberWithValue("LC_PREPAGE", LC_PREPAGE); - cmdTypeBuilder.AddMemberWithValue("LC_DYSYMTAB", LC_DYSYMTAB); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_DYLIB", LC_LOAD_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ID_DYLIB", LC_ID_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_DYLINKER", LC_LOAD_DYLINKER); - cmdTypeBuilder.AddMemberWithValue("LC_ID_DYLINKER", LC_ID_DYLINKER); - cmdTypeBuilder.AddMemberWithValue("LC_PREBOUND_DYLIB", LC_PREBOUND_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ROUTINES", LC_ROUTINES); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_FRAMEWORK", LC_SUB_FRAMEWORK); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_UMBRELLA", LC_SUB_UMBRELLA); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_CLIENT", LC_SUB_CLIENT); - cmdTypeBuilder.AddMemberWithValue("LC_SUB_LIBRARY", LC_SUB_LIBRARY); - cmdTypeBuilder.AddMemberWithValue("LC_TWOLEVEL_HINTS", LC_TWOLEVEL_HINTS); - cmdTypeBuilder.AddMemberWithValue("LC_PREBIND_CKSUM", LC_PREBIND_CKSUM); - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_WEAK_DYLIB", LC_LOAD_WEAK_DYLIB); // (0x18 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT_64", LC_SEGMENT_64); - cmdTypeBuilder.AddMemberWithValue("LC_ROUTINES_64", LC_ROUTINES_64); - cmdTypeBuilder.AddMemberWithValue("LC_UUID", LC_UUID); - cmdTypeBuilder.AddMemberWithValue("LC_RPATH", LC_RPATH); // (0x1c | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_CODE_SIGNATURE", LC_CODE_SIGNATURE); - cmdTypeBuilder.AddMemberWithValue("LC_SEGMENT_SPLIT_INFO", LC_SEGMENT_SPLIT_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_REEXPORT_DYLIB", LC_REEXPORT_DYLIB); // (0x1f | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_LAZY_LOAD_DYLIB", LC_LAZY_LOAD_DYLIB); - cmdTypeBuilder.AddMemberWithValue("LC_ENCRYPTION_INFO", LC_ENCRYPTION_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_INFO", LC_DYLD_INFO); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_INFO_ONLY", LC_DYLD_INFO_ONLY); // (0x22 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_LOAD_UPWARD_DYLIB", LC_LOAD_UPWARD_DYLIB); // (0x23 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_MACOSX", LC_VERSION_MIN_MACOSX); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_IPHONEOS", LC_VERSION_MIN_IPHONEOS); - cmdTypeBuilder.AddMemberWithValue("LC_FUNCTION_STARTS", LC_FUNCTION_STARTS); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_ENVIRONMENT", LC_DYLD_ENVIRONMENT); - cmdTypeBuilder.AddMemberWithValue("LC_MAIN", LC_MAIN); // (0x28 | LC_REQ_DYLD) - cmdTypeBuilder.AddMemberWithValue("LC_DATA_IN_CODE", LC_DATA_IN_CODE); - cmdTypeBuilder.AddMemberWithValue("LC_SOURCE_VERSION", LC_SOURCE_VERSION); - cmdTypeBuilder.AddMemberWithValue("LC_DYLIB_CODE_SIGN_DRS", LC_DYLIB_CODE_SIGN_DRS); - cmdTypeBuilder.AddMemberWithValue("LC_ENCRYPTION_INFO_64", _LC_ENCRYPTION_INFO_64); - cmdTypeBuilder.AddMemberWithValue("LC_LINKER_OPTION", _LC_LINKER_OPTION); - cmdTypeBuilder.AddMemberWithValue("LC_LINKER_OPTIMIZATION_HINT", _LC_LINKER_OPTIMIZATION_HINT); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_TVOS", _LC_VERSION_MIN_TVOS); - cmdTypeBuilder.AddMemberWithValue("LC_VERSION_MIN_WATCHOS", LC_VERSION_MIN_WATCHOS); - cmdTypeBuilder.AddMemberWithValue("LC_NOTE", LC_NOTE); - cmdTypeBuilder.AddMemberWithValue("LC_BUILD_VERSION", LC_BUILD_VERSION); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_EXPORTS_TRIE", LC_DYLD_EXPORTS_TRIE); - cmdTypeBuilder.AddMemberWithValue("LC_DYLD_CHAINED_FIXUPS", LC_DYLD_CHAINED_FIXUPS); - cmdTypeBuilder.AddMemberWithValue("LC_FILESET_ENTRY", LC_FILESET_ENTRY); - Ref cmdTypeEnum = cmdTypeBuilder.Finalize(); - - Ref cmdTypeEnumType = Type::EnumerationType(nullptr, cmdTypeEnum, 4, false); - std::string cmdTypeEnumName = "load_command_type_t"; - std::string cmdTypeEnumId = Type::GenerateAutoTypeId("macho", cmdTypeEnumName); - DefineType(cmdTypeEnumId, cmdTypeEnumName, cmdTypeEnumType); - - StructureBuilder loadCommandBuilder; - loadCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - loadCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - Ref loadCommandStruct = loadCommandBuilder.Finalize(); - QualifiedName loadCommandName = std::string("load_command"); - std::string loadCommandTypeId = Type::GenerateAutoTypeId("macho", loadCommandName); - Ref loadCommandType = Type::StructureType(loadCommandStruct); - DefineType(loadCommandTypeId, loadCommandName, loadCommandType); - - EnumerationBuilder protTypeBuilder; - protTypeBuilder.AddMemberWithValue("VM_PROT_NONE", MACHO_VM_PROT_NONE); - protTypeBuilder.AddMemberWithValue("VM_PROT_READ", MACHO_VM_PROT_READ); - protTypeBuilder.AddMemberWithValue("VM_PROT_WRITE", MACHO_VM_PROT_WRITE); - protTypeBuilder.AddMemberWithValue("VM_PROT_EXECUTE", MACHO_VM_PROT_EXECUTE); - // protTypeBuilder.AddMemberWithValue("VM_PROT_DEFAULT", MACHO_VM_PROT_DEFAULT); - // protTypeBuilder.AddMemberWithValue("VM_PROT_ALL", MACHO_VM_PROT_ALL); - protTypeBuilder.AddMemberWithValue("VM_PROT_NO_CHANGE", MACHO_VM_PROT_NO_CHANGE); - protTypeBuilder.AddMemberWithValue("VM_PROT_COPY_OR_WANTS_COPY", MACHO_VM_PROT_COPY); - // protTypeBuilder.AddMemberWithValue("VM_PROT_WANTS_COPY", MACHO_VM_PROT_WANTS_COPY); - Ref protTypeEnum = protTypeBuilder.Finalize(); - - Ref protTypeEnumType = Type::EnumerationType(nullptr, protTypeEnum, 4, false); - std::string protTypeEnumName = "vm_prot_t"; - std::string protTypeEnumId = Type::GenerateAutoTypeId("macho", protTypeEnumName); - DefineType(protTypeEnumId, protTypeEnumName, protTypeEnumType); - - EnumerationBuilder segFlagsTypeBuilder; - segFlagsTypeBuilder.AddMemberWithValue("SG_HIGHVM", SG_HIGHVM); - segFlagsTypeBuilder.AddMemberWithValue("SG_FVMLIB", SG_FVMLIB); - segFlagsTypeBuilder.AddMemberWithValue("SG_NORELOC", SG_NORELOC); - segFlagsTypeBuilder.AddMemberWithValue("SG_PROTECTED_VERSION_1", SG_PROTECTED_VERSION_1); - Ref segFlagsTypeEnum = segFlagsTypeBuilder.Finalize(); - - Ref segFlagsTypeEnumType = Type::EnumerationType(nullptr, segFlagsTypeEnum, 4, false); - std::string segFlagsTypeEnumName = "sg_flags_t"; - std::string segFlagsTypeEnumId = Type::GenerateAutoTypeId("macho", segFlagsTypeEnumName); - DefineType(segFlagsTypeEnumId, segFlagsTypeEnumName, segFlagsTypeEnumType); - - StructureBuilder loadSegmentCommandBuilder; - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - loadSegmentCommandBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "vmaddr"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "vmsize"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "fileoff"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "filesize"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "maxprot"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "initprot"); - loadSegmentCommandBuilder.AddMember(Type::IntegerType(4, false), "nsects"); - loadSegmentCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("sg_flags_t")), "flags"); - Ref loadSegmentCommandStruct = loadSegmentCommandBuilder.Finalize(); - QualifiedName loadSegmentCommandName = std::string("segment_command"); - std::string loadSegmentCommandTypeId = Type::GenerateAutoTypeId("macho", loadSegmentCommandName); - Ref loadSegmentCommandType = Type::StructureType(loadSegmentCommandStruct); - DefineType(loadSegmentCommandTypeId, loadSegmentCommandName, loadSegmentCommandType); - - StructureBuilder loadSegmentCommand64Builder; - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(4, false), "cmdsize"); - loadSegmentCommand64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "vmaddr"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "vmsize"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "fileoff"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(8, false), "filesize"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "maxprot"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("vm_prot_t")), "initprot"); - loadSegmentCommand64Builder.AddMember(Type::IntegerType(4, false), "nsects"); - loadSegmentCommand64Builder.AddMember(Type::NamedType(this, QualifiedName("sg_flags_t")), "flags"); - Ref loadSegmentCommand64Struct = loadSegmentCommand64Builder.Finalize(); - QualifiedName loadSegment64CommandName = std::string("segment_command_64"); - std::string loadSegment64CommandTypeId = Type::GenerateAutoTypeId("macho", loadSegment64CommandName); - Ref loadSegment64CommandType = Type::StructureType(loadSegmentCommand64Struct); - DefineType(loadSegment64CommandTypeId, loadSegment64CommandName, loadSegment64CommandType); - - StructureBuilder sectionBuilder; - sectionBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "sectname"); - sectionBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "addr"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "size"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "offset"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "align"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reloff"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "nreloc"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "flags"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reserved1"); - sectionBuilder.AddMember(Type::IntegerType(4, false), "reserved2"); - Ref sectionStruct = sectionBuilder.Finalize(); - QualifiedName sectionName = std::string("section"); - std::string sectionTypeId = Type::GenerateAutoTypeId("macho", sectionName); - Ref sectionType = Type::StructureType(sectionStruct); - DefineType(sectionTypeId, sectionName, sectionType); - - StructureBuilder section64Builder; - section64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "sectname"); - section64Builder.AddMember(Type::ArrayType(Type::IntegerType(1, true), 16), "segname"); - section64Builder.AddMember(Type::IntegerType(8, false), "addr"); - section64Builder.AddMember(Type::IntegerType(8, false), "size"); - section64Builder.AddMember(Type::IntegerType(4, false), "offset"); - section64Builder.AddMember(Type::IntegerType(4, false), "align"); - section64Builder.AddMember(Type::IntegerType(4, false), "reloff"); - section64Builder.AddMember(Type::IntegerType(4, false), "nreloc"); - section64Builder.AddMember(Type::IntegerType(4, false), "flags"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved1"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved2"); - section64Builder.AddMember(Type::IntegerType(4, false), "reserved3"); - Ref section64Struct = section64Builder.Finalize(); - QualifiedName section64Name = std::string("section_64"); - std::string section64TypeId = Type::GenerateAutoTypeId("macho", section64Name); - Ref section64Type = Type::StructureType(section64Struct); - DefineType(section64TypeId, section64Name, section64Type); - - StructureBuilder symtabBuilder; - symtabBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "symoff"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "nsyms"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "stroff"); - symtabBuilder.AddMember(Type::IntegerType(4, false), "strsize"); - Ref symtabStruct = symtabBuilder.Finalize(); - QualifiedName symtabName = std::string("symtab"); - std::string symtabTypeId = Type::GenerateAutoTypeId("macho", symtabName); - Ref symtabType = Type::StructureType(symtabStruct); - DefineType(symtabTypeId, symtabName, symtabType); - - StructureBuilder dynsymtabBuilder; - dynsymtabBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "ilocalsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nlocalsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "iextdefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextdefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "iundefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nundefsym"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "tocoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "ntoc"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "modtaboff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nmodtab"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "extrefsymoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextrefsyms"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "indirectsymoff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nindirectsyms"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "extreloff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nextrel"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "locreloff"); - dynsymtabBuilder.AddMember(Type::IntegerType(4, false), "nlocrel"); - Ref dynsymtabStruct = dynsymtabBuilder.Finalize(); - QualifiedName dynsymtabName = std::string("dynsymtab"); - std::string dynsymtabTypeId = Type::GenerateAutoTypeId("macho", dynsymtabName); - Ref dynsymtabType = Type::StructureType(dynsymtabStruct); - DefineType(dynsymtabTypeId, dynsymtabName, dynsymtabType); - - StructureBuilder uuidBuilder; - uuidBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - uuidBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - uuidBuilder.AddMember(Type::ArrayType(Type::IntegerType(1, false), 16), "uuid"); - Ref uuidStruct = uuidBuilder.Finalize(); - QualifiedName uuidName = std::string("uuid"); - std::string uuidTypeId = Type::GenerateAutoTypeId("macho", uuidName); - Ref uuidType = Type::StructureType(uuidStruct); - DefineType(uuidTypeId, uuidName, uuidType); - - StructureBuilder linkeditDataBuilder; - linkeditDataBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "dataoff"); - linkeditDataBuilder.AddMember(Type::IntegerType(4, false), "datasize"); - Ref linkeditDataStruct = linkeditDataBuilder.Finalize(); - QualifiedName linkeditDataName = std::string("linkedit_data"); - std::string linkeditDataTypeId = Type::GenerateAutoTypeId("macho", linkeditDataName); - Ref linkeditDataType = Type::StructureType(linkeditDataStruct); - DefineType(linkeditDataTypeId, linkeditDataName, linkeditDataType); - - StructureBuilder encryptionInfoBuilder; - encryptionInfoBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptoff"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptsize"); - encryptionInfoBuilder.AddMember(Type::IntegerType(4, false), "cryptid"); - Ref encryptionInfoStruct = encryptionInfoBuilder.Finalize(); - QualifiedName encryptionInfoName = std::string("encryption_info"); - std::string encryptionInfoTypeId = Type::GenerateAutoTypeId("macho", encryptionInfoName); - Ref encryptionInfoType = Type::StructureType(encryptionInfoStruct); - DefineType(encryptionInfoTypeId, encryptionInfoName, encryptionInfoType); - - StructureBuilder versionMinBuilder; - versionMinBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "version"); - versionMinBuilder.AddMember(Type::IntegerType(4, false), "sdk"); - Ref versionMinStruct = versionMinBuilder.Finalize(); - QualifiedName versionMinName = std::string("version_min"); - std::string versionMinTypeId = Type::GenerateAutoTypeId("macho", versionMinName); - Ref versionMinType = Type::StructureType(versionMinStruct); - DefineType(versionMinTypeId, versionMinName, versionMinType); - - StructureBuilder dyldInfoBuilder; - dyldInfoBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "rebase_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "rebase_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "weak_bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "weak_bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "lazy_bind_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "lazy_bind_size"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "export_off"); - dyldInfoBuilder.AddMember(Type::IntegerType(4, false), "export_size"); - Ref dyldInfoStruct = dyldInfoBuilder.Finalize(); - QualifiedName dyldInfoName = std::string("dyld_info"); - std::string dyldInfoTypeId = Type::GenerateAutoTypeId("macho", dyldInfoName); - Ref dyldInfoType = Type::StructureType(dyldInfoStruct); - DefineType(dyldInfoTypeId, dyldInfoName, dyldInfoType); - - StructureBuilder dylibBuilder; - dylibBuilder.AddMember(Type::IntegerType(4, false), "name"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "timestamp"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "current_version"); - dylibBuilder.AddMember(Type::IntegerType(4, false), "compatibility_version"); - Ref dylibStruct = dylibBuilder.Finalize(); - QualifiedName dylibName = std::string("dylib"); - std::string dylibTypeId = Type::GenerateAutoTypeId("macho", dylibName); - Ref dylibType = Type::StructureType(dylibStruct); - DefineType(dylibTypeId, dylibName, dylibType); - - StructureBuilder dylibCommandBuilder; - dylibCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - dylibCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - dylibCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("dylib")), "dylib"); - Ref dylibCommandStruct = dylibCommandBuilder.Finalize(); - QualifiedName dylibCommandName = std::string("dylib_command"); - std::string dylibCommandTypeId = Type::GenerateAutoTypeId("macho", dylibCommandName); - Ref dylibCommandType = Type::StructureType(dylibCommandStruct); - DefineType(dylibCommandTypeId, dylibCommandName, dylibCommandType); - - StructureBuilder filesetEntryCommandBuilder; - filesetEntryCommandBuilder.AddMember(Type::NamedType(this, QualifiedName("load_command_type_t")), "cmd"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "cmdsize"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(8, false), "vmaddr"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(8, false), "fileoff"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "entry_id"); - filesetEntryCommandBuilder.AddMember(Type::IntegerType(4, false), "reserved"); - Ref filesetEntryCommandStruct = filesetEntryCommandBuilder.Finalize(); - QualifiedName filesetEntryCommandName = std::string("fileset_entry_command"); - std::string filesetEntryCommandTypeId = Type::GenerateAutoTypeId("macho", filesetEntryCommandName); - Ref filesetEntryCommandType = Type::StructureType(filesetEntryCommandStruct); - DefineType(filesetEntryCommandTypeId, filesetEntryCommandName, filesetEntryCommandType); + MachO::CreateHeaderTypes(this); // uint32_t at 0x10 is offset to mapping table. // first mapping struct in that table is base of primary diff --git a/view/sharedcache/core/Utility.cpp b/view/sharedcache/core/Utility.cpp index 6f8323bfb..b9650b0a5 100644 --- a/view/sharedcache/core/Utility.cpp +++ b/view/sharedcache/core/Utility.cpp @@ -1,6 +1,6 @@ #include "Utility.h" #include "binaryninjaapi.h" -#include "view/macho/machoview.h" +#include "macho/types.h" using namespace BinaryNinja;