1use alloc::vec::Vec;
2use core::fmt::Debug;
3use core::{mem, str};
4
5use crate::read::{
6 self, Architecture, ComdatKind, Error, Export, FileFlags, Import, NoDynamicRelocationIterator,
7 Object, ObjectComdat, ObjectKind, ObjectMap, ObjectSection, ReadError, ReadRef, Result,
8 SectionIndex, SubArchitecture, SymbolIndex,
9};
10use crate::{endian, macho, BigEndian, ByteString, Endian, Endianness, Pod};
11
12use super::{
13 DyldCacheImage, LoadCommandIterator, MachOSection, MachOSectionInternal, MachOSectionIterator,
14 MachOSegment, MachOSegmentInternal, MachOSegmentIterator, MachOSymbol, MachOSymbolIterator,
15 MachOSymbolTable, Nlist, Section, Segment, SymbolTable,
16};
17
18/// A 32-bit Mach-O object file.
19///
20/// This is a file that starts with [`macho::MachHeader32`], and corresponds
21/// to [`crate::FileKind::MachO32`].
22pub type MachOFile32<'data, Endian = Endianness, R = &'data [u8]> =
23 MachOFile<'data, macho::MachHeader32<Endian>, R>;
24/// A 64-bit Mach-O object file.
25///
26/// This is a file that starts with [`macho::MachHeader64`], and corresponds
27/// to [`crate::FileKind::MachO64`].
28pub type MachOFile64<'data, Endian = Endianness, R = &'data [u8]> =
29 MachOFile<'data, macho::MachHeader64<Endian>, R>;
30
31/// A partially parsed Mach-O file.
32///
33/// Most of the functionality of this type is provided by the [`Object`] trait implementation.
34#[derive(Debug)]
35pub struct MachOFile<'data, Mach, R = &'data [u8]>
36where
37 Mach: MachHeader,
38 R: ReadRef<'data>,
39{
40 pub(super) endian: Mach::Endian,
41 pub(super) data: R,
42 pub(super) header_offset: u64,
43 pub(super) header: &'data Mach,
44 pub(super) segments: Vec<MachOSegmentInternal<'data, Mach, R>>,
45 pub(super) sections: Vec<MachOSectionInternal<'data, Mach>>,
46 pub(super) symbols: SymbolTable<'data, Mach, R>,
47}
48
49impl<'data, Mach, R> MachOFile<'data, Mach, R>
50where
51 Mach: MachHeader,
52 R: ReadRef<'data>,
53{
54 /// Parse the raw Mach-O file data.
55 pub fn parse(data: R) -> Result<Self> {
56 let header = Mach::parse(data, 0)?;
57 let endian = header.endian()?;
58
59 // Build a list of segments and sections to make some operations more efficient.
60 let mut segments = Vec::new();
61 let mut sections = Vec::new();
62 let mut symbols = SymbolTable::default();
63 if let Ok(mut commands) = header.load_commands(endian, data, 0) {
64 while let Ok(Some(command)) = commands.next() {
65 if let Some((segment, section_data)) = Mach::Segment::from_command(command)? {
66 let segment_index = segments.len();
67 segments.push(MachOSegmentInternal { segment, data });
68 for section in segment.sections(endian, section_data)? {
69 let index = SectionIndex(sections.len() + 1);
70 sections.push(MachOSectionInternal::parse(index, segment_index, section));
71 }
72 } else if let Some(symtab) = command.symtab()? {
73 symbols = symtab.symbols(endian, data)?;
74 }
75 }
76 }
77
78 Ok(MachOFile {
79 endian,
80 data,
81 header_offset: 0,
82 header,
83 segments,
84 sections,
85 symbols,
86 })
87 }
88
89 /// Parse the Mach-O file for the given image from the dyld shared cache.
90 /// This will read different sections from different subcaches, if necessary.
91 pub fn parse_dyld_cache_image<'cache, E: Endian>(
92 image: &DyldCacheImage<'data, 'cache, E, R>,
93 ) -> Result<Self> {
94 let (data, header_offset) = image.image_data_and_offset()?;
95 let header = Mach::parse(data, header_offset)?;
96 let endian = header.endian()?;
97
98 // Build a list of sections to make some operations more efficient.
99 // Also build a list of segments, because we need to remember which ReadRef
100 // to read each section's data from. Only the DyldCache knows this information,
101 // and we won't have access to it once we've exited this function.
102 let mut segments = Vec::new();
103 let mut sections = Vec::new();
104 let mut linkedit_data: Option<R> = None;
105 let mut symtab = None;
106 if let Ok(mut commands) = header.load_commands(endian, data, header_offset) {
107 while let Ok(Some(command)) = commands.next() {
108 if let Some((segment, section_data)) = Mach::Segment::from_command(command)? {
109 // Each segment can be stored in a different subcache. Get the segment's
110 // address and look it up in the cache mappings, to find the correct cache data.
111 let addr = segment.vmaddr(endian).into();
112 let (data, _offset) = image
113 .cache
114 .data_and_offset_for_address(addr)
115 .read_error("Could not find segment data in dyld shared cache")?;
116 if segment.name() == macho::SEG_LINKEDIT.as_bytes() {
117 linkedit_data = Some(data);
118 }
119 let segment_index = segments.len();
120 segments.push(MachOSegmentInternal { segment, data });
121
122 for section in segment.sections(endian, section_data)? {
123 let index = SectionIndex(sections.len() + 1);
124 sections.push(MachOSectionInternal::parse(index, segment_index, section));
125 }
126 } else if let Some(st) = command.symtab()? {
127 symtab = Some(st);
128 }
129 }
130 }
131
132 // The symbols are found in the __LINKEDIT segment, so make sure to read them from the
133 // correct subcache.
134 let symbols = match (symtab, linkedit_data) {
135 (Some(symtab), Some(linkedit_data)) => symtab.symbols(endian, linkedit_data)?,
136 _ => SymbolTable::default(),
137 };
138
139 Ok(MachOFile {
140 endian,
141 data,
142 header_offset,
143 header,
144 segments,
145 sections,
146 symbols,
147 })
148 }
149
150 /// Return the section at the given index.
151 #[inline]
152 pub(super) fn section_internal(
153 &self,
154 index: SectionIndex,
155 ) -> Result<&MachOSectionInternal<'data, Mach>> {
156 index
157 .0
158 .checked_sub(1)
159 .and_then(|index| self.sections.get(index))
160 .read_error("Invalid Mach-O section index")
161 }
162
163 pub(super) fn segment_internal(
164 &self,
165 index: usize,
166 ) -> Result<&MachOSegmentInternal<'data, Mach, R>> {
167 self.segments
168 .get(index)
169 .read_error("Invalid Mach-O segment index")
170 }
171
172 /// Returns the endianness.
173 pub fn endian(&self) -> Mach::Endian {
174 self.endian
175 }
176
177 /// Returns the raw data.
178 pub fn data(&self) -> R {
179 self.data
180 }
181
182 /// Returns the raw Mach-O file header.
183 pub fn raw_header(&self) -> &'data Mach {
184 self.header
185 }
186
187 /// Return the `LC_BUILD_VERSION` load command if present.
188 pub fn build_version(&self) -> Result<Option<&'data macho::BuildVersionCommand<Mach::Endian>>> {
189 let mut commands = self
190 .header
191 .load_commands(self.endian, self.data, self.header_offset)?;
192 while let Some(command) = commands.next()? {
193 if let Some(build_version) = command.build_version()? {
194 return Ok(Some(build_version));
195 }
196 }
197 Ok(None)
198 }
199}
200
201impl<'data, Mach, R> read::private::Sealed for MachOFile<'data, Mach, R>
202where
203 Mach: MachHeader,
204 R: ReadRef<'data>,
205{
206}
207
208impl<'data, 'file, Mach, R> Object<'data, 'file> for MachOFile<'data, Mach, R>
209where
210 'data: 'file,
211 Mach: MachHeader,
212 R: 'file + ReadRef<'data>,
213{
214 type Segment = MachOSegment<'data, 'file, Mach, R>;
215 type SegmentIterator = MachOSegmentIterator<'data, 'file, Mach, R>;
216 type Section = MachOSection<'data, 'file, Mach, R>;
217 type SectionIterator = MachOSectionIterator<'data, 'file, Mach, R>;
218 type Comdat = MachOComdat<'data, 'file, Mach, R>;
219 type ComdatIterator = MachOComdatIterator<'data, 'file, Mach, R>;
220 type Symbol = MachOSymbol<'data, 'file, Mach, R>;
221 type SymbolIterator = MachOSymbolIterator<'data, 'file, Mach, R>;
222 type SymbolTable = MachOSymbolTable<'data, 'file, Mach, R>;
223 type DynamicRelocationIterator = NoDynamicRelocationIterator;
224
225 fn architecture(&self) -> Architecture {
226 match self.header.cputype(self.endian) {
227 macho::CPU_TYPE_ARM => Architecture::Arm,
228 macho::CPU_TYPE_ARM64 => Architecture::Aarch64,
229 macho::CPU_TYPE_ARM64_32 => Architecture::Aarch64_Ilp32,
230 macho::CPU_TYPE_X86 => Architecture::I386,
231 macho::CPU_TYPE_X86_64 => Architecture::X86_64,
232 macho::CPU_TYPE_MIPS => Architecture::Mips,
233 macho::CPU_TYPE_POWERPC => Architecture::PowerPc,
234 macho::CPU_TYPE_POWERPC64 => Architecture::PowerPc64,
235 _ => Architecture::Unknown,
236 }
237 }
238
239 fn sub_architecture(&self) -> Option<SubArchitecture> {
240 match (
241 self.header.cputype(self.endian),
242 self.header.cpusubtype(self.endian),
243 ) {
244 (macho::CPU_TYPE_ARM64, macho::CPU_SUBTYPE_ARM64E) => Some(SubArchitecture::Arm64E),
245 _ => None,
246 }
247 }
248
249 #[inline]
250 fn is_little_endian(&self) -> bool {
251 self.header.is_little_endian()
252 }
253
254 #[inline]
255 fn is_64(&self) -> bool {
256 self.header.is_type_64()
257 }
258
259 fn kind(&self) -> ObjectKind {
260 match self.header.filetype(self.endian) {
261 macho::MH_OBJECT => ObjectKind::Relocatable,
262 macho::MH_EXECUTE => ObjectKind::Executable,
263 macho::MH_CORE => ObjectKind::Core,
264 macho::MH_DYLIB => ObjectKind::Dynamic,
265 _ => ObjectKind::Unknown,
266 }
267 }
268
269 fn segments(&'file self) -> MachOSegmentIterator<'data, 'file, Mach, R> {
270 MachOSegmentIterator {
271 file: self,
272 iter: self.segments.iter(),
273 }
274 }
275
276 fn section_by_name_bytes(
277 &'file self,
278 section_name: &[u8],
279 ) -> Option<MachOSection<'data, 'file, Mach, R>> {
280 // Translate the "." prefix to the "__" prefix used by OSX/Mach-O, eg
281 // ".debug_info" to "__debug_info", and limit to 16 bytes total.
282 let system_name = if section_name.starts_with(b".") {
283 if section_name.len() > 15 {
284 Some(&section_name[1..15])
285 } else {
286 Some(&section_name[1..])
287 }
288 } else {
289 None
290 };
291 let cmp_section_name = |section: &MachOSection<'data, 'file, Mach, R>| {
292 section
293 .name_bytes()
294 .map(|name| {
295 section_name == name
296 || system_name
297 .filter(|system_name| {
298 name.starts_with(b"__") && name[2..] == **system_name
299 })
300 .is_some()
301 })
302 .unwrap_or(false)
303 };
304
305 self.sections().find(cmp_section_name)
306 }
307
308 fn section_by_index(
309 &'file self,
310 index: SectionIndex,
311 ) -> Result<MachOSection<'data, 'file, Mach, R>> {
312 let internal = *self.section_internal(index)?;
313 Ok(MachOSection {
314 file: self,
315 internal,
316 })
317 }
318
319 fn sections(&'file self) -> MachOSectionIterator<'data, 'file, Mach, R> {
320 MachOSectionIterator {
321 file: self,
322 iter: self.sections.iter(),
323 }
324 }
325
326 fn comdats(&'file self) -> MachOComdatIterator<'data, 'file, Mach, R> {
327 MachOComdatIterator { file: self }
328 }
329
330 fn symbol_by_index(
331 &'file self,
332 index: SymbolIndex,
333 ) -> Result<MachOSymbol<'data, 'file, Mach, R>> {
334 let nlist = self.symbols.symbol(index.0)?;
335 MachOSymbol::new(self, index, nlist).read_error("Unsupported Mach-O symbol index")
336 }
337
338 fn symbols(&'file self) -> MachOSymbolIterator<'data, 'file, Mach, R> {
339 MachOSymbolIterator {
340 file: self,
341 index: 0,
342 }
343 }
344
345 #[inline]
346 fn symbol_table(&'file self) -> Option<MachOSymbolTable<'data, 'file, Mach, R>> {
347 Some(MachOSymbolTable { file: self })
348 }
349
350 fn dynamic_symbols(&'file self) -> MachOSymbolIterator<'data, 'file, Mach, R> {
351 MachOSymbolIterator {
352 file: self,
353 index: self.symbols.len(),
354 }
355 }
356
357 #[inline]
358 fn dynamic_symbol_table(&'file self) -> Option<MachOSymbolTable<'data, 'file, Mach, R>> {
359 None
360 }
361
362 fn object_map(&'file self) -> ObjectMap<'data> {
363 self.symbols.object_map(self.endian)
364 }
365
366 fn imports(&self) -> Result<Vec<Import<'data>>> {
367 let mut dysymtab = None;
368 let mut libraries = Vec::new();
369 let twolevel = self.header.flags(self.endian) & macho::MH_TWOLEVEL != 0;
370 if twolevel {
371 libraries.push(&[][..]);
372 }
373 let mut commands = self
374 .header
375 .load_commands(self.endian, self.data, self.header_offset)?;
376 while let Some(command) = commands.next()? {
377 if let Some(command) = command.dysymtab()? {
378 dysymtab = Some(command);
379 }
380 if twolevel {
381 if let Some(dylib) = command.dylib()? {
382 libraries.push(command.string(self.endian, dylib.dylib.name)?);
383 }
384 }
385 }
386
387 let mut imports = Vec::new();
388 if let Some(dysymtab) = dysymtab {
389 let index = dysymtab.iundefsym.get(self.endian) as usize;
390 let number = dysymtab.nundefsym.get(self.endian) as usize;
391 for i in index..(index.wrapping_add(number)) {
392 let symbol = self.symbols.symbol(i)?;
393 let name = symbol.name(self.endian, self.symbols.strings())?;
394 let library = if twolevel {
395 libraries
396 .get(symbol.library_ordinal(self.endian) as usize)
397 .copied()
398 .read_error("Invalid Mach-O symbol library ordinal")?
399 } else {
400 &[]
401 };
402 imports.push(Import {
403 name: ByteString(name),
404 library: ByteString(library),
405 });
406 }
407 }
408 Ok(imports)
409 }
410
411 fn exports(&self) -> Result<Vec<Export<'data>>> {
412 let mut dysymtab = None;
413 let mut commands = self
414 .header
415 .load_commands(self.endian, self.data, self.header_offset)?;
416 while let Some(command) = commands.next()? {
417 if let Some(command) = command.dysymtab()? {
418 dysymtab = Some(command);
419 break;
420 }
421 }
422
423 let mut exports = Vec::new();
424 if let Some(dysymtab) = dysymtab {
425 let index = dysymtab.iextdefsym.get(self.endian) as usize;
426 let number = dysymtab.nextdefsym.get(self.endian) as usize;
427 for i in index..(index.wrapping_add(number)) {
428 let symbol = self.symbols.symbol(i)?;
429 let name = symbol.name(self.endian, self.symbols.strings())?;
430 let address = symbol.n_value(self.endian).into();
431 exports.push(Export {
432 name: ByteString(name),
433 address,
434 });
435 }
436 }
437 Ok(exports)
438 }
439
440 #[inline]
441 fn dynamic_relocations(&'file self) -> Option<NoDynamicRelocationIterator> {
442 None
443 }
444
445 fn has_debug_symbols(&self) -> bool {
446 self.section_by_name(".debug_info").is_some()
447 }
448
449 fn mach_uuid(&self) -> Result<Option<[u8; 16]>> {
450 self.header.uuid(self.endian, self.data, self.header_offset)
451 }
452
453 fn relative_address_base(&self) -> u64 {
454 0
455 }
456
457 fn entry(&self) -> u64 {
458 if let Ok(mut commands) =
459 self.header
460 .load_commands(self.endian, self.data, self.header_offset)
461 {
462 while let Ok(Some(command)) = commands.next() {
463 if let Ok(Some(command)) = command.entry_point() {
464 return command.entryoff.get(self.endian);
465 }
466 }
467 }
468 0
469 }
470
471 fn flags(&self) -> FileFlags {
472 FileFlags::MachO {
473 flags: self.header.flags(self.endian),
474 }
475 }
476}
477
478/// An iterator for the COMDAT section groups in a [`MachOFile64`].
479pub type MachOComdatIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
480 MachOComdatIterator<'data, 'file, macho::MachHeader32<Endian>, R>;
481/// An iterator for the COMDAT section groups in a [`MachOFile64`].
482pub type MachOComdatIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
483 MachOComdatIterator<'data, 'file, macho::MachHeader64<Endian>, R>;
484
485/// An iterator for the COMDAT section groups in a [`MachOFile`].
486///
487/// This is a stub that doesn't implement any functionality.
488#[derive(Debug)]
489pub struct MachOComdatIterator<'data, 'file, Mach, R = &'data [u8]>
490where
491 Mach: MachHeader,
492 R: ReadRef<'data>,
493{
494 #[allow(unused)]
495 file: &'file MachOFile<'data, Mach, R>,
496}
497
498impl<'data, 'file, Mach, R> Iterator for MachOComdatIterator<'data, 'file, Mach, R>
499where
500 Mach: MachHeader,
501 R: ReadRef<'data>,
502{
503 type Item = MachOComdat<'data, 'file, Mach, R>;
504
505 #[inline]
506 fn next(&mut self) -> Option<Self::Item> {
507 None
508 }
509}
510
511/// A COMDAT section group in a [`MachOFile32`].
512pub type MachOComdat32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
513 MachOComdat<'data, 'file, macho::MachHeader32<Endian>, R>;
514
515/// A COMDAT section group in a [`MachOFile64`].
516pub type MachOComdat64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
517 MachOComdat<'data, 'file, macho::MachHeader64<Endian>, R>;
518
519/// A COMDAT section group in a [`MachOFile`].
520///
521/// This is a stub that doesn't implement any functionality.
522#[derive(Debug)]
523pub struct MachOComdat<'data, 'file, Mach, R = &'data [u8]>
524where
525 Mach: MachHeader,
526 R: ReadRef<'data>,
527{
528 #[allow(unused)]
529 file: &'file MachOFile<'data, Mach, R>,
530}
531
532impl<'data, 'file, Mach, R> read::private::Sealed for MachOComdat<'data, 'file, Mach, R>
533where
534 Mach: MachHeader,
535 R: ReadRef<'data>,
536{
537}
538
539impl<'data, 'file, Mach, R> ObjectComdat<'data> for MachOComdat<'data, 'file, Mach, R>
540where
541 Mach: MachHeader,
542 R: ReadRef<'data>,
543{
544 type SectionIterator = MachOComdatSectionIterator<'data, 'file, Mach, R>;
545
546 #[inline]
547 fn kind(&self) -> ComdatKind {
548 unreachable!();
549 }
550
551 #[inline]
552 fn symbol(&self) -> SymbolIndex {
553 unreachable!();
554 }
555
556 #[inline]
557 fn name_bytes(&self) -> Result<&[u8]> {
558 unreachable!();
559 }
560
561 #[inline]
562 fn name(&self) -> Result<&str> {
563 unreachable!();
564 }
565
566 #[inline]
567 fn sections(&self) -> Self::SectionIterator {
568 unreachable!();
569 }
570}
571
572/// An iterator for the sections in a COMDAT section group in a [`MachOFile32`].
573pub type MachOComdatSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
574 MachOComdatSectionIterator<'data, 'file, macho::MachHeader32<Endian>, R>;
575/// An iterator for the sections in a COMDAT section group in a [`MachOFile64`].
576pub type MachOComdatSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
577 MachOComdatSectionIterator<'data, 'file, macho::MachHeader64<Endian>, R>;
578
579/// An iterator for the sections in a COMDAT section group in a [`MachOFile`].
580///
581/// This is a stub that doesn't implement any functionality.
582#[derive(Debug)]
583pub struct MachOComdatSectionIterator<'data, 'file, Mach, R = &'data [u8]>
584where
585 Mach: MachHeader,
586 R: ReadRef<'data>,
587{
588 #[allow(unused)]
589 file: &'file MachOFile<'data, Mach, R>,
590}
591
592impl<'data, 'file, Mach, R> Iterator for MachOComdatSectionIterator<'data, 'file, Mach, R>
593where
594 Mach: MachHeader,
595 R: ReadRef<'data>,
596{
597 type Item = SectionIndex;
598
599 fn next(&mut self) -> Option<Self::Item> {
600 None
601 }
602}
603
604/// A trait for generic access to [`macho::MachHeader32`] and [`macho::MachHeader64`].
605#[allow(missing_docs)]
606pub trait MachHeader: Debug + Pod {
607 type Word: Into<u64>;
608 type Endian: endian::Endian;
609 type Segment: Segment<Endian = Self::Endian, Section = Self::Section>;
610 type Section: Section<Endian = Self::Endian>;
611 type Nlist: Nlist<Endian = Self::Endian>;
612
613 /// Return true if this type is a 64-bit header.
614 ///
615 /// This is a property of the type, not a value in the header data.
616 fn is_type_64(&self) -> bool;
617
618 /// Return true if the `magic` field signifies big-endian.
619 fn is_big_endian(&self) -> bool;
620
621 /// Return true if the `magic` field signifies little-endian.
622 fn is_little_endian(&self) -> bool;
623
624 fn magic(&self) -> u32;
625 fn cputype(&self, endian: Self::Endian) -> u32;
626 fn cpusubtype(&self, endian: Self::Endian) -> u32;
627 fn filetype(&self, endian: Self::Endian) -> u32;
628 fn ncmds(&self, endian: Self::Endian) -> u32;
629 fn sizeofcmds(&self, endian: Self::Endian) -> u32;
630 fn flags(&self, endian: Self::Endian) -> u32;
631
632 // Provided methods.
633
634 /// Read the file header.
635 ///
636 /// Also checks that the magic field in the file header is a supported format.
637 fn parse<'data, R: ReadRef<'data>>(data: R, offset: u64) -> read::Result<&'data Self> {
638 let header = data
639 .read_at::<Self>(offset)
640 .read_error("Invalid Mach-O header size or alignment")?;
641 if !header.is_supported() {
642 return Err(Error("Unsupported Mach-O header"));
643 }
644 Ok(header)
645 }
646
647 fn is_supported(&self) -> bool {
648 self.is_little_endian() || self.is_big_endian()
649 }
650
651 fn endian(&self) -> Result<Self::Endian> {
652 Self::Endian::from_big_endian(self.is_big_endian()).read_error("Unsupported Mach-O endian")
653 }
654
655 fn load_commands<'data, R: ReadRef<'data>>(
656 &self,
657 endian: Self::Endian,
658 data: R,
659 header_offset: u64,
660 ) -> Result<LoadCommandIterator<'data, Self::Endian>> {
661 let data = data
662 .read_bytes_at(
663 header_offset + mem::size_of::<Self>() as u64,
664 self.sizeofcmds(endian).into(),
665 )
666 .read_error("Invalid Mach-O load command table size")?;
667 Ok(LoadCommandIterator::new(endian, data, self.ncmds(endian)))
668 }
669
670 /// Return the UUID from the `LC_UUID` load command, if one is present.
671 fn uuid<'data, R: ReadRef<'data>>(
672 &self,
673 endian: Self::Endian,
674 data: R,
675 header_offset: u64,
676 ) -> Result<Option<[u8; 16]>> {
677 let mut commands = self.load_commands(endian, data, header_offset)?;
678 while let Some(command) = commands.next()? {
679 if let Ok(Some(uuid)) = command.uuid() {
680 return Ok(Some(uuid.uuid));
681 }
682 }
683 Ok(None)
684 }
685}
686
687impl<Endian: endian::Endian> MachHeader for macho::MachHeader32<Endian> {
688 type Word = u32;
689 type Endian = Endian;
690 type Segment = macho::SegmentCommand32<Endian>;
691 type Section = macho::Section32<Endian>;
692 type Nlist = macho::Nlist32<Endian>;
693
694 fn is_type_64(&self) -> bool {
695 false
696 }
697
698 fn is_big_endian(&self) -> bool {
699 self.magic() == macho::MH_MAGIC
700 }
701
702 fn is_little_endian(&self) -> bool {
703 self.magic() == macho::MH_CIGAM
704 }
705
706 fn magic(&self) -> u32 {
707 self.magic.get(BigEndian)
708 }
709
710 fn cputype(&self, endian: Self::Endian) -> u32 {
711 self.cputype.get(endian)
712 }
713
714 fn cpusubtype(&self, endian: Self::Endian) -> u32 {
715 self.cpusubtype.get(endian)
716 }
717
718 fn filetype(&self, endian: Self::Endian) -> u32 {
719 self.filetype.get(endian)
720 }
721
722 fn ncmds(&self, endian: Self::Endian) -> u32 {
723 self.ncmds.get(endian)
724 }
725
726 fn sizeofcmds(&self, endian: Self::Endian) -> u32 {
727 self.sizeofcmds.get(endian)
728 }
729
730 fn flags(&self, endian: Self::Endian) -> u32 {
731 self.flags.get(endian)
732 }
733}
734
735impl<Endian: endian::Endian> MachHeader for macho::MachHeader64<Endian> {
736 type Word = u64;
737 type Endian = Endian;
738 type Segment = macho::SegmentCommand64<Endian>;
739 type Section = macho::Section64<Endian>;
740 type Nlist = macho::Nlist64<Endian>;
741
742 fn is_type_64(&self) -> bool {
743 true
744 }
745
746 fn is_big_endian(&self) -> bool {
747 self.magic() == macho::MH_MAGIC_64
748 }
749
750 fn is_little_endian(&self) -> bool {
751 self.magic() == macho::MH_CIGAM_64
752 }
753
754 fn magic(&self) -> u32 {
755 self.magic.get(BigEndian)
756 }
757
758 fn cputype(&self, endian: Self::Endian) -> u32 {
759 self.cputype.get(endian)
760 }
761
762 fn cpusubtype(&self, endian: Self::Endian) -> u32 {
763 self.cpusubtype.get(endian)
764 }
765
766 fn filetype(&self, endian: Self::Endian) -> u32 {
767 self.filetype.get(endian)
768 }
769
770 fn ncmds(&self, endian: Self::Endian) -> u32 {
771 self.ncmds.get(endian)
772 }
773
774 fn sizeofcmds(&self, endian: Self::Endian) -> u32 {
775 self.sizeofcmds.get(endian)
776 }
777
778 fn flags(&self, endian: Self::Endian) -> u32 {
779 self.flags.get(endian)
780 }
781}
782