LCOV - code coverage report
Current view: top level - src/elf - segment.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 36.9 % 195 72
Test Date: 2026-04-12:00:00:00 Functions: 41.0 % 39 16

            Line data    Source code
       1              : use bitflags::bitflags;
       2              : use lief_ffi as ffi;
       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         1183 : #[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         2366 :     fn from(value: u64) -> Self {
      73         2366 :         match value {
      74           26 :             0x00000000 => Type::PT_NULL,
      75          988 :             0x00000001 => Type::LOAD,
      76          182 :             0x00000002 => Type::DYNAMIC,
      77          104 :             0x00000003 => Type::INTERP,
      78          286 :             0x00000004 => Type::NOTE,
      79            0 :             0x00000005 => Type::SHLIB,
      80          104 :             0x00000006 => Type::PHDR,
      81           26 :             0x00000007 => Type::TLS,
      82          182 :             0x6474e550 => Type::GNU_EH_FRAME,
      83          182 :             0x6474e551 => Type::GNU_STACK,
      84           78 :             0x6474e553 => Type::GNU_PROPERTY,
      85          156 :             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           26 :             0x670000000 => Type::MIPS_REGINFO,
      91            0 :             0x670000001 => Type::MIPS_RTPROC,
      92            0 :             0x670000002 => Type::MIPS_OPTIONS,
      93           26 :             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         2366 :     }
     116              : }
     117              : impl From<Type> for u64 {
     118            0 :     fn from(value: Type) -> u64 {
     119            0 :         match value {
     120            0 :             Type::PT_NULL => 0x00000000,
     121            0 :             Type::LOAD => 0x00000001,
     122            0 :             Type::DYNAMIC => 0x00000002,
     123            0 :             Type::INTERP => 0x00000003,
     124            0 :             Type::NOTE => 0x00000004,
     125            0 :             Type::SHLIB => 0x00000005,
     126            0 :             Type::PHDR => 0x00000006,
     127            0 :             Type::TLS => 0x00000007,
     128            0 :             Type::GNU_EH_FRAME => 0x6474e550,
     129            0 :             Type::GNU_STACK => 0x6474e551,
     130            0 :             Type::GNU_PROPERTY => 0x6474e553,
     131            0 :             Type::GNU_RELRO => 0x6474e552,
     132            0 :             Type::PAX_FLAGS => 0x65041580,
     133            0 :             Type::ARM_ARCHEXT => 0x270000000,
     134            0 :             Type::ARM_EXIDX => 0x270000001,
     135            0 :             Type::ARM_UNWIND => 0x270000001,
     136            0 :             Type::AARCH64_MEMTAG_MTE => 0x470000002,
     137            0 :             Type::MIPS_REGINFO => 0x670000000,
     138            0 :             Type::MIPS_RTPROC => 0x670000001,
     139            0 :             Type::MIPS_OPTIONS => 0x670000002,
     140            0 :             Type::MIPS_ABIFLAGS => 0x670000003,
     141            0 :             Type::RISCV_ATTRIBUTES => 0x870000003,
     142            0 :             Type::IA_64_EXT => 0xa70000000,
     143            0 :             Type::IA_64_UNWIND => 0xa70000001,
     144            0 :             Type::HP_TLS => 0x20000060000000,
     145            0 :             Type::HP_CORE_NONE => 0x20000060000001,
     146            0 :             Type::HP_CORE_VERSION => 0x20000060000002,
     147            0 :             Type::HP_CORE_KERNEL => 0x20000060000003,
     148            0 :             Type::HP_CORE_COMM => 0x20000060000004,
     149            0 :             Type::HP_CORE_PROC => 0x20000060000005,
     150            0 :             Type::HP_CORE_LOADABLE => 0x20000060000006,
     151            0 :             Type::HP_CORE_STACK => 0x20000060000007,
     152            0 :             Type::HP_CORE_SHM => 0x20000060000008,
     153            0 :             Type::HP_CORE_MMF => 0x20000060000009,
     154            0 :             Type::HP_PARALLEL => 0x20000060000010,
     155            0 :             Type::HP_FASTBIND => 0x20000060000011,
     156            0 :             Type::HP_OPT_ANNOT => 0x20000060000012,
     157            0 :             Type::HP_HSL_ANNOT => 0x20000060000013,
     158            0 :             Type::HP_STACK => 0x20000060000014,
     159            0 :             Type::HP_CORE_UTSNAME => 0x20000060000015,
     160            0 :             Type::UNKNOWN(value) => value,
     161              :         }
     162            0 :     }
     163              : }
     164              : 
     165            0 : bitflags! {
     166            0 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
     167            0 :     pub struct Flags: u32 {
     168            0 :         const NONE = 0x0;
     169            0 :         const X = 0x1;
     170            0 :         const W = 0x2;
     171            0 :         const R = 0x4;
     172            0 :     }
     173            0 : }
     174              : 
     175              : impl Flags {
     176            0 :     pub fn from_value(value: u32) -> Self {
     177            0 :         Flags::from_bits_truncate(value)
     178            0 :     }
     179              : 
     180            0 :     pub fn to_value(&self) -> u32 {
     181            0 :         self.bits()
     182            0 :     }
     183              : }
     184              : 
     185              : /// Structure which represents an ELF segment
     186              : pub struct Segment<'a> {
     187              :     pub(super) ptr: cxx::UniquePtr<ffi::ELF_Segment>,
     188              :     _owner: PhantomData<&'a ffi::ELF_Binary>,
     189              : }
     190              : 
     191              : impl fmt::Debug for Segment<'_> {
     192         1183 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     193         1183 :         f.debug_struct("Segment")
     194         1183 :             .field("p_type", &self.p_type())
     195         1183 :             .field("flags", &self.flags())
     196         1183 :             .field("file_offset", &self.file_offset())
     197         1183 :             .field("virtual_address", &self.virtual_address())
     198         1183 :             .field("physical_address", &self.physical_address())
     199         1183 :             .field("physical_size", &self.physical_size())
     200         1183 :             .field("virtual_size", &self.virtual_size())
     201         1183 :             .field("alignment", &self.alignment())
     202         1183 :             .finish()
     203         1183 :     }
     204              : }
     205              : 
     206              : impl FromFFI<ffi::ELF_Segment> for Segment<'_> {
     207         1209 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Segment>) -> Self {
     208         1209 :         Segment {
     209         1209 :             ptr,
     210         1209 :             _owner: PhantomData,
     211         1209 :         }
     212         1209 :     }
     213              : }
     214              : 
     215              : impl Segment<'_> {
     216              :     /// Create a new segment
     217            0 :     pub fn new() -> Segment<'static> {
     218            0 :         Segment::from_ffi(lief_ffi::ELF_Segment::create())
     219            0 :     }
     220              : 
     221              :     /// Content of the segment as a slice of bytes
     222           52 :     pub fn content(&self) -> &[u8] {
     223           52 :         to_slice!(self.ptr.content());
     224           52 :     }
     225              : 
     226              :     /// The segment's type (LOAD, DYNAMIC, ...)
     227         2366 :     pub fn p_type(&self) -> Type {
     228         2366 :         Type::from(self.ptr.stype())
     229         2366 :     }
     230              : 
     231              :     /// The flag permissions associated with this segment
     232         1183 :     pub fn flags(&self) -> u32 {
     233         1183 :         self.ptr.flags()
     234         1183 :     }
     235              : 
     236              :     /// The file offset of the data associated with this segment
     237         1183 :     pub fn file_offset(&self) -> u64 {
     238         1183 :         self.ptr.file_offset()
     239         1183 :     }
     240              : 
     241              :     /// The virtual address of the segment.
     242         1183 :     pub fn virtual_address(&self) -> u64 {
     243         1183 :         self.ptr.virtual_address()
     244         1183 :     }
     245              :     /// The physical address of the segment.
     246              :     /// This value is not really relevant on systems like Linux or Android.
     247              :     /// On the other hand, Qualcomm trustlets might use this value.
     248              :     ///
     249              :     /// Usually this value matches [`Segment::virtual_address`]
     250         1183 :     pub fn physical_address(&self) -> u64 {
     251         1183 :         self.ptr.physical_address()
     252         1183 :     }
     253              : 
     254              :     /// The **file** size of the data associated with this segment
     255         1183 :     pub fn physical_size(&self) -> u64 {
     256         1183 :         self.ptr.physical_size()
     257         1183 :     }
     258              : 
     259              :     /// The in-memory size of this segment.
     260              :     /// Usually, if the `.bss` segment is wrapped by this segment
     261              :     /// then, virtual_size is larger than physical_size
     262         1183 :     pub fn virtual_size(&self) -> u64 {
     263         1183 :         self.ptr.virtual_size()
     264         1183 :     }
     265              : 
     266              :     /// The offset alignment of the segment
     267         1183 :     pub fn alignment(&self) -> u64 {
     268         1183 :         self.ptr.alignment()
     269         1183 :     }
     270              : 
     271            0 :     pub fn set_type(&mut self, ty: Type) {
     272            0 :         self.ptr.pin_mut().set_type(ty.into());
     273            0 :     }
     274              : 
     275            0 :     pub fn set_flags(&mut self, flags: Flags) {
     276            0 :         self.ptr.pin_mut().set_flags(flags.to_value())
     277            0 :     }
     278              : 
     279            0 :     pub fn set_file_offset(&mut self, offset: u64) {
     280            0 :         self.ptr.pin_mut().set_file_offset(offset);
     281            0 :     }
     282              : 
     283            0 :     pub fn set_virtual_address(&mut self, va: u64) {
     284            0 :         self.ptr.pin_mut().set_virtual_address(va);
     285            0 :     }
     286              : 
     287            0 :     pub fn set_physical_address(&mut self, addr: u64) {
     288            0 :         self.ptr.pin_mut().set_physical_address(addr);
     289            0 :     }
     290              : 
     291            0 :     pub fn set_virtual_size(&mut self, vsize: u64) {
     292            0 :         self.ptr.pin_mut().set_virtual_size(vsize);
     293            0 :     }
     294              : 
     295            0 :     pub fn set_alignment(&mut self, alignment: u64) {
     296            0 :         self.ptr.pin_mut().set_alignment(alignment);
     297            0 :     }
     298              : 
     299            0 :     pub fn set_content(&mut self, content: &[u8]) {
     300            0 :         unsafe {
     301            0 :             self.ptr
     302            0 :                 .pin_mut()
     303            0 :                 .set_content(content.as_ptr(), content.len().try_into().unwrap());
     304            0 :         }
     305            0 :     }
     306              : 
     307              :     /// Clear the content of this segment
     308            0 :     pub fn clear(&mut self) {
     309            0 :         self.ptr.pin_mut().clear()
     310            0 :     }
     311              : 
     312              :     /// Fill the content of this segment with the value provided in parameter
     313            0 :     pub fn fill(&mut self, value: u8) {
     314            0 :         self.ptr.pin_mut().fill(value as i8)
     315            0 :     }
     316              : }
     317              : 
     318              : impl fmt::Display for Segment<'_> {
     319         1183 :     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     320         1183 :         write!(f, "{}", self.ptr.to_string())
     321         1183 :     }
     322              : }
     323              : 
     324         1183 : declare_iterator!(
     325         1183 :     Segments,
     326         1183 :     Segment<'a>,
     327         1183 :     ffi::ELF_Segment,
     328         1183 :     ffi::ELF_Binary,
     329         1183 :     ffi::ELF_Binary_it_segments
     330         1183 : );
        

Generated by: LCOV version 2.1-1