LCOV - code coverage report
Current view: top level - src/pe - chpe_metadata_arm64.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 0.0 % 222 0
Test Date: 2025-08-10:00:00:00 Functions: 0.0 % 52 0

            Line data    Source code
       1              : use super::load_configuration::AsCHPEMetadata;
       2              : use crate::common::FromFFI;
       3              : use crate::declare_iterator;
       4              : use lief_ffi as ffi;
       5              : use std::marker::PhantomData;
       6              : 
       7              : /// This class represents ARM64-specific metadata used in CHPE
       8              : /// (Compatible Hybrid PE) binaries, particularly for hybrid architectures like
       9              : /// ARM64EC and ARM64X.
      10              : ///
      11              : /// It provides access to metadata describing code ranges, redirections, entry points, and other
      12              : /// hybrid-specific information relevant for binary analysis
      13              : pub struct CHPEMetadata<'a> {
      14              :     ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64>,
      15              :     _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
      16              : }
      17              : 
      18              : impl<'a> FromFFI<ffi::PE_CHPEMetadataARM64> for CHPEMetadata<'a> {
      19            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64>) -> Self {
      20            0 :         Self {
      21            0 :             ptr,
      22            0 :             _owner: PhantomData,
      23            0 :         }
      24            0 :     }
      25              : }
      26              : 
      27              : impl CHPEMetadata<'_> {
      28              :     /// RVA to the array that describes architecture-specific ranges
      29            0 :     pub fn code_map(&self) -> u32 {
      30            0 :         self.ptr.code_map()
      31            0 :     }
      32              : 
      33              :     /// Number of entries in the code map
      34            0 :     pub fn code_map_count(&self) -> u32 {
      35            0 :         self.ptr.code_map_count()
      36            0 :     }
      37              : 
      38            0 :     pub fn redirection_metadata(&self) -> u32 {
      39            0 :         self.ptr.redirection_metadata()
      40            0 :     }
      41              : 
      42            0 :     pub fn os_arm64x_dispatch_call_no_redirect(&self) -> u32 {
      43            0 :         self.ptr.os_arm64x_dispatch_call_no_redirect()
      44            0 :     }
      45              : 
      46            0 :     pub fn os_arm64x_dispatch_ret(&self) -> u32 {
      47            0 :         self.ptr.os_arm64x_dispatch_ret()
      48            0 :     }
      49              : 
      50            0 :     pub fn os_arm64x_dispatch_call(&self) -> u32 {
      51            0 :         self.ptr.os_arm64x_dispatch_call()
      52            0 :     }
      53              : 
      54            0 :     pub fn os_arm64x_dispatch_icall(&self) -> u32 {
      55            0 :         self.ptr.os_arm64x_dispatch_icall()
      56            0 :     }
      57              : 
      58            0 :     pub fn os_arm64x_dispatch_icall_cfg(&self) -> u32 {
      59            0 :         self.ptr.os_arm64x_dispatch_icall_cfg()
      60            0 :     }
      61              : 
      62            0 :     pub fn alternate_entry_point(&self) -> u32 {
      63            0 :         self.ptr.alternate_entry_point()
      64            0 :     }
      65              : 
      66            0 :     pub fn auxiliary_iat(&self) -> u32 {
      67            0 :         self.ptr.auxiliary_iat()
      68            0 :     }
      69              : 
      70            0 :     pub fn code_ranges_to_entry_points_count(&self) -> u32 {
      71            0 :         self.ptr.code_ranges_to_entry_points_count()
      72            0 :     }
      73              : 
      74            0 :     pub fn redirection_metadata_count(&self) -> u32 {
      75            0 :         self.ptr.redirection_metadata_count()
      76            0 :     }
      77              : 
      78            0 :     pub fn get_x64_information_function_pointer(&self) -> u32 {
      79            0 :         self.ptr.get_x64_information_function_pointer()
      80            0 :     }
      81              : 
      82            0 :     pub fn set_x64_information_function_pointer(&self) -> u32 {
      83            0 :         self.ptr.set_x64_information_function_pointer()
      84            0 :     }
      85              : 
      86              :     /// RVA to this architecture-specific exception table
      87            0 :     pub fn extra_rfe_table(&self) -> u32 {
      88            0 :         self.ptr.extra_rfe_table()
      89            0 :     }
      90              : 
      91              :     /// Architecture-specific exception table size
      92            0 :     pub fn extra_rfe_table_size(&self) -> u32 {
      93            0 :         self.ptr.extra_rfe_table_size()
      94            0 :     }
      95              : 
      96            0 :     pub fn auxiliary_iat_copy(&self) -> u32 {
      97            0 :         self.ptr.auxiliary_iat_copy()
      98            0 :     }
      99              : 
     100            0 :     pub fn auxiliary_delay_import(&self) -> u32 {
     101            0 :         self.ptr.auxiliary_delay_import()
     102            0 :     }
     103              : 
     104            0 :     pub fn auxiliary_delay_import_copy(&self) -> u32 {
     105            0 :         self.ptr.auxiliary_delay_import_copy()
     106            0 :     }
     107              : 
     108            0 :     pub fn bitfield_info(&self) -> u32 {
     109            0 :         self.ptr.bitfield_info()
     110            0 :     }
     111              : 
     112            0 :     pub fn code_ranges(&self) -> CodeRanges {
     113            0 :         CodeRanges::new(self.ptr.code_ranges())
     114            0 :     }
     115              : 
     116            0 :     pub fn redirections(&self) -> Redirections {
     117            0 :         Redirections::new(self.ptr.redirections())
     118            0 :     }
     119              : 
     120            0 :     pub fn code_range_entry_point(&self) -> CodeRangeEntrypoints {
     121            0 :         CodeRangeEntrypoints::new(self.ptr.code_range_entry_point())
     122            0 :     }
     123              : }
     124              : 
     125              : impl AsCHPEMetadata for CHPEMetadata<'_> {
     126            0 :     fn as_generic(&self) -> &ffi::PE_CHPEMetadata {
     127            0 :         self.ptr.as_ref().unwrap().as_ref()
     128            0 :     }
     129              : }
     130              : 
     131              : impl std::fmt::Debug for CHPEMetadata<'_> {
     132            0 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     133            0 :         f.debug_struct("CHPEMetadataARM64")
     134            0 :             .field("code_map", &self.code_map())
     135            0 :             .field("code_map_count", &self.code_map_count())
     136            0 :             .field("redirection_metadata", &self.redirection_metadata())
     137            0 :             .field(
     138            0 :                 "os_arm64x_dispatch_call_no_redirect",
     139            0 :                 &self.os_arm64x_dispatch_call_no_redirect(),
     140            0 :             )
     141            0 :             .field("os_arm64x_dispatch_ret", &self.os_arm64x_dispatch_ret())
     142            0 :             .field("os_arm64x_dispatch_call", &self.os_arm64x_dispatch_call())
     143            0 :             .field("os_arm64x_dispatch_icall", &self.os_arm64x_dispatch_icall())
     144            0 :             .field(
     145            0 :                 "os_arm64x_dispatch_icall_cfg",
     146            0 :                 &self.os_arm64x_dispatch_icall_cfg(),
     147            0 :             )
     148            0 :             .field("alternate_entry_point", &self.alternate_entry_point())
     149            0 :             .field("auxiliary_iat", &self.auxiliary_iat())
     150            0 :             .field(
     151            0 :                 "code_ranges_to_entry_points_count",
     152            0 :                 &self.code_ranges_to_entry_points_count(),
     153            0 :             )
     154            0 :             .field(
     155            0 :                 "redirection_metadata_count",
     156            0 :                 &self.redirection_metadata_count(),
     157            0 :             )
     158            0 :             .field(
     159            0 :                 "get_x64_information_function_pointer",
     160            0 :                 &self.get_x64_information_function_pointer(),
     161            0 :             )
     162            0 :             .field(
     163            0 :                 "set_x64_information_function_pointer",
     164            0 :                 &self.set_x64_information_function_pointer(),
     165            0 :             )
     166            0 :             .field("extra_rfe_table", &self.extra_rfe_table())
     167            0 :             .field("extra_rfe_table_size", &self.extra_rfe_table_size())
     168            0 :             .field("auxiliary_iat_copy", &self.auxiliary_iat_copy())
     169            0 :             .field("auxiliary_delay_import", &self.auxiliary_delay_import())
     170            0 :             .field(
     171            0 :                 "auxiliary_delay_import_copy",
     172            0 :                 &self.auxiliary_delay_import_copy(),
     173            0 :             )
     174            0 :             .field("bitfield_info", &self.bitfield_info())
     175            0 :             .finish()
     176            0 :     }
     177              : }
     178              : 
     179              : /// Structure that describes architecture-specific ranges
     180              : pub struct RangeEntry<'a> {
     181              :     ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_range_entry_t>,
     182              :     _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
     183              : }
     184              : 
     185              : impl<'a> FromFFI<ffi::PE_CHPEMetadataARM64_range_entry_t> for RangeEntry<'a> {
     186            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_range_entry_t>) -> Self {
     187            0 :         Self {
     188            0 :             ptr,
     189            0 :             _owner: PhantomData,
     190            0 :         }
     191            0 :     }
     192              : }
     193              : 
     194              : #[allow(non_camel_case_types)]
     195            0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     196              : pub enum RangeType {
     197              :     /// Pure ARM64 code
     198              :     ARM64,
     199              : 
     200              :     /// ARM64EC hybrid code (compatible with x64)
     201              :     ARM64EC,
     202              : 
     203              :     /// x64 code
     204              :     AMD64,
     205              :     UNKNOWN(u32),
     206              : }
     207              : 
     208              : impl From<u32> for RangeType {
     209            0 :     fn from(value: u32) -> Self {
     210            0 :         match value {
     211            0 :             0x000000000 => RangeType::ARM64,
     212            0 :             0x000000001 => RangeType::ARM64EC,
     213            0 :             0x000000002 => RangeType::AMD64,
     214            0 :             _ => RangeType::UNKNOWN(value),
     215              :         }
     216            0 :     }
     217              : }
     218              : 
     219              : impl RangeEntry<'_> {
     220              :     /// Raw data (include start RVA and type)
     221            0 :     pub fn start_offset(&self) -> u32 {
     222            0 :         self.ptr.start_offset()
     223            0 :     }
     224              : 
     225              :     /// Range's length
     226            0 :     pub fn length(&self) -> u32 {
     227            0 :         self.ptr.length()
     228            0 :     }
     229              : 
     230              :     /// Start of the range (RVA)
     231            0 :     pub fn start(&self) -> u32 {
     232            0 :         self.ptr.start()
     233            0 :     }
     234              : 
     235              :     /// End of the range (RVA)
     236            0 :     pub fn end(&self) -> u32 {
     237            0 :         self.ptr.end()
     238            0 :     }
     239              : 
     240              :     /// Architecture for this range
     241            0 :     pub fn range_type(&self) -> RangeType {
     242            0 :         RangeType::from(self.ptr.get_type())
     243            0 :     }
     244              : }
     245              : 
     246              : impl std::fmt::Debug for RangeEntry<'_> {
     247            0 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     248            0 :         f.debug_struct("RangeEntry")
     249            0 :             .field("start_offset", &self.start_offset())
     250            0 :             .field("length", &self.length())
     251            0 :             .field("start", &self.start())
     252            0 :             .field("end", &self.end())
     253            0 :             .field("range_type", &self.range_type())
     254            0 :             .finish()
     255            0 :     }
     256              : }
     257              : 
     258              : /// Structure that describes a redirection
     259              : pub struct RedirectionEntry<'a> {
     260              :     ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_redirection_entry_t>,
     261              :     _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
     262              : }
     263              : 
     264              : impl<'a> FromFFI<ffi::PE_CHPEMetadataARM64_redirection_entry_t> for RedirectionEntry<'a> {
     265            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_redirection_entry_t>) -> Self {
     266            0 :         Self {
     267            0 :             ptr,
     268            0 :             _owner: PhantomData,
     269            0 :         }
     270            0 :     }
     271              : }
     272              : 
     273              : impl RedirectionEntry<'_> {
     274            0 :     pub fn src(&self) -> u32 {
     275            0 :         self.ptr.src()
     276            0 :     }
     277              : 
     278            0 :     pub fn dst(&self) -> u32 {
     279            0 :         self.ptr.dst()
     280            0 :     }
     281              : }
     282              : 
     283              : impl std::fmt::Debug for RedirectionEntry<'_> {
     284            0 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     285            0 :         f.debug_struct("RedirectionEntry")
     286            0 :             .field("src", &self.src())
     287            0 :             .field("dst", &self.dst())
     288            0 :             .finish()
     289            0 :     }
     290              : }
     291              : 
     292              : /// Mirror of `IMAGE_ARM64EC_CODE_RANGE_ENTRY_POINT`:
     293              : /// Represents a mapping between code range and its entry point.
     294              : pub struct CodeRangeEntrypoint<'a> {
     295              :     ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_code_range_entry_point_t>,
     296              :     _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
     297              : }
     298              : 
     299              : impl<'a> FromFFI<ffi::PE_CHPEMetadataARM64_code_range_entry_point_t> for CodeRangeEntrypoint<'a> {
     300            0 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_CHPEMetadataARM64_code_range_entry_point_t>) -> Self {
     301            0 :         Self {
     302            0 :             ptr,
     303            0 :             _owner: PhantomData,
     304            0 :         }
     305            0 :     }
     306              : }
     307              : 
     308              : impl CodeRangeEntrypoint<'_> {
     309              :     /// Start of the code range.
     310            0 :     pub fn start_rva(&self) -> u32 {
     311            0 :         self.ptr.start_rva()
     312            0 :     }
     313              : 
     314              :     /// End of the code range (RVA).
     315            0 :     pub fn end_rva(&self) -> u32 {
     316            0 :         self.ptr.end_rva()
     317            0 :     }
     318              : 
     319              :     /// RVA of the entry point for this range.
     320            0 :     pub fn entrypoint(&self) -> u32 {
     321            0 :         self.ptr.entrypoint()
     322            0 :     }
     323              : }
     324              : 
     325              : impl std::fmt::Debug for CodeRangeEntrypoint<'_> {
     326            0 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     327            0 :         f.debug_struct("CodeRangeEntrypoint")
     328            0 :             .field("start_rva", &self.start_rva())
     329            0 :             .field("end_rva", &self.end_rva())
     330            0 :             .field("entrypoint", &self.entrypoint())
     331            0 :             .finish()
     332            0 :     }
     333              : }
     334              : 
     335              : 
     336            0 : declare_iterator!(
     337            0 :     CodeRanges,
     338            0 :     RangeEntry<'a>,
     339            0 :     ffi::PE_CHPEMetadataARM64_range_entry_t,
     340            0 :     ffi::PE_CHPEMetadataARM64,
     341            0 :     ffi::PE_CHPEMetadataARM64_it_const_range_entries
     342            0 : );
     343              : 
     344            0 : declare_iterator!(
     345            0 :     Redirections,
     346            0 :     RedirectionEntry<'a>,
     347            0 :     ffi::PE_CHPEMetadataARM64_redirection_entry_t,
     348            0 :     ffi::PE_CHPEMetadataARM64,
     349            0 :     ffi::PE_CHPEMetadataARM64_it_const_redirection_entries
     350            0 : );
     351              : 
     352            0 : declare_iterator!(
     353            0 :     CodeRangeEntrypoints,
     354            0 :     CodeRangeEntrypoint<'a>,
     355            0 :     ffi::PE_CHPEMetadataARM64_code_range_entry_point_t,
     356            0 :     ffi::PE_CHPEMetadataARM64,
     357            0 :     ffi::PE_CHPEMetadataARM64_it_const_code_range_entry_point
     358            0 : );
        

Generated by: LCOV version 2.1-1