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