1use core::fmt::Debug;
2use core::{iter, slice, str};
3
4use crate::elf;
5use crate::endian::{Endianness, U32Bytes};
6use crate::read::{self, ComdatKind, ObjectComdat, ReadError, ReadRef, SectionIndex, SymbolIndex};
7
8use super::{ElfFile, FileHeader, SectionHeader, Sym};
9
10pub type ElfComdatIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
12 ElfComdatIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
13pub type ElfComdatIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
15 ElfComdatIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
16
17#[derive(Debug)]
19pub struct ElfComdatIterator<'data, 'file, Elf, R = &'data [u8]>
20where
21 Elf: FileHeader,
22 R: ReadRef<'data>,
23{
24 file: &'file ElfFile<'data, Elf, R>,
25 iter: iter::Enumerate<slice::Iter<'data, Elf::SectionHeader>>,
26}
27
28impl<'data, 'file, Elf, R> ElfComdatIterator<'data, 'file, Elf, R>
29where
30 Elf: FileHeader,
31 R: ReadRef<'data>,
32{
33 pub(super) fn new(
34 file: &'file ElfFile<'data, Elf, R>,
35 ) -> ElfComdatIterator<'data, 'file, Elf, R> {
36 let mut iter = file.sections.iter().enumerate();
37 iter.next(); ElfComdatIterator { file, iter }
39 }
40}
41
42impl<'data, 'file, Elf, R> Iterator for ElfComdatIterator<'data, 'file, Elf, R>
43where
44 Elf: FileHeader,
45 R: ReadRef<'data>,
46{
47 type Item = ElfComdat<'data, 'file, Elf, R>;
48
49 fn next(&mut self) -> Option<Self::Item> {
50 for (_index, section) in self.iter.by_ref() {
51 if let Some(comdat) = ElfComdat::parse(self.file, section) {
52 return Some(comdat);
53 }
54 }
55 None
56 }
57}
58
59pub type ElfComdat32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
61 ElfComdat<'data, 'file, elf::FileHeader32<Endian>, R>;
62pub type ElfComdat64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
64 ElfComdat<'data, 'file, elf::FileHeader64<Endian>, R>;
65
66#[derive(Debug)]
70pub struct ElfComdat<'data, 'file, Elf, R = &'data [u8]>
71where
72 Elf: FileHeader,
73 R: ReadRef<'data>,
74{
75 file: &'file ElfFile<'data, Elf, R>,
76 section: &'data Elf::SectionHeader,
77 sections: &'data [U32Bytes<Elf::Endian>],
78}
79
80impl<'data, 'file, Elf, R> ElfComdat<'data, 'file, Elf, R>
81where
82 Elf: FileHeader,
83 R: ReadRef<'data>,
84{
85 fn parse(
86 file: &'file ElfFile<'data, Elf, R>,
87 section: &'data Elf::SectionHeader,
88 ) -> Option<ElfComdat<'data, 'file, Elf, R>> {
89 let (flag, sections) = section.group(file.endian, file.data).ok()??;
90 if flag != elf::GRP_COMDAT {
91 return None;
92 }
93 Some(ElfComdat {
94 file,
95 section,
96 sections,
97 })
98 }
99
100 pub fn elf_file(&self) -> &'file ElfFile<'data, Elf, R> {
102 self.file
103 }
104
105 pub fn elf_section_header(&self) -> &'data Elf::SectionHeader {
107 self.section
108 }
109}
110
111impl<'data, 'file, Elf, R> read::private::Sealed for ElfComdat<'data, 'file, Elf, R>
112where
113 Elf: FileHeader,
114 R: ReadRef<'data>,
115{
116}
117
118impl<'data, 'file, Elf, R> ObjectComdat<'data> for ElfComdat<'data, 'file, Elf, R>
119where
120 Elf: FileHeader,
121 R: ReadRef<'data>,
122{
123 type SectionIterator = ElfComdatSectionIterator<'data, 'file, Elf, R>;
124
125 #[inline]
126 fn kind(&self) -> ComdatKind {
127 ComdatKind::Any
128 }
129
130 #[inline]
131 fn symbol(&self) -> SymbolIndex {
132 SymbolIndex(self.section.sh_info(self.file.endian) as usize)
133 }
134
135 fn name_bytes(&self) -> read::Result<&'data [u8]> {
136 let index = self.symbol();
138 let symbol = self.file.symbols.symbol(index)?;
139 symbol.name(self.file.endian, self.file.symbols.strings())
140 }
141
142 fn name(&self) -> read::Result<&'data str> {
143 let name = self.name_bytes()?;
144 str::from_utf8(name)
145 .ok()
146 .read_error("Non UTF-8 ELF COMDAT name")
147 }
148
149 fn sections(&self) -> Self::SectionIterator {
150 ElfComdatSectionIterator {
151 file: self.file,
152 sections: self.sections.iter(),
153 }
154 }
155}
156
157pub type ElfComdatSectionIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
159 ElfComdatSectionIterator<'data, 'file, elf::FileHeader32<Endian>, R>;
160pub type ElfComdatSectionIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
162 ElfComdatSectionIterator<'data, 'file, elf::FileHeader64<Endian>, R>;
163
164#[derive(Debug)]
166pub struct ElfComdatSectionIterator<'data, 'file, Elf, R = &'data [u8]>
167where
168 Elf: FileHeader,
169 R: ReadRef<'data>,
170{
171 file: &'file ElfFile<'data, Elf, R>,
172 sections: slice::Iter<'data, U32Bytes<Elf::Endian>>,
173}
174
175impl<'data, 'file, Elf, R> Iterator for ElfComdatSectionIterator<'data, 'file, Elf, R>
176where
177 Elf: FileHeader,
178 R: ReadRef<'data>,
179{
180 type Item = SectionIndex;
181
182 fn next(&mut self) -> Option<Self::Item> {
183 let index = self.sections.next()?;
184 Some(SectionIndex(index.get(self.file.endian) as usize))
185 }
186}