LCOV - code coverage report
Current view: top level - src/pe - tls.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 44.8 % 87 39
Test Date: 2025-02-23:00:00:00 Functions: 42.9 % 21 9

            Line data    Source code
       1              : //! This module represents the PE's Thread Local Storage (TLS)
       2              : 
       3              : use lief_ffi as ffi;
       4              : 
       5              : use crate::common::{FromFFI, into_optional, AsFFI};
       6              : use crate::to_slice;
       7              : use std::marker::PhantomData;
       8              : 
       9              : use crate::pe::Section;
      10              : use crate::pe::DataDirectory;
      11              : 
      12              : pub struct TLS<'a> {
      13              :     ptr: cxx::UniquePtr<ffi::PE_TLS>,
      14              :     _owner: PhantomData<&'a ffi::PE_Binary>,
      15              : }
      16              : 
      17              : impl std::fmt::Debug for TLS<'_> {
      18           90 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      19           90 :         f.debug_struct("TLS")
      20           90 :             .field("callbacks", &self.callbacks())
      21           90 :             .field("addressof_index", &self.addressof_index())
      22           90 :             .field("addressof_callbacks", &self.addressof_callbacks())
      23           90 :             .field("sizeof_zero_fill", &self.sizeof_zero_fill())
      24           90 :             .field("characteristics", &self.characteristics())
      25           90 :             .finish()
      26           90 :     }
      27              : }
      28              : 
      29              : impl TLS<'_> {
      30            0 :     pub fn new() -> TLS<'static> {
      31            0 :         TLS::from_ffi(lief_ffi::PE_TLS::create())
      32            0 :     }
      33              :     /// List of callbacks associated with the current TLS
      34              :     ///
      35              :     /// These functions are called before any other functions.
      36           90 :     pub fn callbacks(&self) -> Vec<u64> {
      37           90 :         Vec::from(self.ptr.callbacks().as_slice())
      38           90 :     }
      39              : 
      40              :     /// The location to receive the TLS index assigned by the loader.
      41              :     /// This location should be located in a writable section like `.data`
      42           90 :     pub fn addressof_index(&self) -> u64 {
      43           90 :         self.ptr.addressof_index()
      44           90 :     }
      45              : 
      46              :     /// Pointer to an array of TLS callback functions.
      47              :     ///
      48              :     /// The array is null-terminated, so if there is no callback function this field points to 4
      49              :     /// bytes set to zero.
      50              :     ///
      51              :     /// See [`TLS::callbacks`]
      52           90 :     pub fn addressof_callbacks(&self) -> u64 {
      53           90 :         self.ptr.addressof_callbacks()
      54           90 :     }
      55              : 
      56              :     /// Size in bytes of the zero to be *padded* after the data specified by [`TLS::data_template`]
      57           90 :     pub fn sizeof_zero_fill(&self) -> u32 {
      58           90 :         self.ptr.sizeof_zero_fill()
      59           90 :     }
      60              : 
      61              :     /// The four bits `[23:20]` describe alignment info.
      62              :     ///
      63              :     /// Possible values are those defined as `IMAGE_SCN_ALIGN_*`, which are also used to describe
      64              :     /// alignment of section in object files.
      65              :     ///
      66              :     /// The other 28 bits are reserved for future use.
      67           90 :     pub fn characteristics(&self) -> u32 {
      68           90 :         self.ptr.characteristics()
      69           90 :     }
      70              : 
      71              :     /// The initial content used to initialize TLS data.
      72           90 :     pub fn data_template(&self) -> &[u8] {
      73           90 :         to_slice!(self.ptr.data_template());
      74           90 :     }
      75              : 
      76              :     /// Range of addresses where the [`TLS::data_template`] is located.
      77              :     ///
      78              :     /// The template is a block of data that is used to initialize TLS data.
      79              :     /// The system copies all of this data each time a thread is created, so it
      80              :     /// must not be corrupted.
      81              :     ///
      82              :     /// These addresses are not RVA. It is addresses for which there
      83              :     /// should be a rebase relocation in the `.reloc` section.
      84           90 :     pub fn addressof_raw_data(&self) -> (u64, u64) {
      85           90 :         let vec = Vec::from(self.ptr.addressof_raw_data().as_slice());
      86           90 :         if vec.len() != 2 {
      87            0 :             return (0, 0);
      88           90 :         }
      89           90 :         (vec[0], vec[1])
      90           90 :     }
      91              : 
      92              :     /// The section where the TLS structure is located
      93            0 :     pub fn section(&self) -> Option<Section> {
      94            0 :         into_optional(self.ptr.section())
      95            0 :     }
      96              : 
      97              :     /// The data directory describing the TLS
      98            0 :     pub fn directory(&self) -> Option<DataDirectory> {
      99            0 :         into_optional(self.ptr.data_directory())
     100            0 :     }
     101              : 
     102              :     /// Add an address to the list of callbacks
     103            0 :     pub fn add_callback(&mut self, addr: u64) -> &mut Self {
     104            0 :         self.ptr.pin_mut().add_callback(addr);
     105            0 :         self
     106            0 :     }
     107              : 
     108            0 :     pub fn set_callbacks(&mut self, callbacks: &[u64]) -> &mut Self {
     109            0 :         unsafe {
     110            0 :             self.ptr.pin_mut().set_callbacks(callbacks.as_ptr(), callbacks.len());
     111            0 :         }
     112            0 :         self
     113            0 :     }
     114              : 
     115            0 :     pub fn set_addressof_index(&mut self, addr: u64) -> &mut Self {
     116            0 :         self.ptr.pin_mut().set_addressof_index(addr);
     117            0 :         self
     118            0 :     }
     119              : 
     120            0 :     pub fn set_addressof_callback(&mut self, addr: u64) -> &mut Self {
     121            0 :         self.ptr.pin_mut().set_addressof_callback(addr);
     122            0 :         self
     123            0 :     }
     124              : 
     125            0 :     pub fn set_sizeof_zero_fill(&mut self, size: u32) -> &mut Self {
     126            0 :         self.ptr.pin_mut().set_sizeof_zero_fill(size);
     127            0 :         self
     128            0 :     }
     129              : 
     130            0 :     pub fn set_characteristics(&mut self, characteristics: u32) -> &mut Self {
     131            0 :         self.ptr.pin_mut().set_characteristics(characteristics);
     132            0 :         self
     133            0 :     }
     134              : 
     135            0 :     pub fn set_data_template(&mut self, data: &[u8]) -> &mut Self {
     136            0 :         unsafe {
     137            0 :             self.ptr.pin_mut().set_data_template(data.as_ptr(), data.len());
     138            0 :         }
     139            0 :         self
     140            0 :     }
     141              : }
     142              : 
     143              : 
     144              : impl<'a> FromFFI<ffi::PE_TLS> for TLS<'a> {
     145           90 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_TLS>) -> Self {
     146           90 :         TLS {
     147           90 :             ptr,
     148           90 :             _owner: PhantomData,
     149           90 :         }
     150           90 :     }
     151              : }
     152              : 
     153              : impl<'a> AsFFI<ffi::PE_TLS> for TLS<'a> {
     154            0 :     fn as_ffi(&self) -> &ffi::PE_TLS {
     155            0 :         self.ptr.as_ref().unwrap()
     156            0 :     }
     157              : 
     158            0 :     fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::PE_TLS> {
     159            0 :         self.ptr.pin_mut()
     160            0 :     }
     161              : }
        

Generated by: LCOV version 2.1-1