use crate::{Error, Loader, Source};
#[derive(Debug, Clone)]
pub struct Header {
sh_name_offset: u32,
sh_type: u32,
sh_flags: u32,
sh_addr: u32,
sh_offset: u32,
sh_size: u32,
sh_link: u32,
sh_info: u32,
sh_addralign: u32,
sh_entsize: u32,
}
impl Header {
pub const SIZE_IN_BYTES: u16 = 0x28;
pub const SHT_NULL: u32 = 0x0;
pub const SHT_PROGBITS: u32 = 0x1;
pub const SHT_SYMTAB: u32 = 0x2;
pub const SHT_STRTAB: u32 = 0x3;
pub const SHT_RELA: u32 = 0x4;
pub const SHT_HASH: u32 = 0x5;
pub const SHT_DYNAMIC: u32 = 0x6;
pub const SHT_NOTE: u32 = 0x7;
pub const SHT_NOBITS: u32 = 0x8;
pub const SHT_REL: u32 = 0x9;
pub const SHT_DYNSYM: u32 = 0x0B;
pub const SHT_INIT_ARRAY: u32 = 0x0E;
pub const SHT_FINI_ARRAY: u32 = 0x0F;
pub const SHT_PREINIT_ARRAY: u32 = 0x10;
pub const SHT_GROUP: u32 = 0x11;
pub const SHT_SYMTAB_SHNDX: u32 = 0x12;
pub fn new<DS>(loader: &Loader<DS>, idx: u16) -> Result<Self, Error<DS::Error>>
where
DS: Source,
{
let section_table_offset = loader.e_shoff + u32::from(Self::SIZE_IN_BYTES) * u32::from(idx);
let sh_name_offset = loader.data_source.read_u32_le(section_table_offset)?;
let sh_type = loader
.data_source
.read_u32_le(section_table_offset + 0x04)?;
let sh_flags = loader
.data_source
.read_u32_le(section_table_offset + 0x08)?;
let sh_addr = loader
.data_source
.read_u32_le(section_table_offset + 0x0C)?;
let sh_offset = loader
.data_source
.read_u32_le(section_table_offset + 0x10)?;
let sh_size = loader
.data_source
.read_u32_le(section_table_offset + 0x14)?;
let sh_link = loader
.data_source
.read_u32_le(section_table_offset + 0x18)?;
let sh_info = loader
.data_source
.read_u32_le(section_table_offset + 0x1C)?;
let sh_addralign = loader
.data_source
.read_u32_le(section_table_offset + 0x20)?;
let sh_entsize = loader
.data_source
.read_u32_le(section_table_offset + 0x24)?;
Ok(Self {
sh_name_offset,
sh_type,
sh_flags,
sh_addr,
sh_offset,
sh_size,
sh_link,
sh_info,
sh_addralign,
sh_entsize,
})
}
pub fn sh_name_offset(&self) -> u32 {
self.sh_name_offset
}
pub fn sh_name<'a, DS: Source>(
&self,
loader: &Loader<DS>,
buffer: &'a mut [u8],
) -> Result<&'a str, Error<DS::Error>> {
let string_section_idx = loader.e_shstrndx;
let string_section_header = Self::new(loader, string_section_idx)?;
let string_start = string_section_header.sh_offset + self.sh_name_offset;
for b in buffer.iter_mut() {
*b = 0x00;
}
loader.data_source.read(string_start, buffer)?;
let cstr =
core::ffi::CStr::from_bytes_until_nul(buffer).map_err(|_| Error::NotEnoughSpace)?;
if let Ok(s) = cstr.to_str() {
Ok(s)
} else {
Err(Error::InvalidString)
}
}
pub fn sh_type(&self) -> u32 {
self.sh_type
}
pub fn sh_flags(&self) -> u32 {
self.sh_flags
}
pub fn sh_addr(&self) -> u32 {
self.sh_addr
}
pub fn sh_offset(&self) -> u32 {
self.sh_offset
}
pub fn sh_size(&self) -> u32 {
self.sh_size
}
pub fn sh_link(&self) -> u32 {
self.sh_link
}
pub fn sh_info(&self) -> u32 {
self.sh_info
}
pub fn sh_addralign(&self) -> u32 {
self.sh_addralign
}
pub fn sh_entsize(&self) -> u32 {
self.sh_entsize
}
}