@@ -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,54 @@ 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_ZEROFILL" , S_ZEROFILL},
324+ {" S_CSTRING_LITERALS" , S_CSTRING_LITERALS},
325+ {" S_4BYTE_LITERALS" , S_4BYTE_LITERALS},
326+ {" S_8BYTE_LITERALS" , S_8BYTE_LITERALS},
327+ {" S_LITERAL_POINTERS" , S_LITERAL_POINTERS},
328+ {" S_NON_LAZY_SYMBOL_POINTERS" , S_NON_LAZY_SYMBOL_POINTERS},
329+ {" S_LAZY_SYMBOL_POINTERS" , S_LAZY_SYMBOL_POINTERS},
330+ {" S_SYMBOL_STUBS" , S_SYMBOL_STUBS},
331+ {" S_MOD_INIT_FUNC_POINTERS" , S_MOD_INIT_FUNC_POINTERS},
332+ {" S_MOD_TERM_FUNC_POINTERS" , S_MOD_TERM_FUNC_POINTERS},
333+ {" S_COALESCED" , S_COALESCED},
334+ {" S_GB_ZEROFILL" , S_GB_ZEROFILL},
335+ {" S_INTERPOSING" , S_INTERPOSING},
336+ {" S_16BYTE_LITERALS" , S_16BYTE_LITERALS},
337+ {" S_DTRACE_DOF" , S_DTRACE_DOF},
338+ {" S_LAZY_DYLIB_SYMBOL_POINTERS" , S_LAZY_DYLIB_SYMBOL_POINTERS},
339+ {" S_THREAD_LOCAL_REGULAR" , S_THREAD_LOCAL_REGULAR},
340+ {" S_THREAD_LOCAL_ZEROFILL" , S_THREAD_LOCAL_ZEROFILL},
341+ {" S_THREAD_LOCAL_VARIABLES" , S_THREAD_LOCAL_VARIABLES},
342+ {" S_THREAD_LOCAL_VARIABLE_POINTERS" , S_THREAD_LOCAL_VARIABLE_POINTERS},
343+ {" S_THREAD_LOCAL_INIT_FUNCTION_POINTERS" , S_THREAD_LOCAL_INIT_FUNCTION_POINTERS},
344+ {" S_INIT_FUNC_OFFSETS" , S_INIT_FUNC_OFFSETS},
345+ });
346+
347+ auto sectionAttributesSysEnum = BuildEnum (view, " section_attr_sys_t" , 1 ,
348+ {
349+ {" S_ATTR_DEBUG" , (S_ATTR_DEBUG >> 24 ) & 0xff },
350+ {" S_ATTR_SELF_MODIFYING_CODE" , (S_ATTR_SELF_MODIFYING_CODE >> 24 ) & 0xff },
351+ {" S_ATTR_LIVE_SUPPORT" , (S_ATTR_LIVE_SUPPORT >> 24 ) & 0xff },
352+ {" S_ATTR_NO_DEAD_STRIP" , (S_ATTR_NO_DEAD_STRIP >> 24 ) & 0xff },
353+ {" S_ATTR_STRIP_STATIC_SYMS" , (S_ATTR_STRIP_STATIC_SYMS >> 24 ) & 0xff },
354+ {" S_ATTR_NO_TOC" , (S_ATTR_NO_TOC >> 24 ) & 0xff },
355+ {" S_ATTR_PURE_INSTRUCTIONS" , (S_ATTR_PURE_INSTRUCTIONS >> 24 ) & 0xff },
356+ });
357+
358+ auto sectionAttributesUserEnum = BuildEnum (view, " section_attr_user_t" , 2 ,
359+ {
360+ {" S_ATTR_LOC_RELOC" , (S_ATTR_LOC_RELOC >> 8 ) & 0xffff },
361+ {" S_ATTR_EXT_RELOC" , (S_ATTR_EXT_RELOC >> 8 ) & 0xffff },
362+ {" S_ATTR_SOME_INSTRUCTIONS" , (S_ATTR_SOME_INSTRUCTIONS >> 8 ) & 0xffff },
363+ });
364+
316365 auto sectionType = BuildStruct (view, " section" , true ,
317366 {
318367 // clang-format off
@@ -324,7 +373,9 @@ void CreateHeaderTypes(Ref<BinaryView> view)
324373 {" align" , Type::IntegerType (4 , false )},
325374 {" reloff" , Type::IntegerType (4 , false )},
326375 {" nreloc" , Type::IntegerType (4 , false )},
327- {" flags" , Type::IntegerType (4 , false )},
376+ {" type" , sectionTypeEnum},
377+ {" attrs_user" , sectionAttributesUserEnum},
378+ {" attrs_sys" , sectionAttributesSysEnum},
328379 {" reserved1" , Type::IntegerType (4 , false )},
329380 {" reserved2" , Type::IntegerType (4 , false )}
330381 // clang-format on
@@ -341,7 +392,9 @@ void CreateHeaderTypes(Ref<BinaryView> view)
341392 {" align" , Type::IntegerType (4 , false )},
342393 {" reloff" , Type::IntegerType (4 , false )},
343394 {" nreloc" , Type::IntegerType (4 , false )},
344- {" flags" , Type::IntegerType (4 , false )},
395+ {" type" , sectionTypeEnum},
396+ {" attrs_user" , sectionAttributesUserEnum},
397+ {" attrs_sys" , sectionAttributesSysEnum},
345398 {" reserved1" , Type::IntegerType (4 , false )},
346399 {" reserved2" , Type::IntegerType (4 , false )},
347400 {" reserved3" , Type::IntegerType (4 , false )}
@@ -499,14 +552,22 @@ void CreateHeaderTypes(Ref<BinaryView> view)
499552 // clang-format on
500553 });
501554
555+ QualifiedName filesetEntryIdName (" fileset_entry_id" );
556+ std::string filesetEntryIdId = Type::GenerateAutoTypeId (" macho" , filesetEntryIdName);
557+ auto filesetEntryIdType = Type::NamedType (view,
558+ view->DefineType (filesetEntryIdId, filesetEntryIdName,
559+ TypeBuilder::PointerType (4 , Type::IntegerType (1 , true ))
560+ .SetPointerBase (RelativeToVariableAddressPointerBaseType, -24 )
561+ .Finalize ()));
562+
502563 auto filesetEntryCommandType = BuildStruct (view, " fileset_entry_command" , false ,
503564 {
504565 // clang-format off
505566 {" cmd" , cmdTypeEnum},
506567 {" cmdsize" , Type::IntegerType (4 , false )},
507568 {" vmaddr" , Type::IntegerType (8 , false )},
508569 {" fileoff" , Type::IntegerType (8 , false )},
509- {" entry_id" , Type::IntegerType ( 4 , false ) },
570+ {" entry_id" , filesetEntryIdType },
510571 {" reserved" , Type::IntegerType (4 , false )}
511572 // clang-format on
512573 });
@@ -521,6 +582,103 @@ void CreateHeaderTypes(Ref<BinaryView> view)
521582 // The 'state' field is intentionally ignored.
522583 // clang-format off
523584 });
585+
586+ auto platformTypeEnum = BuildEnum (view, " macho_platform_t" , 4 ,
587+ {
588+ // clang-format off
589+ {" MACHO_PLATFORM_MACOS" , MACHO_PLATFORM_MACOS},
590+ {" MACHO_PLATFORM_IOS" , MACHO_PLATFORM_IOS},
591+ {" MACHO_PLATFORM_TVOS" , MACHO_PLATFORM_TVOS},
592+ {" MACHO_PLATFORM_WATCHOS" , MACHO_PLATFORM_WATCHOS},
593+ {" MACHO_PLATFORM_BRIDGEOS" , MACHO_PLATFORM_BRIDGEOS},
594+ {" MACHO_PLATFORM_MACCATALYST" , MACHO_PLATFORM_MACCATALYST},
595+ {" MACHO_PLATFORM_IOSSIMULATOR" , MACHO_PLATFORM_IOSSIMULATOR},
596+ {" MACHO_PLATFORM_TVOSSIMULATOR" , MACHO_PLATFORM_TVOSSIMULATOR},
597+ {" MACHO_PLATFORM_WATCHOSSIMULATOR" , MACHO_PLATFORM_WATCHOSSIMULATOR},
598+ {" MACHO_PLATFORM_DRIVERKIT" , MACHO_PLATFORM_DRIVERKIT},
599+ {" MACHO_PLATFORM_VISIONOS" , MACHO_PLATFORM_VISIONOS},
600+ {" MACHO_PLATFORM_VISIONOSSIMULATOR" , MACHO_PLATFORM_VISIONOSSIMULATOR},
601+ {" MACHO_PLATFORM_FIRMWARE" , MACHO_PLATFORM_FIRMWARE},
602+ {" MACHO_PLATFORM_SEPOS" , MACHO_PLATFORM_SEPOS},
603+ {" MACHO_PLATFORM_MACOS_EXCLAVECORE" , MACHO_PLATFORM_MACOS_EXCLAVECORE},
604+ {" MACHO_PLATFORM_MACOS_EXCLAVEKIT" , MACHO_PLATFORM_MACOS_EXCLAVEKIT},
605+ {" MACHO_PLATFORM_IOS_EXCLAVECORE" , MACHO_PLATFORM_IOS_EXCLAVECORE},
606+ {" MACHO_PLATFORM_IOS_EXCLAVEKIT" , MACHO_PLATFORM_IOS_EXCLAVEKIT},
607+ {" MACHO_PLATFORM_TVOS_EXCLAVECORE" , MACHO_PLATFORM_TVOS_EXCLAVECORE},
608+ {" MACHO_PLATFORM_TVOS_EXCLAVEKIT" , MACHO_PLATFORM_TVOS_EXCLAVEKIT},
609+ {" MACHO_PLATFORM_WATCHOS_EXCLAVECORE" , MACHO_PLATFORM_WATCHOS_EXCLAVECORE},
610+ {" MACHO_PLATFORM_WATCHOS_EXCLAVEKIT" , MACHO_PLATFORM_WATCHOS_EXCLAVEKIT},
611+ {" MACHO_PLATFORM_VISIONOS_EXCLAVECORE" , MACHO_PLATFORM_VISIONOS_EXCLAVECORE},
612+ {" MACHO_PLATFORM_VISIONOS_EXCLAVEKIT" , MACHO_PLATFORM_VISIONOS_EXCLAVEKIT}
613+ // clang-format on
614+ });
615+
616+ auto buildToolEnum = BuildEnum (view, " macho_build_tool_t" , 4 ,
617+ {
618+ // clang-format off
619+ {" MACHO_TOOL_CLANG" , MACHO_TOOL_CLANG},
620+ {" MACHO_TOOL_SWIFT" , MACHO_TOOL_SWIFT},
621+ {" MACHO_TOOL_LD" , MACHO_TOOL_LD},
622+ {" MACHO_TOOL_LLD" , MACHO_TOOL_LLD},
623+ {" MACHO_TOOL_METAL" , MACHO_TOOL_METAL},
624+ {" MACHO_TOOL_AIRLLD" , MACHO_TOOL_AIRLLD},
625+ {" MACHO_TOOL_AIRNT" , MACHO_TOOL_AIRNT},
626+ {" MACHO_TOOL_AIRNT_PLUGIN" , MACHO_TOOL_AIRNT_PLUGIN},
627+ {" MACHO_TOOL_AIRPACK" , MACHO_TOOL_AIRPACK},
628+ {" MACHO_TOOL_GPUARCHIVER" , MACHO_TOOL_GPUARCHIVER},
629+ {" MACHO_TOOL_METAL_FRAMEWORK" , MACHO_TOOL_METAL_FRAMEWORK},
630+ // clang-format on
631+ });
632+
633+ auto buildToolVersionType = BuildStruct (view, " build_tool_version" , false ,
634+ {
635+ // clang-format off
636+ {" tool" , buildToolEnum},
637+ {" version" , Type::IntegerType (4 , false )}
638+ // clang-format on
639+ });
640+
641+ auto buildVersionCommandType = BuildStruct (view, " build_version_command" , false ,
642+ {
643+ // clang-format off
644+ {" cmd" , cmdTypeEnum},
645+ {" cmdsize" , Type::IntegerType (4 , false )},
646+ {" platform" , platformTypeEnum},
647+ {" minos" , Type::IntegerType (4 , false )},
648+ {" sdk" , Type::IntegerType (4 , false )},
649+ {" ntools" , Type::IntegerType (4 , false )},
650+ {" tools" , Type::ArrayType (buildToolVersionType, 0 )}
651+ // clang-format on
652+ });
653+
654+ auto sourceVersionCommandType = BuildStruct (view, " source_version_command" , false ,
655+ {
656+ // clang-format off
657+ {" cmd" , cmdTypeEnum},
658+ {" cmdsize" , Type::IntegerType (4 , false )},
659+ {" version" , Type::IntegerType (8 , false )}
660+ // clang-format on
661+ });
662+
663+ auto entryPointCommandType = BuildStruct (view, " entry_point_command" , false ,
664+ {
665+ // clang-format off
666+ {" cmd" , cmdTypeEnum},
667+ {" cmdsize" , Type::IntegerType (4 , false )},
668+ {" entryoff" , Type::IntegerType (8 , false )},
669+ {" stacksize" , Type::IntegerType (8 , false )}
670+ // clang-format on
671+ });
672+
673+ // Used for the various LC_LOAD_* commands that have only a single string field.
674+ auto stringCommandType = BuildStruct (view, " string_command" , false ,
675+ {
676+ // clang-format off
677+ {" cmd" , cmdTypeEnum},
678+ {" cmdsize" , Type::IntegerType (4 , false )},
679+ {" value" , lcStringType}
680+ // clang-format on
681+ });
524682}
525683
526684void ApplyHeaderTypes (Ref<BinaryView> view, Ref<Logger> logger, const BinaryReader& incomingReader,
@@ -609,6 +767,9 @@ void ApplyHeaderTypes(Ref<BinaryView> view, Ref<Logger> logger, const BinaryRead
609767 case LC_DYLIB_CODE_SIGN_DRS:
610768 case LC_DYLD_EXPORTS_TRIE:
611769 case LC_DYLD_CHAINED_FIXUPS:
770+ case LC_ATOM_INFO:
771+ case LC_FUNCTION_VARIANTS:
772+ case LC_FUNCTION_VARIANT_FIXUPS:
612773 view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" linkedit_data_command" )));
613774 break ;
614775 case LC_ENCRYPTION_INFO:
@@ -623,8 +784,14 @@ void ApplyHeaderTypes(Ref<BinaryView> view, Ref<Logger> logger, const BinaryRead
623784 view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" dyld_info_command" )));
624785 break ;
625786 case LC_FILESET_ENTRY:
626- view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" fileset_entry_command" )));
787+ {
788+ auto type = Type::NamedType (view, QualifiedName (" fileset_entry_command" ));
789+ view->DefineDataVariable (cmdAddr, type);
790+ if (load.cmdsize - type->GetWidth () <= 150 )
791+ view->DefineDataVariable (cmdAddr + type->GetWidth (),
792+ Type::ArrayType (Type::IntegerType (1 , true ), load.cmdsize - type->GetWidth ()));
627793 break ;
794+ }
628795 case LC_UNIXTHREAD:
629796 {
630797 view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" unix_thread_command" )));
@@ -633,6 +800,40 @@ void ApplyHeaderTypes(Ref<BinaryView> view, Ref<Logger> logger, const BinaryRead
633800 view->DefineDataVariable (reader.GetOffset (), Type::ArrayType (Type::IntegerType (8 , true ), count));
634801 break ;
635802 }
803+ case LC_BUILD_VERSION:
804+ {
805+ view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" build_version_command" )));
806+ reader.SeekRelative (12 );
807+ uint32_t count = reader.Read32 ();
808+ view->DefineDataVariable (
809+ reader.GetOffset (), Type::ArrayType (Type::NamedType (view, QualifiedName (" build_tool_version" )), count));
810+ break ;
811+ }
812+ case LC_SOURCE_VERSION:
813+ view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" source_version_command" )));
814+ break ;
815+ case LC_MAIN:
816+ view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" entry_point_command" )));
817+ break ;
818+ case LC_DYLD_ENVIRONMENT:
819+ case LC_ID_DYLINKER:
820+ case LC_LOAD_DYLINKER:
821+ case LC_RPATH:
822+ case LC_SUB_CLIENT:
823+ case LC_SUB_FRAMEWORK:
824+ case LC_SUB_LIBRARY:
825+ case LC_SUB_UMBRELLA:
826+ case LC_TARGET_TRIPLE:
827+ {
828+ Ref<Type> type = Type::NamedType (view, QualifiedName (" string_command" ));
829+ view->DefineDataVariable (cmdAddr, type);
830+
831+ if (load.cmdsize - type->GetWidth () <= 150 )
832+ view->DefineDataVariable (cmdAddr + type->GetWidth (),
833+ Type::ArrayType (Type::IntegerType (1 , true ), load.cmdsize - type->GetWidth ()));
834+
835+ break ;
836+ }
636837 default :
637838 view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" load_command" )));
638839 break ;
0 commit comments