LCOV - code coverage report
Current view: top level - src/dsc - dyld_shared_cache.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 0.0 % 193 0
Test Date: 2026-04-12:00:00:00 Functions: 0.0 % 47 0

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

Generated by: LCOV version 2.1-1