/// An iterator over the notes in an ELF section or segment. /// /// Returned [`ProgramHeader::notes`](super::ProgramHeader::notes) /// and [`SectionHeader::notes`](super::SectionHeader::notes). #[derive(Debug)] pubstruct NoteIterator<'data, Elf> where
Elf: FileHeader,
{
endian: Elf::Endian,
align: usize,
data: Bytes<'data>,
}
impl<'data, Elf> NoteIterator<'data, Elf> where
Elf: FileHeader,
{ /// An iterator over the notes in an ELF section or segment. /// /// `align` should be from the `p_align` field of the segment, /// or the `sh_addralign` field of the section. Supported values are /// either 4 or 8, but values less than 4 are treated as 4. /// This matches the behaviour of binutils. /// /// Returns `Err` if `align` is invalid. pubfn new(endian: Elf::Endian, align: Elf::Word, data: &'data [u8]) -> read::Result<Self> { let align = match align.into() { 0u64..=4 => 4, 8 => 8,
_ => return Err(Error("Invalid ELF note alignment")),
}; // TODO: check data alignment?
Ok(NoteIterator {
endian,
align,
data: Bytes(data),
})
}
/// Returns the next note. pubfn next(&mutself) -> read::Result<Option<Note<'data, Elf>>> { ifself.data.is_empty() { return Ok(None);
}
let result = self.parse().map(Some); if result.is_err() { self.data = Bytes(&[]);
}
result
}
fn parse(&mutself) -> read::Result<Note<'data, Elf>> { let header = self
.data
.read_at::<Elf::NoteHeader>(0)
.read_error("ELF note is too short")?;
// The name has no alignment requirement. let offset = mem::size_of::<Elf::NoteHeader>(); let namesz = header.n_namesz(self.endian) as usize; let name = self
.data
.read_bytes_at(offset, namesz)
.read_error("Invalid ELF note namesz")?
.0;
// The descriptor must be aligned. let offset = util::align(offset + namesz, self.align); let descsz = header.n_descsz(self.endian) as usize; let desc = self
.data
.read_bytes_at(offset, descsz)
.read_error("Invalid ELF note descsz")?
.0;
// The next note (if any) must be aligned. let offset = util::align(offset + descsz, self.align); ifself.data.skip(offset).is_err() { self.data = Bytes(&[]);
}
Ok(Note { header, name, desc })
}
}
impl<'data, Elf: FileHeader> Iterator for NoteIterator<'data, Elf> { type Item = read::Result<Note<'data, Elf>>;
impl<'data, Elf: FileHeader> Note<'data, Elf> { /// Return the `n_type` field of the `NoteHeader`. /// /// The meaning of this field is determined by `name`. pubfn n_type(&self, endian: Elf::Endian) -> u32 { self.header.n_type(endian)
}
/// Return the `n_namesz` field of the `NoteHeader`. pubfn n_namesz(&self, endian: Elf::Endian) -> u32 { self.header.n_namesz(endian)
}
/// Return the `n_descsz` field of the `NoteHeader`. pubfn n_descsz(&self, endian: Elf::Endian) -> u32 { self.header.n_descsz(endian)
}
/// Return the bytes for the name field following the `NoteHeader`. /// /// This field is usually a string including one or more trailing null bytes /// (but it is not required to be). /// /// The length of this field is given by `n_namesz`. pubfn name_bytes(&self) -> &'data [u8] { self.name
}
/// Return the bytes for the name field following the `NoteHeader`, /// excluding all trailing null bytes. pubfn name(&self) -> &'data [u8] { letmut name = self.name; whilelet [rest @ .., 0] = name {
name = rest;
}
name
}
/// Return the bytes for the desc field following the `NoteHeader`. /// /// The length of this field is given by `n_descsz`. The meaning /// of this field is determined by `name` and `n_type`. pubfn desc(&self) -> &'data [u8] { self.desc
}
/// Return an iterator for properties if this note's type is [`elf::NT_GNU_PROPERTY_TYPE_0`]. pubfn gnu_properties(
&self,
endian: Elf::Endian,
) -> Option<GnuPropertyIterator<'data, Elf::Endian>> { ifself.name() != elf::ELF_NOTE_GNU || self.n_type(endian) != elf::NT_GNU_PROPERTY_TYPE_0 { return None;
} // Use the ELF class instead of the section alignment. // This matches what other parsers do. let align = if Elf::is_type_64_sized() { 8 } else { 4 };
Some(GnuPropertyIterator {
endian,
align,
data: Bytes(self.desc),
})
}
}
/// A trait for generic access to [`elf::NoteHeader32`] and [`elf::NoteHeader64`]. #[allow(missing_docs)] pubtrait NoteHeader: Debug + Pod { type Endian: endian::Endian;
/// An iterator for the properties in a [`elf::NT_GNU_PROPERTY_TYPE_0`] note. /// /// Returned by [`Note::gnu_properties`]. #[derive(Debug)] pubstruct GnuPropertyIterator<'data, Endian: endian::Endian> {
endian: Endian,
align: usize,
data: Bytes<'data>,
}
/// A property in a [`elf::NT_GNU_PROPERTY_TYPE_0`] note. #[derive(Debug)] pubstruct GnuProperty<'data> {
pr_type: u32,
pr_data: &'data [u8],
}
impl<'data> GnuProperty<'data> { /// Return the property type. /// /// This is one of the `GNU_PROPERTY_*` constants. pubfn pr_type(&self) -> u32 { self.pr_type
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.