use core::fmt::Debug;
use core::{iter, slice, str};
use crate::elf;
use crate::endian::{Endianness, U32Bytes};
use crate::read::{self, ComdatKind, ObjectComdat, ReadError, SectionIndex, SymbolIndex};
use super::{ElfFile, FileHeader, SectionHeader, Sym};
pub type ElfComdatIterator32<'data, 'file, Endian = Endianness> =
ElfComdatIterator<'data, 'file, elf::FileHeader32<Endian>>;
pub type ElfComdatIterator64<'data, 'file, Endian = Endianness> =
ElfComdatIterator<'data, 'file, elf::FileHeader64<Endian>>;
#[derive(Debug)]
pub struct ElfComdatIterator<'data, 'file, Elf>
where
'data: 'file,
Elf: FileHeader,
{
pub(super) file: &'file ElfFile<'data, Elf>,
pub(super) iter: iter::Enumerate<slice::Iter<'data, Elf::SectionHeader>>,
}
impl<'data, 'file, Elf: FileHeader> Iterator for ElfComdatIterator<'data, 'file, Elf> {
type Item = ElfComdat<'data, 'file, Elf>;
fn next(&mut self) -> Option<Self::Item> {
while let Some((index, section)) = self.iter.next() {
if let Some(comdat) = ElfComdat::parse(self.file, index, section) {
return Some(comdat);
}
}
None
}
}
pub type ElfComdat32<'data, 'file, Endian = Endianness> =
ElfComdat<'data, 'file, elf::FileHeader32<Endian>>;
pub type ElfComdat64<'data, 'file, Endian = Endianness> =
ElfComdat<'data, 'file, elf::FileHeader64<Endian>>;
#[derive(Debug)]
pub struct ElfComdat<'data, 'file, Elf>
where
'data: 'file,
Elf: FileHeader,
{
file: &'file ElfFile<'data, Elf>,
index: SectionIndex,
section: &'data Elf::SectionHeader,
sections: &'data [U32Bytes<Elf::Endian>],
}
impl<'data, 'file, Elf: FileHeader> ElfComdat<'data, 'file, Elf> {
fn parse(
file: &'file ElfFile<'data, Elf>,
index: usize,
section: &'data Elf::SectionHeader,
) -> Option<ElfComdat<'data, 'file, Elf>> {
let (flag, sections) = section.group(file.endian, file.data).ok()??;
if flag != elf::GRP_COMDAT {
return None;
}
Some(ElfComdat {
file,
index: SectionIndex(index),
section,
sections,
})
}
}
impl<'data, 'file, Elf: FileHeader> read::private::Sealed for ElfComdat<'data, 'file, Elf> {}
impl<'data, 'file, Elf: FileHeader> ObjectComdat<'data> for ElfComdat<'data, 'file, Elf> {
type SectionIterator = ElfComdatSectionIterator<'data, 'file, Elf>;
#[inline]
fn kind(&self) -> ComdatKind {
ComdatKind::Any
}
#[inline]
fn symbol(&self) -> SymbolIndex {
SymbolIndex(self.section.sh_info(self.file.endian) as usize)
}
fn name(&self) -> read::Result<&str> {
let index = self.section.sh_info(self.file.endian) as usize;
let symbol = self.file.symbols.symbol(index)?;
let name = symbol.name(self.file.endian, self.file.symbols.strings())?;
str::from_utf8(name)
.ok()
.read_error("Non UTF-8 ELF COMDAT name")
}
fn sections(&self) -> Self::SectionIterator {
ElfComdatSectionIterator {
file: self.file,
sections: self.sections.iter(),
}
}
}
pub type ElfComdatSectionIterator32<'data, 'file, Endian = Endianness> =
ElfComdatSectionIterator<'data, 'file, elf::FileHeader32<Endian>>;
pub type ElfComdatSectionIterator64<'data, 'file, Endian = Endianness> =
ElfComdatSectionIterator<'data, 'file, elf::FileHeader64<Endian>>;
#[derive(Debug)]
pub struct ElfComdatSectionIterator<'data, 'file, Elf>
where
'data: 'file,
Elf: FileHeader,
{
file: &'file ElfFile<'data, Elf>,
sections: slice::Iter<'data, U32Bytes<Elf::Endian>>,
}
impl<'data, 'file, Elf: FileHeader> Iterator for ElfComdatSectionIterator<'data, 'file, Elf> {
type Item = SectionIndex;
fn next(&mut self) -> Option<Self::Item> {
let index = self.sections.next()?;
Some(SectionIndex(index.get(self.file.endian) as usize))
}
}