Line data Source code
1 : //! Module for the Mach-O file format support in LIEF.
2 : //!
3 : //! To get started, one can use [`crate::macho::parse`], [`crate::macho::FatBinary::parse`] or
4 : //! [`crate::Binary::parse`] to instantiate a [`crate::macho::FatBinary`].
5 : //!
6 : //! Even though the targeted Mach-O binary is not FAT, LIEF **always** return a [`crate::macho::FatBinary`]
7 : //! which can wrap a single [`Binary`].
8 : //!
9 : //! ```
10 : //! let fat = lief::macho::parse("non-fat.macho").unwrap();
11 : //! assert!(fat.iter().len() == 1);
12 : //!
13 : //! let fat = lief::macho::parse("real-fat.macho").unwrap();
14 : //! assert!(fat.iter().len() > 1);
15 : //! ```
16 : //!
17 : //! The [`Binary`] structure exposes the main interface to inspect or modify Mach-O binaries:
18 : //!
19 : //! ```
20 : //! fn inspect_macho(macho: &lief::macho::Binary) {
21 : //! for cmd in macho.commands() {
22 : //! println!("{:?}", cmd);
23 : //! }
24 : //! }
25 : //! ```
26 : //!
27 : pub mod binary;
28 : pub mod binding_info;
29 : pub mod builder;
30 : pub mod commands;
31 : pub mod export_info;
32 : pub mod fat_binary;
33 : pub mod header;
34 : pub mod parser_config;
35 : pub mod relocation;
36 : pub mod section;
37 : pub mod stub;
38 : pub mod symbol;
39 : pub mod thread_local_variables;
40 :
41 : use lief_ffi as ffi;
42 : use std::path::Path;
43 :
44 : #[doc(inline)]
45 : pub use binary::Binary;
46 : #[doc(inline)]
47 : pub use binding_info::BindingInfo;
48 : #[doc(inline)]
49 : pub use commands::Commands;
50 : #[doc(inline)]
51 : pub use export_info::ExportInfo;
52 : #[doc(inline)]
53 : pub use fat_binary::FatBinary;
54 : #[doc(inline)]
55 : pub use header::Header;
56 : #[doc(inline)]
57 : pub use relocation::Relocation;
58 : #[doc(inline)]
59 : pub use section::Generic;
60 : #[doc(inline)]
61 : pub use section::MachOSection;
62 : #[doc(inline)]
63 : pub use section::Section;
64 : #[doc(inline)]
65 : pub use stub::Stub;
66 : #[doc(inline)]
67 : pub use symbol::Symbol;
68 : #[doc(inline)]
69 : pub use thread_local_variables::ThreadLocalVariables;
70 :
71 : use crate::common::AsFFI;
72 :
73 : #[doc(inline)]
74 : pub use parser_config::Config as ParserConfig;
75 :
76 : /// Parse a Mach-O file from the given file path
77 0 : pub fn parse<P: AsRef<Path>>(path: P) -> Option<FatBinary> {
78 0 : FatBinary::parse(path)
79 0 : }
80 :
81 : /// Parse a Mach-O file from the given file path with the provided parser
82 : /// configuration
83 0 : pub fn parse_with_config<P: AsRef<Path>>(path: P, config: &ParserConfig) -> Option<FatBinary> {
84 0 : FatBinary::parse_with_config(path, config)
85 0 : }
86 :
87 : /// Check that the layout of the given binary is correct from the loader
88 : /// perspective
89 0 : pub fn check_layout(binary: &Binary) -> Result<(), String> {
90 0 : cxx::let_cxx_string!(error = "");
91 0 : unsafe {
92 0 : if ffi::MachO_Utils::check_layout(binary.as_ffi(), error.as_mut().get_unchecked_mut()) {
93 0 : return Ok(());
94 0 : }
95 0 : }
96 0 : Err(error.to_string())
97 0 : }
98 :
99 : /// Check that the layout of the given FAT binary is correct from the loader
100 : /// perspective
101 0 : pub fn check_fat_layout(fat: &FatBinary) -> Result<(), String> {
102 0 : cxx::let_cxx_string!(error = "");
103 0 : unsafe {
104 0 : if ffi::MachO_Utils::check_layout_fat(fat.as_ffi(), error.as_mut().get_unchecked_mut()) {
105 0 : return Ok(());
106 0 : }
107 0 : }
108 0 : Err(error.to_string())
109 0 : }
110 :
111 : /// Check if the given file is a FAT Mach-O
112 0 : pub fn is_fat<P: AsRef<Path>>(path: P) -> bool {
113 0 : ffi::MachO_Utils::is_fat(path.as_ref().to_str().unwrap().to_string())
114 0 : }
115 :
116 : /// Check if the given file is a 64-bit Mach-O
117 0 : pub fn is_64<P: AsRef<Path>>(path: P) -> bool {
118 0 : ffi::MachO_Utils::is_64(path.as_ref().to_str().unwrap().to_string())
119 0 : }
120 :
121 : /// Mach-O magic values
122 : #[allow(non_camel_case_types)]
123 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
124 : pub enum MachOType {
125 : /// 32-bit big-endian magic
126 : MAGIC,
127 : /// 32-bit little-endian magic
128 : CIGAM,
129 : /// 64-bit big-endian magic
130 : MAGIC_64,
131 : /// 64-bit little-endian magic
132 : CIGAM_64,
133 : /// Big-endian fat magic
134 : MAGIC_FAT,
135 : /// Little-endian fat magic
136 : CIGAM_FAT,
137 : /// Neural model magic
138 : NEURAL_MODEL,
139 : UNKNOWN(u32),
140 : }
141 :
142 : impl From<u32> for MachOType {
143 0 : fn from(value: u32) -> Self {
144 0 : match value {
145 0 : 0xFEEDFACE => MachOType::MAGIC,
146 0 : 0xCEFAEDFE => MachOType::CIGAM,
147 0 : 0xFEEDFACF => MachOType::MAGIC_64,
148 0 : 0xCFFAEDFE => MachOType::CIGAM_64,
149 0 : 0xCAFEBABE => MachOType::MAGIC_FAT,
150 0 : 0xBEBAFECA => MachOType::CIGAM_FAT,
151 0 : 0xBEEFFACE => MachOType::NEURAL_MODEL,
152 0 : _ => MachOType::UNKNOWN(value),
153 : }
154 0 : }
155 : }
156 :
157 : impl From<MachOType> for u32 {
158 0 : fn from(value: MachOType) -> u32 {
159 0 : match value {
160 0 : MachOType::MAGIC => 0xFEEDFACE,
161 0 : MachOType::CIGAM => 0xCEFAEDFE,
162 0 : MachOType::MAGIC_64 => 0xFEEDFACF,
163 0 : MachOType::CIGAM_64 => 0xCFFAEDFE,
164 0 : MachOType::MAGIC_FAT => 0xCAFEBABE,
165 0 : MachOType::CIGAM_FAT => 0xBEBAFECA,
166 0 : MachOType::NEURAL_MODEL => 0xBEEFFACE,
167 0 : MachOType::UNKNOWN(v) => v,
168 : }
169 0 : }
170 : }
|