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> = MachOSegment<'data, 'file, Mach, R> where Self: 'file, 'data: 'file;
225 type SegmentIterator<'file> = MachOSegmentIterator<'data, 'file, Mach, R> where Self: 'file, 'data: 'file;
226 type Section<'file> = MachOSection<'data, 'file, Mach, R> where Self: 'file, 'data: 'file;
227 type SectionIterator<'file> = MachOSectionIterator<'data, 'file, Mach, R> where Self: 'file, 'data: 'file;
228 type Comdat<'file> = MachOComdat<'data, 'file, Mach, R> where Self: 'file, 'data: 'file;
229 type ComdatIterator<'file> = MachOComdatIterator<'data, 'file, Mach, R> where Self: 'file, 'data: 'file;
230 type Symbol<'file> = MachOSymbol<'data, 'file, Mach, R> where Self: 'file, 'data: 'file;
231 type SymbolIterator<'file> = MachOSymbolIterator<'data, 'file, Mach, R> where Self: 'file, 'data: 'file;
232 type SymbolTable<'file> = MachOSymbolTable<'data, 'file, Mach, R> where Self: 'file, 'data: 'file;
233 type DynamicRelocationIterator<'file> = NoDynamicRelocationIterator where Self: 'file, 'data: 'file;
234
235 fn architecture(&self) -> Architecture {
236 match self.header.cputype(self.endian) {
237 macho::CPU_TYPE_ARM => Architecture::Arm,
238 macho::CPU_TYPE_ARM64 => Architecture::Aarch64,
239 macho::CPU_TYPE_ARM64_32 => Architecture::Aarch64_Ilp32,
240 macho::CPU_TYPE_X86 => Architecture::I386,
241 macho::CPU_TYPE_X86_64 => Architecture::X86_64,
242 macho::CPU_TYPE_MIPS => Architecture::Mips,
243 macho::CPU_TYPE_POWERPC => Architecture::PowerPc,
244 macho::CPU_TYPE_POWERPC64 => Architecture::PowerPc64,
245 _ => Architecture::Unknown,
246 }
247 }
248
249 fn sub_architecture(&self) -> Option<SubArchitecture> {
250 match (
251 self.header.cputype(self.endian),
252 self.header.cpusubtype(self.endian),
253 ) {
254 (macho::CPU_TYPE_ARM64, macho::CPU_SUBTYPE_ARM64E) => Some(SubArchitecture::Arm64E),
255 _ => None,
256 }
257 }
258
259 #[inline]
260 fn is_little_endian(&self) -> bool {
261 self.header.is_little_endian()
262 }
263
264 #[inline]
265 fn is_64(&self) -> bool {
266 self.header.is_type_64()
267 }
268
269 fn kind(&self) -> ObjectKind {
270 match self.header.filetype(self.endian) {
271 macho::MH_OBJECT => ObjectKind::Relocatable,
272 macho::MH_EXECUTE => ObjectKind::Executable,
273 macho::MH_CORE => ObjectKind::Core,
274 macho::MH_DYLIB => ObjectKind::Dynamic,
275 _ => ObjectKind::Unknown,
276 }
277 }
278
279 fn segments(&self) -> MachOSegmentIterator<'data, '_, Mach, R> {
280 MachOSegmentIterator {
281 file: self,
282 iter: self.segments.iter(),
283 }
284 }
285
286 fn section_by_name_bytes<'file>(
287 &'file self,
288 section_name: &[u8],
289 ) -> Option<MachOSection<'data, 'file, Mach, R>> {
290 let make_prefix_matcher = |query_prefix: &'static [u8], name_prefix: &'static [u8]| {
294 const MAX_SECTION_NAME_LEN: usize = 16;
295 let suffix = section_name.strip_prefix(query_prefix).map(|suffix| {
296 let max_len = MAX_SECTION_NAME_LEN - name_prefix.len();
297 &suffix[..suffix.len().min(max_len)]
298 });
299 move |name: &[u8]| suffix.is_some() && name.strip_prefix(name_prefix) == suffix
300 };
301 let matches_underscores_prefix = make_prefix_matcher(b".", b"__");
305 let matches_zdebug_prefix = make_prefix_matcher(b".debug_", b"__zdebug_");
309 self.sections().find(|section| {
310 section.name_bytes().map_or(false, |name| {
311 name == section_name
312 || matches_underscores_prefix(name)
313 || matches_zdebug_prefix(name)
314 })
315 })
316 }
317
318 fn section_by_index(&self, index: SectionIndex) -> Result<MachOSection<'data, '_, Mach, R>> {
319 let internal = *self.section_internal(index)?;
320 Ok(MachOSection {
321 file: self,
322 internal,
323 })
324 }
325
326 fn sections(&self) -> MachOSectionIterator<'data, '_, Mach, R> {
327 MachOSectionIterator {
328 file: self,
329 iter: self.sections.iter(),
330 }
331 }
332
333 fn comdats(&self) -> MachOComdatIterator<'data, '_, Mach, R> {
334 MachOComdatIterator { file: self }
335 }
336
337 fn symbol_by_index(&self, index: SymbolIndex) -> Result<MachOSymbol<'data, '_, Mach, R>> {
338 let nlist = self.symbols.symbol(index)?;
339 MachOSymbol::new(self, index, nlist).read_error("Unsupported Mach-O symbol index")
340 }
341
342 fn symbols(&self) -> MachOSymbolIterator<'data, '_, Mach, R> {
343 MachOSymbolIterator::new(self)
344 }
345
346 #[inline]
347 fn symbol_table(&self) -> Option<MachOSymbolTable<'data, '_, Mach, R>> {
348 Some(MachOSymbolTable { file: self })
349 }
350
351 fn dynamic_symbols(&self) -> MachOSymbolIterator<'data, '_, Mach, R> {
352 MachOSymbolIterator::empty(self)
353 }
354
355 #[inline]
356 fn dynamic_symbol_table(&self) -> Option<MachOSymbolTable<'data, '_, Mach, R>> {
357 None
358 }
359
360 fn object_map(&self) -> ObjectMap<'data> {
361 self.symbols.object_map(self.endian)
362 }
363
364 fn imports(&self) -> Result<Vec<Import<'data>>> {
365 let mut dysymtab = None;
366 let mut libraries = Vec::new();
367 let twolevel = self.header.flags(self.endian) & macho::MH_TWOLEVEL != 0;
368 if twolevel {
369 libraries.push(&[][..]);
370 }
371 let mut commands = self
372 .header
373 .load_commands(self.endian, self.data, self.header_offset)?;
374 while let Some(command) = commands.next()? {
375 if let Some(command) = command.dysymtab()? {
376 dysymtab = Some(command);
377 }
378 if twolevel {
379 if let Some(dylib) = command.dylib()? {
380 libraries.push(command.string(self.endian, dylib.dylib.name)?);
381 }
382 }
383 }
384
385 let mut imports = Vec::new();
386 if let Some(dysymtab) = dysymtab {
387 let index = dysymtab.iundefsym.get(self.endian) as usize;
388 let number = dysymtab.nundefsym.get(self.endian) as usize;
389 for i in index..(index.wrapping_add(number)) {
390 let symbol = self.symbols.symbol(SymbolIndex(i))?;
391 let name = symbol.name(self.endian, self.symbols.strings())?;
392 let library = if twolevel {
393 libraries
394 .get(symbol.library_ordinal(self.endian) as usize)
395 .copied()
396 .read_error("Invalid Mach-O symbol library ordinal")?
397 } else {
398 &[]
399 };
400 imports.push(Import {
401 name: ByteString(name),
402 library: ByteString(library),
403 });
404 }
405 }
406 Ok(imports)
407 }
408
409 fn exports(&self) -> Result<Vec<Export<'data>>> {
410 let mut dysymtab = None;
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 break;
418 }
419 }
420
421 let mut exports = Vec::new();
422 if let Some(dysymtab) = dysymtab {
423 let index = dysymtab.iextdefsym.get(self.endian) as usize;
424 let number = dysymtab.nextdefsym.get(self.endian) as usize;
425 for i in index..(index.wrapping_add(number)) {
426 let symbol = self.symbols.symbol(SymbolIndex(i))?;
427 let name = symbol.name(self.endian, self.symbols.strings())?;
428 let address = symbol.n_value(self.endian).into();
429 exports.push(Export {
430 name: ByteString(name),
431 address,
432 });
433 }
434 }
435 Ok(exports)
436 }
437
438 #[inline]
439 fn dynamic_relocations(&self) -> Option<NoDynamicRelocationIterator> {
440 None
441 }
442
443 fn has_debug_symbols(&self) -> bool {
444 self.section_by_name(".debug_info").is_some()
445 }
446
447 fn mach_uuid(&self) -> Result<Option<[u8; 16]>> {
448 self.header.uuid(self.endian, self.data, self.header_offset)
449 }
450
451 fn relative_address_base(&self) -> u64 {
452 0
453 }
454
455 fn entry(&self) -> u64 {
456 if let Ok(mut commands) =
457 self.header
458 .load_commands(self.endian, self.data, self.header_offset)
459 {
460 while let Ok(Some(command)) = commands.next() {
461 if let Ok(Some(command)) = command.entry_point() {
462 return command.entryoff.get(self.endian);
463 }
464 }
465 }
466 0
467 }
468
469 fn flags(&self) -> FileFlags {
470 FileFlags::MachO {
471 flags: self.header.flags(self.endian),
472 }
473 }
474}
475
476pub type MachOComdatIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
478 MachOComdatIterator<'data, 'file, macho::MachHeader32<Endian>, R>;
479pub type MachOComdatIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
481 MachOComdatIterator<'data, 'file, macho::MachHeader64<Endian>, R>;
482
483#[derive(Debug)]
487pub struct MachOComdatIterator<'data, 'file, Mach, R = &'data [u8]>
488where
489 Mach: MachHeader,
490 R: ReadRef<'data>,
491{
492 #[allow(unused)]
493 file: &'file MachOFile<'data, Mach, R>,
494}
495
496impl<'data, 'file, Mach, R> Iterator for MachOComdatIterator<'data, 'file, Mach, R>
497where
498 Mach: MachHeader,
499 R: ReadRef<'data>,
500{
501 type Item = MachOComdat<'data, 'file, Mach, R>;
502
503 #[inline]
504 fn next(&mut self) -> Option<Self::Item> {
505 None
506 }
507}
508
509pub type MachOComdat32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
511 MachOComdat<'data, 'file, macho::MachHeader32<Endian>, R>;
512
513pub type MachOComdat64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
515 MachOComdat<'data, 'file, macho::MachHeader64<Endian>, R>;
516
517#[derive(Debug)]
521pub struct MachOComdat<'data, 'file, Mach, R = &'data [u8]>
522where
523 Mach: MachHeader,
524 R: ReadRef<'data>,
525{
526 #[allow(unused)]
527 file: &'file MachOFile<'data, Mach, R>,
528}
529
530impl<'data, 'file, Mach, R> read::private::Sealed for MachOComdat<'data, 'file, Mach, R>
531where
532 Mach: MachHeader,
533 R: ReadRef<'data>,
534{
535}
536
537impl<'data, 'file, Mach, R> ObjectComdat<'data> for MachOComdat<'data, 'file, Mach, R>
538where
539 Mach: MachHeader,
540 R: ReadRef<'data>,
541{
542 type SectionIterator = MachOComdatSectionIterator<'data, 'file, Mach, R>;
543
544 #[inline]
545 fn kind(&self) -> ComdatKind {
546 unreachable!();
547 }
548
549 #[inline]
550 fn symbol(&self) -> SymbolIndex {
551 unreachable!();
552 }
553
554 #[inline]
555 fn name_bytes(&self) -> Result<&'data [u8]> {
556 unreachable!();
557 }
558
559 #[inline]
560 fn name(&self) -> Result<&'data str> {
561 unreachable!();
562 }
563
564 #[inline]
565 fn sections(&self) -> Self::SectionIterator {
566 unreachable!();
567 }
568}
569
570pub type MachOComdatSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
572 MachOComdatSectionIterator<'data, 'file, macho::MachHeader32<Endian>, R>;
573pub type MachOComdatSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
575 MachOComdatSectionIterator<'data, 'file, macho::MachHeader64<Endian>, R>;
576
577#[derive(Debug)]
581pub struct MachOComdatSectionIterator<'data, 'file, Mach, R = &'data [u8]>
582where
583 Mach: MachHeader,
584 R: ReadRef<'data>,
585{
586 #[allow(unused)]
587 file: &'file MachOFile<'data, Mach, R>,
588}
589
590impl<'data, 'file, Mach, R> Iterator for MachOComdatSectionIterator<'data, 'file, Mach, R>
591where
592 Mach: MachHeader,
593 R: ReadRef<'data>,
594{
595 type Item = SectionIndex;
596
597 fn next(&mut self) -> Option<Self::Item> {
598 None
599 }
600}
601
602#[allow(missing_docs)]
604pub trait MachHeader: Debug + Pod {
605 type Word: Into<u64>;
606 type Endian: endian::Endian;
607 type Segment: Segment<Endian = Self::Endian, Section = Self::Section>;
608 type Section: Section<Endian = Self::Endian>;
609 type Nlist: Nlist<Endian = Self::Endian>;
610
611 fn is_type_64(&self) -> bool;
615
616 fn is_big_endian(&self) -> bool;
618
619 fn is_little_endian(&self) -> bool;
621
622 fn magic(&self) -> u32;
623 fn cputype(&self, endian: Self::Endian) -> u32;
624 fn cpusubtype(&self, endian: Self::Endian) -> u32;
625 fn filetype(&self, endian: Self::Endian) -> u32;
626 fn ncmds(&self, endian: Self::Endian) -> u32;
627 fn sizeofcmds(&self, endian: Self::Endian) -> u32;
628 fn flags(&self, endian: Self::Endian) -> u32;
629
630 fn parse<'data, R: ReadRef<'data>>(data: R, offset: u64) -> read::Result<&'data Self> {
636 let header = data
637 .read_at::<Self>(offset)
638 .read_error("Invalid Mach-O header size or alignment")?;
639 if !header.is_supported() {
640 return Err(Error("Unsupported Mach-O header"));
641 }
642 Ok(header)
643 }
644
645 fn is_supported(&self) -> bool {
646 self.is_little_endian() || self.is_big_endian()
647 }
648
649 fn endian(&self) -> Result<Self::Endian> {
650 Self::Endian::from_big_endian(self.is_big_endian()).read_error("Unsupported Mach-O endian")
651 }
652
653 fn load_commands<'data, R: ReadRef<'data>>(
654 &self,
655 endian: Self::Endian,
656 data: R,
657 header_offset: u64,
658 ) -> Result<LoadCommandIterator<'data, Self::Endian>> {
659 let data = data
660 .read_bytes_at(
661 header_offset + mem::size_of::<Self>() as u64,
662 self.sizeofcmds(endian).into(),
663 )
664 .read_error("Invalid Mach-O load command table size")?;
665 Ok(LoadCommandIterator::new(endian, data, self.ncmds(endian)))
666 }
667
668 fn uuid<'data, R: ReadRef<'data>>(
670 &self,
671 endian: Self::Endian,
672 data: R,
673 header_offset: u64,
674 ) -> Result<Option<[u8; 16]>> {
675 let mut commands = self.load_commands(endian, data, header_offset)?;
676 while let Some(command) = commands.next()? {
677 if let Ok(Some(uuid)) = command.uuid() {
678 return Ok(Some(uuid.uuid));
679 }
680 }
681 Ok(None)
682 }
683}
684
685impl<Endian: endian::Endian> MachHeader for macho::MachHeader32<Endian> {
686 type Word = u32;
687 type Endian = Endian;
688 type Segment = macho::SegmentCommand32<Endian>;
689 type Section = macho::Section32<Endian>;
690 type Nlist = macho::Nlist32<Endian>;
691
692 fn is_type_64(&self) -> bool {
693 false
694 }
695
696 fn is_big_endian(&self) -> bool {
697 self.magic() == macho::MH_MAGIC
698 }
699
700 fn is_little_endian(&self) -> bool {
701 self.magic() == macho::MH_CIGAM
702 }
703
704 fn magic(&self) -> u32 {
705 self.magic.get(BigEndian)
706 }
707
708 fn cputype(&self, endian: Self::Endian) -> u32 {
709 self.cputype.get(endian)
710 }
711
712 fn cpusubtype(&self, endian: Self::Endian) -> u32 {
713 self.cpusubtype.get(endian)
714 }
715
716 fn filetype(&self, endian: Self::Endian) -> u32 {
717 self.filetype.get(endian)
718 }
719
720 fn ncmds(&self, endian: Self::Endian) -> u32 {
721 self.ncmds.get(endian)
722 }
723
724 fn sizeofcmds(&self, endian: Self::Endian) -> u32 {
725 self.sizeofcmds.get(endian)
726 }
727
728 fn flags(&self, endian: Self::Endian) -> u32 {
729 self.flags.get(endian)
730 }
731}
732
733impl<Endian: endian::Endian> MachHeader for macho::MachHeader64<Endian> {
734 type Word = u64;
735 type Endian = Endian;
736 type Segment = macho::SegmentCommand64<Endian>;
737 type Section = macho::Section64<Endian>;
738 type Nlist = macho::Nlist64<Endian>;
739
740 fn is_type_64(&self) -> bool {
741 true
742 }
743
744 fn is_big_endian(&self) -> bool {
745 self.magic() == macho::MH_MAGIC_64
746 }
747
748 fn is_little_endian(&self) -> bool {
749 self.magic() == macho::MH_CIGAM_64
750 }
751
752 fn magic(&self) -> u32 {
753 self.magic.get(BigEndian)
754 }
755
756 fn cputype(&self, endian: Self::Endian) -> u32 {
757 self.cputype.get(endian)
758 }
759
760 fn cpusubtype(&self, endian: Self::Endian) -> u32 {
761 self.cpusubtype.get(endian)
762 }
763
764 fn filetype(&self, endian: Self::Endian) -> u32 {
765 self.filetype.get(endian)
766 }
767
768 fn ncmds(&self, endian: Self::Endian) -> u32 {
769 self.ncmds.get(endian)
770 }
771
772 fn sizeofcmds(&self, endian: Self::Endian) -> u32 {
773 self.sizeofcmds.get(endian)
774 }
775
776 fn flags(&self, endian: Self::Endian) -> u32 {
777 self.flags.get(endian)
778 }
779}