use core::fmt::Debug;
use crate::elf;
use crate::endian::{self, RunTimeEndian};
use crate::pod::{Bytes, Pod};
use crate::read::util;
use crate::read::{self, Error, ReadError};
use super::FileHeader;
#[derive(Debug)]
pub struct ElfNoteIterator<'data, Elf>
where
Elf: FileHeader,
{
endian: Elf::Endian,
align: usize,
data: Bytes<'data>,
}
impl<'data, Elf> ElfNoteIterator<'data, Elf>
where
Elf: FileHeader,
{
pub(super) fn new(
endian: Elf::Endian,
align: Elf::Word,
data: Bytes<'data>,
) -> read::Result<Self> {
let align = match align.into() {
0u64..=4 => 4,
8 => 8,
_ => return Err(Error("Invalid ELF note alignment")),
};
Ok(ElfNoteIterator {
endian,
align,
data,
})
}
pub(super) fn next(&mut self) -> read::Result<Option<ElfNote<'data, Elf>>> {
let mut data = self.data;
if data.is_empty() {
return Ok(None);
}
let header = data
.read::<Elf::NoteHeader>()
.read_error("ELF note is too short")?;
let namesz = header.n_namesz(self.endian) as usize;
let name = data
.read_bytes_at(0, namesz)
.read_error("Invalid ELF note namesz")?
.0;
data.skip(util::align(namesz, self.align))
.read_error("ELF note is too short")?;
let descsz = header.n_descsz(self.endian) as usize;
let desc = data
.read_bytes_at(0, descsz)
.read_error("Invalid ELF note descsz")?
.0;
if data.skip(util::align(descsz, self.align)).is_err() {
data = Bytes(&[]);
}
self.data = data;
Ok(Some(ElfNote { header, name, desc }))
}
}
pub type ElfNote32<'data, Endian = RunTimeEndian> = ElfNote<'data, elf::FileHeader32<Endian>>;
pub type ElfNote64<'data, Endian = RunTimeEndian> = ElfNote<'data, elf::FileHeader64<Endian>>;
#[derive(Debug)]
pub struct ElfNote<'data, Elf>
where
Elf: FileHeader,
{
header: &'data Elf::NoteHeader,
name: &'data [u8],
desc: &'data [u8],
}
impl<'data, Elf: FileHeader> ElfNote<'data, Elf> {
pub fn n_type(&self, endian: Elf::Endian) -> u32 {
self.header.n_type(endian)
}
pub fn n_namesz(&self, endian: Elf::Endian) -> u32 {
self.header.n_namesz(endian)
}
pub fn n_descsz(&self, endian: Elf::Endian) -> u32 {
self.header.n_descsz(endian)
}
pub fn name(&self) -> &'data [u8] {
self.name
}
pub fn desc(&self) -> &'data [u8] {
self.desc
}
}
#[allow(missing_docs)]
pub trait NoteHeader: Debug + Pod {
type Endian: endian::Endian;
fn n_namesz(&self, endian: Self::Endian) -> u32;
fn n_descsz(&self, endian: Self::Endian) -> u32;
fn n_type(&self, endian: Self::Endian) -> u32;
}
impl<Endian: endian::Endian> NoteHeader for elf::NoteHeader32<Endian> {
type Endian = Endian;
#[inline]
fn n_namesz(&self, endian: Self::Endian) -> u32 {
self.n_namesz.get(endian)
}
#[inline]
fn n_descsz(&self, endian: Self::Endian) -> u32 {
self.n_descsz.get(endian)
}
#[inline]
fn n_type(&self, endian: Self::Endian) -> u32 {
self.n_type.get(endian)
}
}
impl<Endian: endian::Endian> NoteHeader for elf::NoteHeader64<Endian> {
type Endian = Endian;
#[inline]
fn n_namesz(&self, endian: Self::Endian) -> u32 {
self.n_namesz.get(endian)
}
#[inline]
fn n_descsz(&self, endian: Self::Endian) -> u32 {
self.n_descsz.get(endian)
}
#[inline]
fn n_type(&self, endian: Self::Endian) -> u32 {
self.n_type.get(endian)
}
}