1use alloc::vec::Vec;
2
3use crate::read::{Bytes, ReadError, ReadRef, Result, StringTable, SymbolIndex};
4use crate::{elf, endian};
5
6use super::FileHeader;
7
8#[derive(Debug, Default, Clone, Copy)]
12pub struct Version<'data> {
13 name: &'data [u8],
14 hash: u32,
15 valid: bool,
17 file: Option<&'data [u8]>,
18}
19
20impl<'data> Version<'data> {
21 pub fn name(&self) -> &'data [u8] {
23 self.name
24 }
25
26 pub fn hash(&self) -> u32 {
28 self.hash
29 }
30
31 pub fn file(&self) -> Option<&'data [u8]> {
36 self.file
37 }
38}
39
40#[derive(Debug, Clone)]
49pub struct VersionTable<'data, Elf: FileHeader> {
50 symbols: &'data [elf::Versym<Elf::Endian>],
51 versions: Vec<Version<'data>>,
52}
53
54impl<'data, Elf: FileHeader> Default for VersionTable<'data, Elf> {
55 fn default() -> Self {
56 VersionTable {
57 symbols: &[],
58 versions: Vec::new(),
59 }
60 }
61}
62
63impl<'data, Elf: FileHeader> VersionTable<'data, Elf> {
64 pub fn parse<R: ReadRef<'data>>(
66 endian: Elf::Endian,
67 versyms: &'data [elf::Versym<Elf::Endian>],
68 verdefs: Option<VerdefIterator<'data, Elf>>,
69 verneeds: Option<VerneedIterator<'data, Elf>>,
70 strings: StringTable<'data, R>,
71 ) -> Result<Self> {
72 let mut max_index = 0;
73 if let Some(mut verdefs) = verdefs.clone() {
74 while let Some((verdef, _)) = verdefs.next()? {
75 if verdef.vd_flags.get(endian).contains(elf::VER_FLG_BASE) {
76 continue;
77 }
78 let index = verdef.vd_ndx.get(endian);
79 if max_index < index.0 {
80 max_index = index.0;
81 }
82 }
83 }
84 if let Some(mut verneeds) = verneeds.clone() {
85 while let Some((_, mut vernauxs)) = verneeds.next()? {
86 while let Some(vernaux) = vernauxs.next()? {
87 let index = vernaux.vna_other(endian).index();
88 if max_index < index.0 {
89 max_index = index.0;
90 }
91 }
92 }
93 }
94
95 let mut versions = vec![Version::default(); max_index as usize + 1];
98
99 if let Some(mut verdefs) = verdefs {
100 while let Some((verdef, mut verdauxs)) = verdefs.next()? {
101 if verdef.vd_flags.get(endian).contains(elf::VER_FLG_BASE) {
102 continue;
103 }
104 let index = verdef.vd_ndx.get(endian);
105 if index.is_special() {
106 continue;
108 }
109 if let Some(verdaux) = verdauxs.next()? {
110 versions[usize::from(index)] = Version {
111 name: verdaux.name(endian, strings)?,
112 hash: verdef.vd_hash.get(endian),
113 valid: true,
114 file: None,
115 };
116 }
117 }
118 }
119 if let Some(mut verneeds) = verneeds {
120 while let Some((verneed, mut vernauxs)) = verneeds.next()? {
121 while let Some(vernaux) = vernauxs.next()? {
122 let index = vernaux.vna_other(endian).index();
124 if index.is_special() {
125 continue;
127 }
128 versions[usize::from(index)] = Version {
129 name: vernaux.name(endian, strings)?,
130 hash: vernaux.vna_hash.get(endian),
131 valid: true,
132 file: Some(verneed.file(endian, strings)?),
133 };
134 }
135 }
136 }
137
138 Ok(VersionTable {
139 symbols: versyms,
140 versions,
141 })
142 }
143
144 pub fn is_empty(&self) -> bool {
146 self.symbols.is_empty()
147 }
148
149 pub fn version_index(&self, endian: Elf::Endian, index: SymbolIndex) -> elf::VersymIndex {
151 match self.symbols.get(index.0) {
152 Some(versym) => versym.0.get(endian),
153 None => elf::VER_NDX_GLOBAL.into(),
156 }
157 }
158
159 pub fn version(&self, index: elf::VersionIndex) -> Result<Option<&Version<'data>>> {
164 if index.is_special() {
165 return Ok(None);
166 }
167 self.versions
168 .get(usize::from(index))
169 .filter(|version| version.valid)
170 .read_error("Invalid ELF symbol version index")
171 .map(Some)
172 }
173
174 pub fn matches(
180 &self,
181 endian: Elf::Endian,
182 index: SymbolIndex,
183 need: Option<&Version<'_>>,
184 ) -> bool {
185 let version_index = self.version_index(endian, index);
186 let def = match self.version(version_index.index()) {
187 Ok(def) => def,
188 Err(_) => return false,
189 };
190 match (def, need) {
191 (Some(def), Some(need)) => need.hash == def.hash && need.name == def.name,
192 (None, Some(_need)) => {
193 false
195 }
196 (Some(_def), None) => {
197 !version_index.is_hidden()
200 }
201 (None, None) => true,
202 }
203 }
204}
205
206#[derive(Debug, Clone)]
208pub struct VerdefIterator<'data, Elf: FileHeader> {
209 endian: Elf::Endian,
210 data: Bytes<'data>,
211}
212
213impl<'data, Elf: FileHeader> VerdefIterator<'data, Elf> {
214 pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self {
215 VerdefIterator {
216 endian,
217 data: Bytes(data),
218 }
219 }
220
221 pub fn next(
223 &mut self,
224 ) -> Result<Option<(&'data elf::Verdef<Elf::Endian>, VerdauxIterator<'data, Elf>)>> {
225 if self.data.is_empty() {
226 return Ok(None);
227 }
228
229 let result = self.parse().map(Some);
230 if result.is_err() {
231 self.data = Bytes(&[]);
232 }
233 result
234 }
235
236 fn parse(&mut self) -> Result<(&'data elf::Verdef<Elf::Endian>, VerdauxIterator<'data, Elf>)> {
237 let verdef = self
238 .data
239 .read_at::<elf::Verdef<_>>(0)
240 .read_error("ELF verdef is too short")?;
241
242 let mut verdaux_data = self.data;
243 verdaux_data
244 .skip(verdef.vd_aux.get(self.endian) as usize)
245 .read_error("Invalid ELF vd_aux")?;
246 let verdaux =
247 VerdauxIterator::new(self.endian, verdaux_data.0, verdef.vd_cnt.get(self.endian));
248
249 let next = verdef.vd_next.get(self.endian);
250 if next != 0 {
251 self.data
252 .skip(next as usize)
253 .read_error("Invalid ELF vd_next")?;
254 } else {
255 self.data = Bytes(&[]);
256 }
257 Ok((verdef, verdaux))
258 }
259}
260
261impl<'data, Elf: FileHeader> Iterator for VerdefIterator<'data, Elf> {
262 type Item = Result<(&'data elf::Verdef<Elf::Endian>, VerdauxIterator<'data, Elf>)>;
263
264 fn next(&mut self) -> Option<Self::Item> {
265 self.next().transpose()
266 }
267}
268
269#[derive(Debug, Clone)]
271pub struct VerdauxIterator<'data, Elf: FileHeader> {
272 endian: Elf::Endian,
273 data: Bytes<'data>,
274 count: u16,
275}
276
277impl<'data, Elf: FileHeader> VerdauxIterator<'data, Elf> {
278 pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self {
279 VerdauxIterator {
280 endian,
281 data: Bytes(data),
282 count,
283 }
284 }
285
286 pub fn next(&mut self) -> Result<Option<&'data elf::Verdaux<Elf::Endian>>> {
288 if self.count == 0 {
289 return Ok(None);
290 }
291
292 let result = self.parse().map(Some);
293 if result.is_err() {
294 self.count = 0;
295 } else {
296 self.count -= 1;
297 }
298 result
299 }
300
301 fn parse(&mut self) -> Result<&'data elf::Verdaux<Elf::Endian>> {
302 let verdaux = self
303 .data
304 .read_at::<elf::Verdaux<_>>(0)
305 .read_error("ELF verdaux is too short")?;
306
307 self.data
308 .skip(verdaux.vda_next.get(self.endian) as usize)
309 .read_error("Invalid ELF vda_next")?;
310 Ok(verdaux)
311 }
312}
313
314impl<'data, Elf: FileHeader> Iterator for VerdauxIterator<'data, Elf> {
315 type Item = Result<&'data elf::Verdaux<Elf::Endian>>;
316
317 fn next(&mut self) -> Option<Self::Item> {
318 self.next().transpose()
319 }
320}
321
322#[derive(Debug, Clone)]
324pub struct VerneedIterator<'data, Elf: FileHeader> {
325 endian: Elf::Endian,
326 data: Bytes<'data>,
327}
328
329impl<'data, Elf: FileHeader> VerneedIterator<'data, Elf> {
330 pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self {
331 VerneedIterator {
332 endian,
333 data: Bytes(data),
334 }
335 }
336
337 pub fn next(
339 &mut self,
340 ) -> Result<
341 Option<(
342 &'data elf::Verneed<Elf::Endian>,
343 VernauxIterator<'data, Elf>,
344 )>,
345 > {
346 if self.data.is_empty() {
347 return Ok(None);
348 }
349
350 let result = self.parse().map(Some);
351 if result.is_err() {
352 self.data = Bytes(&[]);
353 }
354 result
355 }
356
357 fn parse(
358 &mut self,
359 ) -> Result<(
360 &'data elf::Verneed<Elf::Endian>,
361 VernauxIterator<'data, Elf>,
362 )> {
363 let verneed = self
364 .data
365 .read_at::<elf::Verneed<_>>(0)
366 .read_error("ELF verneed is too short")?;
367
368 let mut vernaux_data = self.data;
369 vernaux_data
370 .skip(verneed.vn_aux.get(self.endian) as usize)
371 .read_error("Invalid ELF vn_aux")?;
372 let vernaux =
373 VernauxIterator::new(self.endian, vernaux_data.0, verneed.vn_cnt.get(self.endian));
374
375 let next = verneed.vn_next.get(self.endian);
376 if next != 0 {
377 self.data
378 .skip(next as usize)
379 .read_error("Invalid ELF vn_next")?;
380 } else {
381 self.data = Bytes(&[]);
382 }
383 Ok((verneed, vernaux))
384 }
385}
386
387impl<'data, Elf: FileHeader> Iterator for VerneedIterator<'data, Elf> {
388 type Item = Result<(
389 &'data elf::Verneed<Elf::Endian>,
390 VernauxIterator<'data, Elf>,
391 )>;
392
393 fn next(&mut self) -> Option<Self::Item> {
394 self.next().transpose()
395 }
396}
397
398#[derive(Debug, Clone)]
400pub struct VernauxIterator<'data, Elf: FileHeader> {
401 endian: Elf::Endian,
402 data: Bytes<'data>,
403 count: u16,
404}
405
406impl<'data, Elf: FileHeader> VernauxIterator<'data, Elf> {
407 pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self {
408 VernauxIterator {
409 endian,
410 data: Bytes(data),
411 count,
412 }
413 }
414
415 pub fn next(&mut self) -> Result<Option<&'data elf::Vernaux<Elf::Endian>>> {
417 if self.count == 0 {
418 return Ok(None);
419 }
420
421 let result = self.parse().map(Some);
422 if result.is_err() {
423 self.count = 0;
424 } else {
425 self.count -= 1;
426 }
427 result
428 }
429
430 fn parse(&mut self) -> Result<&'data elf::Vernaux<Elf::Endian>> {
431 let vernaux = self
432 .data
433 .read_at::<elf::Vernaux<_>>(0)
434 .read_error("ELF vernaux is too short")?;
435 self.data
436 .skip(vernaux.vna_next.get(self.endian) as usize)
437 .read_error("Invalid ELF vna_next")?;
438 Ok(vernaux)
439 }
440}
441
442impl<'data, Elf: FileHeader> Iterator for VernauxIterator<'data, Elf> {
443 type Item = Result<&'data elf::Vernaux<Elf::Endian>>;
444
445 fn next(&mut self) -> Option<Self::Item> {
446 self.next().transpose()
447 }
448}
449
450impl<Endian: endian::Endian> elf::Verdaux<Endian> {
451 pub fn name<'data, R: ReadRef<'data>>(
453 &self,
454 endian: Endian,
455 strings: StringTable<'data, R>,
456 ) -> Result<&'data [u8]> {
457 strings
458 .get(self.vda_name.get(endian))
459 .read_error("Invalid ELF vda_name")
460 }
461}
462
463impl<Endian: endian::Endian> elf::Verneed<Endian> {
464 pub fn file<'data, R: ReadRef<'data>>(
466 &self,
467 endian: Endian,
468 strings: StringTable<'data, R>,
469 ) -> Result<&'data [u8]> {
470 strings
471 .get(self.vn_file.get(endian))
472 .read_error("Invalid ELF vn_file")
473 }
474}
475
476impl<Endian: endian::Endian> elf::Vernaux<Endian> {
477 pub fn name<'data, R: ReadRef<'data>>(
479 &self,
480 endian: Endian,
481 strings: StringTable<'data, R>,
482 ) -> Result<&'data [u8]> {
483 strings
484 .get(self.vna_name.get(endian))
485 .read_error("Invalid ELF vna_name")
486 }
487}