@@ -275,7 +275,8 @@ void CreateHeaderTypes(Ref<BinaryView> view)
275275 {" SG_HIGHVM" , SG_HIGHVM},
276276 {" SG_FVMLIB" , SG_FVMLIB},
277277 {" SG_NORELOC" , SG_NORELOC},
278- {" SG_PROTECTED_VERSION_1" , SG_PROTECTED_VERSION_1}
278+ {" SG_PROTECTED_VERSION_1" , SG_PROTECTED_VERSION_1},
279+ {" SG_READ_ONLY_DATA" , SG_READ_ONLY_DATA},
279280 // clang-format on
280281 });
281282
@@ -313,6 +314,45 @@ void CreateHeaderTypes(Ref<BinaryView> view)
313314 // clang-format on
314315 });
315316
317+ // TODO: These three enums are technically a single field 32-bit field in the struct. The upper 24 bits are bit
318+ // flags while the lower 8 bits are mutually exclusive. This prevents Binary Ninja from rendering them in an ORd
319+ // form. The upper 24 bits are split into two enums because a 24 bit enum field isn't handle correctly either.
320+ auto sectionTypeEnum = BuildEnum (view, " section_type_t" , 1 ,
321+ {
322+ {" S_REGULAR" , S_REGULAR},
323+ {" S_CSTRING_LITERALS" , S_CSTRING_LITERALS},
324+ {" S_4BYTE_LITERALS" , S_4BYTE_LITERALS},
325+ {" S_8BYTE_LITERALS" , S_8BYTE_LITERALS},
326+ {" S_LITERAL_POINTERS" , S_LITERAL_POINTERS},
327+ {" S_NON_LAZY_SYMBOL_POINTERS" , S_NON_LAZY_SYMBOL_POINTERS},
328+ {" S_LAZY_SYMBOL_POINTERS" , S_LAZY_SYMBOL_POINTERS},
329+ {" S_SYMBOL_STUBS" , S_SYMBOL_STUBS},
330+ {" S_MOD_INIT_FUNC_POINTERS" , S_MOD_INIT_FUNC_POINTERS},
331+ {" S_MOD_TERM_FUNC_POINTERS" , S_MOD_TERM_FUNC_POINTERS},
332+ {" S_COALESCED" , S_COALESCED},
333+ {" S_GB_ZEROFILL" , S_GB_ZEROFILL},
334+ {" S_INTERPOSING" , S_INTERPOSING},
335+ {" S_16BYTE_LITERALS" , S_16BYTE_LITERALS},
336+ });
337+
338+ auto sectionAttributesSysEnum = BuildEnum (view, " section_attr_sys_t" , 1 ,
339+ {
340+ {" S_ATTR_DEBUG" , (S_ATTR_DEBUG >> 24 ) & 0xff },
341+ {" S_ATTR_SELF_MODIFYING_CODE" , (S_ATTR_SELF_MODIFYING_CODE >> 24 ) & 0xff },
342+ {" S_ATTR_LIVE_SUPPORT" , (S_ATTR_LIVE_SUPPORT >> 24 ) & 0xff },
343+ {" S_ATTR_NO_DEAD_STRIP" , (S_ATTR_NO_DEAD_STRIP >> 24 ) & 0xff },
344+ {" S_ATTR_STRIP_STATIC_SYMS" , (S_ATTR_STRIP_STATIC_SYMS >> 24 ) & 0xff },
345+ {" S_ATTR_NO_TOC" , (S_ATTR_NO_TOC >> 24 ) & 0xff },
346+ {" S_ATTR_PURE_INSTRUCTIONS" , (S_ATTR_PURE_INSTRUCTIONS >> 24 ) & 0xff },
347+ });
348+
349+ auto sectionAttributesUserEnum = BuildEnum (view, " section_attr_user_t" , 2 ,
350+ {
351+ {" S_ATTR_LOC_RELOC" , (S_ATTR_LOC_RELOC >> 8 ) & 0xffff },
352+ {" S_ATTR_EXT_RELOC" , (S_ATTR_EXT_RELOC >> 8 ) & 0xffff },
353+ {" S_ATTR_SOME_INSTRUCTIONS" , (S_ATTR_SOME_INSTRUCTIONS >> 8 ) & 0xffff },
354+ });
355+
316356 auto sectionType = BuildStruct (view, " section" , true ,
317357 {
318358 // clang-format off
@@ -324,7 +364,9 @@ void CreateHeaderTypes(Ref<BinaryView> view)
324364 {" align" , Type::IntegerType (4 , false )},
325365 {" reloff" , Type::IntegerType (4 , false )},
326366 {" nreloc" , Type::IntegerType (4 , false )},
327- {" flags" , Type::IntegerType (4 , false )},
367+ {" type" , sectionTypeEnum},
368+ {" attrs_user" , sectionAttributesUserEnum},
369+ {" attrs_sys" , sectionAttributesSysEnum},
328370 {" reserved1" , Type::IntegerType (4 , false )},
329371 {" reserved2" , Type::IntegerType (4 , false )}
330372 // clang-format on
@@ -341,7 +383,9 @@ void CreateHeaderTypes(Ref<BinaryView> view)
341383 {" align" , Type::IntegerType (4 , false )},
342384 {" reloff" , Type::IntegerType (4 , false )},
343385 {" nreloc" , Type::IntegerType (4 , false )},
344- {" flags" , Type::IntegerType (4 , false )},
386+ {" type" , sectionTypeEnum},
387+ {" attrs_user" , sectionAttributesUserEnum},
388+ {" attrs_sys" , sectionAttributesSysEnum},
345389 {" reserved1" , Type::IntegerType (4 , false )},
346390 {" reserved2" , Type::IntegerType (4 , false )},
347391 {" reserved3" , Type::IntegerType (4 , false )}
@@ -499,14 +543,22 @@ void CreateHeaderTypes(Ref<BinaryView> view)
499543 // clang-format on
500544 });
501545
546+ QualifiedName filesetEntryIdName (" fileset_entry_id" );
547+ std::string filesetEntryIdId = Type::GenerateAutoTypeId (" macho" , filesetEntryIdName);
548+ auto filesetEntryIdType = Type::NamedType (view,
549+ view->DefineType (filesetEntryIdId, filesetEntryIdName,
550+ TypeBuilder::PointerType (4 , Type::IntegerType (1 , true ))
551+ .SetPointerBase (RelativeToVariableAddressPointerBaseType, -24 )
552+ .Finalize ()));
553+
502554 auto filesetEntryCommandType = BuildStruct (view, " fileset_entry_command" , false ,
503555 {
504556 // clang-format off
505557 {" cmd" , cmdTypeEnum},
506558 {" cmdsize" , Type::IntegerType (4 , false )},
507559 {" vmaddr" , Type::IntegerType (8 , false )},
508560 {" fileoff" , Type::IntegerType (8 , false )},
509- {" entry_id" , Type::IntegerType ( 4 , false ) },
561+ {" entry_id" , filesetEntryIdType },
510562 {" reserved" , Type::IntegerType (4 , false )}
511563 // clang-format on
512564 });
@@ -521,6 +573,103 @@ void CreateHeaderTypes(Ref<BinaryView> view)
521573 // The 'state' field is intentionally ignored.
522574 // clang-format off
523575 });
576+
577+ auto platformTypeEnum = BuildEnum (view, " macho_platform_t" , 4 ,
578+ {
579+ // clang-format off
580+ {" MACHO_PLATFORM_MACOS" , MACHO_PLATFORM_MACOS},
581+ {" MACHO_PLATFORM_IOS" , MACHO_PLATFORM_IOS},
582+ {" MACHO_PLATFORM_TVOS" , MACHO_PLATFORM_TVOS},
583+ {" MACHO_PLATFORM_WATCHOS" , MACHO_PLATFORM_WATCHOS},
584+ {" MACHO_PLATFORM_BRIDGEOS" , MACHO_PLATFORM_BRIDGEOS},
585+ {" MACHO_PLATFORM_MACCATALYST" , MACHO_PLATFORM_MACCATALYST},
586+ {" MACHO_PLATFORM_IOSSIMULATOR" , MACHO_PLATFORM_IOSSIMULATOR},
587+ {" MACHO_PLATFORM_TVOSSIMULATOR" , MACHO_PLATFORM_TVOSSIMULATOR},
588+ {" MACHO_PLATFORM_WATCHOSSIMULATOR" , MACHO_PLATFORM_WATCHOSSIMULATOR},
589+ {" MACHO_PLATFORM_DRIVERKIT" , MACHO_PLATFORM_DRIVERKIT},
590+ {" MACHO_PLATFORM_VISIONOS" , MACHO_PLATFORM_VISIONOS},
591+ {" MACHO_PLATFORM_VISIONOSSIMULATOR" , MACHO_PLATFORM_VISIONOSSIMULATOR},
592+ {" MACHO_PLATFORM_FIRMWARE" , MACHO_PLATFORM_FIRMWARE},
593+ {" MACHO_PLATFORM_SEPOS" , MACHO_PLATFORM_SEPOS},
594+ {" MACHO_PLATFORM_MACOS_EXCLAVECORE" , MACHO_PLATFORM_MACOS_EXCLAVECORE},
595+ {" MACHO_PLATFORM_MACOS_EXCLAVEKIT" , MACHO_PLATFORM_MACOS_EXCLAVEKIT},
596+ {" MACHO_PLATFORM_IOS_EXCLAVECORE" , MACHO_PLATFORM_IOS_EXCLAVECORE},
597+ {" MACHO_PLATFORM_IOS_EXCLAVEKIT" , MACHO_PLATFORM_IOS_EXCLAVEKIT},
598+ {" MACHO_PLATFORM_TVOS_EXCLAVECORE" , MACHO_PLATFORM_TVOS_EXCLAVECORE},
599+ {" MACHO_PLATFORM_TVOS_EXCLAVEKIT" , MACHO_PLATFORM_TVOS_EXCLAVEKIT},
600+ {" MACHO_PLATFORM_WATCHOS_EXCLAVECORE" , MACHO_PLATFORM_WATCHOS_EXCLAVECORE},
601+ {" MACHO_PLATFORM_WATCHOS_EXCLAVEKIT" , MACHO_PLATFORM_WATCHOS_EXCLAVEKIT},
602+ {" MACHO_PLATFORM_VISIONOS_EXCLAVECORE" , MACHO_PLATFORM_VISIONOS_EXCLAVECORE},
603+ {" MACHO_PLATFORM_VISIONOS_EXCLAVEKIT" , MACHO_PLATFORM_VISIONOS_EXCLAVEKIT}
604+ // clang-format on
605+ });
606+
607+ auto buildToolEnum = BuildEnum (view, " macho_build_tool_t" , 4 ,
608+ {
609+ // clang-format off
610+ {" MACHO_TOOL_CLANG" , MACHO_TOOL_CLANG},
611+ {" MACHO_TOOL_SWIFT" , MACHO_TOOL_SWIFT},
612+ {" MACHO_TOOL_LD" , MACHO_TOOL_LD},
613+ {" MACHO_TOOL_LLD" , MACHO_TOOL_LLD},
614+ {" MACHO_TOOL_METAL" , MACHO_TOOL_METAL},
615+ {" MACHO_TOOL_AIRLLD" , MACHO_TOOL_AIRLLD},
616+ {" MACHO_TOOL_AIRNT" , MACHO_TOOL_AIRNT},
617+ {" MACHO_TOOL_AIRNT_PLUGIN" , MACHO_TOOL_AIRNT_PLUGIN},
618+ {" MACHO_TOOL_AIRPACK" , MACHO_TOOL_AIRPACK},
619+ {" MACHO_TOOL_GPUARCHIVER" , MACHO_TOOL_GPUARCHIVER},
620+ {" MACHO_TOOL_METAL_FRAMEWORK" , MACHO_TOOL_METAL_FRAMEWORK},
621+ // clang-format on
622+ });
623+
624+ auto buildToolVersionType = BuildStruct (view, " build_tool_version" , false ,
625+ {
626+ // clang-format off
627+ {" tool" , buildToolEnum},
628+ {" version" , Type::IntegerType (4 , false )}
629+ // clang-format on
630+ });
631+
632+ auto buildVersionCommandType = BuildStruct (view, " build_version_command" , false ,
633+ {
634+ // clang-format off
635+ {" cmd" , cmdTypeEnum},
636+ {" cmdsize" , Type::IntegerType (4 , false )},
637+ {" platform" , platformTypeEnum},
638+ {" minos" , Type::IntegerType (4 , false )},
639+ {" sdk" , Type::IntegerType (4 , false )},
640+ {" ntools" , Type::IntegerType (4 , false )},
641+ {" tools" , Type::ArrayType (buildToolVersionType, 0 )}
642+ // clang-format on
643+ });
644+
645+ auto sourceVersionCommandType = BuildStruct (view, " source_version_command" , false ,
646+ {
647+ // clang-format off
648+ {" cmd" , cmdTypeEnum},
649+ {" cmdsize" , Type::IntegerType (4 , false )},
650+ {" version" , Type::IntegerType (8 , false )}
651+ // clang-format on
652+ });
653+
654+ auto entryPointCommandType = BuildStruct (view, " entry_point_command" , false ,
655+ {
656+ // clang-format off
657+ {" cmd" , cmdTypeEnum},
658+ {" cmdsize" , Type::IntegerType (4 , false )},
659+ {" entryoff" , Type::IntegerType (8 , false )},
660+ {" stacksize" , Type::IntegerType (8 , false )}
661+ // clang-format on
662+ });
663+
664+ // Used for the various LC_LOAD_* commands that have only a single string field.
665+ auto stringCommandType = BuildStruct (view, " string_command" , false ,
666+ {
667+ // clang-format off
668+ {" cmd" , cmdTypeEnum},
669+ {" cmdsize" , Type::IntegerType (4 , false )},
670+ {" value" , lcStringType}
671+ // clang-format on
672+ });
524673}
525674
526675void ApplyHeaderTypes (Ref<BinaryView> view, Ref<Logger> logger, const BinaryReader& incomingReader,
@@ -609,6 +758,9 @@ void ApplyHeaderTypes(Ref<BinaryView> view, Ref<Logger> logger, const BinaryRead
609758 case LC_DYLIB_CODE_SIGN_DRS:
610759 case LC_DYLD_EXPORTS_TRIE:
611760 case LC_DYLD_CHAINED_FIXUPS:
761+ case LC_ATOM_INFO:
762+ case LC_FUNCTION_VARIANTS:
763+ case LC_FUNCTION_VARIANT_FIXUPS:
612764 view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" linkedit_data_command" )));
613765 break ;
614766 case LC_ENCRYPTION_INFO:
@@ -623,8 +775,14 @@ void ApplyHeaderTypes(Ref<BinaryView> view, Ref<Logger> logger, const BinaryRead
623775 view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" dyld_info_command" )));
624776 break ;
625777 case LC_FILESET_ENTRY:
626- view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" fileset_entry_command" )));
778+ {
779+ auto type = Type::NamedType (view, QualifiedName (" fileset_entry_command" ));
780+ view->DefineDataVariable (cmdAddr, type);
781+ if (load.cmdsize - type->GetWidth () <= 150 )
782+ view->DefineDataVariable (cmdAddr + type->GetWidth (),
783+ Type::ArrayType (Type::IntegerType (1 , true ), load.cmdsize - type->GetWidth ()));
627784 break ;
785+ }
628786 case LC_UNIXTHREAD:
629787 {
630788 view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" unix_thread_command" )));
@@ -633,6 +791,40 @@ void ApplyHeaderTypes(Ref<BinaryView> view, Ref<Logger> logger, const BinaryRead
633791 view->DefineDataVariable (reader.GetOffset (), Type::ArrayType (Type::IntegerType (8 , true ), count));
634792 break ;
635793 }
794+ case LC_BUILD_VERSION:
795+ {
796+ view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" build_version_command" )));
797+ reader.SeekRelative (12 );
798+ uint32_t count = reader.Read32 ();
799+ view->DefineDataVariable (
800+ reader.GetOffset (), Type::ArrayType (Type::NamedType (view, QualifiedName (" build_tool_version" )), count));
801+ break ;
802+ }
803+ case LC_SOURCE_VERSION:
804+ view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" source_version_command" )));
805+ break ;
806+ case LC_MAIN:
807+ view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" entry_point_command" )));
808+ break ;
809+ case LC_DYLD_ENVIRONMENT:
810+ case LC_ID_DYLINKER:
811+ case LC_LOAD_DYLINKER:
812+ case LC_RPATH:
813+ case LC_SUB_CLIENT:
814+ case LC_SUB_FRAMEWORK:
815+ case LC_SUB_LIBRARY:
816+ case LC_SUB_UMBRELLA:
817+ case LC_TARGET_TRIPLE:
818+ {
819+ Ref<Type> type = Type::NamedType (view, QualifiedName (" string_command" ));
820+ view->DefineDataVariable (cmdAddr, type);
821+
822+ if (load.cmdsize - type->GetWidth () <= 150 )
823+ view->DefineDataVariable (cmdAddr + type->GetWidth (),
824+ Type::ArrayType (Type::IntegerType (1 , true ), load.cmdsize - type->GetWidth ()));
825+
826+ break ;
827+ }
636828 default :
637829 view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" load_command" )));
638830 break ;
0 commit comments