LCOV - code coverage report
Current view: top level - src/elf - segment.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 35.9 % 184 66
Test Date: 2025-06-24:00:00:00 Functions: 43.2 % 37 16

            Line data    Source code
       1              : use lief_ffi as ffi;
       2              : use bitflags::bitflags;
       3              : use std::fmt;
       4              : use std::marker::PhantomData;
       5              : 
       6              : use crate::common::FromFFI;
       7              : use crate::{declare_iterator, to_slice};
       8              : 
       9              : #[allow(non_camel_case_types)]
      10          828 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
      11              : pub enum Type {
      12              :     /// Unused segment
      13              :     PT_NULL,
      14              :     /// Loadable segment
      15              :     LOAD,
      16              :     /// Dynamic linking information.
      17              :     DYNAMIC,
      18              :     /// Interpreter pathname.
      19              :     INTERP,
      20              :     /// Auxiliary information.
      21              :     NOTE,
      22              :     /// Reserved
      23              :     SHLIB,
      24              :     /// The program header table itself.
      25              :     PHDR,
      26              :     /// The thread-local storage template.
      27              :     TLS,
      28              :     GNU_EH_FRAME,
      29              :     /// Indicates stack executability
      30              :     GNU_STACK,
      31              :     /// GNU property
      32              :     GNU_PROPERTY,
      33              :     /// Read-only after relocation.
      34              :     GNU_RELRO,
      35              :     PAX_FLAGS,
      36              :     /// Platform architecture compatibility info
      37              :     ARM_ARCHEXT,
      38              :     ARM_EXIDX,
      39              :     ARM_UNWIND,
      40              :     AARCH64_MEMTAG_MTE,
      41              :     /// Register usage information
      42              :     MIPS_REGINFO,
      43              :     /// Runtime procedure table.
      44              :     MIPS_RTPROC,
      45              :     /// Options segment.
      46              :     MIPS_OPTIONS,
      47              :     /// Abiflags segment.
      48              :     MIPS_ABIFLAGS,
      49              :     RISCV_ATTRIBUTES,
      50              :     IA_64_EXT,
      51              :     IA_64_UNWIND,
      52              :     HP_TLS,
      53              :     HP_CORE_NONE,
      54              :     HP_CORE_VERSION,
      55              :     HP_CORE_KERNEL,
      56              :     HP_CORE_COMM,
      57              :     HP_CORE_PROC,
      58              :     HP_CORE_LOADABLE,
      59              :     HP_CORE_STACK,
      60              :     HP_CORE_SHM,
      61              :     HP_CORE_MMF,
      62              :     HP_PARALLEL,
      63              :     HP_FASTBIND,
      64              :     HP_OPT_ANNOT,
      65              :     HP_HSL_ANNOT,
      66              :     HP_STACK,
      67              :     HP_CORE_UTSNAME,
      68              :     UNKNOWN(u64),
      69              : }
      70              : 
      71              : impl From<u64> for Type {
      72         1656 :     fn from(value: u64) -> Self {
      73         1656 :         match value {
      74           24 :             0x00000000 => Type::PT_NULL,
      75          720 :             0x00000001 => Type::LOAD,
      76          120 :             0x00000002 => Type::DYNAMIC,
      77           96 :             0x00000003 => Type::INTERP,
      78          168 :             0x00000004 => Type::NOTE,
      79            0 :             0x00000005 => Type::SHLIB,
      80           96 :             0x00000006 => Type::PHDR,
      81           24 :             0x00000007 => Type::TLS,
      82          120 :             0x6474e550 => Type::GNU_EH_FRAME,
      83          120 :             0x6474e551 => Type::GNU_STACK,
      84           24 :             0x6474e553 => Type::GNU_PROPERTY,
      85           96 :             0x6474e552 => Type::GNU_RELRO,
      86            0 :             0x65041580 => Type::PAX_FLAGS,
      87            0 :             0x270000000 => Type::ARM_ARCHEXT,
      88            0 :             0x270000001 => Type::ARM_EXIDX,
      89            0 :             0x470000002 => Type::AARCH64_MEMTAG_MTE,
      90           24 :             0x670000000 => Type::MIPS_REGINFO,
      91            0 :             0x670000001 => Type::MIPS_RTPROC,
      92            0 :             0x670000002 => Type::MIPS_OPTIONS,
      93           24 :             0x670000003 => Type::MIPS_ABIFLAGS,
      94            0 :             0x870000003 => Type::RISCV_ATTRIBUTES,
      95            0 :             0xa70000000 => Type::IA_64_EXT,
      96            0 :             0xa70000001 => Type::IA_64_UNWIND,
      97            0 :             0x20000060000000 => Type::HP_TLS,
      98            0 :             0x20000060000001 => Type::HP_CORE_NONE,
      99            0 :             0x20000060000002 => Type::HP_CORE_VERSION,
     100            0 :             0x20000060000003 => Type::HP_CORE_KERNEL,
     101            0 :             0x20000060000004 => Type::HP_CORE_COMM,
     102            0 :             0x20000060000005 => Type::HP_CORE_PROC,
     103            0 :             0x20000060000006 => Type::HP_CORE_LOADABLE,
     104            0 :             0x20000060000007 => Type::HP_CORE_STACK,
     105            0 :             0x20000060000008 => Type::HP_CORE_SHM,
     106            0 :             0x20000060000009 => Type::HP_CORE_MMF,
     107            0 :             0x20000060000010 => Type::HP_PARALLEL,
     108            0 :             0x20000060000011 => Type::HP_FASTBIND,
     109            0 :             0x20000060000012 => Type::HP_OPT_ANNOT,
     110            0 :             0x20000060000013 => Type::HP_HSL_ANNOT,
     111            0 :             0x20000060000014 => Type::HP_STACK,
     112            0 :             0x20000060000015 => Type::HP_CORE_UTSNAME,
     113            0 :             _ => Type::UNKNOWN(value),
     114              : 
     115              :         }
     116         1656 :     }
     117              : }
     118              : impl From<Type> for u64 {
     119            0 :     fn from(value: Type) -> u64 {
     120            0 :         match value {
     121            0 :             Type::PT_NULL => 0x00000000,
     122            0 :             Type::LOAD => 0x00000001,
     123            0 :             Type::DYNAMIC => 0x00000002,
     124            0 :             Type::INTERP => 0x00000003,
     125            0 :             Type::NOTE => 0x00000004,
     126            0 :             Type::SHLIB => 0x00000005,
     127            0 :             Type::PHDR => 0x00000006,
     128            0 :             Type::TLS => 0x00000007,
     129            0 :             Type::GNU_EH_FRAME => 0x6474e550,
     130            0 :             Type::GNU_STACK => 0x6474e551,
     131            0 :             Type::GNU_PROPERTY => 0x6474e553,
     132            0 :             Type::GNU_RELRO => 0x6474e552,
     133            0 :             Type::PAX_FLAGS => 0x65041580,
     134            0 :             Type::ARM_ARCHEXT => 0x270000000,
     135            0 :             Type::ARM_EXIDX => 0x270000001,
     136            0 :             Type::ARM_UNWIND => 0x270000001,
     137            0 :             Type::AARCH64_MEMTAG_MTE => 0x470000002,
     138            0 :             Type::MIPS_REGINFO => 0x670000000,
     139            0 :             Type::MIPS_RTPROC => 0x670000001,
     140            0 :             Type::MIPS_OPTIONS => 0x670000002,
     141            0 :             Type::MIPS_ABIFLAGS => 0x670000003,
     142            0 :             Type::RISCV_ATTRIBUTES => 0x870000003,
     143            0 :             Type::IA_64_EXT => 0xa70000000,
     144            0 :             Type::IA_64_UNWIND => 0xa70000001,
     145            0 :             Type::HP_TLS => 0x20000060000000,
     146            0 :             Type::HP_CORE_NONE => 0x20000060000001,
     147            0 :             Type::HP_CORE_VERSION => 0x20000060000002,
     148            0 :             Type::HP_CORE_KERNEL => 0x20000060000003,
     149            0 :             Type::HP_CORE_COMM => 0x20000060000004,
     150            0 :             Type::HP_CORE_PROC => 0x20000060000005,
     151            0 :             Type::HP_CORE_LOADABLE => 0x20000060000006,
     152            0 :             Type::HP_CORE_STACK => 0x20000060000007,
     153            0 :             Type::HP_CORE_SHM => 0x20000060000008,
     154            0 :             Type::HP_CORE_MMF => 0x20000060000009,
     155            0 :             Type::HP_PARALLEL => 0x20000060000010,
     156            0 :             Type::HP_FASTBIND => 0x20000060000011,
     157            0 :             Type::HP_OPT_ANNOT => 0x20000060000012,
     158            0 :             Type::HP_HSL_ANNOT => 0x20000060000013,
     159            0 :             Type::HP_STACK => 0x20000060000014,
     160            0 :             Type::HP_CORE_UTSNAME => 0x20000060000015,
     161            0 :             Type::UNKNOWN(value) => value,
     162              :         }
     163            0 :     }
     164              : }
     165              : 
     166            0 : bitflags! {
     167            0 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     168            0 :     pub struct Flags: u32 {
     169            0 :         const NONE = 0x0;
     170            0 :         const X = 0x1;
     171            0 :         const W = 0x2;
     172            0 :         const R = 0x4;
     173            0 :     }
     174            0 : }
     175              : 
     176              : 
     177              : impl Flags {
     178            0 :     pub fn from_value(value: u32) -> Self {
     179            0 :         Flags::from_bits_truncate(value)
     180            0 :     }
     181              : 
     182            0 :     pub fn to_value(&self) -> u32 {
     183            0 :         self.bits() as u32
     184            0 :     }
     185              : }
     186              : 
     187              : /// Structure which reprents an ELF segment
     188              : pub struct Segment<'a> {
     189              :     pub(super) ptr: cxx::UniquePtr<ffi::ELF_Segment>,
     190              :     _owner: PhantomData<&'a ffi::ELF_Binary>
     191              : }
     192              : 
     193              : impl fmt::Debug for Segment<'_> {
     194          828 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     195          828 :         f.debug_struct("Segment")
     196          828 :             .field("p_type", &self.p_type())
     197          828 :             .field("flags", &self.flags())
     198          828 :             .field("file_offset", &self.file_offset())
     199          828 :             .field("virtual_address", &self.virtual_address())
     200          828 :             .field("physical_address", &self.physical_address())
     201          828 :             .field("physical_size", &self.physical_size())
     202          828 :             .field("virtual_size", &self.virtual_size())
     203          828 :             .field("alignment", &self.alignment())
     204          828 :             .finish()
     205          828 :     }
     206              : }
     207              : 
     208              : impl FromFFI<ffi::ELF_Segment> for Segment<'_> {
     209          852 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Segment>) -> Self {
     210          852 :         Segment {
     211          852 :             ptr,
     212          852 :             _owner: PhantomData
     213          852 :         }
     214          852 :     }
     215              : }
     216              : 
     217              : impl Segment<'_> {
     218              :     /// Create a new segment
     219            0 :     pub fn new() -> Segment<'static> {
     220            0 :         Segment::from_ffi(lief_ffi::ELF_Segment::create())
     221            0 :     }
     222              : 
     223              :     /// Content of the segment as a slice of bytes
     224           48 :     pub fn content(&self) -> &[u8] {
     225           48 :         to_slice!(self.ptr.content());
     226           48 :     }
     227              : 
     228              :     /// The segment's type (LOAD, DYNAMIC, ...)
     229         1656 :     pub fn p_type(&self) -> Type {
     230         1656 :         Type::from(self.ptr.stype())
     231         1656 :     }
     232              : 
     233              :     /// The flag permissions associated with this segment
     234          828 :     pub fn flags(&self) -> u32 {
     235          828 :         self.ptr.flags()
     236          828 :     }
     237              : 
     238              :     /// The file offset of the data associated with this segment
     239          828 :     pub fn file_offset(&self) -> u64 {
     240          828 :         self.ptr.file_offset()
     241          828 :     }
     242              : 
     243              :     /// The virtual address of the segment.
     244          828 :     pub fn virtual_address(&self) -> u64 {
     245          828 :         self.ptr.virtual_address()
     246          828 :     }
     247              :     /// The physical address of the segment.
     248              :     /// This value is not really relevant on systems like Linux or Android.
     249              :     /// On the other hand, Qualcomm trustlets might use this value.
     250              :     ///
     251              :     /// Usually this value matches [`Segment::virtual_address`]
     252          828 :     pub fn physical_address(&self) -> u64 {
     253          828 :         self.ptr.physical_address()
     254          828 :     }
     255              : 
     256              :     /// The **file** size of the data associated with this segment
     257          828 :     pub fn physical_size(&self) -> u64 {
     258          828 :         self.ptr.physical_size()
     259          828 :     }
     260              : 
     261              :     /// The in-memory size of this segment.
     262              :     /// Usually, if the `.bss` segment is wrapped by this segment
     263              :     /// then, virtual_size is larger than physical_size
     264          828 :     pub fn virtual_size(&self) -> u64 {
     265          828 :         self.ptr.virtual_size()
     266          828 :     }
     267              : 
     268              :     /// The offset alignment of the segment
     269          828 :     pub fn alignment(&self) -> u64 {
     270          828 :         self.ptr.alignment()
     271          828 :     }
     272              : 
     273            0 :     pub fn set_type(&mut self, ty: Type) {
     274            0 :         self.ptr.pin_mut().set_type(ty.into());
     275            0 :     }
     276              : 
     277            0 :     pub fn set_flags(&mut self, flags: Flags) {
     278            0 :         self.ptr.pin_mut().set_flags(flags.to_value())
     279            0 :     }
     280              : 
     281            0 :     pub fn set_file_offset(&mut self, offset: u64) {
     282            0 :         self.ptr.pin_mut().set_file_offset(offset);
     283            0 :     }
     284              : 
     285            0 :     pub fn set_virtual_address(&mut self, va: u64) {
     286            0 :         self.ptr.pin_mut().set_virtual_address(va);
     287            0 :     }
     288              : 
     289            0 :     pub fn set_physical_address(&mut self, addr: u64) {
     290            0 :         self.ptr.pin_mut().set_physical_address(addr);
     291            0 :     }
     292              : 
     293            0 :     pub fn set_virtual_size(&mut self, vsize: u64) {
     294            0 :         self.ptr.pin_mut().set_virtual_size(vsize);
     295            0 :     }
     296              : 
     297            0 :     pub fn set_alignment(&mut self, alignment: u64) {
     298            0 :         self.ptr.pin_mut().set_alignment(alignment);
     299            0 :     }
     300              : 
     301            0 :     pub fn set_content(&mut self, content: &[u8]) {
     302            0 :         unsafe {
     303            0 :             self.ptr.pin_mut().set_content(
     304            0 :                 content.as_ptr(),
     305            0 :                 content.len().try_into().unwrap()
     306            0 :             );
     307            0 :         }
     308            0 :     }
     309              : }
     310              : 
     311              : impl fmt::Display for Segment<'_> {
     312          828 :     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     313          828 :         write!(f, "{}", self.ptr.to_string())
     314          828 :     }
     315              : }
     316              : 
     317          828 : declare_iterator!(Segments, Segment<'a>, ffi::ELF_Segment, ffi::ELF_Binary, ffi::ELF_Binary_it_segments);
        

Generated by: LCOV version 2.1-1