1use crate::abi;
3use crate::endian::EndianParse;
4use crate::file::Class;
5use crate::parse::{ParseAt, ParseError, ParsingTable};
6use crate::string_table::StringTable;
7
8#[derive(Debug, PartialEq, Eq)]
9pub struct SymbolRequirement<'data> {
10 pub file: &'data str,
11 pub name: &'data str,
12 pub hash: u32,
13 pub flags: u16,
14 pub hidden: bool,
15}
16
17#[derive(Debug)]
18pub struct SymbolDefinition<'data, E: EndianParse> {
19 pub hash: u32,
20 pub flags: u16,
21 pub names: SymbolNamesIterator<'data, E>,
22 pub hidden: bool,
23}
24
25#[derive(Debug)]
26pub struct SymbolNamesIterator<'data, E: EndianParse> {
27 vda_iter: VerDefAuxIterator<'data, E>,
28 strtab: &'data StringTable<'data>,
29}
30
31impl<'data, E: EndianParse> SymbolNamesIterator<'data, E> {
32 pub fn new(vda_iter: VerDefAuxIterator<'data, E>, strtab: &'data StringTable<'data>) -> Self {
33 SymbolNamesIterator { vda_iter, strtab }
34 }
35}
36
37impl<'data, E: EndianParse> Iterator for SymbolNamesIterator<'data, E> {
38 type Item = Result<&'data str, ParseError>;
39 fn next(&mut self) -> Option<Self::Item> {
40 let vda = self.vda_iter.next();
41 match vda {
42 Some(vda) => Some(self.strtab.get(vda.vda_name as usize)),
43 None => None,
44 }
45 }
46}
47
48#[derive(Debug)]
49pub struct SymbolVersionTable<'data, E: EndianParse> {
50 version_ids: VersionIndexTable<'data, E>,
51
52 verneeds: Option<(VerNeedIterator<'data, E>, StringTable<'data>)>,
53 verdefs: Option<(VerDefIterator<'data, E>, StringTable<'data>)>,
54}
55
56impl<'data, E: EndianParse> SymbolVersionTable<'data, E> {
57 pub fn new(
58 version_ids: VersionIndexTable<'data, E>,
59 verneeds: Option<(VerNeedIterator<'data, E>, StringTable<'data>)>,
60 verdefs: Option<(VerDefIterator<'data, E>, StringTable<'data>)>,
61 ) -> Self {
62 SymbolVersionTable {
63 version_ids,
64 verneeds,
65 verdefs,
66 }
67 }
68
69 pub fn get_requirement(
70 &self,
71 sym_idx: usize,
72 ) -> Result<Option<SymbolRequirement<'_>>, ParseError> {
73 let (verneeds, verneed_strs) = match self.verneeds {
74 Some(verneeds) => verneeds,
75 None => {
76 return Ok(None);
77 }
78 };
79
80 let ver_ndx = self.version_ids.get(sym_idx)?;
81 let iter = verneeds;
82 for (vn, vna_iter) in iter {
83 for vna in vna_iter {
84 if vna.vna_other != ver_ndx.index() {
85 continue;
86 }
87
88 let file = verneed_strs.get(vn.vn_file as usize)?;
89 let name = verneed_strs.get(vna.vna_name as usize)?;
90 let hash = vna.vna_hash;
91 let hidden = ver_ndx.is_hidden();
92 return Ok(Some(SymbolRequirement {
93 file,
94 name,
95 hash,
96 flags: vna.vna_flags,
97 hidden,
98 }));
99 }
100 }
101
102 Ok(None)
107 }
108
109 pub fn get_definition(
110 &self,
111 sym_idx: usize,
112 ) -> Result<Option<SymbolDefinition<'_, E>>, ParseError> {
113 let (ref verdefs, ref verdef_strs) = match self.verdefs {
114 Some(ref verdefs) => verdefs,
115 None => {
116 return Ok(None);
117 }
118 };
119
120 let ver_ndx = self.version_ids.get(sym_idx)?;
121 let iter = *verdefs;
122 for (vd, vda_iter) in iter {
123 if vd.vd_ndx != ver_ndx.index() {
124 continue;
125 }
126
127 let flags = vd.vd_flags;
128 let hash = vd.vd_hash;
129 let hidden = ver_ndx.is_hidden();
130 return Ok(Some(SymbolDefinition {
131 hash,
132 flags,
133 names: SymbolNamesIterator {
134 vda_iter,
135 strtab: verdef_strs,
136 },
137 hidden,
138 }));
139 }
140
141 Ok(None)
146 }
147}
148
149pub type VersionIndexTable<'data, E> = ParsingTable<'data, E, VersionIndex>;
159
160#[derive(Debug, PartialEq, Eq)]
174pub struct VersionIndex(pub u16);
175
176impl VersionIndex {
177 pub fn index(&self) -> u16 {
178 self.0 & abi::VER_NDX_VERSION
179 }
180
181 pub fn is_local(&self) -> bool {
182 self.index() == abi::VER_NDX_LOCAL
183 }
184
185 pub fn is_global(&self) -> bool {
186 self.index() == abi::VER_NDX_GLOBAL
187 }
188
189 pub fn is_hidden(&self) -> bool {
190 (self.0 & abi::VER_NDX_HIDDEN) != 0
191 }
192}
193
194impl ParseAt for VersionIndex {
195 fn parse_at<E: EndianParse>(
196 endian: E,
197 _class: Class,
198 offset: &mut usize,
199 data: &[u8],
200 ) -> Result<Self, ParseError> {
201 Ok(VersionIndex(endian.parse_u16_at(offset, data)?))
202 }
203
204 #[inline]
205 fn size_for(_class: Class) -> usize {
206 core::mem::size_of::<u16>()
207 }
208}
209
210#[derive(Debug, PartialEq, Eq)]
229pub struct VerDef {
230 pub vd_flags: u16,
232 pub vd_ndx: u16,
234 pub vd_cnt: u16,
236 pub vd_hash: u32,
238 vd_aux: u32,
240 vd_next: u32,
242}
243
244impl ParseAt for VerDef {
245 fn parse_at<E: EndianParse>(
246 endian: E,
247 _class: Class,
248 offset: &mut usize,
249 data: &[u8],
250 ) -> Result<Self, ParseError> {
251 let vd_version = endian.parse_u16_at(offset, data)?;
252 if vd_version != abi::VER_DEF_CURRENT {
253 return Err(ParseError::UnsupportedVersion((
254 vd_version as u64,
255 abi::VER_DEF_CURRENT as u64,
256 )));
257 }
258
259 Ok(VerDef {
260 vd_flags: endian.parse_u16_at(offset, data)?,
261 vd_ndx: endian.parse_u16_at(offset, data)?,
262 vd_cnt: endian.parse_u16_at(offset, data)?,
263 vd_hash: endian.parse_u32_at(offset, data)?,
264 vd_aux: endian.parse_u32_at(offset, data)?,
265 vd_next: endian.parse_u32_at(offset, data)?,
266 })
267 }
268
269 #[inline]
270 fn size_for(_class: Class) -> usize {
271 ELFVERDEFSIZE
272 }
273}
274
275const ELFVERDEFSIZE: usize = 20;
276
277#[derive(Debug, Clone, Copy)]
278pub struct VerDefIterator<'data, E: EndianParse> {
279 endian: E,
280 class: Class,
281 count: u64,
284 data: &'data [u8],
285 offset: usize,
286}
287
288impl<'data, E: EndianParse> VerDefIterator<'data, E> {
289 pub fn new(
290 endian: E,
291 class: Class,
292 count: u64,
293 starting_offset: usize,
294 data: &'data [u8],
295 ) -> Self {
296 VerDefIterator {
297 endian,
298 class,
299 count,
300 data,
301 offset: starting_offset,
302 }
303 }
304}
305
306impl<'data, E: EndianParse> Iterator for VerDefIterator<'data, E> {
307 type Item = (VerDef, VerDefAuxIterator<'data, E>);
308 fn next(&mut self) -> Option<Self::Item> {
309 if self.data.is_empty() || self.count == 0 {
310 return None;
311 }
312
313 let mut start = self.offset;
314 let vd = VerDef::parse_at(self.endian, self.class, &mut start, self.data).ok()?;
315 let vda_iter = VerDefAuxIterator::new(
316 self.endian,
317 self.class,
318 vd.vd_cnt,
319 self.offset + vd.vd_aux as usize,
320 self.data,
321 );
322
323 match self.offset.checked_add(vd.vd_next as usize) {
325 Some(new_off) => self.offset = new_off,
326 None => self.count = 0,
327 }
328 self.count -= 1;
329
330 if self.count > 0 && vd.vd_next == 0 {
333 self.count = 0
334 }
335 Some((vd, vda_iter))
336 }
337}
338
339#[derive(Debug, PartialEq, Eq)]
341pub struct VerDefAux {
342 pub vda_name: u32,
344 vda_next: u32,
346}
347
348impl ParseAt for VerDefAux {
349 fn parse_at<E: EndianParse>(
350 endian: E,
351 _class: Class,
352 offset: &mut usize,
353 data: &[u8],
354 ) -> Result<Self, ParseError> {
355 Ok(VerDefAux {
356 vda_name: endian.parse_u32_at(offset, data)?,
357 vda_next: endian.parse_u32_at(offset, data)?,
358 })
359 }
360
361 #[inline]
362 fn size_for(_class: Class) -> usize {
363 8
364 }
365}
366
367#[derive(Debug)]
368pub struct VerDefAuxIterator<'data, E: EndianParse> {
369 endian: E,
370 class: Class,
371 count: u16,
372 data: &'data [u8],
373 offset: usize,
374}
375
376impl<'data, E: EndianParse> VerDefAuxIterator<'data, E> {
377 pub fn new(
378 endian: E,
379 class: Class,
380 count: u16,
381 starting_offset: usize,
382 data: &'data [u8],
383 ) -> Self {
384 VerDefAuxIterator {
385 endian,
386 class,
387 count,
388 data,
389 offset: starting_offset,
390 }
391 }
392}
393
394impl<'data, E: EndianParse> Iterator for VerDefAuxIterator<'data, E> {
395 type Item = VerDefAux;
396 fn next(&mut self) -> Option<Self::Item> {
397 if self.data.is_empty() || self.count == 0 {
398 return None;
399 }
400
401 let mut start = self.offset;
427 let vda = VerDefAux::parse_at(self.endian, self.class, &mut start, self.data).ok()?;
428
429 match self.offset.checked_add(vda.vda_next as usize) {
431 Some(new_off) => self.offset = new_off,
432 None => self.count = 0,
433 }
434 self.count -= 1;
435
436 if self.count > 0 && vda.vda_next == 0 {
439 self.count = 0
440 }
441 Some(vda)
442 }
443}
444
445#[derive(Debug, PartialEq, Eq)]
464pub struct VerNeed {
465 pub vn_cnt: u16,
467 pub vn_file: u32,
469 vn_aux: u32,
471 vn_next: u32,
473}
474
475impl ParseAt for VerNeed {
476 fn parse_at<E: EndianParse>(
477 endian: E,
478 _class: Class,
479 offset: &mut usize,
480 data: &[u8],
481 ) -> Result<Self, ParseError> {
482 let vd_version = endian.parse_u16_at(offset, data)?;
483 if vd_version != abi::VER_NEED_CURRENT {
484 return Err(ParseError::UnsupportedVersion((
485 vd_version as u64,
486 abi::VER_DEF_CURRENT as u64,
487 )));
488 }
489 Ok(VerNeed {
490 vn_cnt: endian.parse_u16_at(offset, data)?,
491 vn_file: endian.parse_u32_at(offset, data)?,
492 vn_aux: endian.parse_u32_at(offset, data)?,
493 vn_next: endian.parse_u32_at(offset, data)?,
494 })
495 }
496
497 #[inline]
498 fn size_for(_class: Class) -> usize {
499 ELFVERNEEDSIZE
500 }
501}
502
503const ELFVERNEEDSIZE: usize = 16;
504
505#[derive(Debug, Copy, Clone)]
506pub struct VerNeedIterator<'data, E: EndianParse> {
507 endian: E,
508 class: Class,
509 count: u64,
512 data: &'data [u8],
513 offset: usize,
514}
515
516impl<'data, E: EndianParse> VerNeedIterator<'data, E> {
517 pub fn new(
518 endian: E,
519 class: Class,
520 count: u64,
521 starting_offset: usize,
522 data: &'data [u8],
523 ) -> Self {
524 VerNeedIterator {
525 endian,
526 class,
527 count,
528 data,
529 offset: starting_offset,
530 }
531 }
532}
533
534impl<'data, E: EndianParse> Iterator for VerNeedIterator<'data, E> {
535 type Item = (VerNeed, VerNeedAuxIterator<'data, E>);
536 fn next(&mut self) -> Option<Self::Item> {
537 if self.data.is_empty() || self.count == 0 {
538 return None;
539 }
540
541 let mut start = self.offset;
542 let vn = VerNeed::parse_at(self.endian, self.class, &mut start, self.data).ok()?;
543 let vna_iter = VerNeedAuxIterator::new(
544 self.endian,
545 self.class,
546 vn.vn_cnt,
547 self.offset + vn.vn_aux as usize,
548 self.data,
549 );
550
551 match self.offset.checked_add(vn.vn_next as usize) {
553 Some(new_off) => self.offset = new_off,
554 None => self.count = 0,
555 }
556 self.count -= 1;
557
558 if self.count > 0 && vn.vn_next == 0 {
561 self.count = 0
562 }
563 Some((vn, vna_iter))
564 }
565}
566
567#[derive(Debug, PartialEq, Eq)]
569pub struct VerNeedAux {
570 pub vna_hash: u32,
572 pub vna_flags: u16,
574 pub vna_other: u16,
576 pub vna_name: u32,
578 vna_next: u32,
580}
581
582impl ParseAt for VerNeedAux {
583 fn parse_at<E: EndianParse>(
584 endian: E,
585 _class: Class,
586 offset: &mut usize,
587 data: &[u8],
588 ) -> Result<Self, ParseError> {
589 Ok(VerNeedAux {
590 vna_hash: endian.parse_u32_at(offset, data)?,
591 vna_flags: endian.parse_u16_at(offset, data)?,
592 vna_other: endian.parse_u16_at(offset, data)?,
593 vna_name: endian.parse_u32_at(offset, data)?,
594 vna_next: endian.parse_u32_at(offset, data)?,
595 })
596 }
597
598 #[inline]
599 fn size_for(_class: Class) -> usize {
600 16
601 }
602}
603
604#[derive(Debug)]
605pub struct VerNeedAuxIterator<'data, E: EndianParse> {
606 endian: E,
607 class: Class,
608 count: u16,
609 data: &'data [u8],
610 offset: usize,
611}
612
613impl<'data, E: EndianParse> VerNeedAuxIterator<'data, E> {
614 pub fn new(
615 endian: E,
616 class: Class,
617 count: u16,
618 starting_offset: usize,
619 data: &'data [u8],
620 ) -> Self {
621 VerNeedAuxIterator {
622 endian,
623 class,
624 count,
625 data,
626 offset: starting_offset,
627 }
628 }
629}
630
631impl<'data, E: EndianParse> Iterator for VerNeedAuxIterator<'data, E> {
632 type Item = VerNeedAux;
633 fn next(&mut self) -> Option<Self::Item> {
634 if self.data.is_empty() || self.count == 0 {
635 return None;
636 }
637
638 let mut start = self.offset;
639 let vna = VerNeedAux::parse_at(self.endian, self.class, &mut start, self.data).ok()?;
640
641 match self.offset.checked_add(vna.vna_next as usize) {
643 Some(new_off) => self.offset = new_off,
644 None => self.count = 0,
645 }
646 self.count -= 1;
647
648 if self.count > 0 && vna.vna_next == 0 {
651 self.count = 0
652 }
653 Some(vna)
654 }
655}
656
657#[cfg(test)]
667mod iter_tests {
668 use super::*;
669 use crate::endian::LittleEndian;
670
671 #[rustfmt::skip]
672 const GNU_VERNEED_STRINGS: [u8; 65] = [
673 0x00, 0x5a, 0x4c, 0x49, 0x42, 0x5f, 0x31, 0x2e, 0x32, 0x2e, 0x30, 0x00,
675 0x47, 0x4c, 0x49, 0x42, 0x43, 0x5f, 0x32, 0x2e, 0x33, 0x33, 0x00,
677 0x47, 0x4c, 0x49, 0x42, 0x43, 0x5f, 0x32, 0x2e, 0x32, 0x2e, 0x35, 0x00,
679 0x6c, 0x69, 0x62, 0x7a, 0x2e, 0x73, 0x6f, 0x2e, 0x31, 0x00,
681 0x6c, 0x69, 0x62, 0x63, 0x2e, 0x73, 0x6f, 0x2e, 0x36, 0x00,
683 0x47, 0x4c, 0x49, 0x42, 0x43, 0x5f, 0x32, 0x2e, 0x33, 0x00,
685 ];
686
687 #[rustfmt::skip]
688 const GNU_VERNEED_DATA: [u8; 96] = [
689 0x01, 0x00, 0x01, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
691 0xc0, 0xe5, 0x27, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693 0x01, 0x00, 0x03, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 0x13, 0x69, 0x69, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
697 0xb3, 0x91, 0x96, 0x06, 0x00, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
699 0x94, 0x91, 0x96, 0x06, 0x00, 0x00, 0x09, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 ];
702
703 #[test]
704 fn verneed_iter() {
705 let iter = VerNeedIterator::new(LittleEndian, Class::ELF64, 2, 0, &GNU_VERNEED_DATA);
706 let entries: Vec<(VerNeed, Vec<VerNeedAux>)> =
707 iter.map(|(vn, iter)| (vn, iter.collect())).collect();
708
709 assert_eq!(entries.len(), 2);
710 }
711
712 #[test]
713 fn verneed_iter_early_termination_on_broken_next_link() {
714 let iter = VerNeedIterator::new(LittleEndian, Class::ELF64, 3, 0, &GNU_VERNEED_DATA);
716 let entries: Vec<(VerNeed, Vec<VerNeedAux>)> =
717 iter.map(|(vn, iter)| (vn, iter.collect())).collect();
718
719 assert_eq!(entries.len(), 2);
721 }
722
723 #[test]
724 fn verneedaux_iter_one_entry() {
725 let mut iter =
726 VerNeedAuxIterator::new(LittleEndian, Class::ELF64, 1, 0x10, &GNU_VERNEED_DATA);
727 let aux1 = iter.next().expect("Failed to parse");
728 assert_eq!(
729 aux1,
730 VerNeedAux {
731 vna_hash: 0x0827e5c0,
732 vna_flags: 0,
733 vna_other: 0x0a,
734 vna_name: 0x01,
735 vna_next: 0
736 }
737 );
738 assert!(iter.next().is_none());
739 }
740
741 #[test]
742 fn verneedaux_iter_multiple_entries() {
743 let mut iter =
744 VerNeedAuxIterator::new(LittleEndian, Class::ELF64, 3, 0x30, &GNU_VERNEED_DATA);
745 let aux1 = iter.next().expect("Failed to parse");
746 assert_eq!(
747 aux1,
748 VerNeedAux {
749 vna_hash: 0x0d696913,
750 vna_flags: 0,
751 vna_other: 0x0c,
752 vna_name: 0x0c,
753 vna_next: 0x10
754 }
755 );
756 let aux2 = iter.next().expect("Failed to parse");
757 assert_eq!(
758 aux2,
759 VerNeedAux {
760 vna_hash: 0x069691b3,
761 vna_flags: 0,
762 vna_other: 0x0b,
763 vna_name: 0x17,
764 vna_next: 0x10
765 }
766 );
767 let aux3 = iter.next().expect("Failed to parse");
768 assert_eq!(
769 aux3,
770 VerNeedAux {
771 vna_hash: 0x06969194,
772 vna_flags: 0,
773 vna_other: 0x09,
774 vna_name: 0x37,
775 vna_next: 0
776 }
777 );
778 assert!(iter.next().is_none());
779 }
780
781 #[test]
783 fn verneedaux_iter_two_lists_interspersed() {
784 #[rustfmt::skip]
785 let data: [u8; 64] = [
786 0xc0, 0xe5, 0x27, 0x08, 0x00, 0x00, 0x0a, 0x00, 0xcc, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
788 0x13, 0x69, 0x69, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0xd7, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
790 0xb3, 0x91, 0x96, 0x06, 0x00, 0x00, 0x0b, 0x00, 0xe1, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792 0x94, 0x91, 0x96, 0x06, 0x00, 0x00, 0x09, 0x00, 0xec, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
794 ];
795
796 let mut iter1 = VerNeedAuxIterator::new(LittleEndian, Class::ELF64, 2, 0, &data);
797 let mut iter2 = VerNeedAuxIterator::new(LittleEndian, Class::ELF64, 2, 0x10, &data);
798
799 let aux1_1 = iter1.next().expect("Failed to parse");
800 assert_eq!(
801 aux1_1,
802 VerNeedAux {
803 vna_hash: 0x0827e5c0,
804 vna_flags: 0,
805 vna_other: 0x0a,
806 vna_name: 0x0ccc,
807 vna_next: 0x20,
808 }
809 );
810 let aux2_1 = iter2.next().expect("Failed to parse");
811 assert_eq!(
812 aux2_1,
813 VerNeedAux {
814 vna_hash: 0x0d696913,
815 vna_flags: 0,
816 vna_other: 0x0c,
817 vna_name: 0x0cd7,
818 vna_next: 0x20
819 }
820 );
821 let aux1_2 = iter1.next().expect("Failed to parse");
822 assert_eq!(
823 aux1_2,
824 VerNeedAux {
825 vna_hash: 0x069691b3,
826 vna_flags: 0,
827 vna_other: 0x0b,
828 vna_name: 0x0ce1,
829 vna_next: 0
830 }
831 );
832 let aux2_2 = iter2.next().expect("Failed to parse");
833 assert_eq!(
834 aux2_2,
835 VerNeedAux {
836 vna_hash: 0x06969194,
837 vna_flags: 0,
838 vna_other: 0x09,
839 vna_name: 0x0cec,
840 vna_next: 0
841 }
842 );
843 assert!(iter1.next().is_none());
844 assert!(iter2.next().is_none());
845 }
846
847 #[test]
848 fn verneedaux_iter_early_termination_on_broken_next_link() {
849 let iter = VerNeedAuxIterator::new(LittleEndian, Class::ELF64, 7, 0x10, &GNU_VERNEED_DATA);
851 let entries: Vec<VerNeedAux> = iter.collect();
852
853 assert_eq!(entries.len(), 1);
855 }
856
857 #[rustfmt::skip]
858 const GNU_VERDEF_STRINGS: [u8; 34] = [
859 0x00, 0x4c, 0x49, 0x42, 0x43, 0x54, 0x46, 0x5f, 0x31, 0x2e, 0x30, 0x00,
861 0x4c, 0x49, 0x42, 0x43, 0x54, 0x46, 0x5f, 0x31, 0x2e, 0x31, 0x00,
863 0x4c, 0x49, 0x42, 0x43, 0x54, 0x46, 0x5f, 0x31, 0x2e, 0x32, 0x00,
865 ];
866
867 #[rustfmt::skip]
869 const GNU_VERDEF_DATA: [u8; 128] = [
870 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
872 0xb0, 0x7a, 0x07, 0x0b, 0x14, 0x00, 0x00, 0x00,
874 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
876 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
878 0x02, 0x00, 0x01, 0x00, 0x70, 0x2f, 0x8f, 0x08,
880 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
882 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
886 0x71, 0x2f, 0x8f, 0x08, 0x14, 0x00, 0x00, 0x00,
888 0x24, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
890 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
892 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
894 0x04, 0x00, 0x02, 0x00, 0x72, 0x2f, 0x8f, 0x08,
896 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
898 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
900 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
902 ];
903
904 #[test]
905 fn verdef_iter() {
906 let iter = VerDefIterator::new(LittleEndian, Class::ELF64, 4, 0, &GNU_VERDEF_DATA);
907 let entries: Vec<(VerDef, Vec<VerDefAux>)> =
908 iter.map(|(vd, iter)| (vd, iter.collect())).collect();
909
910 assert_eq!(entries.len(), 4);
911
912 assert_eq!(
913 entries,
914 vec![
915 (
916 VerDef {
917 vd_flags: 1,
918 vd_ndx: 1,
919 vd_cnt: 1,
920 vd_hash: 0x0B077AB0,
921 vd_aux: 20,
922 vd_next: 28,
923 },
924 vec![VerDefAux {
925 vda_name: 0x1,
926 vda_next: 0
927 }]
928 ),
929 (
930 VerDef {
931 vd_flags: 0,
932 vd_ndx: 2,
933 vd_cnt: 1,
934 vd_hash: 0x088f2f70,
935 vd_aux: 20,
936 vd_next: 28,
937 },
938 vec![VerDefAux {
939 vda_name: 0xC,
940 vda_next: 0
941 }]
942 ),
943 (
944 VerDef {
945 vd_flags: 0,
946 vd_ndx: 3,
947 vd_cnt: 2,
948 vd_hash: 0x088f2f71,
949 vd_aux: 20,
950 vd_next: 36,
951 },
952 vec![
953 VerDefAux {
954 vda_name: 0x17,
955 vda_next: 8
956 },
957 VerDefAux {
958 vda_name: 0xC,
959 vda_next: 0
960 }
961 ]
962 ),
963 (
964 VerDef {
965 vd_flags: 0,
966 vd_ndx: 4,
967 vd_cnt: 2,
968 vd_hash: 0x088f2f72,
969 vd_aux: 20,
970 vd_next: 0,
971 },
972 vec![
973 VerDefAux {
974 vda_name: 0xC,
975 vda_next: 8
976 },
977 VerDefAux {
978 vda_name: 0x17,
979 vda_next: 0
980 }
981 ]
982 ),
983 ]
984 );
985 }
986
987 #[test]
988 fn verdef_iter_early_termination_on_broken_next_link() {
989 let iter = VerDefIterator::new(LittleEndian, Class::ELF64, 7, 0, &GNU_VERDEF_DATA);
991 let entries: Vec<(VerDef, Vec<VerDefAux>)> =
992 iter.map(|(vn, iter)| (vn, iter.collect())).collect();
993
994 assert_eq!(entries.len(), 4);
996 }
997
998 #[test]
999 fn verdefaux_iter_one_entry() {
1000 let mut iter =
1001 VerDefAuxIterator::new(LittleEndian, Class::ELF64, 1, 0x14, &GNU_VERDEF_DATA);
1002 let aux1 = iter.next().expect("Failed to parse");
1003 assert_eq!(
1004 aux1,
1005 VerDefAux {
1006 vda_name: 0x01,
1007 vda_next: 0
1008 }
1009 );
1010 assert!(iter.next().is_none());
1011 }
1012
1013 #[test]
1014 fn verdefaux_iter_multiple_entries() {
1015 let mut iter =
1016 VerDefAuxIterator::new(LittleEndian, Class::ELF64, 2, 0x4C, &GNU_VERDEF_DATA);
1017 let aux1 = iter.next().expect("Failed to parse");
1018 assert_eq!(
1019 aux1,
1020 VerDefAux {
1021 vda_name: 0x17,
1022 vda_next: 8
1023 }
1024 );
1025 let aux1 = iter.next().expect("Failed to parse");
1026 assert_eq!(
1027 aux1,
1028 VerDefAux {
1029 vda_name: 0xC,
1030 vda_next: 0
1031 }
1032 );
1033 assert!(iter.next().is_none());
1034 }
1035
1036 #[test]
1038 fn verdefaux_iter_two_lists_interspersed() {
1039 #[rustfmt::skip]
1040 let data: [u8; 32] = [
1041 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1046
1047 let mut iter1 = VerDefAuxIterator::new(LittleEndian, Class::ELF64, 2, 0, &data);
1048 let mut iter2 = VerDefAuxIterator::new(LittleEndian, Class::ELF64, 2, 8, &data);
1049
1050 let aux1_1 = iter1.next().expect("Failed to parse");
1051 assert_eq!(
1052 aux1_1,
1053 VerDefAux {
1054 vda_name: 0x0001,
1055 vda_next: 0x10,
1056 }
1057 );
1058 let aux2_1 = iter2.next().expect("Failed to parse");
1059 assert_eq!(
1060 aux2_1,
1061 VerDefAux {
1062 vda_name: 0x00A1,
1063 vda_next: 0x10,
1064 }
1065 );
1066 let aux1_2 = iter1.next().expect("Failed to parse");
1067 assert_eq!(
1068 aux1_2,
1069 VerDefAux {
1070 vda_name: 0x0002,
1071 vda_next: 0,
1072 }
1073 );
1074 let aux2_2 = iter2.next().expect("Failed to parse");
1075 assert_eq!(
1076 aux2_2,
1077 VerDefAux {
1078 vda_name: 0x00A2,
1079 vda_next: 0,
1080 }
1081 );
1082 assert!(iter1.next().is_none());
1083 assert!(iter2.next().is_none());
1084 }
1085
1086 #[test]
1087 fn verdefaux_iter_early_termination_on_broken_next_link() {
1088 let iter = VerDefAuxIterator::new(LittleEndian, Class::ELF64, 7, 0x14, &GNU_VERDEF_DATA);
1090 let entries: Vec<VerDefAux> = iter.collect();
1091
1092 assert_eq!(entries.len(), 1);
1094 }
1095
1096 #[test]
1097 fn version_table() {
1098 let ver_idx_buf: [u8; 10] = [0x02, 0x00, 0x03, 0x00, 0x09, 0x00, 0x0A, 0x00, 0xff, 0xff];
1099 let version_ids = VersionIndexTable::new(LittleEndian, Class::ELF64, &ver_idx_buf);
1100 let verdefs = VerDefIterator::new(LittleEndian, Class::ELF64, 4, 0, &GNU_VERDEF_DATA);
1101 let verneed_strs = StringTable::new(&GNU_VERNEED_STRINGS);
1102 let verneeds = VerNeedIterator::new(LittleEndian, Class::ELF64, 2, 0, &GNU_VERNEED_DATA);
1103 let verdef_strs = StringTable::new(&GNU_VERDEF_STRINGS);
1104
1105 let table = SymbolVersionTable::new(
1106 version_ids,
1107 Some((verneeds, verneed_strs)),
1108 Some((verdefs, verdef_strs)),
1109 );
1110
1111 let def1 = table
1112 .get_definition(0)
1113 .expect("Failed to parse definition")
1114 .expect("Failed to find def");
1115 assert_eq!(def1.hash, 0x088f2f70);
1116 assert_eq!(def1.flags, 0);
1117 let def1_names: Vec<&str> = def1
1118 .names
1119 .map(|res| res.expect("Failed to parse"))
1120 .collect();
1121 assert_eq!(def1_names, ["LIBCTF_1.1"]);
1122 assert!(!def1.hidden);
1123
1124 let def2 = table
1125 .get_definition(1)
1126 .expect("Failed to parse definition")
1127 .expect("Failed to find def");
1128 assert_eq!(def2.hash, 0x088f2f71);
1129 assert_eq!(def2.flags, 0);
1130 let def2_names: Vec<&str> = def2
1131 .names
1132 .map(|res| res.expect("Failed to parse"))
1133 .collect();
1134 assert_eq!(def2_names, ["LIBCTF_1.2", "LIBCTF_1.1"]);
1135 assert!(!def2.hidden);
1136
1137 let req1 = table
1138 .get_requirement(2)
1139 .expect("Failed to parse definition")
1140 .expect("Failed to find req");
1141 assert_eq!(
1142 req1,
1143 SymbolRequirement {
1144 file: "libc.so.6",
1145 name: "GLIBC_2.3",
1146 hash: 0x6969194,
1147 flags: 0,
1148 hidden: false
1149 }
1150 );
1151
1152 let req2 = table
1153 .get_requirement(3)
1154 .expect("Failed to parse definition")
1155 .expect("Failed to find req");
1156 assert_eq!(
1157 req2,
1158 SymbolRequirement {
1159 file: "libz.so.1",
1160 name: "ZLIB_1.2.0",
1161 hash: 0x827E5C0,
1162 flags: 0,
1163 hidden: false
1164 }
1165 );
1166
1167 assert!(table.get_definition(4).expect("Failed to parse").is_none());
1172 assert!(table.get_requirement(4).expect("Failed to parse").is_none());
1173 }
1174}
1175
1176#[cfg(test)]
1177mod parse_tests {
1178 use super::*;
1179 use crate::endian::{BigEndian, LittleEndian};
1180 use crate::parse::{test_parse_for, test_parse_fuzz_too_short};
1181
1182 #[test]
1183 fn parse_verndx32_lsb() {
1184 test_parse_for(LittleEndian, Class::ELF32, VersionIndex(0x0100));
1185 }
1186
1187 #[test]
1188 fn parse_verndx32_msb() {
1189 test_parse_for(BigEndian, Class::ELF32, VersionIndex(0x0001));
1190 }
1191
1192 #[test]
1193 fn parse_verndx64_lsb() {
1194 test_parse_for(LittleEndian, Class::ELF64, VersionIndex(0x0100));
1195 }
1196
1197 #[test]
1198 fn parse_verndx64_msb() {
1199 test_parse_for(BigEndian, Class::ELF64, VersionIndex(0x0001));
1200 }
1201
1202 #[test]
1203 fn parse_verndx32_lsb_fuzz_too_short() {
1204 test_parse_fuzz_too_short::<_, VersionIndex>(LittleEndian, Class::ELF32);
1205 }
1206
1207 #[test]
1208 fn parse_verndx32_msb_fuzz_too_short() {
1209 test_parse_fuzz_too_short::<_, VersionIndex>(BigEndian, Class::ELF32);
1210 }
1211
1212 #[test]
1213 fn parse_verndx64_lsb_fuzz_too_short() {
1214 test_parse_fuzz_too_short::<_, VersionIndex>(LittleEndian, Class::ELF64);
1215 }
1216
1217 #[test]
1218 fn parse_verndx64_msb_fuzz_too_short() {
1219 test_parse_fuzz_too_short::<_, VersionIndex>(BigEndian, Class::ELF64);
1220 }
1221
1222 #[test]
1226 fn parse_verdef32_lsb() {
1227 let mut data = [0u8; ELFVERDEFSIZE];
1228 for (n, elem) in data.iter_mut().enumerate().take(ELFVERDEFSIZE) {
1229 *elem = n as u8;
1230 }
1231 data[0] = 1;
1232 data[1] = 0;
1233
1234 let mut offset = 0;
1235 let entry = VerDef::parse_at(LittleEndian, Class::ELF32, &mut offset, data.as_ref())
1236 .expect("Failed to parse VerDef");
1237
1238 assert_eq!(
1239 entry,
1240 VerDef {
1241 vd_flags: 0x0302,
1242 vd_ndx: 0x0504,
1243 vd_cnt: 0x0706,
1244 vd_hash: 0x0B0A0908,
1245 vd_aux: 0x0F0E0D0C,
1246 vd_next: 0x13121110,
1247 }
1248 );
1249 assert_eq!(offset, ELFVERDEFSIZE);
1250 }
1251
1252 #[test]
1253 fn parse_verdef32_fuzz_too_short() {
1254 let mut data = [0u8; ELFVERDEFSIZE];
1255 data[1] = 1;
1256 for n in 0..ELFVERDEFSIZE {
1257 let buf = data.split_at(n).0;
1258 let mut offset: usize = 0;
1259 let error = VerDef::parse_at(BigEndian, Class::ELF32, &mut offset, buf)
1260 .expect_err("Expected an error");
1261 assert!(
1262 matches!(error, ParseError::SliceReadError(_)),
1263 "Unexpected Error type found: {error}"
1264 );
1265 }
1266 }
1267
1268 #[test]
1269 fn parse_verdef64_msb() {
1270 let mut data = [0u8; ELFVERDEFSIZE];
1271 for (n, elem) in data.iter_mut().enumerate().take(ELFVERDEFSIZE).skip(2) {
1272 *elem = n as u8;
1273 }
1274 data[1] = 1;
1275
1276 let mut offset = 0;
1277 let entry = VerDef::parse_at(BigEndian, Class::ELF64, &mut offset, data.as_ref())
1278 .expect("Failed to parse VerDef");
1279
1280 assert_eq!(
1281 entry,
1282 VerDef {
1283 vd_flags: 0x0203,
1284 vd_ndx: 0x0405,
1285 vd_cnt: 0x0607,
1286 vd_hash: 0x08090A0B,
1287 vd_aux: 0x0C0D0E0F,
1288 vd_next: 0x10111213,
1289 }
1290 );
1291 assert_eq!(offset, ELFVERDEFSIZE);
1292 }
1293
1294 #[test]
1295 fn parse_verdef64_fuzz_too_short() {
1296 let mut data = [0u8; ELFVERDEFSIZE];
1297 data[1] = 1;
1298 for n in 0..ELFVERDEFSIZE {
1299 let buf = data.split_at(n).0;
1300 let mut offset: usize = 0;
1301 let error = VerDef::parse_at(BigEndian, Class::ELF64, &mut offset, buf)
1302 .expect_err("Expected an error");
1303 assert!(
1304 matches!(error, ParseError::SliceReadError(_)),
1305 "Unexpected Error type found: {error}"
1306 );
1307 }
1308 }
1309
1310 #[test]
1311 fn parse_verdef_bad_version_errors() {
1312 let data = [0u8; ELFVERDEFSIZE];
1313 let mut offset = 0;
1316 let err = VerDef::parse_at(BigEndian, Class::ELF64, &mut offset, data.as_ref())
1317 .expect_err("Expected an error");
1318 assert!(
1319 matches!(err, ParseError::UnsupportedVersion((0, 1))),
1320 "Unexpected Error type found: {err}"
1321 );
1322 }
1323
1324 #[test]
1328 fn parse_verdefaux32_lsb() {
1329 test_parse_for(
1330 LittleEndian,
1331 Class::ELF32,
1332 VerDefAux {
1333 vda_name: 0x03020100,
1334 vda_next: 0x07060504,
1335 },
1336 );
1337 }
1338
1339 #[test]
1340 fn parse_verdefaux32_msb() {
1341 test_parse_for(
1342 BigEndian,
1343 Class::ELF32,
1344 VerDefAux {
1345 vda_name: 0x00010203,
1346 vda_next: 0x04050607,
1347 },
1348 );
1349 }
1350
1351 #[test]
1352 fn parse_verdefaux64_lsb() {
1353 test_parse_for(
1354 LittleEndian,
1355 Class::ELF64,
1356 VerDefAux {
1357 vda_name: 0x03020100,
1358 vda_next: 0x07060504,
1359 },
1360 );
1361 }
1362
1363 #[test]
1364 fn parse_verdefaux64_msb() {
1365 test_parse_for(
1366 BigEndian,
1367 Class::ELF64,
1368 VerDefAux {
1369 vda_name: 0x00010203,
1370 vda_next: 0x04050607,
1371 },
1372 );
1373 }
1374
1375 #[test]
1376 fn parse_verdefaux32_lsb_fuzz_too_short() {
1377 test_parse_fuzz_too_short::<_, VerDefAux>(LittleEndian, Class::ELF32);
1378 }
1379
1380 #[test]
1381 fn parse_verdefaux32_msb_fuzz_too_short() {
1382 test_parse_fuzz_too_short::<_, VerDefAux>(BigEndian, Class::ELF32);
1383 }
1384
1385 #[test]
1386 fn parse_verdefaux64_lsb_fuzz_too_short() {
1387 test_parse_fuzz_too_short::<_, VerDefAux>(LittleEndian, Class::ELF64);
1388 }
1389
1390 #[test]
1391 fn parse_verdefaux64_msb_fuzz_too_short() {
1392 test_parse_fuzz_too_short::<_, VerDefAux>(BigEndian, Class::ELF64);
1393 }
1394
1395 #[test]
1399 fn parse_verneed32_lsb() {
1400 let mut data = [0u8; ELFVERNEEDSIZE];
1401 for (n, elem) in data.iter_mut().enumerate().take(ELFVERNEEDSIZE) {
1402 *elem = n as u8;
1403 }
1404 data[0] = 1;
1405 data[1] = 0;
1406
1407 let mut offset = 0;
1408 let entry = VerNeed::parse_at(LittleEndian, Class::ELF32, &mut offset, data.as_ref())
1409 .expect("Failed to parse VerNeed");
1410
1411 assert_eq!(
1412 entry,
1413 VerNeed {
1414 vn_cnt: 0x0302,
1415 vn_file: 0x07060504,
1416 vn_aux: 0x0B0A0908,
1417 vn_next: 0x0F0E0D0C,
1418 }
1419 );
1420 assert_eq!(offset, ELFVERNEEDSIZE);
1421 }
1422
1423 #[test]
1424 fn parse_verneed32_fuzz_too_short() {
1425 let mut data = [0u8; ELFVERNEEDSIZE];
1426 data[1] = 1;
1427 for n in 0..ELFVERNEEDSIZE {
1428 let buf = data.split_at(n).0;
1429 let mut offset: usize = 0;
1430 let error = VerNeed::parse_at(BigEndian, Class::ELF32, &mut offset, buf)
1431 .expect_err("Expected an error");
1432 assert!(
1433 matches!(error, ParseError::SliceReadError(_)),
1434 "Unexpected Error type found: {error}"
1435 );
1436 }
1437 }
1438
1439 #[test]
1440 fn parse_verneed64_msb() {
1441 let mut data = [0u8; ELFVERNEEDSIZE];
1442 for (n, elem) in data.iter_mut().enumerate().take(ELFVERNEEDSIZE) {
1443 *elem = n as u8;
1444 }
1445 data[1] = 1;
1446
1447 let mut offset = 0;
1448 let entry = VerNeed::parse_at(BigEndian, Class::ELF64, &mut offset, data.as_ref())
1449 .expect("Failed to parse VerNeed");
1450
1451 assert_eq!(
1452 entry,
1453 VerNeed {
1454 vn_cnt: 0x0203,
1455 vn_file: 0x04050607,
1456 vn_aux: 0x08090A0B,
1457 vn_next: 0x0C0D0E0F,
1458 }
1459 );
1460 assert_eq!(offset, ELFVERNEEDSIZE);
1461 }
1462
1463 #[test]
1464 fn parse_verneed64_fuzz_too_short() {
1465 let mut data = [0u8; ELFVERNEEDSIZE];
1466 data[1] = 1;
1467 for n in 0..ELFVERNEEDSIZE {
1468 let buf = data.split_at(n).0;
1469 let mut offset: usize = 0;
1470 let error = VerNeed::parse_at(BigEndian, Class::ELF64, &mut offset, buf)
1471 .expect_err("Expected an error");
1472 assert!(
1473 matches!(error, ParseError::SliceReadError(_)),
1474 "Unexpected Error type found: {error}"
1475 );
1476 }
1477 }
1478
1479 #[test]
1483 fn parse_verneedaux32_lsb() {
1484 test_parse_for(
1485 LittleEndian,
1486 Class::ELF32,
1487 VerNeedAux {
1488 vna_hash: 0x03020100,
1489 vna_flags: 0x0504,
1490 vna_other: 0x0706,
1491 vna_name: 0x0B0A0908,
1492 vna_next: 0x0F0E0D0C,
1493 },
1494 );
1495 }
1496
1497 #[test]
1498 fn parse_verneedaux32_msb() {
1499 test_parse_for(
1500 BigEndian,
1501 Class::ELF32,
1502 VerNeedAux {
1503 vna_hash: 0x00010203,
1504 vna_flags: 0x0405,
1505 vna_other: 0x0607,
1506 vna_name: 0x08090A0B,
1507 vna_next: 0x0C0D0E0F,
1508 },
1509 );
1510 }
1511
1512 #[test]
1513 fn parse_verneedaux64_lsb() {
1514 test_parse_for(
1515 LittleEndian,
1516 Class::ELF64,
1517 VerNeedAux {
1518 vna_hash: 0x03020100,
1519 vna_flags: 0x0504,
1520 vna_other: 0x0706,
1521 vna_name: 0x0B0A0908,
1522 vna_next: 0x0F0E0D0C,
1523 },
1524 );
1525 }
1526
1527 #[test]
1528 fn parse_verneedaux64_msb() {
1529 test_parse_for(
1530 BigEndian,
1531 Class::ELF64,
1532 VerNeedAux {
1533 vna_hash: 0x00010203,
1534 vna_flags: 0x0405,
1535 vna_other: 0x0607,
1536 vna_name: 0x08090A0B,
1537 vna_next: 0x0C0D0E0F,
1538 },
1539 );
1540 }
1541
1542 #[test]
1543 fn parse_verneedaux32_lsb_fuzz_too_short() {
1544 test_parse_fuzz_too_short::<_, VerNeedAux>(LittleEndian, Class::ELF32);
1545 }
1546
1547 #[test]
1548 fn parse_verneedaux32_msb_fuzz_too_short() {
1549 test_parse_fuzz_too_short::<_, VerNeedAux>(BigEndian, Class::ELF32);
1550 }
1551
1552 #[test]
1553 fn parse_verneedaux64_lsb_fuzz_too_short() {
1554 test_parse_fuzz_too_short::<_, VerNeedAux>(LittleEndian, Class::ELF64);
1555 }
1556
1557 #[test]
1558 fn parse_verneedaux64_msb_fuzz_too_short() {
1559 test_parse_fuzz_too_short::<_, VerNeedAux>(BigEndian, Class::ELF64);
1560 }
1561}
1562
1563#[cfg(test)]
1564mod version_index_tests {
1565 use super::*;
1566
1567 #[test]
1568 fn is_local() {
1569 let idx = VersionIndex(0);
1570 assert!(idx.is_local());
1571 }
1572
1573 #[test]
1574 fn is_global() {
1575 let idx = VersionIndex(1);
1576 assert!(idx.is_global());
1577 }
1578
1579 #[test]
1580 fn index_visible() {
1581 let idx = VersionIndex(42);
1582 assert_eq!(idx.index(), 42);
1583 assert!(!idx.is_hidden());
1584 }
1585
1586 #[test]
1587 fn index_hidden() {
1588 let idx = VersionIndex(42 | abi::VER_NDX_HIDDEN);
1589 assert_eq!(idx.index(), 42);
1590 assert!(idx.is_hidden());
1591 }
1592}