Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use bitflags::bitflags;
4 :
5 : use std::{fmt, marker::PhantomData};
6 : use crate::common::FromFFI;
7 :
8 : #[allow(non_camel_case_types)]
9 360 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
10 : pub enum FileType {
11 : OBJECT,
12 : EXECUTE,
13 : FVMLIB,
14 : CORE,
15 : PRELOAD,
16 : DYLIB,
17 : DYLINKER,
18 : BUNDLE,
19 : DYLIB_STUB,
20 : DSYM,
21 : KEXT_BUNDLE,
22 : FILESET,
23 : GPU_EXECUTE,
24 : GPU_DYLIB,
25 : UNKNOWN(u32),
26 : }
27 :
28 : impl From<u32> for FileType {
29 360 : fn from(value: u32) -> Self {
30 360 : match value {
31 12 : 0x00000001 => FileType::OBJECT,
32 48 : 0x00000002 => FileType::EXECUTE,
33 0 : 0x00000003 => FileType::FVMLIB,
34 0 : 0x00000004 => FileType::CORE,
35 0 : 0x00000005 => FileType::PRELOAD,
36 120 : 0x00000006 => FileType::DYLIB,
37 0 : 0x00000007 => FileType::DYLINKER,
38 0 : 0x00000008 => FileType::BUNDLE,
39 0 : 0x00000009 => FileType::DYLIB_STUB,
40 0 : 0x0000000a => FileType::DSYM,
41 0 : 0x0000000b => FileType::KEXT_BUNDLE,
42 0 : 0x0000000c => FileType::FILESET,
43 180 : 0x0000000d => FileType::GPU_EXECUTE,
44 0 : 0x0000000e => FileType::GPU_DYLIB,
45 0 : _ => FileType::UNKNOWN(value),
46 :
47 : }
48 360 : }
49 : }
50 : impl From<FileType> for u32 {
51 0 : fn from(value: FileType) -> u32 {
52 0 : match value {
53 0 : FileType::OBJECT => 0x00000001,
54 0 : FileType::EXECUTE => 0x00000002,
55 0 : FileType::FVMLIB => 0x00000003,
56 0 : FileType::CORE => 0x00000004,
57 0 : FileType::PRELOAD => 0x00000005,
58 0 : FileType::DYLIB => 0x00000006,
59 0 : FileType::DYLINKER => 0x00000007,
60 0 : FileType::BUNDLE => 0x00000008,
61 0 : FileType::DYLIB_STUB => 0x00000009,
62 0 : FileType::DSYM => 0x0000000a,
63 0 : FileType::KEXT_BUNDLE => 0x0000000b,
64 0 : FileType::FILESET => 0x0000000c,
65 0 : FileType::GPU_EXECUTE => 0x0000000d,
66 0 : FileType::GPU_DYLIB => 0x0000000e,
67 0 : FileType::UNKNOWN(value) => value,
68 : }
69 0 : }
70 : }
71 :
72 :
73 : #[allow(non_camel_case_types)]
74 360 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
75 : pub enum CpuType {
76 : ANY,
77 : X86,
78 : X86_64,
79 : MIPS,
80 : MC98000,
81 : HPPA,
82 : ARM,
83 : ARM64,
84 : MC88000,
85 : SPARC,
86 : I860,
87 : ALPHA,
88 : POWERPC,
89 : POWERPC64,
90 : APPLE_GPU,
91 : AMD_GPU,
92 : INTEL_GPU,
93 : AIR64,
94 : UNKNOWN(i32),
95 : }
96 :
97 : impl From<i32> for CpuType {
98 360 : fn from(value: i32) -> Self {
99 360 : match value {
100 0 : -1 => CpuType::ANY,
101 24 : 0x00000007 => CpuType::X86,
102 48 : 0x01000007 => CpuType::X86_64,
103 0 : 0x00000008 => CpuType::MIPS,
104 0 : 0x0000000a => CpuType::MC98000,
105 0 : 0x0000000b => CpuType::HPPA,
106 24 : 0x0000000c => CpuType::ARM,
107 84 : 0x0100000c => CpuType::ARM64,
108 0 : 0x0000000d => CpuType::MC88000,
109 0 : 0x0000000e => CpuType::SPARC,
110 0 : 0x0000000f => CpuType::I860,
111 0 : 0x00000010 => CpuType::ALPHA,
112 0 : 0x00000012 => CpuType::POWERPC,
113 0 : 0x01000012 => CpuType::POWERPC64,
114 180 : 0x01000013 => CpuType::APPLE_GPU,
115 0 : 0x01000014 => CpuType::AMD_GPU,
116 0 : 0x01000015 => CpuType::INTEL_GPU,
117 0 : 0x01000017 => CpuType::AIR64,
118 0 : _ => CpuType::UNKNOWN(value),
119 :
120 : }
121 360 : }
122 : }
123 : impl From<CpuType> for i32 {
124 0 : fn from(value: CpuType) -> i32 {
125 0 : match value {
126 0 : CpuType::ANY => -1,
127 0 : CpuType::X86 => 0x00000007,
128 0 : CpuType::X86_64 => 0x01000007,
129 0 : CpuType::MIPS => 0x00000008,
130 0 : CpuType::MC98000 => 0x0000000a,
131 0 : CpuType::HPPA => 0x0000000b,
132 0 : CpuType::ARM => 0x0000000c,
133 0 : CpuType::ARM64 => 0x0100000c,
134 0 : CpuType::MC88000 => 0x0000000d,
135 0 : CpuType::SPARC => 0x0000000e,
136 0 : CpuType::I860 => 0x0000000f,
137 0 : CpuType::ALPHA => 0x00000010,
138 0 : CpuType::POWERPC => 0x00000012,
139 0 : CpuType::POWERPC64 => 0x01000012,
140 0 : CpuType::APPLE_GPU => 0x01000013,
141 0 : CpuType::AMD_GPU => 0x01000014,
142 0 : CpuType::INTEL_GPU => 0x01000015,
143 0 : CpuType::AIR64 => 0x01000017,
144 0 : CpuType::UNKNOWN(_) => -1,
145 : }
146 0 : }
147 : }
148 :
149 :
150 0 : bitflags! {
151 360 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
152 0 : pub struct Flags: u32 {
153 0 : const NOUNDEFS = 0x1;
154 0 : const INCRLINK = 0x2;
155 0 : const DYLDLINK = 0x4;
156 0 : const BINDATLOAD = 0x8;
157 0 : const PREBOUND = 0x10;
158 0 : const SPLIT_SEGS = 0x20;
159 0 : const LAZY_INIT = 0x40;
160 0 : const TWOLEVEL = 0x80;
161 0 : const FORCE_FLAT = 0x100;
162 0 : const NOMULTIDEFS = 0x200;
163 0 : const NOFIXPREBINDING = 0x400;
164 0 : const PREBINDABLE = 0x800;
165 0 : const ALLMODSBOUND = 0x1000;
166 0 : const SUBSECTIONS_VIA_SYMBOLS = 0x2000;
167 0 : const CANONICAL = 0x4000;
168 0 : const WEAK_DEFINES = 0x8000;
169 0 : const BINDS_TO_WEAK = 0x10000;
170 0 : const ALLOW_STACK_EXECUTION = 0x20000;
171 0 : const ROOT_SAFE = 0x40000;
172 0 : const SETUID_SAFE = 0x80000;
173 0 : const NO_REEXPORTED_DYLIBS = 0x100000;
174 0 : const PIE = 0x200000;
175 0 : const DEAD_STRIPPABLE_DYLIB = 0x400000;
176 0 : const HAS_TLV_DESCRIPTORS = 0x800000;
177 0 : const NO_HEAP_EXECUTION = 0x1000000;
178 0 : const APP_EXTENSION_SAFE = 0x2000000;
179 0 : const NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x04000000;
180 0 : const SIM_SUPPORT = 0x08000000;
181 0 : const IMPLICIT_PAGEZERO = 0x10000000;
182 0 : const DYLIB_IN_CACHE = 0x80000000;
183 0 : }
184 0 : }
185 :
186 :
187 : impl From<u32> for Flags {
188 360 : fn from(value: u32) -> Self {
189 360 : Flags::from_bits_truncate(value)
190 360 : }
191 : }
192 : impl From<Flags> for u32 {
193 0 : fn from(value: Flags) -> Self {
194 0 : value.bits()
195 0 : }
196 : }
197 :
198 : /// Structure that represents the main Mach-O header (at the beginning of the file)
199 : pub struct Header<'a> {
200 : ptr: cxx::UniquePtr<ffi::MachO_Header>,
201 : _owner: PhantomData<&'a ffi::MachO_Binary>
202 : }
203 :
204 : impl FromFFI<ffi::MachO_Header> for Header<'_> {
205 1080 : fn from_ffi(hdr: cxx::UniquePtr<ffi::MachO_Header>) -> Self {
206 1080 : Self {
207 1080 : ptr: hdr,
208 1080 : _owner: PhantomData
209 1080 : }
210 1080 : }
211 : }
212 :
213 : impl Header<'_> {
214 : /// The Mach-O magic bytes. These bytes determine whether it is
215 : /// a 32 bits Mach-O, a 64 bits Mach-O files etc.
216 360 : pub fn magic(&self) -> u32 {
217 360 : self.ptr.magic()
218 360 : }
219 :
220 : /// The CPU architecture targeted by this binary
221 360 : pub fn cpu_type(&self) -> CpuType {
222 360 : CpuType::from(self.ptr.cpu_type())
223 360 : }
224 :
225 : /// Return the CPU subtype supported by the Mach-O binary.
226 : /// For ARM architectures, this value could represent the minimum version
227 : /// for which the Mach-O binary has been compiled for.
228 360 : pub fn cpu_subtype(&self) -> u32 {
229 360 : self.ptr.cpu_subtype()
230 360 : }
231 :
232 : /// Return the type of the Mach-O file (executable, object, shared library, ...)
233 360 : pub fn file_type(&self) -> FileType {
234 360 : FileType::from(self.ptr.file_type())
235 360 : }
236 :
237 : /// Number of [`crate::macho::Commands`] present in the Mach-O binary
238 360 : pub fn nb_cmds(&self) -> u32 {
239 360 : self.ptr.nb_cmds()
240 360 : }
241 :
242 : /// The raw size of **all** the load commands (`LC_xxx`)
243 360 : pub fn sizeof_cmds(&self) -> u32 {
244 360 : self.ptr.sizeof_cmds()
245 360 : }
246 :
247 : /// Header flags
248 360 : pub fn flags(&self) -> Flags {
249 360 : Flags::from(self.ptr.flags())
250 360 : }
251 :
252 : /// According to the official specs, a reserved value
253 360 : pub fn reserved(&self) -> u32 {
254 360 : self.ptr.reserved()
255 360 : }
256 :
257 : /// True if the binary is 32-bit
258 360 : pub fn is_32bit(&self) -> bool {
259 360 : self.ptr.is_32bit()
260 360 : }
261 :
262 : /// True if the binary is 64-bit
263 360 : pub fn is_64bit(&self) -> bool {
264 360 : self.ptr.is_64bit()
265 360 : }
266 : }
267 :
268 : impl fmt::Debug for Header<'_> {
269 360 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 360 : f.debug_struct("Header")
271 360 : .field("magic", &self.magic())
272 360 : .field("cpu_type", &self.cpu_type())
273 360 : .field("cpu_subtype", &self.cpu_subtype())
274 360 : .field("file_type", &self.file_type())
275 360 : .field("nb_cmds", &self.nb_cmds())
276 360 : .field("sizeof_cmds", &self.sizeof_cmds())
277 360 : .field("flags", &self.flags())
278 360 : .field("reserved", &self.reserved())
279 360 : .finish()
280 360 : }
281 : }
|