Line data Source code
1 : //! Module for Dyld shared cache support
2 : //!
3 : //! ### Getting Started
4 : //!
5 : //! ```rust
6 : //! let dyld_cache = lief::dsc::from_path("macos-15.0.1/");
7 : //! for dylib in dyld_cache.libraries() {
8 : //! println!("0x{:016x}: {}", dylib.address(), dylib.path());
9 : //! let macho: lief::macho::Binary = dylib.get().expect("Can't get Mach-O representation");
10 : //! }
11 : //! ```
12 : //!
13 : //! ### Performance Considerations
14 : //!
15 : //! <div class="warning">
16 : //! If you aim at extracting several libraries from a dyld shared cache, it is
17 : //! <b>highly</b> recommended to enable caching. Otherwise, performances can be
18 : //! impacted.
19 : //! </div>
20 : //!
21 : //! See: [`crate::dsc::enable_cache`] and [`crate::dsc::enable_cache_from_dir`]
22 : use lief_ffi as ffi;
23 : use std::ffi::{CString, c_char};
24 : use std::path::Path;
25 : use crate::common::into_optional;
26 :
27 : pub mod dyld_shared_cache;
28 : pub mod mapping_info;
29 : pub mod subcache;
30 : pub mod dylib;
31 : pub mod uuid;
32 :
33 : mod caching;
34 :
35 : #[doc(inline)]
36 : pub use dyld_shared_cache::DyldSharedCache;
37 :
38 : #[doc(inline)]
39 : pub use dylib::Dylib;
40 :
41 : #[doc(inline)]
42 : pub use subcache::SubCache;
43 :
44 : #[doc(inline)]
45 : pub use mapping_info::MappingInfo;
46 :
47 : #[doc(inline)]
48 : pub use uuid::UUID;
49 :
50 : #[doc(inline)]
51 : pub use caching::enable_cache;
52 :
53 : #[doc(inline)]
54 : pub use caching::enable_cache_from_dir;
55 :
56 :
57 : /// Load a shared cache from a single file or from a directory specified
58 : /// by the `path` parameter.
59 : ///
60 : /// In the case where multiple architectures are
61 : /// available in the `path` directory, the `arch` parameter can be used to
62 : /// define which architecture should be prefered.
63 : ///
64 : /// **Example:**
65 : ///
66 : /// ```rust
67 : /// // From a directory (split caches)
68 : /// let cache = lief::dsc::load("vision-pro-2.0/", "");
69 : ///
70 : /// // From a single cache file
71 : /// let cache = lief::dsc::load("ios-14.2/dyld_shared_cache_arm64", "");
72 : ///
73 : /// // From a directory with multiple architectures
74 : /// let cache = LIEF::dsc::load("macos-12.6/", /*arch=*/"x86_64h");
75 : /// ```
76 0 : pub fn load_from_path<P: AsRef<Path>>(path: P, arch: &str) -> Option<DyldSharedCache> {
77 0 : into_optional(ffi::dsc_DyldSharedCache::from_path(path.as_ref().to_str().unwrap(), arch))
78 0 : }
79 :
80 0 : pub fn load_from_files<P: AsRef<Path>>(files: &[P]) -> Option<DyldSharedCache> {
81 0 : let mut c_strings = Vec::new();
82 0 : let mut c_ptrs = Vec::new();
83 0 : for file in files.iter() {
84 0 : let c_str = CString::new(file.as_ref().to_str().unwrap()).unwrap();
85 0 : c_strings.push(c_str);
86 0 : let c_ptr = c_strings.last().unwrap().as_ptr() as *const c_char;
87 0 : c_ptrs.push(c_ptr);
88 0 : }
89 0 : let files_ptr: *const *const c_char = c_ptrs.as_ptr();
90 0 : unsafe {
91 0 : into_optional(ffi::dsc_DyldSharedCache::from_files(files_ptr as *const c_char, c_ptrs.len()))
92 0 : }
93 0 : }
94 :
95 : /// Check if the given file is a dyld shared cache
96 0 : pub fn is_shared_cache<P: AsRef<Path>>(path: P) -> bool {
97 0 : ffi::dsc_Utils::is_shared_cache(path.as_ref().to_str().unwrap())
98 0 : }
|