LCOV - code coverage report
Current view: top level - src/macho/commands - thread_command.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 90.9 % 33 30
Test Date: 2024-10-27:00:00:00 Functions: 87.5 % 8 7

            Line data    Source code
       1              : use lief_ffi as ffi;
       2              : use super::Command;
       3              : use crate::common::FromFFI;
       4              : use crate::to_slice;
       5              : 
       6              : use crate::macho::header::CpuType;
       7              : use std::marker::PhantomData;
       8              : 
       9              : /// Structure that represents the `LC_THREAD` / `LC_UNIXTHREAD` commands and that
      10              : /// can be used to get the binary entrypoint when the `LC_MAIN` is not present
      11              : ///
      12              : /// Generally speaking, this command aims at defining the original state
      13              : /// of the main thread which includes the registers' values
      14              : pub struct ThreadCommand<'a> {
      15              :     ptr: cxx::UniquePtr<ffi::MachO_ThreadCommand>,
      16              :     _owner: PhantomData<&'a ffi::MachO_Binary>
      17              : }
      18              : 
      19              : impl ThreadCommand<'_> {
      20              : 
      21              :     /// Integer that defines a special *flavor* for the thread.
      22              :     ///
      23              :     /// The meaning of this value depends on the architecture. The list of
      24              :     /// the values can be found in the XNU kernel files:
      25              :     /// - xnu/osfmk/mach/arm/thread_status.h  for the ARM/AArch64 architectures
      26              :     /// - xnu/osfmk/mach/i386/thread_status.h for the x86/x86-64 architectures
      27           16 :     pub fn flavor(&self) -> u32 {
      28           16 :         self.ptr.flavor()
      29           16 :     }
      30              : 
      31              :     /// The CPU architecture that is targeted by this Thread Command
      32            0 :     pub fn architecture(&self) -> CpuType {
      33            0 :         CpuType::from(self.ptr.architecture())
      34            0 :     }
      35              : 
      36              :     /// Size of the thread state data with 32-bits alignment.
      37              :     ///
      38              :     /// This value should match `state().len()`
      39           16 :     pub fn count(&self) -> u32 {
      40           16 :         self.ptr.count()
      41           16 :     }
      42              : 
      43              :     /// Return the initial Program Counter regardless of the underlying architecture.
      44              :     /// This value, when non null, can be used to determine the binary's entrypoint.
      45              :     ///
      46              :     /// Underneath, it works by looking for the PC register value in the [`ThreadCommand::state`]
      47              :     /// data
      48           16 :     pub fn pc(&self) -> u64 {
      49           16 :         self.ptr.pc()
      50           16 :     }
      51              : 
      52              :     /// The actual thread state as a vector of bytes. Depending on the architecture(),
      53              :     /// these data can be casted into `x86_thread_state_t, x86_thread_state64_t, ...`
      54            8 :     pub fn state(&self) -> &[u8] {
      55            8 :         to_slice!(self.ptr.state());
      56            8 :     }
      57              : }
      58              : 
      59              : impl std::fmt::Debug for ThreadCommand<'_> {
      60           16 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      61           16 :         let base = self as &dyn Command;
      62           16 :         f.debug_struct("ThreadCommand")
      63           16 :             .field("base", &base)
      64           16 :             .field("flavor", &self.flavor())
      65           16 :             .field("count", &self.count())
      66           16 :             .field("pc", &self.pc())
      67           16 :             .finish()
      68           16 :     }
      69              : }
      70              : 
      71              : impl FromFFI<ffi::MachO_ThreadCommand> for ThreadCommand<'_> {
      72           16 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_ThreadCommand>) -> Self {
      73           16 :         Self {
      74           16 :             ptr: cmd,
      75           16 :             _owner: PhantomData
      76           16 :         }
      77           16 :     }
      78              : }
      79              : 
      80              : impl Command for ThreadCommand<'_> {
      81           64 :     fn get_base(&self) -> &ffi::MachO_Command {
      82           64 :         self.ptr.as_ref().unwrap().as_ref()
      83           64 :     }
      84              : }
        

Generated by: LCOV version 2.1-1