LCOV - code coverage report
Current view: top level - src/macho/commands - segment.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 63.3 % 128 81
Test Date: 2026-04-12:00:00:00 Functions: 46.2 % 39 18

            Line data    Source code
       1              : use super::Command;
       2              : use crate::common::{into_optional, FromFFI};
       3              : use crate::declare_iterator;
       4              : use crate::to_slice;
       5              : use lief_ffi as ffi;
       6              : use std::marker::PhantomData;
       7              : 
       8              : use crate::macho::relocation::Relocation;
       9              : use crate::macho::section::Section;
      10              : 
      11              : use bitflags::bitflags;
      12              : 
      13            0 : bitflags! {
      14            0 :     /// Segment flags
      15            0 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
      16            0 :     pub struct Flags: u64 {
      17            0 :         const HIGHVM = 0x1;
      18            0 :         const FVMLIB = 0x2;
      19            0 :         const NORELOC = 0x4;
      20            0 :         const PROTECTED_VERSION_1 = 0x8;
      21            0 :         const READ_ONLY = 0x10;
      22            0 :     }
      23            0 : }
      24              : 
      25              : impl From<u64> for Flags {
      26            0 :     fn from(value: u64) -> Self {
      27            0 :         Flags::from_bits_truncate(value)
      28            0 :     }
      29              : }
      30              : impl From<Flags> for u64 {
      31            0 :     fn from(value: Flags) -> Self {
      32            0 :         value.bits()
      33            0 :     }
      34              : }
      35              : impl std::fmt::Display for Flags {
      36            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
      37            0 :         bitflags::parser::to_writer(self, f)
      38            0 :     }
      39              : }
      40              : 
      41            0 : bitflags! {
      42            0 :     /// VM protection flags
      43            0 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
      44            0 :     pub struct VmProtections: u32 {
      45            0 :         const READ = 0x1;
      46            0 :         const WRITE = 0x2;
      47            0 :         const EXECUTE = 0x4;
      48            0 :     }
      49            0 : }
      50              : 
      51              : impl From<u32> for VmProtections {
      52            0 :     fn from(value: u32) -> Self {
      53            0 :         VmProtections::from_bits_truncate(value)
      54            0 :     }
      55              : }
      56              : impl From<VmProtections> for u32 {
      57            0 :     fn from(value: VmProtections) -> Self {
      58            0 :         value.bits()
      59            0 :     }
      60              : }
      61              : impl std::fmt::Display for VmProtections {
      62            0 :     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
      63            0 :         bitflags::parser::to_writer(self, f)
      64            0 :     }
      65              : }
      66              : 
      67              : /// Class which represents a `LC_SEGMENT/LC_SEGMENT_64` command
      68              : pub struct Segment<'a> {
      69              :     ptr: cxx::UniquePtr<ffi::MachO_SegmentCommand>,
      70              :     _owner: PhantomData<&'a ffi::MachO_Binary>,
      71              : }
      72              : 
      73              : impl Segment<'_> {
      74              :     /// Name of the segment (e.g. `__TEXT`)
      75       365235 :     pub fn name(&self) -> String {
      76       365235 :         self.ptr.name().to_string()
      77       365235 :     }
      78              : 
      79              :     /// Absolute virtual base address of the segment
      80       365235 :     pub fn virtual_address(&self) -> u64 {
      81       365235 :         self.ptr.virtual_address()
      82       365235 :     }
      83              : 
      84              :     /// Virtual size of the segment
      85       365235 :     pub fn virtual_size(&self) -> u64 {
      86       365235 :         self.ptr.virtual_size()
      87       365235 :     }
      88              : 
      89              :     /// Size of this segment in the binary file
      90       365235 :     pub fn file_size(&self) -> u64 {
      91       365235 :         self.ptr.file_size()
      92       365235 :     }
      93              : 
      94              :     /// Offset of the data of this segment in the file
      95       365235 :     pub fn file_offset(&self) -> u64 {
      96       365235 :         self.ptr.file_offset()
      97       365235 :     }
      98              : 
      99              :     /// The maximum of protections for this segment
     100       365235 :     pub fn max_protection(&self) -> u32 {
     101       365235 :         self.ptr.max_protection()
     102       365235 :     }
     103              : 
     104              :     /// The initial protections of this segment
     105       365235 :     pub fn init_protection(&self) -> u32 {
     106       365235 :         self.ptr.init_protection()
     107       365235 :     }
     108              : 
     109              :     /// The number of sections associated with this segment
     110       365235 :     pub fn numberof_sections(&self) -> u32 {
     111       365235 :         self.ptr.numberof_sections()
     112       365235 :     }
     113              : 
     114              :     /// Flags associated with this segment
     115       365235 :     pub fn flags(&self) -> u32 {
     116       365235 :         self.ptr.flags()
     117       365235 :     }
     118              : 
     119              :     /// The raw content of this segment as a slice of bytes
     120         1300 :     pub fn content(&self) -> &[u8] {
     121         1300 :         to_slice!(self.ptr.content());
     122         1300 :     }
     123              : 
     124              :     /// Iterator over the [`crate::macho::Section`] owned by this segment
     125         1300 :     pub fn sections(&self) -> Sections<'_> {
     126         1300 :         Sections::new(self.ptr.sections())
     127         1300 :     }
     128              : 
     129              :     /// Return an iterator over the [`crate::macho::Relocation`] linked to this segment
     130              :     ///
     131              :     /// For Mach-O executable or library this iterator should be empty as
     132              :     /// the relocations are managed by the Dyld's rebase opcodes.
     133              :     /// On the other hand, for object files (`.o`) this iterator should not be empty.
     134         1300 :     pub fn relocations(&self) -> Relocations<'_> {
     135         1300 :         Relocations::new(self.ptr.relocations())
     136         1300 :     }
     137              : 
     138              :     /// The original index of this segment or -1 if not defined
     139            0 :     pub fn index(&self) -> Option<u8> {
     140            0 :         let idx = self.ptr.index();
     141            0 :         if idx < 0 {
     142            0 :             None
     143              :         } else {
     144            0 :             Some(idx as u8)
     145              :         }
     146            0 :     }
     147              : 
     148              :     /// Return the [`Section`] with the given name (if any)
     149            0 :     pub fn get_section(&self, name: &str) -> Option<Section<'_>> {
     150            0 :         into_optional(self.ptr.get_section(name.to_string()))
     151            0 :     }
     152              : }
     153              : 
     154              : impl std::fmt::Debug for Segment<'_> {
     155       365235 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     156       365235 :         let base = self as &dyn Command;
     157       365235 :         f.debug_struct("Segment")
     158       365235 :             .field("base", &base)
     159       365235 :             .field("name", &self.name())
     160       365235 :             .field("virtual_address", &self.virtual_address())
     161       365235 :             .field("virtual_size", &self.virtual_size())
     162       365235 :             .field("file_size", &self.file_size())
     163       365235 :             .field("file_offset", &self.file_offset())
     164       365235 :             .field("max_protection", &self.max_protection())
     165       365235 :             .field("init_protection", &self.init_protection())
     166       365235 :             .field("numberof_sections", &self.numberof_sections())
     167       365235 :             .field("flags", &self.flags())
     168       365235 :             .finish()
     169       365235 :     }
     170              : }
     171              : 
     172              : impl FromFFI<ffi::MachO_SegmentCommand> for Segment<'_> {
     173       365235 :     fn from_ffi(cmd: cxx::UniquePtr<ffi::MachO_SegmentCommand>) -> Self {
     174       365235 :         Self {
     175       365235 :             ptr: cmd,
     176       365235 :             _owner: PhantomData,
     177       365235 :         }
     178       365235 :     }
     179              : }
     180              : 
     181              : impl Command for Segment<'_> {
     182      1460940 :     fn get_base(&self) -> &ffi::MachO_Command {
     183      1460940 :         self.ptr.as_ref().unwrap().as_ref()
     184      1460940 :     }
     185              : }
     186              : 
     187         1300 : declare_iterator!(
     188         1300 :     Segments,
     189         1300 :     Segment<'a>,
     190         1300 :     ffi::MachO_SegmentCommand,
     191         1300 :     ffi::MachO_Binary,
     192         1300 :     ffi::MachO_Binary_it_segments
     193         1300 : );
     194         4121 : declare_iterator!(
     195         4121 :     Sections,
     196         4121 :     Section<'a>,
     197         4121 :     ffi::MachO_Section,
     198         4121 :     ffi::MachO_SegmentCommand,
     199         4121 :     ffi::MachO_SegmentCommand_it_sections
     200         4121 : );
     201       135018 : declare_iterator!(
     202       135018 :     Relocations,
     203       135018 :     Relocation<'a>,
     204       135018 :     ffi::MachO_Relocation,
     205       135018 :     ffi::MachO_SegmentCommand,
     206       135018 :     ffi::MachO_SegmentCommand_it_relocations
     207       135018 : );
        

Generated by: LCOV version 2.1-1