@@ -275,7 +275,8 @@ void CreateHeaderTypes(Ref<BinaryView> view)
275
275
{" SG_HIGHVM" , SG_HIGHVM},
276
276
{" SG_FVMLIB" , SG_FVMLIB},
277
277
{" 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},
279
280
// clang-format on
280
281
});
281
282
@@ -313,6 +314,45 @@ void CreateHeaderTypes(Ref<BinaryView> view)
313
314
// clang-format on
314
315
});
315
316
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
+
316
356
auto sectionType = BuildStruct (view, " section" , true ,
317
357
{
318
358
// clang-format off
@@ -324,7 +364,9 @@ void CreateHeaderTypes(Ref<BinaryView> view)
324
364
{" align" , Type::IntegerType (4 , false )},
325
365
{" reloff" , Type::IntegerType (4 , false )},
326
366
{" nreloc" , Type::IntegerType (4 , false )},
327
- {" flags" , Type::IntegerType (4 , false )},
367
+ {" type" , sectionTypeEnum},
368
+ {" attrs_user" , sectionAttributesUserEnum},
369
+ {" attrs_sys" , sectionAttributesSysEnum},
328
370
{" reserved1" , Type::IntegerType (4 , false )},
329
371
{" reserved2" , Type::IntegerType (4 , false )}
330
372
// clang-format on
@@ -341,7 +383,9 @@ void CreateHeaderTypes(Ref<BinaryView> view)
341
383
{" align" , Type::IntegerType (4 , false )},
342
384
{" reloff" , Type::IntegerType (4 , false )},
343
385
{" nreloc" , Type::IntegerType (4 , false )},
344
- {" flags" , Type::IntegerType (4 , false )},
386
+ {" type" , sectionTypeEnum},
387
+ {" attrs_user" , sectionAttributesUserEnum},
388
+ {" attrs_sys" , sectionAttributesSysEnum},
345
389
{" reserved1" , Type::IntegerType (4 , false )},
346
390
{" reserved2" , Type::IntegerType (4 , false )},
347
391
{" reserved3" , Type::IntegerType (4 , false )}
@@ -499,14 +543,22 @@ void CreateHeaderTypes(Ref<BinaryView> view)
499
543
// clang-format on
500
544
});
501
545
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
+
502
554
auto filesetEntryCommandType = BuildStruct (view, " fileset_entry_command" , false ,
503
555
{
504
556
// clang-format off
505
557
{" cmd" , cmdTypeEnum},
506
558
{" cmdsize" , Type::IntegerType (4 , false )},
507
559
{" vmaddr" , Type::IntegerType (8 , false )},
508
560
{" fileoff" , Type::IntegerType (8 , false )},
509
- {" entry_id" , Type::IntegerType ( 4 , false ) },
561
+ {" entry_id" , filesetEntryIdType },
510
562
{" reserved" , Type::IntegerType (4 , false )}
511
563
// clang-format on
512
564
});
@@ -521,6 +573,103 @@ void CreateHeaderTypes(Ref<BinaryView> view)
521
573
// The 'state' field is intentionally ignored.
522
574
// clang-format off
523
575
});
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
+ });
524
673
}
525
674
526
675
void ApplyHeaderTypes (Ref<BinaryView> view, Ref<Logger> logger, const BinaryReader& incomingReader,
@@ -609,6 +758,9 @@ void ApplyHeaderTypes(Ref<BinaryView> view, Ref<Logger> logger, const BinaryRead
609
758
case LC_DYLIB_CODE_SIGN_DRS:
610
759
case LC_DYLD_EXPORTS_TRIE:
611
760
case LC_DYLD_CHAINED_FIXUPS:
761
+ case LC_ATOM_INFO:
762
+ case LC_FUNCTION_VARIANTS:
763
+ case LC_FUNCTION_VARIANT_FIXUPS:
612
764
view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" linkedit_data_command" )));
613
765
break ;
614
766
case LC_ENCRYPTION_INFO:
@@ -623,8 +775,14 @@ void ApplyHeaderTypes(Ref<BinaryView> view, Ref<Logger> logger, const BinaryRead
623
775
view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" dyld_info_command" )));
624
776
break ;
625
777
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 ()));
627
784
break ;
785
+ }
628
786
case LC_UNIXTHREAD:
629
787
{
630
788
view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" unix_thread_command" )));
@@ -633,6 +791,40 @@ void ApplyHeaderTypes(Ref<BinaryView> view, Ref<Logger> logger, const BinaryRead
633
791
view->DefineDataVariable (reader.GetOffset (), Type::ArrayType (Type::IntegerType (8 , true ), count));
634
792
break ;
635
793
}
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
+ }
636
828
default :
637
829
view->DefineDataVariable (cmdAddr, Type::NamedType (view, QualifiedName (" load_command" )));
638
830
break ;
0 commit comments