use super::utils::Convert;
use super::*;
use std::convert::TryFrom;
#[derive(Debug, Default)]
pub struct Dynamic {
pub tag: ElfSxword,
pub value: ElfXword,
}
#[repr(C)]
#[derive(Default)]
struct Elf32Dyn {
d_tag: ElfSword,
d_value: ElfWord,
}
#[repr(C)]
#[derive(Default)]
struct Elf64Dyn {
d_tag: ElfSxword,
d_value: ElfXword,
}
pub struct DynamicSectionAccessor<'a> {
elfio: &'a Elfio,
section: &'a dyn ElfSectionTrait,
}
impl<'a> DynamicSectionAccessor<'a> {
pub fn new(elfio: &'a Elfio, section: &'a dyn ElfSectionTrait) -> DynamicSectionAccessor<'a> {
DynamicSectionAccessor { elfio, section }
}
pub fn get_entries_num(&self) -> ElfXword {
let max_entries = self.get_entries_num_internal();
for i in 0..max_entries {
let entry = self.get_entry(i).unwrap();
if entry.tag == constant::DT_NULL {
return i + 1;
}
}
0
}
fn get_entries_num_internal(&self) -> ElfXword {
if self.section.get_entry_size() != 0 {
return self.section.get_size() / self.section.get_entry_size();
}
0
}
pub fn get_entry(&self, index: ElfXword) -> Option<Dynamic> {
let entries_num = self.get_entries_num_internal();
if entries_num == 0 || index > entries_num - 1 {
return None;
}
let offset: usize = (index * self.section.get_entry_size()) as usize;
let end: usize = offset + self.section.get_entry_size() as usize;
let entry_area = &self.section.get_data()[offset..end];
let converter = self.elfio.get_converter();
if self.elfio.get_class() == constant::ELFCLASS64 {
let entry = Elf64Dyn {
d_tag: converter.convert(i64::from_ne_bytes(
<[u8; 8]>::try_from(&entry_area[0..8])
.unwrap_or([0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]),
)),
d_value: converter.convert(u64::from_ne_bytes(
<[u8; 8]>::try_from(&entry_area[8..16])
.unwrap_or([0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]),
)),
};
Some(Dynamic {
tag: entry.d_tag,
value: entry.d_value,
})
} else {
let entry = Elf32Dyn {
d_tag: converter.convert(i32::from_ne_bytes(
<[u8; 4]>::try_from(&entry_area[0..4]).unwrap_or([0u8, 0u8, 0u8, 0u8]),
)),
d_value: converter.convert(u32::from_ne_bytes(
<[u8; 4]>::try_from(&entry_area[4..8]).unwrap_or([0u8, 0u8, 0u8, 0u8]),
)),
};
Some(Dynamic {
tag: entry.d_tag as ElfSxword,
value: entry.d_value as ElfXword,
})
}
}
}