LCOV - code coverage report
Current view: top level - src/elf - segment.rs (source / functions) Coverage Total Hit
Test: lief.lcov Lines: 76.7 % 86 66
Test Date: 2024-10-27:00:00:00 Functions: 61.5 % 26 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          552 : #[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              :     /// Platform architecture compatibility info
      36              :     ARM_ARCHEXT,
      37              :     ARM_EXIDX,
      38              :     ARM_UNWIND,
      39              :     AARCH64_MEMTAG_MTE,
      40              :     /// Register usage information
      41              :     MIPS_REGINFO,
      42              :     /// Runtime procedure table.
      43              :     MIPS_RTPROC,
      44              :     /// Options segment.
      45              :     MIPS_OPTIONS,
      46              :     /// Abiflags segment.
      47              :     MIPS_ABIFLAGS,
      48              :     RISCV_ATTRIBUTES,
      49              :     UNKNOWN(u64),
      50              : }
      51              : 
      52              : impl Type {
      53         1104 :     pub fn from_value(value: u64) -> Self {
      54         1104 :         match value {
      55           16 :             0x00000000 => Type::PT_NULL,
      56          480 :             0x00000001 => Type::LOAD,
      57           80 :             0x00000002 => Type::DYNAMIC,
      58           64 :             0x00000003 => Type::INTERP,
      59          112 :             0x00000004 => Type::NOTE,
      60            0 :             0x00000005 => Type::SHLIB,
      61           64 :             0x00000006 => Type::PHDR,
      62           16 :             0x00000007 => Type::TLS,
      63           80 :             0x6474e550 => Type::GNU_EH_FRAME,
      64           80 :             0x6474e551 => Type::GNU_STACK,
      65           16 :             0x6474e553 => Type::GNU_PROPERTY,
      66           64 :             0x6474e552 => Type::GNU_RELRO,
      67            0 :             0x270000000 => Type::ARM_ARCHEXT,
      68            0 :             0x270000001 => Type::ARM_EXIDX,
      69            0 :             0x470000002 => Type::AARCH64_MEMTAG_MTE,
      70           16 :             0x670000000 => Type::MIPS_REGINFO,
      71            0 :             0x670000001 => Type::MIPS_RTPROC,
      72            0 :             0x670000002 => Type::MIPS_OPTIONS,
      73           16 :             0x670000003 => Type::MIPS_ABIFLAGS,
      74            0 :             0x870000003 => Type::RISCV_ATTRIBUTES,
      75            0 :             _ => Type::UNKNOWN(value),
      76              : 
      77              :         }
      78         1104 :     }
      79              : }
      80              : 
      81              : 
      82              : 
      83            0 : bitflags! {
      84            0 :     #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
      85            0 :     pub struct Flags: u32 {
      86            0 :         const NONE = 0x0;
      87            0 :         const X = 0x1;
      88            0 :         const W = 0x2;
      89            0 :         const R = 0x4;
      90            0 :     }
      91            0 : }
      92              : 
      93              : 
      94              : impl Flags {
      95            0 :     pub fn from_value(value: u32) -> Self {
      96            0 :         Flags::from_bits_truncate(value)
      97            0 :     }
      98              : }
      99              : 
     100              : /// Structure which reprents an ELF segment
     101              : pub struct Segment<'a> {
     102              :     ptr: cxx::UniquePtr<ffi::ELF_Segment>,
     103              :     _owner: PhantomData<&'a ffi::ELF_Binary>
     104              : }
     105              : 
     106              : impl fmt::Debug for Segment<'_> {
     107          552 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     108          552 :         f.debug_struct("Segment")
     109          552 :             .field("p_type", &self.p_type())
     110          552 :             .field("flags", &self.flags())
     111          552 :             .field("file_offset", &self.file_offset())
     112          552 :             .field("virtual_address", &self.virtual_address())
     113          552 :             .field("physical_address", &self.physical_address())
     114          552 :             .field("physical_size", &self.physical_size())
     115          552 :             .field("virtual_size", &self.virtual_size())
     116          552 :             .field("alignment", &self.alignment())
     117          552 :             .finish()
     118          552 :     }
     119              : }
     120              : 
     121              : impl FromFFI<ffi::ELF_Segment> for Segment<'_> {
     122          568 :     fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Segment>) -> Self {
     123          568 :         Segment {
     124          568 :             ptr,
     125          568 :             _owner: PhantomData
     126          568 :         }
     127          568 :     }
     128              : }
     129              : 
     130              : impl<'a> Segment<'a> {
     131              :     /// Content of the segment as a slice of bytes
     132           32 :     pub fn content(&self) -> &[u8] {
     133           32 :         to_slice!(self.ptr.content());
     134           32 :     }
     135              : 
     136              :     /// The segment's type (LOAD, DYNAMIC, ...)
     137         1104 :     pub fn p_type(&self) -> Type {
     138         1104 :         Type::from_value(self.ptr.stype())
     139         1104 :     }
     140              : 
     141              :     /// The flag permissions associated with this segment
     142          552 :     pub fn flags(&self) -> u32 {
     143          552 :         self.ptr.flags()
     144          552 :     }
     145              : 
     146              :     /// The file offset of the data associated with this segment
     147          552 :     pub fn file_offset(&self) -> u64 {
     148          552 :         self.ptr.file_offset()
     149          552 :     }
     150              : 
     151              :     /// The virtual address of the segment.
     152          552 :     pub fn virtual_address(&self) -> u64 {
     153          552 :         self.ptr.virtual_address()
     154          552 :     }
     155              :     /// The physical address of the segment.
     156              :     /// This value is not really relevant on systems like Linux or Android.
     157              :     /// On the other hand, Qualcomm trustlets might use this value.
     158              :     ///
     159              :     /// Usually this value matches [`Segment::virtual_address`]
     160          552 :     pub fn physical_address(&self) -> u64 {
     161          552 :         self.ptr.physical_address()
     162          552 :     }
     163              : 
     164              :     /// The **file** size of the data associated with this segment
     165          552 :     pub fn physical_size(&self) -> u64 {
     166          552 :         self.ptr.physical_size()
     167          552 :     }
     168              : 
     169              :     /// The in-memory size of this segment.
     170              :     /// Usually, if the `.bss` segment is wrapped by this segment
     171              :     /// then, virtual_size is larger than physical_size
     172          552 :     pub fn virtual_size(&self) -> u64 {
     173          552 :         self.ptr.virtual_size()
     174          552 :     }
     175              : 
     176              :     /// The offset alignment of the segment
     177          552 :     pub fn alignment(&self) -> u64 {
     178          552 :         self.ptr.alignment()
     179          552 :     }
     180              : }
     181              : 
     182              : impl fmt::Display for Segment<'_> {
     183          552 :     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     184          552 :         write!(f, "{}", self.ptr.to_string())
     185          552 :     }
     186              : }
     187              : 
     188          552 : declare_iterator!(Segments, Segment<'a>, ffi::ELF_Segment, ffi::ELF_Binary, ffi::ELF_Binary_it_segments);
        

Generated by: LCOV version 2.1-1