@@ -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