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: 2026-04-12:00:00:00 Functions: 87.5 % 8 7

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

Generated by: LCOV version 2.1-1