forked from Vector35/view-macho
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmachoview.h
1331 lines (1197 loc) · 43 KB
/
machoview.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#pragma once
#include <exception>
#include <vector>
#include <string.h>
#include "binaryninjaapi.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
//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)
//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_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"
//Symbol Types (N_TYPE)
#define N_UNDF 0x0
#define N_ABS 0x2
#define N_SECT 0xe
#define N_PBUD 0xc
#define N_INDR 0xa
#define N_ARM_THUMB_DEF 0x0008
/*
* 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 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