use crate::Elf;
use crate::ElfError;
use core::str;
use scroll_derive::Pread;
use bit_field::BitField;
#[derive(PartialEq, Eq)]
pub enum SectionType {
Null,
ProgBits,
SymTab,
StrTab,
Rela,
Hash,
Dynamic,
Note,
NoBits,
Rel,
ShLib,
DynSym,
Os(u32),
Proc(u32),
}
#[derive(Debug, Pread)]
#[repr(C)]
pub struct SectionHeader {
pub name: u32,
pub section_type: u32,
pub flags: u64,
pub address: u64,
pub offset: u64,
pub size: u64,
pub link: u32,
pub info: u32,
pub alignment: u64,
pub entry_size: u64,
}
impl SectionHeader {
pub(crate) fn validate(&self) -> Result<(), ElfError> {
match self.section_type {
0..=11 | 0x60000000..=0x7fffffff => Ok(()),
_ => Err(ElfError::SectionInvalidType),
}?;
Ok(())
}
pub fn section_type(&self) -> SectionType {
match self.section_type {
0 => SectionType::Null,
1 => SectionType::ProgBits,
2 => SectionType::SymTab,
3 => SectionType::StrTab,
4 => SectionType::Rela,
5 => SectionType::Hash,
6 => SectionType::Dynamic,
7 => SectionType::Note,
8 => SectionType::NoBits,
9 => SectionType::Rel,
10 => SectionType::ShLib,
11 => SectionType::DynSym,
0x60000000..=0x6fffffff => SectionType::Os(self.section_type),
0x70000000..=0x7fffffff => SectionType::Proc(self.section_type),
_ => panic!("section_type called on section with invalid type. Was validate called?"),
}
}
pub fn name<'a>(&self, elf: &'a Elf) -> Option<&'a str> {
if self.name == 0 {
return None;
}
let string_table = elf.sections().nth(elf.header.string_table_index as usize)?;
crate::from_utf8_null_terminated(&string_table.data(elf)?[(self.name as usize)..]).ok()
}
pub fn data<'a>(&self, elf: &'a Elf) -> Option<&'a [u8]> {
match self.section_type() {
SectionType::Null | SectionType::NoBits => return None,
_ => (),
}
Some(&elf.bytes[(self.offset as usize)..((self.offset + self.size) as usize)])
}
pub fn is_writable(&self) -> bool {
self.flags.get_bit(0)
}
pub fn is_allocated(&self) -> bool {
self.flags.get_bit(1)
}
pub fn is_executable(&self) -> bool {
self.flags.get_bit(2)
}
}