Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use crate::common::{FromFFI, into_optional};
4 : use crate::declare_iterator;
5 : use super::{SubCache, Dylib, MappingInfo};
6 :
7 : #[allow(non_camel_case_types)]
8 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
9 : /// This enum wraps the dyld's git tags for which the structure of
10 : /// dyld shared cache evolved
11 : pub enum Version {
12 : /// dyld-95.3 (2007-10-30)
13 : DYLD_95_3,
14 : /// dyld-195.5 (2011-07-13)
15 : DYLD_195_5,
16 : /// dyld-239.3 (2013-10-29)
17 : DYLD_239_3,
18 : /// dyld-360.14 (2015-09-04)
19 : DYLD_360_14,
20 : /// dyld-421.1 (2016-09-22)
21 : DYLD_421_1,
22 : /// dyld-832.7.1 (2020-11-19)
23 : DYLD_832_7_1,
24 : /// dyld-940 (2021-02-09)
25 : DYLD_940,
26 : /// dyld-1042.1 (2022-10-19)
27 : DYLD_1042_1,
28 : /// This value is used for versions of dyld not publicly released or not yet
29 : /// supported by LIEF
30 : UNRELEASED,
31 : UNKNOWN(u32),
32 : }
33 :
34 : impl From<u32> for Version {
35 0 : fn from(value: u32) -> Self {
36 0 : match value {
37 0 : 0x00000001 => Version::DYLD_95_3,
38 0 : 0x00000002 => Version::DYLD_195_5,
39 0 : 0x00000003 => Version::DYLD_239_3,
40 0 : 0x00000004 => Version::DYLD_360_14,
41 0 : 0x00000005 => Version::DYLD_421_1,
42 0 : 0x00000006 => Version::DYLD_832_7_1,
43 0 : 0x00000007 => Version::DYLD_940,
44 0 : 0x00000008 => Version::DYLD_1042_1,
45 0 : 0x00000009 => Version::UNRELEASED,
46 0 : _ => Version::UNKNOWN(value),
47 :
48 : }
49 0 : }
50 : }
51 : impl From<Version> for u32 {
52 0 : fn from(value: Version) -> u32 {
53 0 : match value {
54 0 : Version::DYLD_95_3 => 0x00000001,
55 0 : Version::DYLD_195_5 => 0x00000002,
56 0 : Version::DYLD_239_3 => 0x00000003,
57 0 : Version::DYLD_360_14 => 0x00000004,
58 0 : Version::DYLD_421_1 => 0x00000005,
59 0 : Version::DYLD_832_7_1 => 0x00000006,
60 0 : Version::DYLD_940 => 0x00000007,
61 0 : Version::DYLD_1042_1 => 0x00000008,
62 0 : Version::UNRELEASED => 0x00000009,
63 0 : Version::UNKNOWN(_) => 0,
64 :
65 : }
66 0 : }
67 : }
68 :
69 :
70 : #[allow(non_camel_case_types)]
71 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
72 : /// Platforms supported by the dyld shared cache
73 : pub enum Platform {
74 : MACOS,
75 : IOS,
76 : TVOS,
77 : WATCHOS,
78 : BRIDGEOS,
79 : IOSMAC,
80 : IOS_SIMULATOR,
81 : TVOS_SIMULATOR,
82 : WATCHOS_SIMULATOR,
83 : DRIVERKIT,
84 : VISIONOS,
85 : VISIONOS_SIMULATOR,
86 : FIRMWARE,
87 : SEPOS,
88 : ANY,
89 : UNKNOWN(u32),
90 : }
91 :
92 : impl From<u32> for Platform {
93 0 : fn from(value: u32) -> Self {
94 0 : match value {
95 0 : 0x00000001 => Platform::MACOS,
96 0 : 0x00000002 => Platform::IOS,
97 0 : 0x00000003 => Platform::TVOS,
98 0 : 0x00000004 => Platform::WATCHOS,
99 0 : 0x00000005 => Platform::BRIDGEOS,
100 0 : 0x00000006 => Platform::IOSMAC,
101 0 : 0x00000007 => Platform::IOS_SIMULATOR,
102 0 : 0x00000008 => Platform::TVOS_SIMULATOR,
103 0 : 0x00000009 => Platform::WATCHOS_SIMULATOR,
104 0 : 0x0000000a => Platform::DRIVERKIT,
105 0 : 0x0000000b => Platform::VISIONOS,
106 0 : 0x0000000c => Platform::VISIONOS_SIMULATOR,
107 0 : 0x0000000d => Platform::FIRMWARE,
108 0 : 0x0000000e => Platform::SEPOS,
109 0 : 0xffffffff => Platform::ANY,
110 0 : _ => Platform::UNKNOWN(value),
111 :
112 : }
113 0 : }
114 : }
115 : impl From<Platform> for u32 {
116 0 : fn from(value: Platform) -> u32 {
117 0 : match value {
118 0 : Platform::MACOS => 0x00000001,
119 0 : Platform::IOS => 0x00000002,
120 0 : Platform::TVOS => 0x00000003,
121 0 : Platform::WATCHOS => 0x00000004,
122 0 : Platform::BRIDGEOS => 0x00000005,
123 0 : Platform::IOSMAC => 0x00000006,
124 0 : Platform::IOS_SIMULATOR => 0x00000007,
125 0 : Platform::TVOS_SIMULATOR => 0x00000008,
126 0 : Platform::WATCHOS_SIMULATOR => 0x00000009,
127 0 : Platform::DRIVERKIT => 0x0000000a,
128 0 : Platform::VISIONOS => 0x0000000b,
129 0 : Platform::VISIONOS_SIMULATOR => 0x0000000c,
130 0 : Platform::FIRMWARE => 0x0000000d,
131 0 : Platform::SEPOS => 0x0000000e,
132 0 : Platform::ANY => 0xffffffff,
133 0 : Platform::UNKNOWN(_) => 0,
134 :
135 : }
136 0 : }
137 : }
138 :
139 : #[allow(non_camel_case_types)]
140 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
141 : /// Architecture supported by the dyld shared cache
142 : pub enum Arch {
143 : I386,
144 : X86_64,
145 : X86_64H,
146 : ARMV5,
147 : ARMV6,
148 : ARMV7,
149 : ARM64,
150 : ARM64E,
151 : UNKNOWN(u32),
152 : }
153 :
154 : impl From<u32> for Arch {
155 0 : fn from(value: u32) -> Self {
156 0 : match value {
157 0 : 0x00000001 => Arch::I386,
158 0 : 0x00000002 => Arch::X86_64,
159 0 : 0x00000003 => Arch::X86_64H,
160 0 : 0x00000004 => Arch::ARMV5,
161 0 : 0x00000005 => Arch::ARMV6,
162 0 : 0x00000006 => Arch::ARMV7,
163 0 : 0x00000007 => Arch::ARM64,
164 0 : 0x00000008 => Arch::ARM64E,
165 0 : _ => Arch::UNKNOWN(value),
166 :
167 : }
168 0 : }
169 : }
170 : impl From<Arch> for u32 {
171 0 : fn from(value: Arch) -> u32 {
172 0 : match value {
173 0 : Arch::I386 => 0x00000001,
174 0 : Arch::X86_64 => 0x00000002,
175 0 : Arch::X86_64H => 0x00000003,
176 0 : Arch::ARMV5 => 0x00000004,
177 0 : Arch::ARMV6 => 0x00000005,
178 0 : Arch::ARMV7 => 0x00000006,
179 0 : Arch::ARM64 => 0x00000007,
180 0 : Arch::ARM64E => 0x00000008,
181 0 : Arch::UNKNOWN(_) => 0,
182 :
183 : }
184 0 : }
185 : }
186 :
187 : /// This struct interfaces a dyld shared cache file.
188 : pub struct DyldSharedCache {
189 : ptr: cxx::UniquePtr<ffi::dsc_DyldSharedCache>,
190 : }
191 :
192 : impl FromFFI<ffi::dsc_DyldSharedCache> for DyldSharedCache {
193 0 : fn from_ffi(info: cxx::UniquePtr<ffi::dsc_DyldSharedCache>) -> Self {
194 0 : Self {
195 0 : ptr: info,
196 0 : }
197 0 : }
198 : }
199 :
200 : impl DyldSharedCache {
201 : /// Filename of the dyld shared file associated with this object.
202 : ///
203 : /// For instance: `dyld_shared_cache_arm64e, dyld_shared_cache_arm64e.62.dyldlinkedit`
204 0 : pub fn filename(&self) -> String {
205 0 : self.ptr.filename().to_string()
206 0 : }
207 :
208 : /// Full path to the original dyld shared cache file associated with object
209 : /// (e.g. `/home/lief/downloads/visionos/dyld_shared_cache_arm64e.42`)
210 0 : pub fn filepath(&self) -> String {
211 0 : self.ptr.filepath().to_string()
212 0 : }
213 :
214 : /// Based address of this cache
215 0 : pub fn load_address(&self) -> u64 {
216 0 : self.ptr.load_address()
217 0 : }
218 :
219 : /// Version of dyld used by this cache
220 0 : pub fn version(&self) -> Version {
221 0 : Version::from(self.ptr.version())
222 0 : }
223 :
224 : /// Name of the architecture targeted by this cache (`x86_64h`)
225 0 : pub fn arch_name(&self) -> String {
226 0 : self.ptr.arch_name().to_string()
227 0 : }
228 :
229 : /// Platform targeted by this cache (e.g. vision-os)
230 0 : pub fn platform(&self) -> Platform {
231 0 : Platform::from(self.ptr.platform())
232 0 : }
233 :
234 : /// Architecture targeted by this cache
235 0 : pub fn arch(&self) -> Arch {
236 0 : Arch::from(self.ptr.arch())
237 0 : }
238 :
239 : /// Find the [`Dylib`] that encompasses the given virtual address.
240 0 : pub fn find_lib_from_va(&self, va: u64) -> Option<Dylib> {
241 0 : into_optional(self.ptr.find_lib_from_va(va))
242 0 : }
243 :
244 : /// Find the [`Dylib`] whose [`Dylib::path`] matches the provided path.
245 0 : pub fn find_lib_from_path(&self, path: &str) -> Option<Dylib> {
246 0 : into_optional(self.ptr.find_lib_from_path(path))
247 0 : }
248 :
249 : /// Find the [`Dylib`] whose filename of [`Dylib::path`] matches the provided name.
250 : ///
251 : /// If multiple libraries have the same name (but with a different path),
252 : /// the **first one** matching the provided name is returned.
253 0 : pub fn find_lib_from_name(&self, name: &str) -> Option<Dylib> {
254 0 : into_optional(self.ptr.find_lib_from_name(name))
255 0 : }
256 :
257 : /// True if the subcaches are associated with this cache
258 0 : pub fn has_subcaches(&self) -> bool {
259 0 : self.ptr.has_subcaches()
260 0 : }
261 :
262 : /// Return an iterator over the different [`Dylib`] libraries embedded
263 : /// in this dyld shared cache
264 0 : pub fn libraries(&self) -> Dylibs {
265 0 : Dylibs::new(self.ptr.libraries())
266 0 : }
267 :
268 : /// Return an iterator over the different [`MappingInfo`] associated
269 : /// with this dyld shared cache
270 0 : pub fn mapping_info(&self) -> MappingInfoIt {
271 0 : MappingInfoIt::new(self.ptr.mapping_info())
272 0 : }
273 :
274 : /// Return an interator over the subcaches associated with this (main) dyld shared
275 : /// cache.
276 0 : pub fn subcaches(&self) -> SubCacheIt {
277 0 : SubCacheIt::new(self.ptr.subcaches())
278 0 : }
279 :
280 : /// When enabled, this function allows to record and to keep in *cache*,
281 : /// dyld shared cache information that are costly to access.
282 : ///
283 : /// For instance, GOT symbols, rebases information, stub symbols, ...
284 : ///
285 : /// It is **highly** recommended to enable this function when processing
286 : /// a dyld shared cache several times or when extracting a large number of
287 : /// [`Dylib`] with enhanced extraction options (e.g. [`crate::dsc::dylib::ExtractOpt::fix_memory`])
288 : ///
289 : /// One can enable caching by calling this function:
290 : ///
291 : /// ```rust
292 : /// let dyld_cache = lief::dsc::load_from_path("macos-15.0.1/", "");
293 : /// dyld_cache.enable_caching("/home/user/.cache/lief-dsc");
294 : /// ```
295 : ///
296 : /// One can also enable this cache optimization **globally** using the
297 : /// function: [`crate::dsc::enable_cache`] or by setting the environment variable
298 : /// `DYLDSC_ENABLE_CACHE` to 1.
299 0 : pub fn enable_caching(&self, target_cache_dir: &str) {
300 0 : self.ptr.enable_caching(target_cache_dir)
301 0 : }
302 :
303 : /// Flush internal information into the on-disk cache (see: enable_caching)
304 0 : pub fn flush_cache(&self) {
305 0 : self.ptr.flush_cache()
306 0 : }
307 : }
308 :
309 0 : declare_iterator!(
310 0 : Dylibs,
311 0 : Dylib<'a>,
312 0 : ffi::dsc_Dylib,
313 0 : ffi::dsc_DyldSharedCache,
314 0 : ffi::dsc_DyldSharedCache_it_libraries
315 0 : );
316 :
317 0 : declare_iterator!(
318 0 : MappingInfoIt,
319 0 : MappingInfo<'a>,
320 0 : ffi::dsc_MappingInfo,
321 0 : ffi::dsc_DyldSharedCache,
322 0 : ffi::dsc_DyldSharedCache_it_mapping_info
323 0 : );
324 :
325 0 : declare_iterator!(
326 0 : SubCacheIt,
327 0 : SubCache<'a>,
328 0 : ffi::dsc_SubCache,
329 0 : ffi::dsc_DyldSharedCache,
330 0 : ffi::dsc_DyldSharedCache_it_subcaches
331 0 : );
|