object/read/macho/
fat.rs
1use crate::endian::BigEndian;
2use crate::macho;
3use crate::pod::Pod;
4use crate::read::{Architecture, Error, ReadError, ReadRef, Result};
5
6pub use macho::{FatArch32, FatArch64, FatHeader};
7
8pub type MachOFatFile32<'data> = MachOFatFile<'data, macho::FatArch32>;
13
14pub type MachOFatFile64<'data> = MachOFatFile<'data, macho::FatArch64>;
19
20#[derive(Debug, Clone)]
25pub struct MachOFatFile<'data, Fat: FatArch> {
26 header: &'data macho::FatHeader,
27 arches: &'data [Fat],
28}
29
30impl<'data, Fat: FatArch> MachOFatFile<'data, Fat> {
31 pub fn parse<R: ReadRef<'data>>(data: R) -> Result<Self> {
33 let mut offset = 0;
34 let header = data
35 .read::<FatHeader>(&mut offset)
36 .read_error("Invalid fat header size or alignment")?;
37 if header.magic.get(BigEndian) != Fat::MAGIC {
38 return Err(Error("Invalid fat magic"));
39 }
40 let arches = data
41 .read_slice::<Fat>(&mut offset, header.nfat_arch.get(BigEndian) as usize)
42 .read_error("Invalid nfat_arch")?;
43 Ok(MachOFatFile { header, arches })
44 }
45
46 pub fn header(&self) -> &'data macho::FatHeader {
48 self.header
49 }
50
51 pub fn arches(&self) -> &'data [Fat] {
53 self.arches
54 }
55}
56
57#[allow(missing_docs)]
59pub trait FatArch: Pod {
60 type Word: Into<u64>;
61 const MAGIC: u32;
62
63 fn cputype(&self) -> u32;
64 fn cpusubtype(&self) -> u32;
65 fn offset(&self) -> Self::Word;
66 fn size(&self) -> Self::Word;
67 fn align(&self) -> u32;
68
69 fn architecture(&self) -> Architecture {
70 match self.cputype() {
71 macho::CPU_TYPE_ARM => Architecture::Arm,
72 macho::CPU_TYPE_ARM64 => Architecture::Aarch64,
73 macho::CPU_TYPE_X86 => Architecture::I386,
74 macho::CPU_TYPE_X86_64 => Architecture::X86_64,
75 macho::CPU_TYPE_MIPS => Architecture::Mips,
76 macho::CPU_TYPE_POWERPC => Architecture::PowerPc,
77 macho::CPU_TYPE_POWERPC64 => Architecture::PowerPc64,
78 _ => Architecture::Unknown,
79 }
80 }
81
82 fn file_range(&self) -> (u64, u64) {
83 (self.offset().into(), self.size().into())
84 }
85
86 fn data<'data, R: ReadRef<'data>>(&self, file: R) -> Result<&'data [u8]> {
87 file.read_bytes_at(self.offset().into(), self.size().into())
88 .read_error("Invalid fat arch offset or size")
89 }
90}
91
92impl FatArch for FatArch32 {
93 type Word = u32;
94 const MAGIC: u32 = macho::FAT_MAGIC;
95
96 fn cputype(&self) -> u32 {
97 self.cputype.get(BigEndian)
98 }
99
100 fn cpusubtype(&self) -> u32 {
101 self.cpusubtype.get(BigEndian)
102 }
103
104 fn offset(&self) -> Self::Word {
105 self.offset.get(BigEndian)
106 }
107
108 fn size(&self) -> Self::Word {
109 self.size.get(BigEndian)
110 }
111
112 fn align(&self) -> u32 {
113 self.align.get(BigEndian)
114 }
115}
116
117impl FatArch for FatArch64 {
118 type Word = u64;
119 const MAGIC: u32 = macho::FAT_MAGIC_64;
120
121 fn cputype(&self) -> u32 {
122 self.cputype.get(BigEndian)
123 }
124
125 fn cpusubtype(&self) -> u32 {
126 self.cpusubtype.get(BigEndian)
127 }
128
129 fn offset(&self) -> Self::Word {
130 self.offset.get(BigEndian)
131 }
132
133 fn size(&self) -> Self::Word {
134 self.size.get(BigEndian)
135 }
136
137 fn align(&self) -> u32 {
138 self.align.get(BigEndian)
139 }
140}