pub const NT_GNU_ABI_TAG: u32 = 1;
pub const ELF_NOTE_ABI: u32 = NT_GNU_ABI_TAG;
pub const ELF_NOTE_OS_LINUX: u32 = 0;
pub const ELF_NOTE_OS_GNU: u32 = 1;
pub const ELF_NOTE_OS_SOLARIS2: u32 = 2;
pub const ELF_NOTE_OS_FREEBSD: u32 = 3;
pub const NT_GNU_HWCAP: u32 = 2;
pub const NT_GNU_BUILD_ID: u32 = 3;
pub const NT_GNU_GOLD_VERSION: u32 = 4;
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "std", derive(Pread, Pwrite, IOread, IOwrite, SizeWith))]
#[repr(C)]
pub struct Nhdr32 {
pub n_namesz: u32,
pub n_descsz: u32,
pub n_type: u32,
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "std", derive(Pread, Pwrite, IOread, IOwrite, SizeWith))]
#[repr(C)]
pub struct Nhdr64 {
pub n_namesz: u64,
pub n_descsz: u64,
pub n_type: u64,
}
if_std! {
use error;
use container;
use scroll::{ctx, Pread};
pub struct NoteIterator<'a> {
pub data: &'a [u8],
pub size: usize,
pub offset: usize,
pub ctx: (usize, container::Ctx), }
impl<'a> Iterator for NoteIterator<'a> {
type Item = error::Result<Note<'a>>;
fn next(&mut self) -> Option<Self::Item> {
if self.offset >= self.size {
None
} else {
debug!("NoteIterator - {:#x}", self.offset);
match self.data.gread_with(&mut self.offset, self.ctx) {
Ok(res) => Some(Ok(res)),
Err(e) => Some(Err(e.into()))
}
}
}
}
#[derive(Debug)]
struct NoteHeader {
n_namesz: usize,
n_descsz: usize,
n_type: u32,
}
impl From<Nhdr32> for NoteHeader {
fn from(header: Nhdr32) -> Self {
NoteHeader {
n_namesz: header.n_namesz as usize,
n_descsz: header.n_descsz as usize,
n_type: header.n_type,
}
}
}
impl From<Nhdr64> for NoteHeader {
fn from(header: Nhdr64) -> Self {
NoteHeader {
n_namesz: header.n_namesz as usize,
n_descsz: header.n_descsz as usize,
n_type: header.n_type as u32,
}
}
}
fn align(alignment: usize, offset: &mut usize) {
let diff = *offset % alignment;
if diff != 0 {
*offset += alignment - diff;
}
}
#[derive(Debug)]
pub struct Note<'a> {
pub n_type: u32,
pub name: &'a str, pub desc: &'a [u8], }
impl<'a> Note<'a> {
pub fn type_to_str(&self) -> &'static str {
match self.n_type {
NT_GNU_ABI_TAG => "NT_GNU_ABI_TAG",
NT_GNU_HWCAP => "NT_GNU_HWCAP",
NT_GNU_BUILD_ID => "NT_GNU_BUILD_ID",
NT_GNU_GOLD_VERSION => "NT_GNU_GOLD_VERSION",
_ => "NT_UNKNOWN"
}
}
}
impl<'a> ctx::TryFromCtx<'a, (usize, container::Ctx)> for Note<'a> {
type Error = error::Error;
type Size = usize;
fn try_from_ctx(bytes: &'a [u8], (alignment, ctx): (usize, container::Ctx)) -> Result<(Self, Self::Size), Self::Error> {
let offset = &mut 0;
let header: NoteHeader = {
match alignment {
4 => bytes.gread_with::<Nhdr32>(offset, ctx.le)?.into(),
8 => bytes.gread_with::<Nhdr64>(offset, ctx.le)?.into(),
_ => return Err(error::Error::Malformed(format!("Notes has unimplemented alignment requirement: {:#x}", alignment)))
}
};
debug!("{:?} - {:#x}", header, *offset);
let name = bytes.gread_with::<&'a str>(offset, ctx::StrCtx::Length(header.n_namesz - 1))?;
*offset += 1;
align(alignment, offset);
debug!("note name {} - {:#x}", name, *offset);
let desc = bytes.gread_with::<&'a [u8]>(offset, header.n_descsz)?;
align(alignment, offset);
debug!("desc {:?} - {:#x}", desc, *offset);
Ok((Note {
name,
desc,
n_type: header.n_type,
}, *offset))
}
}
}