use super::utils::Convert;
use super::*;
use std::convert::TryFrom;
pub struct Note {
pub ntype: ElfWord,
pub name: String,
pub description: Vec<u8>,
}
pub struct NoteSectionAccessor<'a> {
elfio: &'a Elfio,
section: &'a dyn ElfSectionTrait,
note_start_positions: Vec<usize>,
}
impl<'a> NoteSectionAccessor<'a> {
pub fn new(elfio: &'a Elfio, section: &'a dyn ElfSectionTrait) -> NoteSectionAccessor<'a> {
let mut note_accessor = NoteSectionAccessor {
elfio,
section,
note_start_positions: Vec::<usize>::new(),
};
let data = section.get_data();
let size = data.len();
if data.is_empty() {
return note_accessor;
}
let align = std::mem::size_of::<ElfWord>();
let mut current: usize = 0;
while (current + 3 * align) <= size {
note_accessor.note_start_positions.push(current);
let converter = elfio.get_converter();
let namesz = converter.convert(u32::from_ne_bytes(
<[u8; 4]>::try_from(&data[current..current + 4]).unwrap_or([0x8, 0u8, 0u8, 0u8]),
));
let descsz = converter.convert(u32::from_ne_bytes(
<[u8; 4]>::try_from(&data[current + 4..current + 8])
.unwrap_or([0x8, 0u8, 0u8, 0u8]),
));
current += 3 * align
+ ((namesz as usize + align - 1) / align) * align
+ ((descsz as usize + align - 1) / align) * align;
}
note_accessor
}
pub fn get_notes_num(&self) -> ElfWord {
self.note_start_positions.len() as ElfWord
}
pub fn get_note(&self, index: ElfWord) -> Option<Note> {
let index = index as usize;
let data = self.section.get_data();
if index >= self.note_start_positions.len() {
return None;
}
let area = &data[self.note_start_positions[index]..];
let align = std::mem::size_of::<ElfWord>();
let converter = self.elfio.get_converter();
let name_size = converter.convert(u32::from_ne_bytes(
<[u8; 4]>::try_from(&area[0..4]).unwrap_or([0x8, 0u8, 0u8, 0u8]),
));
let desc_size = converter.convert(u32::from_ne_bytes(
<[u8; 4]>::try_from(&area[4..8]).unwrap_or([0x8, 0u8, 0u8, 0u8]),
));
let ntype = converter.convert(u32::from_ne_bytes(
<[u8; 4]>::try_from(&area[8..12]).unwrap_or([0x8, 0u8, 0u8, 0u8]),
));
let max_name_size = data.len() - self.note_start_positions[index];
if name_size < 1
|| name_size > max_name_size as u32
|| name_size + desc_size > max_name_size as u32
{
return None;
}
Some(Note {
ntype,
name: unsafe {
::std::str::from_utf8_unchecked(&area[12..12 + name_size as usize - 1]).to_string()
},
description: {
let desc_pos = 12 + ((name_size as usize + align - 1) / align) * align;
area[desc_pos..desc_pos + desc_size as usize].to_vec()
},
})
}
}