1use crate::error;
4use core::convert::TryFrom;
5use core::fmt::{self, Display};
6use scroll::{ctx, Endian};
7use scroll::{IOread, IOwrite, Pread, Pwrite, SizeWith};
8
9#[repr(C)]
15#[derive(Debug, Clone, Copy, Pread, Pwrite, SizeWith)]
16pub struct LoadCommandHeader {
18 pub cmd: u32,
19 pub cmdsize: u32,
20}
21
22impl Display for LoadCommandHeader {
23 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
24 write!(
25 fmt,
26 "LoadCommandHeader: {} size: {}",
27 cmd_to_str(self.cmd),
28 self.cmdsize
29 )
30 }
31}
32
33pub const SIZEOF_LOAD_COMMAND: usize = 8;
34
35pub type LcStr = u32;
36
37pub const SIZEOF_LC_STR: usize = 4;
38
39#[repr(C)]
40#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
41pub struct Section32 {
42 pub sectname: [u8; 16],
44 pub segname: [u8; 16],
46 pub addr: u32,
48 pub size: u32,
50 pub offset: u32,
52 pub align: u32,
54 pub reloff: u32,
56 pub nreloc: u32,
58 pub flags: u32,
60 pub reserved1: u32,
62 pub reserved2: u32,
64}
65
66pub const SIZEOF_SECTION_32: usize = 68;
67
68#[repr(C)]
70#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
71pub struct Section64 {
72 pub sectname: [u8; 16],
74 pub segname: [u8; 16],
76 pub addr: u64,
78 pub size: u64,
80 pub offset: u32,
82 pub align: u32,
84 pub reloff: u32,
86 pub nreloc: u32,
88 pub flags: u32,
90 pub reserved1: u32,
92 pub reserved2: u32,
94 pub reserved3: u32,
96}
97
98pub const SIZEOF_SECTION_64: usize = 80;
99
100#[repr(C)]
101#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
102pub struct SegmentCommand32 {
103 pub cmd: u32,
104 pub cmdsize: u32,
105 pub segname: [u8; 16],
106 pub vmaddr: u32,
107 pub vmsize: u32,
108 pub fileoff: u32,
109 pub filesize: u32,
110 pub maxprot: u32,
111 pub initprot: u32,
112 pub nsects: u32,
113 pub flags: u32,
114}
115
116pub const SIZEOF_SEGMENT_COMMAND_32: usize = 56;
117
118impl SegmentCommand32 {
119 pub fn name(&self) -> error::Result<&str> {
120 Ok(self.segname.pread::<&str>(0)?)
121 }
122}
123
124#[repr(C)]
125#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
126pub struct SegmentCommand64 {
127 pub cmd: u32,
128 pub cmdsize: u32,
129 pub segname: [u8; 16],
130 pub vmaddr: u64,
131 pub vmsize: u64,
132 pub fileoff: u64,
133 pub filesize: u64,
134 pub maxprot: u32,
135 pub initprot: u32,
136 pub nsects: u32,
137 pub flags: u32,
138}
139
140pub const SIZEOF_SEGMENT_COMMAND_64: usize = 72;
141
142impl SegmentCommand64 {
143 pub fn name(&self) -> error::Result<&str> {
144 Ok(self.segname.pread::<&str>(0)?)
145 }
146}
147#[repr(C)]
152#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
153pub struct Fvmlib {
154 pub name: u32,
156 pub minor_version: u32,
158 pub header_addr: u32,
160}
161
162pub const SIZEOF_FVMLIB: usize = 12;
163
164#[repr(C)]
170#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
171pub struct FvmlibCommand {
172 pub cmd: u32,
174 pub cmdsize: u32,
176 pub fvmlib: Fvmlib,
178}
179
180pub const SIZEOF_FVMLIB_COMMAND: usize = 20;
181
182#[repr(C)]
202#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
203pub struct Dylib {
204 pub name: LcStr,
206 pub timestamp: u32,
208 pub current_version: u32,
210 pub compatibility_version: u32,
212}
213
214pub const SIZEOF_DYLIB: usize = 16;
215
216#[repr(C)]
217#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
218pub struct DylibCommand {
219 pub cmd: u32,
221 pub cmdsize: u32,
223 pub dylib: Dylib,
225}
226
227pub const SIZEOF_DYLIB_COMMAND: usize = 20;
228
229#[repr(C)]
238#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
239pub struct SubFrameworkCommand {
240 pub cmd: u32,
242 pub cmdsize: u32,
244 pub umbrella: u32,
246}
247
248pub const SIZEOF_SUB_FRAMEWORK_COMMAND: usize = 12;
249
250#[repr(C)]
258#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
259pub struct SubClientCommand {
260 pub cmd: u32,
262 pub cmdsize: u32,
264 pub client: LcStr,
266}
267
268pub const SIZEOF_SUB_CLIENT_COMMAND: usize = 12;
269
270#[repr(C)]
282#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
283pub struct SubUmbrellaCommand {
284 pub cmd: u32,
286 pub cmdsize: u32,
288 pub sub_umbrella: LcStr,
290}
291
292pub const SIZEOF_SUB_UMBRELLA_COMMAND: usize = 12;
293
294#[repr(C)]
308#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
309pub struct SubLibraryCommand {
310 pub cmd: u32,
312 pub cmdsize: u32,
314 pub sub_library: LcStr,
316}
317
318pub const SIZEOF_SUB_LIBRARY_COMMAND: usize = 12;
319
320#[repr(C)]
328#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
329pub struct PreboundDylibCommand {
330 pub cmd: u32,
332 pub cmdsize: u32,
334 pub name: LcStr,
336 pub nmodules: u32,
338 pub linked_modules: LcStr,
341}
342
343pub const SIZEOF_PREBOUND_DYLIB_COMMAND: usize = 20;
344
345#[repr(C)]
347#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
348pub struct DylinkerCommand {
349 pub cmd: u32,
350 pub cmdsize: u32,
351 pub name: LcStr,
352}
353
354pub const SIZEOF_DYLINKER_COMMAND: usize = 12;
355
356#[repr(C)]
381#[derive(Copy)]
382pub struct ThreadCommand {
383 pub cmd: u32,
385 pub cmdsize: u32,
387
388 pub flavor: u32,
390
391 pub count: u32,
393
394 pub thread_state: [u32; 70],
396}
397
398impl ThreadCommand {
399 pub fn instruction_pointer(&self, cputype: super::cputype::CpuType) -> error::Result<u64> {
400 match cputype {
408 super::cputype::CPU_TYPE_X86 => {
409 let eip: u32 = self.thread_state[10];
428 Ok(u64::from(eip))
429 }
430 super::cputype::CPU_TYPE_X86_64 => {
431 let rip: u64 =
455 (u64::from(self.thread_state[32])) | ((u64::from(self.thread_state[33])) << 32);
456 Ok(rip)
457 }
458 super::cputype::CPU_TYPE_ARM => {
459 let pc: u32 = self.thread_state[15];
467 Ok(u64::from(pc))
468 }
469 super::cputype::CPU_TYPE_ARM64 | super::cputype::CPU_TYPE_ARM64_32 => {
470 let pc: u64 =
480 (u64::from(self.thread_state[64])) | ((u64::from(self.thread_state[65])) << 32);
481 Ok(pc)
482 }
483 super::cputype::CPU_TYPE_POWERPC => Ok(u64::from(self.thread_state[0])),
486 _ => Err(error::Error::Malformed(format!(
494 "unable to find instruction pointer for cputype {:?}",
495 cputype
496 ))),
497 }
498 }
499}
500
501impl<'a> ctx::TryFromCtx<'a, Endian> for ThreadCommand {
502 type Error = crate::error::Error;
503 fn try_from_ctx(bytes: &'a [u8], le: Endian) -> error::Result<(Self, usize)> {
504 let lc = bytes.pread_with::<LoadCommandHeader>(0, le)?;
505
506 let flavor: u32 = bytes.pread_with(8, le)?;
508 let count: u32 = bytes.pread_with(12, le)?;
509
510 if count > 70 {
511 return Err(error::Error::Malformed(format!(
512 "thread command specifies {} longs for thread state but we handle only 70",
513 count
514 )));
515 }
516
517 let thread_state_byte_length = count as usize * 4;
519
520 if bytes.len() < 16 + thread_state_byte_length {
522 return Err(error::Error::Malformed(format!(
523 "thread command specifies {} bytes for thread state but has only {}",
524 thread_state_byte_length,
525 bytes.len()
526 )));
527 }
528
529 let thread_state_bytes = &bytes[16..16 + thread_state_byte_length];
530
531 let mut thread_state: [u32; 70] = [0; 70];
533 for (i, state) in thread_state.iter_mut().enumerate().take(count as usize) {
534 *state = thread_state_bytes.pread_with(i * 4, le)?;
535 }
536
537 Ok((
538 ThreadCommand {
539 cmd: lc.cmd,
540 cmdsize: lc.cmdsize,
541 flavor,
542 count,
543 thread_state,
544 },
545 lc.cmdsize as _,
546 ))
547 }
548}
549
550impl Clone for ThreadCommand {
551 fn clone(&self) -> Self {
552 *self
553 }
554}
555
556impl fmt::Debug for ThreadCommand {
557 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
558 fmt.debug_struct("ThreadCommand")
559 .field("cmd", &self.cmd)
560 .field("cmdsize", &self.cmdsize)
561 .field("flavor", &self.flavor)
562 .field("count", &self.count)
563 .field("thread_state", &&self.thread_state[..])
564 .finish()
565 }
566}
567
568#[repr(C)]
575#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
576pub struct RoutinesCommand32 {
577 pub cmd: u32,
579 pub cmdsize: u32,
581 pub init_address: u32,
583 pub init_module: u32,
585 pub reserved1: u32,
586 pub reserved2: u32,
587 pub reserved3: u32,
588 pub reserved4: u32,
589 pub reserved5: u32,
590 pub reserved6: u32,
591}
592
593#[repr(C)]
595#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
596pub struct RoutinesCommand64 {
597 pub cmd: u32,
599 pub cmdsize: u32,
601 pub init_address: u64,
603 pub init_module: u64,
605 pub reserved1: u64,
606 pub reserved2: u64,
607 pub reserved3: u64,
608 pub reserved4: u64,
609 pub reserved5: u64,
610 pub reserved6: u64,
611}
612
613#[repr(C)]
614#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
615pub struct SymtabCommand {
616 pub cmd: u32,
617 pub cmdsize: u32,
618 pub symoff: u32,
619 pub nsyms: u32,
620 pub stroff: u32,
621 pub strsize: u32,
622}
623
624impl Default for SymtabCommand {
625 fn default() -> Self {
626 SymtabCommand {
627 cmd: LC_SYMTAB,
628 cmdsize: SIZEOF_SYMTAB_COMMAND as u32,
629 symoff: 0,
630 nsyms: 0,
631 stroff: 0,
632 strsize: 0,
633 }
634 }
635}
636
637impl SymtabCommand {
638 pub fn new() -> Self {
639 Default::default()
640 }
641}
642
643pub const SIZEOF_SYMTAB_COMMAND: usize = 24;
644
645#[repr(C)]
684#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
685pub struct DysymtabCommand {
686 pub cmd: u32,
687 pub cmdsize: u32,
688 pub ilocalsym: u32,
690 pub nlocalsym: u32,
692 pub iextdefsym: u32,
694 pub nextdefsym: u32,
696 pub iundefsym: u32,
698 pub nundefsym: u32,
700 pub tocoff: u32,
702 pub ntoc: u32,
704 pub modtaboff: u32,
706 pub nmodtab: u32,
708 pub extrefsymoff: u32,
710 pub nextrefsyms: u32,
712 pub indirectsymoff: u32,
714 pub nindirectsyms: u32,
716 pub extreloff: u32,
718 pub nextrel: u32,
720 pub locreloff: u32,
722 pub nlocrel: u32,
724}
725
726impl Default for DysymtabCommand {
727 fn default() -> Self {
728 DysymtabCommand {
729 cmd: LC_DYSYMTAB,
730 cmdsize: SIZEOF_DYSYMTAB_COMMAND as u32,
731 ilocalsym: 0,
732 nlocalsym: 0,
733 iextdefsym: 0,
734 nextdefsym: 0,
735 iundefsym: 0,
736 nundefsym: 0,
737 tocoff: 0,
738 ntoc: 0,
739 modtaboff: 0,
740 nmodtab: 0,
741 extrefsymoff: 0,
742 nextrefsyms: 0,
743 indirectsymoff: 0,
744 nindirectsyms: 0,
745 extreloff: 0,
746 nextrel: 0,
747 locreloff: 0,
748 nlocrel: 0,
749 }
750 }
751}
752
753impl DysymtabCommand {
754 pub fn new() -> Self {
755 Default::default()
756 }
757}
758
759pub const SIZEOF_DYSYMTAB_COMMAND: usize = 80;
760
761#[repr(C)]
764#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
765pub struct DylibTableOfContents {
766 pub symbol_index: u32,
768 pub module_index: u32,
770}
771
772#[repr(C)]
775#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
776pub struct DylibModule {
777 pub module_name: u32,
779 pub iextdefsym: u32,
781 pub nextdefsym: u32,
783 pub irefsym: u32,
785 pub nrefsym: u32,
787 pub ilocalsym: u32,
789 pub nlocalsym: u32,
791
792 pub iextrel: u32,
794 pub nextrel: u32,
796
797 pub iinit_iterm: u32,
799 pub ninit_nterm: u32,
801 pub objc_module_info_addr: u32,
803 pub objc_module_info_size: u32,
805}
806
807#[repr(C)]
810#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
811pub struct DylibModule64 {
812 pub module_name: u32,
814
815 pub iextdefsym: u32,
817 pub nextdefsym: u32,
819 pub irefsym: u32,
821 pub nrefsym: u32,
823 pub ilocalsym: u32,
825 pub nlocalsym: u32,
827
828 pub iextrel: u32,
830 pub nextrel: u32,
832
833 pub iinit_iterm: u32,
835 pub ninit_nterm: u32,
837
838 pub objc_module_info_size: u32,
840 pub objc_module_info_addr: u64,
842}
843
844#[repr(C)]
851#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
852pub struct DylibReference {
853 pub isym: [u8; 24],
855 pub flags: u64,
857}
858
859#[repr(C)]
862#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
863pub struct TwolevelHintsCommand {
864 pub cmd: u32,
866 pub cmdsize: u32,
868 pub offset: u32,
870 pub nhints: u32,
872}
873
874#[repr(C)]
889#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
890pub struct TwolevelHint {
891 pub isub_image: u64,
893 pub itoc: [u8; 24],
895}
896
897#[repr(C)]
907#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
908pub struct PrebindCksumCommand {
909 pub cmd: u32,
911 pub cmdsize: u32,
913 pub cksum: u32,
915}
916
917#[repr(C)]
920#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
921pub struct UuidCommand {
922 pub cmd: u32,
924 pub cmdsize: u32,
926 pub uuid: [u8; 16],
928}
929
930pub const SIZEOF_UUID_COMMAND: usize = 24;
931
932#[repr(C)]
935#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
936pub struct RpathCommand {
937 pub cmd: u32,
939 pub cmdsize: u32,
941 pub path: LcStr,
943}
944
945pub const SIZEOF_RPATH_COMMAND: usize = 12;
946
947#[repr(C)]
950#[derive(Default, Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
951pub struct LinkeditDataCommand {
952 pub cmd: u32,
955 pub cmdsize: u32,
957 pub dataoff: u32,
959 pub datasize: u32,
961}
962
963pub const SIZEOF_LINKEDIT_DATA_COMMAND: usize = 16;
964
965#[repr(C)]
968#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
969pub struct EncryptionInfoCommand32 {
970 pub cmd: u32,
972 pub cmdsize: u32,
974 pub cryptoff: u32,
976 pub cryptsize: u32,
978 pub cryptid: u32,
980}
981
982pub const SIZEOF_ENCRYPTION_INFO_COMMAND_32: usize = 20;
983
984#[repr(C)]
987#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
988pub struct EncryptionInfoCommand64 {
989 pub cmd: u32,
991 pub cmdsize: u32,
993 pub cryptoff: u32,
995 pub cryptsize: u32,
997 pub cryptid: u32,
999 pub pad: u32,
1001}
1002
1003pub const SIZEOF_ENCRYPTION_INFO_COMMAND_64: usize = 24;
1004
1005#[non_exhaustive]
1007#[repr(u32)]
1008#[derive(Debug)]
1009pub enum Platform {
1010 Macos = LC_VERSION_MIN_MACOSX,
1011 Iphoneos = LC_VERSION_MIN_IPHONEOS,
1012 Tvos = LC_VERSION_MIN_TVOS,
1013 Watchos = LC_VERSION_MIN_WATCHOS,
1014}
1015
1016impl TryFrom<u32> for Platform {
1017 type Error = error::Error;
1018
1019 fn try_from(cmd: u32) -> Result<Self, Self::Error> {
1020 Ok(match cmd {
1021 LC_VERSION_MIN_MACOSX => Platform::Macos,
1022 LC_VERSION_MIN_IPHONEOS => Platform::Iphoneos,
1023 LC_VERSION_MIN_TVOS => Platform::Tvos,
1024 LC_VERSION_MIN_WATCHOS => Platform::Watchos,
1025 _ => {
1026 return Err(error::Error::Malformed(format!(
1027 "unknown platform for load command: {:x}",
1028 cmd
1029 )))
1030 }
1031 })
1032 }
1033}
1034
1035#[repr(C)]
1039#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1040pub struct VersionMinCommand {
1041 pub cmd: u32,
1043 pub cmdsize: u32,
1044 pub version: u32,
1046 pub sdk: u32,
1048}
1049
1050impl VersionMinCommand {
1051 pub fn new(platform: Platform) -> Self {
1052 VersionMinCommand {
1053 cmd: platform as u32,
1054 cmdsize: SIZEOF_VERSION_MIN_COMMAND as u32,
1055 version: 0,
1056 sdk: 0,
1057 }
1058 }
1059
1060 pub fn platform(&self) -> Platform {
1061 Platform::try_from(self.cmd).expect("impossible platform (implementation error)")
1066 }
1067}
1068
1069pub const SIZEOF_VERSION_MIN_COMMAND: usize = 16;
1070
1071#[repr(C)]
1072#[derive(Default, Debug, Clone, Copy, Pread, Pwrite, SizeWith)]
1073pub struct DyldInfoCommand {
1074 pub cmd: u32,
1076 pub cmdsize: u32,
1078 pub rebase_off: u32,
1080 pub rebase_size: u32,
1082 pub bind_off: u32,
1084 pub bind_size: u32,
1086 pub weak_bind_off: u32,
1088 pub weak_bind_size: u32,
1090 pub lazy_bind_off: u32,
1092 pub lazy_bind_size: u32,
1094 pub export_off: u32,
1096 pub export_size: u32,
1098}
1099
1100pub const SIZEOF_DYLIB_INFO_COMMAND: usize = 48;
1101
1102#[repr(C)]
1104#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1105pub struct LinkerOptionCommand {
1106 pub cmd: u32,
1108 pub cmdsize: u32,
1109 pub count: u32,
1111}
1112
1113pub const SIZEOF_LINKER_OPTION_COMMAND: usize = 12;
1114
1115#[repr(C)]
1123#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1124pub struct SymsegCommand {
1125 pub cmd: u32,
1127 pub cmdsize: u32,
1129 pub offset: u32,
1131 pub size: u32,
1133}
1134
1135pub const SIZEOF_SYMSEG_COMMAND: usize = 16;
1136
1137#[repr(C)]
1142#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1143pub struct IdentCommand {
1144 pub cmd: u32,
1146 pub cmdsize: u32,
1148}
1149
1150pub const SIZEOF_IDENT_COMMAND: usize = 8;
1151
1152#[repr(C)]
1157#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1158pub struct FvmfileCommand {
1159 pub cmd: u32,
1161 pub cmdsize: u32,
1163 pub name: LcStr,
1165 pub header_addr: u32,
1167}
1168
1169pub const SIZEOF_FVMFILE_COMMAND: usize = 16;
1170
1171#[repr(C)]
1176#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1177pub struct EntryPointCommand {
1178 pub cmd: u32,
1179 pub cmdsize: u32,
1180 pub entryoff: u64,
1182 pub stacksize: u64,
1184}
1185
1186pub const SIZEOF_ENTRY_POINT_COMMAND: usize = 24;
1187
1188#[repr(C)]
1192#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1193pub struct BuildVersionCommand {
1194 pub cmd: u32,
1196 pub cmdsize: u32,
1197 pub platform: u32,
1199 pub minos: u32,
1201 pub sdk: u32,
1203 pub ntools: u32,
1205}
1206
1207#[repr(C)]
1209#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1210pub struct BuildToolVersion {
1211 pub tool: u32,
1213 pub version: u32,
1215}
1216
1217#[repr(C)]
1220#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1221pub struct FilesetEntryCommand {
1222 pub cmd: u32,
1224 pub cmdsize: u32,
1225 pub vmaddr: u64,
1227 pub fileoff: u64,
1229 pub entry_id: LcStr,
1231 pub reserved: u32,
1233}
1234
1235#[repr(C)]
1238#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1239pub struct SourceVersionCommand {
1240 pub cmd: u32,
1242 pub cmdsize: u32,
1243 pub version: u64,
1245}
1246
1247#[repr(C)]
1251#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1252pub struct DataInCodeEntry {
1253 pub offset: u32,
1255 pub length: u16,
1257 pub kind: u16,
1259}
1260
1261#[repr(C)]
1264#[derive(Debug, Clone, Copy, Pread, Pwrite, IOread, IOwrite, SizeWith)]
1265pub struct NoteCommand {
1266 pub cmd: u32,
1268 pub cmdsize: u32,
1269 pub data_owner: [u8; 16],
1271 pub offset: u64,
1273 pub size: u64,
1275}
1276
1277pub const LC_REQ_DYLD: u32 = 0x8000_0000;
1282pub const LC_LOAD_WEAK_DYLIB: u32 = 0x18 | LC_REQ_DYLD;
1283pub const LC_RPATH: u32 = 0x1c | LC_REQ_DYLD;
1284pub const LC_REEXPORT_DYLIB: u32 = 0x1f | LC_REQ_DYLD;
1285pub const LC_DYLD_INFO_ONLY: u32 = 0x22 | LC_REQ_DYLD;
1286pub const LC_LOAD_UPWARD_DYLIB: u32 = 0x23 | LC_REQ_DYLD;
1287pub const LC_MAIN: u32 = 0x28 | LC_REQ_DYLD;
1288pub const LC_DYLD_EXPORTS_TRIE: u32 = 0x33 | LC_REQ_DYLD;
1289pub const LC_DYLD_CHAINED_FIXUPS: u32 = 0x34 | LC_REQ_DYLD;
1290pub const LC_SEGMENT: u32 = 0x1;
1291pub const LC_SYMTAB: u32 = 0x2;
1292pub const LC_SYMSEG: u32 = 0x3;
1293pub const LC_THREAD: u32 = 0x4;
1294pub const LC_UNIXTHREAD: u32 = 0x5;
1295pub const LC_LOADFVMLIB: u32 = 0x6;
1296pub const LC_IDFVMLIB: u32 = 0x7;
1297pub const LC_IDENT: u32 = 0x8;
1298pub const LC_FVMFILE: u32 = 0x9;
1299pub const LC_PREPAGE: u32 = 0xa;
1300pub const LC_DYSYMTAB: u32 = 0xb;
1301pub const LC_LOAD_DYLIB: u32 = 0xc;
1302pub const LC_ID_DYLIB: u32 = 0xd;
1303pub const LC_LOAD_DYLINKER: u32 = 0xe;
1304pub const LC_ID_DYLINKER: u32 = 0xf;
1305pub const LC_PREBOUND_DYLIB: u32 = 0x10;
1306pub const LC_ROUTINES: u32 = 0x11;
1307pub const LC_SUB_FRAMEWORK: u32 = 0x12;
1308pub const LC_SUB_UMBRELLA: u32 = 0x13;
1309pub const LC_SUB_CLIENT: u32 = 0x14;
1310pub const LC_SUB_LIBRARY: u32 = 0x15;
1311pub const LC_TWOLEVEL_HINTS: u32 = 0x16;
1312pub const LC_PREBIND_CKSUM: u32 = 0x17;
1313pub const LC_SEGMENT_64: u32 = 0x19;
1314pub const LC_ROUTINES_64: u32 = 0x1a;
1315pub const LC_UUID: u32 = 0x1b;
1316pub const LC_CODE_SIGNATURE: u32 = 0x1d;
1317pub const LC_SEGMENT_SPLIT_INFO: u32 = 0x1e;
1318pub const LC_LAZY_LOAD_DYLIB: u32 = 0x20;
1319pub const LC_ENCRYPTION_INFO: u32 = 0x21;
1320pub const LC_DYLD_INFO: u32 = 0x22;
1321pub const LC_VERSION_MIN_MACOSX: u32 = 0x24;
1322pub const LC_VERSION_MIN_IPHONEOS: u32 = 0x25;
1323pub const LC_FUNCTION_STARTS: u32 = 0x26;
1324pub const LC_DYLD_ENVIRONMENT: u32 = 0x27;
1325pub const LC_DATA_IN_CODE: u32 = 0x29;
1326pub const LC_SOURCE_VERSION: u32 = 0x2A;
1327pub const LC_DYLIB_CODE_SIGN_DRS: u32 = 0x2B;
1328pub const LC_ENCRYPTION_INFO_64: u32 = 0x2C;
1329pub const LC_LINKER_OPTION: u32 = 0x2D;
1330pub const LC_LINKER_OPTIMIZATION_HINT: u32 = 0x2E;
1331pub const LC_VERSION_MIN_TVOS: u32 = 0x2F;
1332pub const LC_VERSION_MIN_WATCHOS: u32 = 0x30;
1333pub const LC_NOTE: u32 = 0x31;
1334pub const LC_BUILD_VERSION: u32 = 0x32;
1335pub const LC_FILESET_ENTRY: u32 = 0x35 | LC_REQ_DYLD;
1336pub const PLATFORM_MACOS: u32 = 1;
1337pub const PLATFORM_IOS: u32 = 2;
1338pub const PLATFORM_TVOS: u32 = 3;
1339pub const PLATFORM_WATCHOS: u32 = 4;
1340pub const PLATFORM_BRIDGEOS: u32 = 5;
1341pub const PLATFORM_MACCATALYST: u32 = 6;
1342pub const PLATFORM_IOSSIMULATOR: u32 = 7;
1343pub const PLATFORM_TVOSSIMULATOR: u32 = 8;
1344pub const PLATFORM_WATCHOSSIMULATOR: u32 = 9;
1345pub const PLATFORM_DRIVERKIT: u32 = 10;
1346pub const PLATFORM_VISIONOS: u32 = 11;
1347pub const PLATFORM_VISIONOSSIMULATOR: u32 = 12;
1348pub const TOOL_CLANG: u32 = 1;
1349pub const TOOL_SWIFT: u32 = 2;
1350pub const TOOL_LD: u32 = 3;
1351pub const TOOL_LLD: u32 = 4;
1352
1353pub fn cmd_to_str(cmd: u32) -> &'static str {
1354 match cmd {
1355 LC_SEGMENT => "LC_SEGMENT",
1356 LC_SYMTAB => "LC_SYMTAB",
1357 LC_SYMSEG => "LC_SYMSEG",
1358 LC_THREAD => "LC_THREAD",
1359 LC_UNIXTHREAD => "LC_UNIXTHREAD",
1360 LC_LOADFVMLIB => "LC_LOADFVMLIB",
1361 LC_IDFVMLIB => "LC_IDFVMLIB",
1362 LC_IDENT => "LC_IDENT",
1363 LC_FVMFILE => "LC_FVMFILE",
1364 LC_PREPAGE => "LC_PREPAGE",
1365 LC_DYSYMTAB => "LC_DYSYMTAB",
1366 LC_LOAD_DYLIB => "LC_LOAD_DYLIB",
1367 LC_ID_DYLIB => "LC_ID_DYLIB",
1368 LC_LOAD_DYLINKER => "LC_LOAD_DYLINKER",
1369 LC_ID_DYLINKER => "LC_ID_DYLINKER",
1370 LC_PREBOUND_DYLIB => "LC_PREBOUND_DYLIB",
1371 LC_ROUTINES => "LC_ROUTINES",
1372 LC_SUB_FRAMEWORK => "LC_SUB_FRAMEWORK",
1373 LC_SUB_UMBRELLA => "LC_SUB_UMBRELLA",
1374 LC_SUB_CLIENT => "LC_SUB_CLIENT",
1375 LC_SUB_LIBRARY => "LC_SUB_LIBRARY",
1376 LC_TWOLEVEL_HINTS => "LC_TWOLEVEL_HINTS",
1377 LC_PREBIND_CKSUM => "LC_PREBIND_CKSUM",
1378 LC_LOAD_WEAK_DYLIB => "LC_LOAD_WEAK_DYLIB",
1379 LC_SEGMENT_64 => "LC_SEGMENT_64",
1380 LC_ROUTINES_64 => "LC_ROUTINES_64",
1381 LC_UUID => "LC_UUID",
1382 LC_RPATH => "LC_RPATH",
1383 LC_CODE_SIGNATURE => "LC_CODE_SIGNATURE",
1384 LC_SEGMENT_SPLIT_INFO => "LC_SEGMENT_SPLIT_INFO",
1385 LC_REEXPORT_DYLIB => "LC_REEXPORT_DYLIB",
1386 LC_LAZY_LOAD_DYLIB => "LC_LAZY_LOAD_DYLIB",
1387 LC_ENCRYPTION_INFO => "LC_ENCRYPTION_INFO",
1388 LC_DYLD_INFO => "LC_DYLD_INFO",
1389 LC_DYLD_INFO_ONLY => "LC_DYLD_INFO_ONLY",
1390 LC_LOAD_UPWARD_DYLIB => "LC_LOAD_UPWARD_DYLIB",
1391 LC_VERSION_MIN_MACOSX => "LC_VERSION_MIN_MACOSX",
1392 LC_VERSION_MIN_IPHONEOS => "LC_VERSION_MIN_IPHONEOS",
1393 LC_FUNCTION_STARTS => "LC_FUNCTION_STARTS",
1394 LC_DYLD_ENVIRONMENT => "LC_DYLD_ENVIRONMENT",
1395 LC_MAIN => "LC_MAIN",
1396 LC_DATA_IN_CODE => "LC_DATA_IN_CODE",
1397 LC_SOURCE_VERSION => "LC_SOURCE_VERSION",
1398 LC_DYLIB_CODE_SIGN_DRS => "LC_DYLIB_CODE_SIGN_DRS",
1399 LC_ENCRYPTION_INFO_64 => "LC_ENCRYPTION_INFO_64",
1400 LC_LINKER_OPTION => "LC_LINKER_OPTION",
1401 LC_LINKER_OPTIMIZATION_HINT => "LC_LINKER_OPTIMIZATION_HINT",
1402 LC_VERSION_MIN_TVOS => "LC_VERSION_MIN_TVOS",
1403 LC_VERSION_MIN_WATCHOS => "LC_VERSION_MIN_WATCHOS",
1404 LC_NOTE => "LC_NOTE",
1405 LC_BUILD_VERSION => "LC_BUILD_VERSION",
1406 LC_FILESET_ENTRY => "LC_FILESET_ENTRY",
1407 LC_DYLD_EXPORTS_TRIE => "LC_DYLD_EXPORTS_TRIE",
1408 LC_DYLD_CHAINED_FIXUPS => "LC_DYLD_CHAINED_FIXUPS",
1409 _ => "LC_UNKNOWN",
1410 }
1411}
1412
1413#[derive(Debug)]
1418#[allow(clippy::large_enum_variant)]
1419#[non_exhaustive]
1420pub enum CommandVariant {
1422 Segment32(SegmentCommand32),
1423 Segment64(SegmentCommand64),
1424 Uuid(UuidCommand),
1425 Symtab(SymtabCommand),
1426 Symseg(SymsegCommand),
1427 Thread(ThreadCommand),
1428 Unixthread(ThreadCommand),
1429 LoadFvmlib(FvmlibCommand),
1430 IdFvmlib(FvmlibCommand),
1431 Ident(IdentCommand),
1432 Fvmfile(FvmfileCommand),
1433 Prepage(LoadCommandHeader),
1434 Dysymtab(DysymtabCommand),
1435 LoadDylib(DylibCommand),
1436 IdDylib(DylibCommand),
1437 LoadDylinker(DylinkerCommand),
1438 IdDylinker(DylinkerCommand),
1439 PreboundDylib(PreboundDylibCommand),
1440 Routines32(RoutinesCommand32),
1441 Routines64(RoutinesCommand64),
1442 SubFramework(SubFrameworkCommand),
1443 SubUmbrella(SubUmbrellaCommand),
1444 SubClient(SubClientCommand),
1445 SubLibrary(SubLibraryCommand),
1446 TwolevelHints(TwolevelHintsCommand),
1447 PrebindCksum(PrebindCksumCommand),
1448 LoadWeakDylib(DylibCommand),
1449 Rpath(RpathCommand),
1450 CodeSignature(LinkeditDataCommand),
1451 SegmentSplitInfo(LinkeditDataCommand),
1452 ReexportDylib(DylibCommand),
1453 LazyLoadDylib(DylibCommand),
1454 EncryptionInfo32(EncryptionInfoCommand32),
1455 EncryptionInfo64(EncryptionInfoCommand64),
1456 DyldInfo(DyldInfoCommand),
1457 DyldInfoOnly(DyldInfoCommand),
1458 LoadUpwardDylib(DylibCommand),
1459 VersionMinMacosx(VersionMinCommand),
1460 VersionMinIphoneos(VersionMinCommand),
1461 FunctionStarts(LinkeditDataCommand),
1462 DyldEnvironment(DylinkerCommand),
1463 Main(EntryPointCommand),
1464 DataInCode(LinkeditDataCommand),
1465 BuildVersion(BuildVersionCommand),
1466 FilesetEntry(FilesetEntryCommand),
1467 SourceVersion(SourceVersionCommand),
1468 DylibCodeSignDrs(LinkeditDataCommand),
1469 LinkerOption(LinkeditDataCommand),
1470 LinkerOptimizationHint(LinkeditDataCommand),
1471 VersionMinTvos(VersionMinCommand),
1472 VersionMinWatchos(VersionMinCommand),
1473 DyldExportsTrie(LinkeditDataCommand),
1474 DyldChainedFixups(LinkeditDataCommand),
1475 Note(NoteCommand),
1476 Unimplemented(LoadCommandHeader),
1477}
1478
1479impl<'a> ctx::TryFromCtx<'a, Endian> for CommandVariant {
1480 type Error = crate::error::Error;
1481 fn try_from_ctx(bytes: &'a [u8], le: Endian) -> error::Result<(Self, usize)> {
1482 use self::CommandVariant::*;
1483 let lc = bytes.pread_with::<LoadCommandHeader>(0, le)?;
1484 let size = lc.cmdsize as usize;
1485 if size > bytes.len() {
1487 return Err(error::Error::Malformed(format!(
1488 "{} has size larger than remainder of binary: {:?}",
1489 &lc,
1490 bytes.len()
1491 )));
1492 }
1493 match lc.cmd {
1494 LC_SEGMENT => {
1495 let comm = bytes.pread_with::<SegmentCommand32>(0, le)?;
1496 Ok((Segment32(comm), size))
1497 }
1498 LC_SEGMENT_64 => {
1499 let comm = bytes.pread_with::<SegmentCommand64>(0, le)?;
1500 Ok((Segment64(comm), size))
1501 }
1502 LC_DYSYMTAB => {
1503 let comm = bytes.pread_with::<DysymtabCommand>(0, le)?;
1504 Ok((Dysymtab(comm), size))
1505 }
1506 LC_LOAD_DYLINKER => {
1507 let comm = bytes.pread_with::<DylinkerCommand>(0, le)?;
1508 Ok((LoadDylinker(comm), size))
1509 }
1510 LC_ID_DYLINKER => {
1511 let comm = bytes.pread_with::<DylinkerCommand>(0, le)?;
1512 Ok((IdDylinker(comm), size))
1513 }
1514 LC_UUID => {
1515 let comm = bytes.pread_with::<UuidCommand>(0, le)?;
1516 Ok((Uuid(comm), size))
1517 }
1518 LC_SYMTAB => {
1519 let comm = bytes.pread_with::<SymtabCommand>(0, le)?;
1520 Ok((Symtab(comm), size))
1521 }
1522 LC_SYMSEG => {
1523 let comm = bytes.pread_with::<SymsegCommand>(0, le)?;
1524 Ok((Symseg(comm), size))
1525 }
1526 LC_THREAD => {
1527 let comm = bytes.pread_with::<ThreadCommand>(0, le)?;
1528 Ok((Thread(comm), size))
1529 }
1530 LC_UNIXTHREAD => {
1531 let comm = bytes.pread_with::<ThreadCommand>(0, le)?;
1532 Ok((Unixthread(comm), size))
1533 }
1534 LC_LOADFVMLIB => {
1535 let comm = bytes.pread_with::<FvmlibCommand>(0, le)?;
1536 Ok((LoadFvmlib(comm), size))
1537 }
1538 LC_IDFVMLIB => {
1539 let comm = bytes.pread_with::<FvmlibCommand>(0, le)?;
1540 Ok((IdFvmlib(comm), size))
1541 }
1542 LC_IDENT => {
1543 let comm = bytes.pread_with::<IdentCommand>(0, le)?;
1544 Ok((Ident(comm), size))
1545 }
1546 LC_FVMFILE => {
1547 let comm = bytes.pread_with::<FvmfileCommand>(0, le)?;
1548 Ok((Fvmfile(comm), size))
1549 }
1550 LC_PREPAGE => {
1551 let comm = bytes.pread_with::<LoadCommandHeader>(0, le)?;
1552 Ok((Prepage(comm), size))
1553 }
1554 LC_LOAD_DYLIB => {
1555 let comm = bytes.pread_with::<DylibCommand>(0, le)?;
1556 Ok((LoadDylib(comm), size))
1557 }
1558 LC_ID_DYLIB => {
1559 let comm = bytes.pread_with::<DylibCommand>(0, le)?;
1560 Ok((IdDylib(comm), size))
1561 }
1562 LC_PREBOUND_DYLIB => {
1563 let comm = bytes.pread_with::<PreboundDylibCommand>(0, le)?;
1564 Ok((PreboundDylib(comm), size))
1565 }
1566 LC_ROUTINES => {
1567 let comm = bytes.pread_with::<RoutinesCommand32>(0, le)?;
1568 Ok((Routines32(comm), size))
1569 }
1570 LC_ROUTINES_64 => {
1571 let comm = bytes.pread_with::<RoutinesCommand64>(0, le)?;
1572 Ok((Routines64(comm), size))
1573 }
1574 LC_SUB_FRAMEWORK => {
1575 let comm = bytes.pread_with::<SubFrameworkCommand>(0, le)?;
1576 Ok((SubFramework(comm), size))
1577 }
1578 LC_SUB_UMBRELLA => {
1579 let comm = bytes.pread_with::<SubUmbrellaCommand>(0, le)?;
1580 Ok((SubUmbrella(comm), size))
1581 }
1582 LC_SUB_CLIENT => {
1583 let comm = bytes.pread_with::<SubClientCommand>(0, le)?;
1584 Ok((SubClient(comm), size))
1585 }
1586 LC_SUB_LIBRARY => {
1587 let comm = bytes.pread_with::<SubLibraryCommand>(0, le)?;
1588 Ok((SubLibrary(comm), size))
1589 }
1590 LC_TWOLEVEL_HINTS => {
1591 let comm = bytes.pread_with::<TwolevelHintsCommand>(0, le)?;
1592 Ok((TwolevelHints(comm), size))
1593 }
1594 LC_PREBIND_CKSUM => {
1595 let comm = bytes.pread_with::<PrebindCksumCommand>(0, le)?;
1596 Ok((PrebindCksum(comm), size))
1597 }
1598 LC_LOAD_WEAK_DYLIB => {
1599 let comm = bytes.pread_with::<DylibCommand>(0, le)?;
1600 Ok((LoadWeakDylib(comm), size))
1601 }
1602 LC_RPATH => {
1603 let comm = bytes.pread_with::<RpathCommand>(0, le)?;
1604 Ok((Rpath(comm), size))
1605 }
1606 LC_CODE_SIGNATURE => {
1607 let comm = bytes.pread_with::<LinkeditDataCommand>(0, le)?;
1608 Ok((CodeSignature(comm), size))
1609 }
1610 LC_SEGMENT_SPLIT_INFO => {
1611 let comm = bytes.pread_with::<LinkeditDataCommand>(0, le)?;
1612 Ok((SegmentSplitInfo(comm), size))
1613 }
1614 LC_REEXPORT_DYLIB => {
1615 let comm = bytes.pread_with::<DylibCommand>(0, le)?;
1616 Ok((ReexportDylib(comm), size))
1617 }
1618 LC_LAZY_LOAD_DYLIB => {
1619 let comm = bytes.pread_with::<DylibCommand>(0, le)?;
1620 Ok((LazyLoadDylib(comm), size))
1621 }
1622 LC_ENCRYPTION_INFO => {
1623 let comm = bytes.pread_with::<EncryptionInfoCommand32>(0, le)?;
1624 Ok((EncryptionInfo32(comm), size))
1625 }
1626 LC_ENCRYPTION_INFO_64 => {
1627 let comm = bytes.pread_with::<EncryptionInfoCommand64>(0, le)?;
1628 Ok((EncryptionInfo64(comm), size))
1629 }
1630 LC_DYLD_INFO => {
1631 let comm = bytes.pread_with::<DyldInfoCommand>(0, le)?;
1632 Ok((DyldInfo(comm), size))
1633 }
1634 LC_DYLD_INFO_ONLY => {
1635 let comm = bytes.pread_with::<DyldInfoCommand>(0, le)?;
1636 Ok((DyldInfoOnly(comm), size))
1637 }
1638 LC_LOAD_UPWARD_DYLIB => {
1639 let comm = bytes.pread_with::<DylibCommand>(0, le)?;
1640 Ok((LoadUpwardDylib(comm), size))
1641 }
1642 LC_VERSION_MIN_MACOSX => {
1643 let comm = bytes.pread_with::<VersionMinCommand>(0, le)?;
1644 Ok((VersionMinMacosx(comm), size))
1645 }
1646 LC_VERSION_MIN_IPHONEOS => {
1647 let comm = bytes.pread_with::<VersionMinCommand>(0, le)?;
1648 Ok((VersionMinIphoneos(comm), size))
1649 }
1650 LC_FUNCTION_STARTS => {
1651 let comm = bytes.pread_with::<LinkeditDataCommand>(0, le)?;
1652 Ok((FunctionStarts(comm), size))
1653 }
1654 LC_DYLD_ENVIRONMENT => {
1655 let comm = bytes.pread_with::<DylinkerCommand>(0, le)?;
1656 Ok((DyldEnvironment(comm), size))
1657 }
1658 LC_MAIN => {
1659 let comm = bytes.pread_with::<EntryPointCommand>(0, le)?;
1660 Ok((Main(comm), size))
1661 }
1662 LC_DATA_IN_CODE => {
1663 let comm = bytes.pread_with::<LinkeditDataCommand>(0, le)?;
1664 Ok((DataInCode(comm), size))
1665 }
1666 LC_BUILD_VERSION => {
1667 let comm = bytes.pread_with::<BuildVersionCommand>(0, le)?;
1668 Ok((BuildVersion(comm), size))
1669 }
1670 LC_FILESET_ENTRY => {
1671 let comm = bytes.pread_with::<FilesetEntryCommand>(0, le)?;
1672 Ok((FilesetEntry(comm), size))
1673 }
1674 LC_SOURCE_VERSION => {
1675 let comm = bytes.pread_with::<SourceVersionCommand>(0, le)?;
1676 Ok((SourceVersion(comm), size))
1677 }
1678 LC_DYLIB_CODE_SIGN_DRS => {
1679 let comm = bytes.pread_with::<LinkeditDataCommand>(0, le)?;
1680 Ok((DylibCodeSignDrs(comm), size))
1681 }
1682 LC_LINKER_OPTION => {
1683 let comm = bytes.pread_with::<LinkeditDataCommand>(0, le)?;
1684 Ok((LinkerOption(comm), size))
1685 }
1686 LC_LINKER_OPTIMIZATION_HINT => {
1687 let comm = bytes.pread_with::<LinkeditDataCommand>(0, le)?;
1688 Ok((LinkerOptimizationHint(comm), size))
1689 }
1690 LC_VERSION_MIN_TVOS => {
1691 let comm = bytes.pread_with::<VersionMinCommand>(0, le)?;
1692 Ok((VersionMinTvos(comm), size))
1693 }
1694 LC_VERSION_MIN_WATCHOS => {
1695 let comm = bytes.pread_with::<VersionMinCommand>(0, le)?;
1696 Ok((VersionMinWatchos(comm), size))
1697 }
1698 LC_DYLD_EXPORTS_TRIE => {
1699 let comm = bytes.pread_with::<LinkeditDataCommand>(0, le)?;
1700 Ok((DyldExportsTrie(comm), size))
1701 }
1702 LC_DYLD_CHAINED_FIXUPS => {
1703 let comm = bytes.pread_with::<LinkeditDataCommand>(0, le)?;
1704 Ok((DyldChainedFixups(comm), size))
1705 }
1706 LC_NOTE => {
1707 let comm = bytes.pread_with::<NoteCommand>(0, le)?;
1708 Ok((Note(comm), size))
1709 }
1710 _ => Ok((Unimplemented(lc), size)),
1711 }
1712 }
1713}
1714
1715impl CommandVariant {
1716 pub fn cmdsize(&self) -> usize {
1717 use self::CommandVariant::*;
1718 let cmdsize = match *self {
1719 Segment32(comm) => comm.cmdsize,
1720 Segment64(comm) => comm.cmdsize,
1721 Uuid(comm) => comm.cmdsize,
1722 Symtab(comm) => comm.cmdsize,
1723 Symseg(comm) => comm.cmdsize,
1724 Thread(comm) => comm.cmdsize,
1725 Unixthread(comm) => comm.cmdsize,
1726 LoadFvmlib(comm) => comm.cmdsize,
1727 IdFvmlib(comm) => comm.cmdsize,
1728 Ident(comm) => comm.cmdsize,
1729 Fvmfile(comm) => comm.cmdsize,
1730 Prepage(comm) => comm.cmdsize,
1731 Dysymtab(comm) => comm.cmdsize,
1732 LoadDylib(comm) => comm.cmdsize,
1733 IdDylib(comm) => comm.cmdsize,
1734 LoadDylinker(comm) => comm.cmdsize,
1735 IdDylinker(comm) => comm.cmdsize,
1736 PreboundDylib(comm) => comm.cmdsize,
1737 Routines32(comm) => comm.cmdsize,
1738 Routines64(comm) => comm.cmdsize,
1739 SubFramework(comm) => comm.cmdsize,
1740 SubUmbrella(comm) => comm.cmdsize,
1741 SubClient(comm) => comm.cmdsize,
1742 SubLibrary(comm) => comm.cmdsize,
1743 TwolevelHints(comm) => comm.cmdsize,
1744 PrebindCksum(comm) => comm.cmdsize,
1745 LoadWeakDylib(comm) => comm.cmdsize,
1746 Rpath(comm) => comm.cmdsize,
1747 CodeSignature(comm) => comm.cmdsize,
1748 SegmentSplitInfo(comm) => comm.cmdsize,
1749 ReexportDylib(comm) => comm.cmdsize,
1750 LazyLoadDylib(comm) => comm.cmdsize,
1751 EncryptionInfo32(comm) => comm.cmdsize,
1752 EncryptionInfo64(comm) => comm.cmdsize,
1753 DyldInfo(comm) => comm.cmdsize,
1754 DyldInfoOnly(comm) => comm.cmdsize,
1755 LoadUpwardDylib(comm) => comm.cmdsize,
1756 VersionMinMacosx(comm) => comm.cmdsize,
1757 VersionMinIphoneos(comm) => comm.cmdsize,
1758 FunctionStarts(comm) => comm.cmdsize,
1759 DyldEnvironment(comm) => comm.cmdsize,
1760 Main(comm) => comm.cmdsize,
1761 DataInCode(comm) => comm.cmdsize,
1762 BuildVersion(comm) => comm.cmdsize,
1763 FilesetEntry(comm) => comm.cmdsize,
1764 SourceVersion(comm) => comm.cmdsize,
1765 DylibCodeSignDrs(comm) => comm.cmdsize,
1766 LinkerOption(comm) => comm.cmdsize,
1767 LinkerOptimizationHint(comm) => comm.cmdsize,
1768 VersionMinTvos(comm) => comm.cmdsize,
1769 VersionMinWatchos(comm) => comm.cmdsize,
1770 DyldExportsTrie(comm) => comm.cmdsize,
1771 DyldChainedFixups(comm) => comm.cmdsize,
1772 Note(comm) => comm.cmdsize,
1773 Unimplemented(comm) => comm.cmdsize,
1774 };
1775 cmdsize as usize
1776 }
1777 pub fn cmd(&self) -> u32 {
1778 use self::CommandVariant::*;
1779 match *self {
1780 Segment32(comm) => comm.cmd,
1781 Segment64(comm) => comm.cmd,
1782 Uuid(comm) => comm.cmd,
1783 Symtab(comm) => comm.cmd,
1784 Symseg(comm) => comm.cmd,
1785 Thread(comm) => comm.cmd,
1786 Unixthread(comm) => comm.cmd,
1787 LoadFvmlib(comm) => comm.cmd,
1788 IdFvmlib(comm) => comm.cmd,
1789 Ident(comm) => comm.cmd,
1790 Fvmfile(comm) => comm.cmd,
1791 Prepage(comm) => comm.cmd,
1792 Dysymtab(comm) => comm.cmd,
1793 LoadDylib(comm) => comm.cmd,
1794 IdDylib(comm) => comm.cmd,
1795 LoadDylinker(comm) => comm.cmd,
1796 IdDylinker(comm) => comm.cmd,
1797 PreboundDylib(comm) => comm.cmd,
1798 Routines32(comm) => comm.cmd,
1799 Routines64(comm) => comm.cmd,
1800 SubFramework(comm) => comm.cmd,
1801 SubUmbrella(comm) => comm.cmd,
1802 SubClient(comm) => comm.cmd,
1803 SubLibrary(comm) => comm.cmd,
1804 TwolevelHints(comm) => comm.cmd,
1805 PrebindCksum(comm) => comm.cmd,
1806 LoadWeakDylib(comm) => comm.cmd,
1807 Rpath(comm) => comm.cmd,
1808 CodeSignature(comm) => comm.cmd,
1809 SegmentSplitInfo(comm) => comm.cmd,
1810 ReexportDylib(comm) => comm.cmd,
1811 LazyLoadDylib(comm) => comm.cmd,
1812 EncryptionInfo32(comm) => comm.cmd,
1813 EncryptionInfo64(comm) => comm.cmd,
1814 DyldInfo(comm) => comm.cmd,
1815 DyldInfoOnly(comm) => comm.cmd,
1816 LoadUpwardDylib(comm) => comm.cmd,
1817 VersionMinMacosx(comm) => comm.cmd,
1818 VersionMinIphoneos(comm) => comm.cmd,
1819 FunctionStarts(comm) => comm.cmd,
1820 DyldEnvironment(comm) => comm.cmd,
1821 Main(comm) => comm.cmd,
1822 DataInCode(comm) => comm.cmd,
1823 BuildVersion(comm) => comm.cmd,
1824 FilesetEntry(comm) => comm.cmd,
1825 SourceVersion(comm) => comm.cmd,
1826 DylibCodeSignDrs(comm) => comm.cmd,
1827 LinkerOption(comm) => comm.cmd,
1828 LinkerOptimizationHint(comm) => comm.cmd,
1829 VersionMinTvos(comm) => comm.cmd,
1830 VersionMinWatchos(comm) => comm.cmd,
1831 DyldExportsTrie(comm) => comm.cmd,
1832 DyldChainedFixups(comm) => comm.cmd,
1833 Note(comm) => comm.cmd,
1834 Unimplemented(comm) => comm.cmd,
1835 }
1836 }
1837}
1838
1839#[derive(Debug)]
1840pub struct LoadCommand {
1842 pub offset: usize,
1844 pub command: CommandVariant,
1846}
1847
1848impl LoadCommand {
1849 pub fn parse(bytes: &[u8], offset: &mut usize, le: scroll::Endian) -> error::Result<Self> {
1851 let start = *offset;
1852 let command = bytes.pread_with::<CommandVariant>(start, le)?;
1853 let size = command.cmdsize();
1854 *offset = start + size;
1855 Ok(LoadCommand {
1856 offset: start,
1857 command,
1858 })
1859 }
1860}