use core::convert::TryInto;
use crate::elf;
use crate::endian;
use crate::read::{Bytes, Error, ReadError, Result};
use super::FileHeader;
#[derive(Debug, Clone)]
pub struct AttributesSection<'data, Elf: FileHeader> {
endian: Elf::Endian,
version: u8,
data: Bytes<'data>,
}
impl<'data, Elf: FileHeader> AttributesSection<'data, Elf> {
pub fn new(endian: Elf::Endian, data: &'data [u8]) -> Result<Self> {
let mut data = Bytes(data);
let version = data.read::<u8>().cloned().unwrap_or(b'A');
Ok(AttributesSection {
endian,
version,
data,
})
}
pub fn version(&self) -> u8 {
self.version
}
pub fn subsections(&self) -> Result<AttributesSubsectionIterator<'data, Elf>> {
if self.version != b'A' {
return Err(Error("Unsupported ELF attributes section version"));
}
Ok(AttributesSubsectionIterator {
endian: self.endian,
data: self.data,
})
}
}
#[derive(Debug, Clone)]
pub struct AttributesSubsectionIterator<'data, Elf: FileHeader> {
endian: Elf::Endian,
data: Bytes<'data>,
}
impl<'data, Elf: FileHeader> AttributesSubsectionIterator<'data, Elf> {
pub fn next(&mut self) -> Result<Option<AttributesSubsection<'data, Elf>>> {
if self.data.is_empty() {
return Ok(None);
}
let result = self.parse().map(Some);
if result.is_err() {
self.data = Bytes(&[]);
}
result
}
fn parse(&mut self) -> Result<AttributesSubsection<'data, Elf>> {
let mut data = self.data;
let length = data
.read::<endian::U32Bytes<Elf::Endian>>()
.read_error("ELF attributes section is too short")?
.get(self.endian);
let mut data = self
.data
.read_bytes(length as usize)
.read_error("Invalid ELF attributes subsection length")?;
data.skip(4)
.read_error("Invalid ELF attributes subsection length")?;
let vendor = data
.read_string()
.read_error("Invalid ELF attributes vendor")?;
Ok(AttributesSubsection {
endian: self.endian,
length,
vendor,
data,
})
}
}
impl<'data, Elf: FileHeader> Iterator for AttributesSubsectionIterator<'data, Elf> {
type Item = Result<AttributesSubsection<'data, Elf>>;
fn next(&mut self) -> Option<Self::Item> {
self.next().transpose()
}
}
#[derive(Debug, Clone)]
pub struct AttributesSubsection<'data, Elf: FileHeader> {
endian: Elf::Endian,
length: u32,
vendor: &'data [u8],
data: Bytes<'data>,
}
impl<'data, Elf: FileHeader> AttributesSubsection<'data, Elf> {
pub fn length(&self) -> u32 {
self.length
}
pub fn vendor(&self) -> &'data [u8] {
self.vendor
}
pub fn subsubsections(&self) -> AttributesSubsubsectionIterator<'data, Elf> {
AttributesSubsubsectionIterator {
endian: self.endian,
data: self.data,
}
}
}
#[derive(Debug, Clone)]
pub struct AttributesSubsubsectionIterator<'data, Elf: FileHeader> {
endian: Elf::Endian,
data: Bytes<'data>,
}
impl<'data, Elf: FileHeader> AttributesSubsubsectionIterator<'data, Elf> {
pub fn next(&mut self) -> Result<Option<AttributesSubsubsection<'data>>> {
if self.data.is_empty() {
return Ok(None);
}
let result = self.parse().map(Some);
if result.is_err() {
self.data = Bytes(&[]);
}
result
}
fn parse(&mut self) -> Result<AttributesSubsubsection<'data>> {
let mut 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);
let mut data = self
.data
.read_bytes(length as usize)
.read_error("Invalid ELF attributes sub-subsection length")?;
data.skip(1 + 4)
.read_error("Invalid ELF attributes sub-subsection length")?;
let indices = if tag == elf::Tag_Section || tag == elf::Tag_Symbol {
data.read_string()
.map(Bytes)
.read_error("Missing ELF attributes sub-subsection indices")?
} else if tag == elf::Tag_File {
Bytes(&[])
} else {
return Err(Error("Unimplemented ELF attributes sub-subsection tag"));
};
Ok(AttributesSubsubsection {
tag,
length,
indices,
data,
})
}
}
impl<'data, Elf: FileHeader> Iterator for AttributesSubsubsectionIterator<'data, Elf> {
type Item = Result<AttributesSubsubsection<'data>>;
fn next(&mut self) -> Option<Self::Item> {
self.next().transpose()
}
}
#[derive(Debug, Clone)]
pub struct AttributesSubsubsection<'data> {
tag: u8,
length: u32,
indices: Bytes<'data>,
data: Bytes<'data>,
}
impl<'data> AttributesSubsubsection<'data> {
pub fn tag(&self) -> u8 {
self.tag
}
pub fn length(&self) -> u32 {
self.length
}
pub fn indices_data(&self) -> &'data [u8] {
self.indices.0
}
pub fn indices(&self) -> AttributeIndexIterator<'data> {
AttributeIndexIterator { data: self.indices }
}
pub fn attributes_data(&self) -> &'data [u8] {
self.data.0
}
pub fn attributes(&self) -> AttributeReader<'data> {
AttributeReader { data: self.data }
}
}
#[derive(Debug, Clone)]
pub struct AttributeIndexIterator<'data> {
data: Bytes<'data>,
}
impl<'data> AttributeIndexIterator<'data> {
pub fn next(&mut self) -> Result<Option<u32>> {
if self.data.is_empty() {
return Ok(None);
}
let result = self.parse().map(Some);
if result.is_err() {
self.data = Bytes(&[]);
}
result
}
fn parse(&mut self) -> Result<u32> {
let err = "Invalid ELF attribute index";
self.data
.read_uleb128()
.read_error(err)?
.try_into()
.map_err(|_| ())
.read_error(err)
}
}
impl<'data> Iterator for AttributeIndexIterator<'data> {
type Item = Result<u32>;
fn next(&mut self) -> Option<Self::Item> {
self.next().transpose()
}
}
#[derive(Debug, Clone)]
pub struct AttributeReader<'data> {
data: Bytes<'data>,
}
impl<'data> AttributeReader<'data> {
pub fn read_tag(&mut self) -> Result<Option<u64>> {
if self.data.is_empty() {
return Ok(None);
}
let err = "Invalid ELF attribute tag";
self.data.read_uleb128().read_error(err).map(Some)
}
pub fn read_integer(&mut self) -> Result<u64> {
let err = "Invalid ELF attribute integer value";
self.data.read_uleb128().read_error(err)
}
pub fn read_string(&mut self) -> Result<&'data [u8]> {
let err = "Invalid ELF attribute string value";
self.data.read_string().read_error(err)
}
}