1use alloc::vec::Vec;
2use core::fmt::Debug;
3use core::{mem, str};
4
5use crate::endian::{self, BigEndian, Endian, Endianness};
6use crate::macho;
7use crate::pod::Pod;
8use crate::read::{
9 self, Architecture, ByteString, ComdatKind, Error, Export, FileFlags, Import,
10 NoDynamicRelocationIterator, Object, ObjectComdat, ObjectKind, ObjectMap, ObjectSection,
11 ReadError, ReadRef, Result, SectionIndex, SubArchitecture, SymbolIndex,
12};
13
14use super::{
15 DyldCacheImage, LoadCommandIterator, MachOSection, MachOSectionInternal, MachOSectionIterator,
16 MachOSegment, MachOSegmentInternal, MachOSegmentIterator, MachOSymbol, MachOSymbolIterator,
17 MachOSymbolTable, Nlist, Section, Segment, SymbolTable,
18};
19
20pub type MachOFile32<'data, Endian = Endianness, R = &'data [u8]> =
25 MachOFile<'data, macho::MachHeader32<Endian>, R>;
26pub type MachOFile64<'data, Endian = Endianness, R = &'data [u8]> =
31 MachOFile<'data, macho::MachHeader64<Endian>, R>;
32
33#[derive(Debug)]
37pub struct MachOFile<'data, Mach, R = &'data [u8]>
38where
39 Mach: MachHeader,
40 R: ReadRef<'data>,
41{
42 pub(super) endian: Mach::Endian,
43 pub(super) data: R,
44 pub(super) header_offset: u64,
45 pub(super) header: &'data Mach,
46 pub(super) segments: Vec<MachOSegmentInternal<'data, Mach, R>>,
47 pub(super) sections: Vec<MachOSectionInternal<'data, Mach, R>>,
48 pub(super) symbols: SymbolTable<'data, Mach, R>,
49}
50
51impl<'data, Mach, R> MachOFile<'data, Mach, R>
52where
53 Mach: MachHeader,
54 R: ReadRef<'data>,
55{
56 pub fn parse(data: R) -> Result<Self> {
58 let header = Mach::parse(data, 0)?;
59 let endian = header.endian()?;
60
61 let mut segments = Vec::new();
63 let mut sections = Vec::new();
64 let mut symbols = SymbolTable::default();
65 if let Ok(mut commands) = header.load_commands(endian, data, 0) {
66 while let Ok(Some(command)) = commands.next() {
67 if let Some((segment, section_data)) = Mach::Segment::from_command(command)? {
68 segments.push(MachOSegmentInternal { segment, data });
69 for section in segment.sections(endian, section_data)? {
70 let index = SectionIndex(sections.len() + 1);
71 sections.push(MachOSectionInternal::parse(index, section, data));
72 }
73 } else if let Some(symtab) = command.symtab()? {
74 symbols = symtab.symbols(endian, data)?;
75 }
76 }
77 }
78
79 Ok(MachOFile {
80 endian,
81 data,
82 header_offset: 0,
83 header,
84 segments,
85 sections,
86 symbols,
87 })
88 }
89
90 pub fn parse_dyld_cache_image<'cache, E: Endian>(
93 image: &DyldCacheImage<'data, 'cache, E, R>,
94 ) -> Result<Self> {
95 let (data, header_offset) = image.image_data_and_offset()?;
96 let header = Mach::parse(data, header_offset)?;
97 let endian = header.endian()?;
98
99 let mut segments = Vec::new();
104 let mut sections = Vec::new();
105 let mut linkedit_data: Option<R> = None;
106 let mut symtab = None;
107 if let Ok(mut commands) = header.load_commands(endian, data, header_offset) {
108 while let Ok(Some(command)) = commands.next() {
109 if let Some((segment, section_data)) = Mach::Segment::from_command(command)? {
110 let addr = segment.vmaddr(endian).into();
114 let (data, _offset) = image
115 .cache
116 .data_and_offset_for_address(addr)
117 .read_error("Could not find segment data in dyld shared cache")?;
118 if segment.name() == macho::SEG_LINKEDIT.as_bytes() {
119 linkedit_data = Some(data);
120 }
121 segments.push(MachOSegmentInternal { segment, data });
122
123 for section in segment.sections(endian, section_data)? {
124 let index = SectionIndex(sections.len() + 1);
125 sections.push(MachOSectionInternal::parse(index, section, data));
126 }
127 } else if let Some(st) = command.symtab()? {
128 symtab = Some(st);
129 }
130 }
131 }
132
133 let symbols = match (symtab, linkedit_data) {
136 (Some(symtab), Some(linkedit_data)) => symtab.symbols(endian, linkedit_data)?,
137 _ => SymbolTable::default(),
138 };
139
140 Ok(MachOFile {
141 endian,
142 data,
143 header_offset,
144 header,
145 segments,
146 sections,
147 symbols,
148 })
149 }
150
151 #[inline]
153 pub(super) fn section_internal(
154 &self,
155 index: SectionIndex,
156 ) -> Result<&MachOSectionInternal<'data, Mach, R>> {
157 index
158 .0
159 .checked_sub(1)
160 .and_then(|index| self.sections.get(index))
161 .read_error("Invalid Mach-O section index")
162 }
163
164 pub fn endian(&self) -> Mach::Endian {
166 self.endian
167 }
168
169 pub fn data(&self) -> R {
171 self.data
172 }
173
174 #[deprecated(note = "Use `macho_header` instead")]
176 pub fn raw_header(&self) -> &'data Mach {
177 self.header
178 }
179
180 pub fn macho_header(&self) -> &'data Mach {
182 self.header
183 }
184
185 pub fn macho_load_commands(&self) -> Result<LoadCommandIterator<'data, Mach::Endian>> {
187 self.header
188 .load_commands(self.endian, self.data, self.header_offset)
189 }
190
191 pub fn macho_symbol_table(&self) -> &SymbolTable<'data, Mach, R> {
195 &self.symbols
196 }
197
198 pub fn build_version(&self) -> Result<Option<&'data macho::BuildVersionCommand<Mach::Endian>>> {
200 let mut commands = self
201 .header
202 .load_commands(self.endian, self.data, self.header_offset)?;
203 while let Some(command) = commands.next()? {
204 if let Some(build_version) = command.build_version()? {
205 return Ok(Some(build_version));
206 }
207 }
208 Ok(None)
209 }
210}
211
212impl<'data, Mach, R> read::private::Sealed for MachOFile<'data, Mach, R>
213where
214 Mach: MachHeader,
215 R: ReadRef<'data>,
216{
217}
218
219impl<'data, Mach, R> Object<'data> for MachOFile<'data, Mach, R>
220where
221 Mach: MachHeader,
222 R: ReadRef<'data>,
223{
224 type Segment<'file>
225 = MachOSegment<'data, 'file, Mach, R>
226 where
227 Self: 'file,
228 'data: 'file;
229 type SegmentIterator<'file>
230 = MachOSegmentIterator<'data, 'file, Mach, R>
231 where
232 Self: 'file,
233 'data: 'file;
234 type Section<'file>
235 = MachOSection<'data, 'file, Mach, R>
236 where
237 Self: 'file,
238 'data: 'file;
239 type SectionIterator<'file>
240 = MachOSectionIterator<'data, 'file, Mach, R>
241 where
242 Self: 'file,
243 'data: 'file;
244 type Comdat<'file>
245 = MachOComdat<'data, 'file, Mach, R>
246 where
247 Self: 'file,
248 'data: 'file;
249 type ComdatIterator<'file>
250 = MachOComdatIterator<'data, 'file, Mach, R>
251 where
252 Self: 'file,
253 'data: 'file;
254 type Symbol<'file>
255 = MachOSymbol<'data, 'file, Mach, R>
256 where
257 Self: 'file,
258 'data: 'file;
259 type SymbolIterator<'file>
260 = MachOSymbolIterator<'data, 'file, Mach, R>
261 where
262 Self: 'file,
263 'data: 'file;
264 type SymbolTable<'file>
265 = MachOSymbolTable<'data, 'file, Mach, R>
266 where
267 Self: 'file,
268 'data: 'file;
269 type DynamicRelocationIterator<'file>
270 = NoDynamicRelocationIterator
271 where
272 Self: 'file,
273 'data: 'file;
274
275 fn architecture(&self) -> Architecture {
276 match self.header.cputype(self.endian) {
277 macho::CPU_TYPE_ARM => Architecture::Arm,
278 macho::CPU_TYPE_ARM64 => Architecture::Aarch64,
279 macho::CPU_TYPE_ARM64_32 => Architecture::Aarch64_Ilp32,
280 macho::CPU_TYPE_X86 => Architecture::I386,
281 macho::CPU_TYPE_X86_64 => Architecture::X86_64,
282 macho::CPU_TYPE_MIPS => Architecture::Mips,
283 macho::CPU_TYPE_POWERPC => Architecture::PowerPc,
284 macho::CPU_TYPE_POWERPC64 => Architecture::PowerPc64,
285 _ => Architecture::Unknown,
286 }
287 }
288
289 fn sub_architecture(&self) -> Option<SubArchitecture> {
290 match (
291 self.header.cputype(self.endian),
292 self.header.cpusubtype(self.endian),
293 ) {
294 (macho::CPU_TYPE_ARM64, macho::CPU_SUBTYPE_ARM64E) => Some(SubArchitecture::Arm64E),
295 _ => None,
296 }
297 }
298
299 #[inline]
300 fn is_little_endian(&self) -> bool {
301 self.header.is_little_endian()
302 }
303
304 #[inline]
305 fn is_64(&self) -> bool {
306 self.header.is_type_64()
307 }
308
309 fn kind(&self) -> ObjectKind {
310 match self.header.filetype(self.endian) {
311 macho::MH_OBJECT => ObjectKind::Relocatable,
312 macho::MH_EXECUTE => ObjectKind::Executable,
313 macho::MH_CORE => ObjectKind::Core,
314 macho::MH_DYLIB => ObjectKind::Dynamic,
315 _ => ObjectKind::Unknown,
316 }
317 }
318
319 fn segments(&self) -> MachOSegmentIterator<'data, '_, Mach, R> {
320 MachOSegmentIterator {
321 file: self,
322 iter: self.segments.iter(),
323 }
324 }
325
326 fn section_by_name_bytes<'file>(
327 &'file self,
328 section_name: &[u8],
329 ) -> Option<MachOSection<'data, 'file, Mach, R>> {
330 let make_prefix_matcher = |query_prefix: &'static [u8], name_prefix: &'static [u8]| {
334 const MAX_SECTION_NAME_LEN: usize = 16;
335 let suffix = section_name.strip_prefix(query_prefix).map(|suffix| {
336 let max_len = MAX_SECTION_NAME_LEN - name_prefix.len();
337 &suffix[..suffix.len().min(max_len)]
338 });
339 move |name: &[u8]| suffix.is_some() && name.strip_prefix(name_prefix) == suffix
340 };
341 let matches_underscores_prefix = make_prefix_matcher(b".", b"__");
345 let matches_zdebug_prefix = make_prefix_matcher(b".debug_", b"__zdebug_");
349 self.sections().find(|section| {
350 section.name_bytes().map_or(false, |name| {
351 name == section_name
352 || matches_underscores_prefix(name)
353 || matches_zdebug_prefix(name)
354 })
355 })
356 }
357
358 fn section_by_index(&self, index: SectionIndex) -> Result<MachOSection<'data, '_, Mach, R>> {
359 let internal = *self.section_internal(index)?;
360 Ok(MachOSection {
361 file: self,
362 internal,
363 })
364 }
365
366 fn sections(&self) -> MachOSectionIterator<'data, '_, Mach, R> {
367 MachOSectionIterator {
368 file: self,
369 iter: self.sections.iter(),
370 }
371 }
372
373 fn comdats(&self) -> MachOComdatIterator<'data, '_, Mach, R> {
374 MachOComdatIterator { file: self }
375 }
376
377 fn symbol_by_index(&self, index: SymbolIndex) -> Result<MachOSymbol<'data, '_, Mach, R>> {
378 let nlist = self.symbols.symbol(index)?;
379 MachOSymbol::new(self, index, nlist).read_error("Unsupported Mach-O symbol index")
380 }
381
382 fn symbols(&self) -> MachOSymbolIterator<'data, '_, Mach, R> {
383 MachOSymbolIterator::new(self)
384 }
385
386 #[inline]
387 fn symbol_table(&self) -> Option<MachOSymbolTable<'data, '_, Mach, R>> {
388 Some(MachOSymbolTable { file: self })
389 }
390
391 fn dynamic_symbols(&self) -> MachOSymbolIterator<'data, '_, Mach, R> {
392 MachOSymbolIterator::empty(self)
393 }
394
395 #[inline]
396 fn dynamic_symbol_table(&self) -> Option<MachOSymbolTable<'data, '_, Mach, R>> {
397 None
398 }
399
400 fn object_map(&self) -> ObjectMap<'data> {
401 self.symbols.object_map(self.endian)
402 }
403
404 fn imports(&self) -> Result<Vec<Import<'data>>> {
405 let mut dysymtab = None;
406 let mut libraries = Vec::new();
407 let twolevel = self.header.flags(self.endian) & macho::MH_TWOLEVEL != 0;
408 if twolevel {
409 libraries.push(&[][..]);
410 }
411 let mut commands = self
412 .header
413 .load_commands(self.endian, self.data, self.header_offset)?;
414 while let Some(command) = commands.next()? {
415 if let Some(command) = command.dysymtab()? {
416 dysymtab = Some(command);
417 }
418 if twolevel {
419 if let Some(dylib) = command.dylib()? {
420 libraries.push(command.string(self.endian, dylib.dylib.name)?);
421 }
422 }
423 }
424
425 let mut imports = Vec::new();
426 if let Some(dysymtab) = dysymtab {
427 let index = dysymtab.iundefsym.get(self.endian) as usize;
428 let number = dysymtab.nundefsym.get(self.endian) as usize;
429 for i in index..(index.wrapping_add(number)) {
430 let symbol = self.symbols.symbol(SymbolIndex(i))?;
431 let name = symbol.name(self.endian, self.symbols.strings())?;
432 let library = if twolevel {
433 libraries
434 .get(symbol.library_ordinal(self.endian) as usize)
435 .copied()
436 .read_error("Invalid Mach-O symbol library ordinal")?
437 } else {
438 &[]
439 };
440 imports.push(Import {
441 name: ByteString(name),
442 library: ByteString(library),
443 });
444 }
445 }
446 Ok(imports)
447 }
448
449 fn exports(&self) -> Result<Vec<Export<'data>>> {
450 let mut dysymtab = None;
451 let mut commands = self
452 .header
453 .load_commands(self.endian, self.data, self.header_offset)?;
454 while let Some(command) = commands.next()? {
455 if let Some(command) = command.dysymtab()? {
456 dysymtab = Some(command);
457 break;
458 }
459 }
460
461 let mut exports = Vec::new();
462 if let Some(dysymtab) = dysymtab {
463 let index = dysymtab.iextdefsym.get(self.endian) as usize;
464 let number = dysymtab.nextdefsym.get(self.endian) as usize;
465 for i in index..(index.wrapping_add(number)) {
466 let symbol = self.symbols.symbol(SymbolIndex(i))?;
467 let name = symbol.name(self.endian, self.symbols.strings())?;
468 let address = symbol.n_value(self.endian).into();
469 exports.push(Export {
470 name: ByteString(name),
471 address,
472 });
473 }
474 }
475 Ok(exports)
476 }
477
478 #[inline]
479 fn dynamic_relocations(&self) -> Option<NoDynamicRelocationIterator> {
480 None
481 }
482
483 fn has_debug_symbols(&self) -> bool {
484 self.section_by_name(".debug_info").is_some()
485 }
486
487 fn mach_uuid(&self) -> Result<Option<[u8; 16]>> {
488 self.header.uuid(self.endian, self.data, self.header_offset)
489 }
490
491 fn relative_address_base(&self) -> u64 {
492 0
493 }
494
495 fn entry(&self) -> u64 {
496 if let Ok(mut commands) =
497 self.header
498 .load_commands(self.endian, self.data, self.header_offset)
499 {
500 while let Ok(Some(command)) = commands.next() {
501 if let Ok(Some(command)) = command.entry_point() {
502 return command.entryoff.get(self.endian);
503 }
504 }
505 }
506 0
507 }
508
509 fn flags(&self) -> FileFlags {
510 FileFlags::MachO {
511 flags: self.header.flags(self.endian),
512 }
513 }
514}
515
516pub type MachOComdatIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
518 MachOComdatIterator<'data, 'file, macho::MachHeader32<Endian>, R>;
519pub type MachOComdatIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
521 MachOComdatIterator<'data, 'file, macho::MachHeader64<Endian>, R>;
522
523#[derive(Debug)]
527pub struct MachOComdatIterator<'data, 'file, Mach, R = &'data [u8]>
528where
529 Mach: MachHeader,
530 R: ReadRef<'data>,
531{
532 #[allow(unused)]
533 file: &'file MachOFile<'data, Mach, R>,
534}
535
536impl<'data, 'file, Mach, R> Iterator for MachOComdatIterator<'data, 'file, Mach, R>
537where
538 Mach: MachHeader,
539 R: ReadRef<'data>,
540{
541 type Item = MachOComdat<'data, 'file, Mach, R>;
542
543 #[inline]
544 fn next(&mut self) -> Option<Self::Item> {
545 None
546 }
547}
548
549pub type MachOComdat32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
551 MachOComdat<'data, 'file, macho::MachHeader32<Endian>, R>;
552
553pub type MachOComdat64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
555 MachOComdat<'data, 'file, macho::MachHeader64<Endian>, R>;
556
557#[derive(Debug)]
561pub struct MachOComdat<'data, 'file, Mach, R = &'data [u8]>
562where
563 Mach: MachHeader,
564 R: ReadRef<'data>,
565{
566 #[allow(unused)]
567 file: &'file MachOFile<'data, Mach, R>,
568}
569
570impl<'data, 'file, Mach, R> read::private::Sealed for MachOComdat<'data, 'file, Mach, R>
571where
572 Mach: MachHeader,
573 R: ReadRef<'data>,
574{
575}
576
577impl<'data, 'file, Mach, R> ObjectComdat<'data> for MachOComdat<'data, 'file, Mach, R>
578where
579 Mach: MachHeader,
580 R: ReadRef<'data>,
581{
582 type SectionIterator = MachOComdatSectionIterator<'data, 'file, Mach, R>;
583
584 #[inline]
585 fn kind(&self) -> ComdatKind {
586 unreachable!();
587 }
588
589 #[inline]
590 fn symbol(&self) -> SymbolIndex {
591 unreachable!();
592 }
593
594 #[inline]
595 fn name_bytes(&self) -> Result<&'data [u8]> {
596 unreachable!();
597 }
598
599 #[inline]
600 fn name(&self) -> Result<&'data str> {
601 unreachable!();
602 }
603
604 #[inline]
605 fn sections(&self) -> Self::SectionIterator {
606 unreachable!();
607 }
608}
609
610pub type MachOComdatSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
612 MachOComdatSectionIterator<'data, 'file, macho::MachHeader32<Endian>, R>;
613pub type MachOComdatSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
615 MachOComdatSectionIterator<'data, 'file, macho::MachHeader64<Endian>, R>;
616
617#[derive(Debug)]
621pub struct MachOComdatSectionIterator<'data, 'file, Mach, R = &'data [u8]>
622where
623 Mach: MachHeader,
624 R: ReadRef<'data>,
625{
626 #[allow(unused)]
627 file: &'file MachOFile<'data, Mach, R>,
628}
629
630impl<'data, 'file, Mach, R> Iterator for MachOComdatSectionIterator<'data, 'file, Mach, R>
631where
632 Mach: MachHeader,
633 R: ReadRef<'data>,
634{
635 type Item = SectionIndex;
636
637 fn next(&mut self) -> Option<Self::Item> {
638 None
639 }
640}
641
642#[allow(missing_docs)]
644pub trait MachHeader: Debug + Pod {
645 type Word: Into<u64>;
646 type Endian: endian::Endian;
647 type Segment: Segment<Endian = Self::Endian, Section = Self::Section>;
648 type Section: Section<Endian = Self::Endian>;
649 type Nlist: Nlist<Endian = Self::Endian>;
650
651 fn is_type_64(&self) -> bool;
655
656 fn is_big_endian(&self) -> bool;
658
659 fn is_little_endian(&self) -> bool;
661
662 fn magic(&self) -> u32;
663 fn cputype(&self, endian: Self::Endian) -> u32;
664 fn cpusubtype(&self, endian: Self::Endian) -> u32;
665 fn filetype(&self, endian: Self::Endian) -> u32;
666 fn ncmds(&self, endian: Self::Endian) -> u32;
667 fn sizeofcmds(&self, endian: Self::Endian) -> u32;
668 fn flags(&self, endian: Self::Endian) -> u32;
669
670 fn parse<'data, R: ReadRef<'data>>(data: R, offset: u64) -> read::Result<&'data Self> {
676 let header = data
677 .read_at::<Self>(offset)
678 .read_error("Invalid Mach-O header size or alignment")?;
679 if !header.is_supported() {
680 return Err(Error("Unsupported Mach-O header"));
681 }
682 Ok(header)
683 }
684
685 fn is_supported(&self) -> bool {
686 self.is_little_endian() || self.is_big_endian()
687 }
688
689 fn endian(&self) -> Result<Self::Endian> {
690 Self::Endian::from_big_endian(self.is_big_endian()).read_error("Unsupported Mach-O endian")
691 }
692
693 fn load_commands<'data, R: ReadRef<'data>>(
694 &self,
695 endian: Self::Endian,
696 data: R,
697 header_offset: u64,
698 ) -> Result<LoadCommandIterator<'data, Self::Endian>> {
699 let data = data
700 .read_bytes_at(
701 header_offset + mem::size_of::<Self>() as u64,
702 self.sizeofcmds(endian).into(),
703 )
704 .read_error("Invalid Mach-O load command table size")?;
705 Ok(LoadCommandIterator::new(endian, data, self.ncmds(endian)))
706 }
707
708 fn uuid<'data, R: ReadRef<'data>>(
710 &self,
711 endian: Self::Endian,
712 data: R,
713 header_offset: u64,
714 ) -> Result<Option<[u8; 16]>> {
715 let mut commands = self.load_commands(endian, data, header_offset)?;
716 while let Some(command) = commands.next()? {
717 if let Ok(Some(uuid)) = command.uuid() {
718 return Ok(Some(uuid.uuid));
719 }
720 }
721 Ok(None)
722 }
723}
724
725impl<Endian: endian::Endian> MachHeader for macho::MachHeader32<Endian> {
726 type Word = u32;
727 type Endian = Endian;
728 type Segment = macho::SegmentCommand32<Endian>;
729 type Section = macho::Section32<Endian>;
730 type Nlist = macho::Nlist32<Endian>;
731
732 fn is_type_64(&self) -> bool {
733 false
734 }
735
736 fn is_big_endian(&self) -> bool {
737 self.magic() == macho::MH_MAGIC
738 }
739
740 fn is_little_endian(&self) -> bool {
741 self.magic() == macho::MH_CIGAM
742 }
743
744 fn magic(&self) -> u32 {
745 self.magic.get(BigEndian)
746 }
747
748 fn cputype(&self, endian: Self::Endian) -> u32 {
749 self.cputype.get(endian)
750 }
751
752 fn cpusubtype(&self, endian: Self::Endian) -> u32 {
753 self.cpusubtype.get(endian)
754 }
755
756 fn filetype(&self, endian: Self::Endian) -> u32 {
757 self.filetype.get(endian)
758 }
759
760 fn ncmds(&self, endian: Self::Endian) -> u32 {
761 self.ncmds.get(endian)
762 }
763
764 fn sizeofcmds(&self, endian: Self::Endian) -> u32 {
765 self.sizeofcmds.get(endian)
766 }
767
768 fn flags(&self, endian: Self::Endian) -> u32 {
769 self.flags.get(endian)
770 }
771}
772
773impl<Endian: endian::Endian> MachHeader for macho::MachHeader64<Endian> {
774 type Word = u64;
775 type Endian = Endian;
776 type Segment = macho::SegmentCommand64<Endian>;
777 type Section = macho::Section64<Endian>;
778 type Nlist = macho::Nlist64<Endian>;
779
780 fn is_type_64(&self) -> bool {
781 true
782 }
783
784 fn is_big_endian(&self) -> bool {
785 self.magic() == macho::MH_MAGIC_64
786 }
787
788 fn is_little_endian(&self) -> bool {
789 self.magic() == macho::MH_CIGAM_64
790 }
791
792 fn magic(&self) -> u32 {
793 self.magic.get(BigEndian)
794 }
795
796 fn cputype(&self, endian: Self::Endian) -> u32 {
797 self.cputype.get(endian)
798 }
799
800 fn cpusubtype(&self, endian: Self::Endian) -> u32 {
801 self.cpusubtype.get(endian)
802 }
803
804 fn filetype(&self, endian: Self::Endian) -> u32 {
805 self.filetype.get(endian)
806 }
807
808 fn ncmds(&self, endian: Self::Endian) -> u32 {
809 self.ncmds.get(endian)
810 }
811
812 fn sizeofcmds(&self, endian: Self::Endian) -> u32 {
813 self.sizeofcmds.get(endian)
814 }
815
816 fn flags(&self, endian: Self::Endian) -> u32 {
817 self.flags.get(endian)
818 }
819}