/// An ELF attributes section. /// /// This may be a GNU attributes section, or an architecture specific attributes section. /// /// An attributes section contains a series of [`AttributesSubsection`]. /// /// Returned by [`SectionHeader::attributes`](super::SectionHeader::attributes) /// and [`SectionHeader::gnu_attributes`](super::SectionHeader::gnu_attributes). #[derive(Debug, Clone)] pubstruct AttributesSection<'data, Elf: FileHeader> {
endian: Elf::Endian,
version: u8,
data: Bytes<'data>,
}
impl<'data, Elf: FileHeader> AttributesSection<'data, Elf> { /// Parse an ELF attributes section given the section data. pubfn new(endian: Elf::Endian, data: &'data [u8]) -> Result<Self> { letmut data = Bytes(data);
// Skip the version field that is one byte long. // If the section is empty then the version doesn't matter. let version = data.read::<u8>().cloned().unwrap_or(b'A');
/// Return the version of the attributes section. pubfn version(&self) -> u8 { self.version
}
/// Return an iterator over the subsections. pubfn subsections(&self) -> Result<AttributesSubsectionIterator<'data, Elf>> { // There is currently only one format version. ifself.version != b'A' { return Err(Error("Unsupported ELF attributes section version"));
}
/// An iterator for the subsections in an [`AttributesSection`]. #[derive(Debug, Clone)] pubstruct AttributesSubsectionIterator<'data, Elf: FileHeader> {
endian: Elf::Endian,
data: Bytes<'data>,
}
let result = self.parse().map(Some); if result.is_err() { self.data = Bytes(&[]);
}
result
}
fn parse(&mutself) -> Result<AttributesSubsection<'data, Elf>> { // First read the subsection length. letmut data = self.data; let length = data
.read::<endian::U32Bytes<Elf::Endian>>()
.read_error("ELF attributes section is too short")?
.get(self.endian);
// Now read the entire subsection, updating self.data. letmut data = self
.data
.read_bytes(length as usize)
.read_error("Invalid ELF attributes subsection length")?; // Skip the subsection length field.
data.skip(4)
.read_error("Invalid ELF attributes subsection length")?;
// TODO: errors here should not prevent reading the next subsection. let vendor = data
.read_string()
.read_error("Invalid ELF attributes vendor")?;
/// A subsection in an [`AttributesSection`]. /// /// A subsection is identified by a vendor name. It contains a series of /// [`AttributesSubsubsection`]. #[derive(Debug, Clone)] pubstruct AttributesSubsection<'data, Elf: FileHeader> {
endian: Elf::Endian,
length: u32,
vendor: &'data [u8],
data: Bytes<'data>,
}
impl<'data, Elf: FileHeader> AttributesSubsection<'data, Elf> { /// Return the length of the attributes subsection. pubfn length(&self) -> u32 { self.length
}
/// Return the vendor name of the attributes subsection. pubfn vendor(&self) -> &'data [u8] { self.vendor
}
/// Return an iterator over the sub-subsections. pubfn subsubsections(&self) -> AttributesSubsubsectionIterator<'data, Elf> {
AttributesSubsubsectionIterator {
endian: self.endian,
data: self.data,
}
}
}
/// An iterator for the sub-subsections in an [`AttributesSubsection`]. #[derive(Debug, Clone)] pubstruct AttributesSubsubsectionIterator<'data, Elf: FileHeader> {
endian: Elf::Endian,
data: Bytes<'data>,
}
let result = self.parse().map(Some); if result.is_err() { self.data = Bytes(&[]);
}
result
}
fn parse(&mutself) -> Result<AttributesSubsubsection<'data>> { // The format of a sub-section looks like this: // // <file-tag> <size> <attribute>* // | <section-tag> <size> <section-number>* 0 <attribute>* // | <symbol-tag> <size> <symbol-number>* 0 <attribute>* letmut data = self.data; let tag = *data
.read::<u8>()
.read_error("ELF attributes subsection is too short")?; let length = data
.read::<endian::U32Bytes<Elf::Endian>>()
.read_error("ELF attributes subsection is too short")?
.get(self.endian);
// Now read the entire sub-subsection, updating self.data. letmut data = self
.data
.read_bytes(length as usize)
.read_error("Invalid ELF attributes sub-subsection length")?; // Skip the tag and sub-subsection size field.
data.skip(1 + 4)
.read_error("Invalid ELF attributes sub-subsection length")?;
// TODO: errors here should not prevent reading the next sub-subsection. let indices = if tag == elf::Tag_Section || tag == elf::Tag_Symbol {
data.read_string()
.map(Bytes)
.read_error("Missing ELF attributes sub-subsection indices")?
} elseif tag == elf::Tag_File {
Bytes(&[])
} else { return Err(Error("Unimplemented ELF attributes sub-subsection tag"));
};
/// A sub-subsection in an [`AttributesSubsection`]. /// /// A sub-subsection is identified by a tag. It contains an optional series of indices, /// followed by a series of attributes. #[derive(Debug, Clone)] pubstruct AttributesSubsubsection<'data> {
tag: u8,
length: u32,
indices: Bytes<'data>,
data: Bytes<'data>,
}
impl<'data> AttributesSubsubsection<'data> { /// Return the tag of the attributes sub-subsection. pubfn tag(&self) -> u8 { self.tag
}
/// Return the length of the attributes sub-subsection. pubfn length(&self) -> u32 { self.length
}
/// Return the data containing the indices. pubfn indices_data(&self) -> &'data [u8] { self.indices.0
}
/// Return the indices. /// /// This will be section indices if the tag is `Tag_Section`, /// or symbol indices if the tag is `Tag_Symbol`, /// and otherwise it will be empty. pubfn indices(&self) -> AttributeIndexIterator<'data> {
AttributeIndexIterator { data: self.indices }
}
/// Return the data containing the attributes. pubfn attributes_data(&self) -> &'data [u8] { self.data.0
}
/// Return a parser for the data containing the attributes. pubfn attributes(&self) -> AttributeReader<'data> {
AttributeReader { data: self.data }
}
}
/// An iterator over the indices in an [`AttributesSubsubsection`]. #[derive(Debug, Clone)] pubstruct AttributeIndexIterator<'data> {
data: Bytes<'data>,
}
impl<'data> AttributeIndexIterator<'data> { /// Parse the next index. pubfn next(&mutself) -> Result<Option<u32>> { ifself.data.is_empty() { return Ok(None);
}
let result = self.parse().map(Some); if result.is_err() { self.data = Bytes(&[]);
}
result
}
/// A parser for the attributes in an [`AttributesSubsubsection`]. /// /// The parser relies on the caller to know the format of the data for each attribute tag. #[derive(Debug, Clone)] pubstruct AttributeReader<'data> {
data: Bytes<'data>,
}
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.