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)]
10pub struct VersionIndex(pub u16);
11
12impl VersionIndex {
13 pub fn index(&self) -> u16 {
15 self.0 & elf::VERSYM_VERSION
16 }
17
18 pub fn is_local(&self) -> bool {
20 self.index() == elf::VER_NDX_LOCAL
21 }
22
23 pub fn is_global(&self) -> bool {
25 self.index() == elf::VER_NDX_GLOBAL
26 }
27
28 pub fn is_hidden(&self) -> bool {
30 self.0 & elf::VERSYM_HIDDEN != 0
31 }
32}
33
34#[derive(Debug, Default, Clone, Copy)]
38pub struct Version<'data> {
39 name: &'data [u8],
40 hash: u32,
41 valid: bool,
43 file: Option<&'data [u8]>,
44}
45
46impl<'data> Version<'data> {
47 pub fn name(&self) -> &'data [u8] {
49 self.name
50 }
51
52 pub fn hash(&self) -> u32 {
54 self.hash
55 }
56
57 pub fn file(&self) -> Option<&'data [u8]> {
62 self.file
63 }
64}
65
66#[derive(Debug, Clone)]
75pub struct VersionTable<'data, Elf: FileHeader> {
76 symbols: &'data [elf::Versym<Elf::Endian>],
77 versions: Vec<Version<'data>>,
78}
79
80impl<'data, Elf: FileHeader> Default for VersionTable<'data, Elf> {
81 fn default() -> Self {
82 VersionTable {
83 symbols: &[],
84 versions: Vec::new(),
85 }
86 }
87}
88
89impl<'data, Elf: FileHeader> VersionTable<'data, Elf> {
90 pub fn parse<R: ReadRef<'data>>(
92 endian: Elf::Endian,
93 versyms: &'data [elf::Versym<Elf::Endian>],
94 verdefs: Option<VerdefIterator<'data, Elf>>,
95 verneeds: Option<VerneedIterator<'data, Elf>>,
96 strings: StringTable<'data, R>,
97 ) -> Result<Self> {
98 let mut max_index = 0;
99 if let Some(mut verdefs) = verdefs.clone() {
100 while let Some((verdef, _)) = verdefs.next()? {
101 if verdef.vd_flags.get(endian) & elf::VER_FLG_BASE != 0 {
102 continue;
103 }
104 let index = verdef.vd_ndx.get(endian) & elf::VERSYM_VERSION;
105 if max_index < index {
106 max_index = index;
107 }
108 }
109 }
110 if let Some(mut verneeds) = verneeds.clone() {
111 while let Some((_, mut vernauxs)) = verneeds.next()? {
112 while let Some(vernaux) = vernauxs.next()? {
113 let index = vernaux.vna_other.get(endian) & elf::VERSYM_VERSION;
114 if max_index < index {
115 max_index = index;
116 }
117 }
118 }
119 }
120
121 let mut versions = vec![Version::default(); max_index as usize + 1];
124
125 if let Some(mut verdefs) = verdefs {
126 while let Some((verdef, mut verdauxs)) = verdefs.next()? {
127 if verdef.vd_flags.get(endian) & elf::VER_FLG_BASE != 0 {
128 continue;
129 }
130 let index = verdef.vd_ndx.get(endian) & elf::VERSYM_VERSION;
131 if index <= elf::VER_NDX_GLOBAL {
132 continue;
134 }
135 if let Some(verdaux) = verdauxs.next()? {
136 versions[usize::from(index)] = Version {
137 name: verdaux.name(endian, strings)?,
138 hash: verdef.vd_hash.get(endian),
139 valid: true,
140 file: None,
141 };
142 }
143 }
144 }
145 if let Some(mut verneeds) = verneeds {
146 while let Some((verneed, mut vernauxs)) = verneeds.next()? {
147 while let Some(vernaux) = vernauxs.next()? {
148 let index = vernaux.vna_other.get(endian) & elf::VERSYM_VERSION;
149 if index <= elf::VER_NDX_GLOBAL {
150 continue;
152 }
153 versions[usize::from(index)] = Version {
154 name: vernaux.name(endian, strings)?,
155 hash: vernaux.vna_hash.get(endian),
156 valid: true,
157 file: Some(verneed.file(endian, strings)?),
158 };
159 }
160 }
161 }
162
163 Ok(VersionTable {
164 symbols: versyms,
165 versions,
166 })
167 }
168
169 pub fn is_empty(&self) -> bool {
171 self.symbols.is_empty()
172 }
173
174 pub fn version_index(&self, endian: Elf::Endian, index: SymbolIndex) -> VersionIndex {
176 let version_index = match self.symbols.get(index.0) {
177 Some(x) => x.0.get(endian),
178 None => elf::VER_NDX_GLOBAL,
181 };
182 VersionIndex(version_index)
183 }
184
185 pub fn version(&self, index: VersionIndex) -> Result<Option<&Version<'data>>> {
190 if index.index() <= elf::VER_NDX_GLOBAL {
191 return Ok(None);
192 }
193 self.versions
194 .get(usize::from(index.index()))
195 .filter(|version| version.valid)
196 .read_error("Invalid ELF symbol version index")
197 .map(Some)
198 }
199
200 pub fn matches(
206 &self,
207 endian: Elf::Endian,
208 index: SymbolIndex,
209 need: Option<&Version<'_>>,
210 ) -> bool {
211 let version_index = self.version_index(endian, index);
212 let def = match self.version(version_index) {
213 Ok(def) => def,
214 Err(_) => return false,
215 };
216 match (def, need) {
217 (Some(def), Some(need)) => need.hash == def.hash && need.name == def.name,
218 (None, Some(_need)) => {
219 false
221 }
222 (Some(_def), None) => {
223 !version_index.is_hidden()
226 }
227 (None, None) => true,
228 }
229 }
230}
231
232#[derive(Debug, Clone)]
234pub struct VerdefIterator<'data, Elf: FileHeader> {
235 endian: Elf::Endian,
236 data: Bytes<'data>,
237}
238
239impl<'data, Elf: FileHeader> VerdefIterator<'data, Elf> {
240 pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self {
241 VerdefIterator {
242 endian,
243 data: Bytes(data),
244 }
245 }
246
247 pub fn next(
249 &mut self,
250 ) -> Result<Option<(&'data elf::Verdef<Elf::Endian>, VerdauxIterator<'data, Elf>)>> {
251 if self.data.is_empty() {
252 return Ok(None);
253 }
254
255 let result = self.parse().map(Some);
256 if result.is_err() {
257 self.data = Bytes(&[]);
258 }
259 result
260 }
261
262 fn parse(&mut self) -> Result<(&'data elf::Verdef<Elf::Endian>, VerdauxIterator<'data, Elf>)> {
263 let verdef = self
264 .data
265 .read_at::<elf::Verdef<_>>(0)
266 .read_error("ELF verdef is too short")?;
267
268 let mut verdaux_data = self.data;
269 verdaux_data
270 .skip(verdef.vd_aux.get(self.endian) as usize)
271 .read_error("Invalid ELF vd_aux")?;
272 let verdaux =
273 VerdauxIterator::new(self.endian, verdaux_data.0, verdef.vd_cnt.get(self.endian));
274
275 let next = verdef.vd_next.get(self.endian);
276 if next != 0 {
277 self.data
278 .skip(next as usize)
279 .read_error("Invalid ELF vd_next")?;
280 } else {
281 self.data = Bytes(&[]);
282 }
283 Ok((verdef, verdaux))
284 }
285}
286
287impl<'data, Elf: FileHeader> Iterator for VerdefIterator<'data, Elf> {
288 type Item = Result<(&'data elf::Verdef<Elf::Endian>, VerdauxIterator<'data, Elf>)>;
289
290 fn next(&mut self) -> Option<Self::Item> {
291 self.next().transpose()
292 }
293}
294
295#[derive(Debug, Clone)]
297pub struct VerdauxIterator<'data, Elf: FileHeader> {
298 endian: Elf::Endian,
299 data: Bytes<'data>,
300 count: u16,
301}
302
303impl<'data, Elf: FileHeader> VerdauxIterator<'data, Elf> {
304 pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self {
305 VerdauxIterator {
306 endian,
307 data: Bytes(data),
308 count,
309 }
310 }
311
312 pub fn next(&mut self) -> Result<Option<&'data elf::Verdaux<Elf::Endian>>> {
314 if self.count == 0 {
315 return Ok(None);
316 }
317
318 let result = self.parse().map(Some);
319 if result.is_err() {
320 self.count = 0;
321 } else {
322 self.count -= 1;
323 }
324 result
325 }
326
327 fn parse(&mut self) -> Result<&'data elf::Verdaux<Elf::Endian>> {
328 let verdaux = self
329 .data
330 .read_at::<elf::Verdaux<_>>(0)
331 .read_error("ELF verdaux is too short")?;
332
333 self.data
334 .skip(verdaux.vda_next.get(self.endian) as usize)
335 .read_error("Invalid ELF vda_next")?;
336 Ok(verdaux)
337 }
338}
339
340impl<'data, Elf: FileHeader> Iterator for VerdauxIterator<'data, Elf> {
341 type Item = Result<&'data elf::Verdaux<Elf::Endian>>;
342
343 fn next(&mut self) -> Option<Self::Item> {
344 self.next().transpose()
345 }
346}
347
348#[derive(Debug, Clone)]
350pub struct VerneedIterator<'data, Elf: FileHeader> {
351 endian: Elf::Endian,
352 data: Bytes<'data>,
353}
354
355impl<'data, Elf: FileHeader> VerneedIterator<'data, Elf> {
356 pub(super) fn new(endian: Elf::Endian, data: &'data [u8]) -> Self {
357 VerneedIterator {
358 endian,
359 data: Bytes(data),
360 }
361 }
362
363 pub fn next(
365 &mut self,
366 ) -> Result<
367 Option<(
368 &'data elf::Verneed<Elf::Endian>,
369 VernauxIterator<'data, Elf>,
370 )>,
371 > {
372 if self.data.is_empty() {
373 return Ok(None);
374 }
375
376 let result = self.parse().map(Some);
377 if result.is_err() {
378 self.data = Bytes(&[]);
379 }
380 result
381 }
382
383 fn parse(
384 &mut self,
385 ) -> Result<(
386 &'data elf::Verneed<Elf::Endian>,
387 VernauxIterator<'data, Elf>,
388 )> {
389 let verneed = self
390 .data
391 .read_at::<elf::Verneed<_>>(0)
392 .read_error("ELF verneed is too short")?;
393
394 let mut vernaux_data = self.data;
395 vernaux_data
396 .skip(verneed.vn_aux.get(self.endian) as usize)
397 .read_error("Invalid ELF vn_aux")?;
398 let vernaux =
399 VernauxIterator::new(self.endian, vernaux_data.0, verneed.vn_cnt.get(self.endian));
400
401 let next = verneed.vn_next.get(self.endian);
402 if next != 0 {
403 self.data
404 .skip(next as usize)
405 .read_error("Invalid ELF vn_next")?;
406 } else {
407 self.data = Bytes(&[]);
408 }
409 Ok((verneed, vernaux))
410 }
411}
412
413impl<'data, Elf: FileHeader> Iterator for VerneedIterator<'data, Elf> {
414 type Item = Result<(
415 &'data elf::Verneed<Elf::Endian>,
416 VernauxIterator<'data, Elf>,
417 )>;
418
419 fn next(&mut self) -> Option<Self::Item> {
420 self.next().transpose()
421 }
422}
423
424#[derive(Debug, Clone)]
426pub struct VernauxIterator<'data, Elf: FileHeader> {
427 endian: Elf::Endian,
428 data: Bytes<'data>,
429 count: u16,
430}
431
432impl<'data, Elf: FileHeader> VernauxIterator<'data, Elf> {
433 pub(super) fn new(endian: Elf::Endian, data: &'data [u8], count: u16) -> Self {
434 VernauxIterator {
435 endian,
436 data: Bytes(data),
437 count,
438 }
439 }
440
441 pub fn next(&mut self) -> Result<Option<&'data elf::Vernaux<Elf::Endian>>> {
443 if self.count == 0 {
444 return Ok(None);
445 }
446
447 let result = self.parse().map(Some);
448 if result.is_err() {
449 self.count = 0;
450 } else {
451 self.count -= 1;
452 }
453 result
454 }
455
456 fn parse(&mut self) -> Result<&'data elf::Vernaux<Elf::Endian>> {
457 let vernaux = self
458 .data
459 .read_at::<elf::Vernaux<_>>(0)
460 .read_error("ELF vernaux is too short")?;
461 self.data
462 .skip(vernaux.vna_next.get(self.endian) as usize)
463 .read_error("Invalid ELF vna_next")?;
464 Ok(vernaux)
465 }
466}
467
468impl<'data, Elf: FileHeader> Iterator for VernauxIterator<'data, Elf> {
469 type Item = Result<&'data elf::Vernaux<Elf::Endian>>;
470
471 fn next(&mut self) -> Option<Self::Item> {
472 self.next().transpose()
473 }
474}
475
476impl<Endian: endian::Endian> elf::Verdaux<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.vda_name.get(endian))
485 .read_error("Invalid ELF vda_name")
486 }
487}
488
489impl<Endian: endian::Endian> elf::Verneed<Endian> {
490 pub fn file<'data, R: ReadRef<'data>>(
492 &self,
493 endian: Endian,
494 strings: StringTable<'data, R>,
495 ) -> Result<&'data [u8]> {
496 strings
497 .get(self.vn_file.get(endian))
498 .read_error("Invalid ELF vn_file")
499 }
500}
501
502impl<Endian: endian::Endian> elf::Vernaux<Endian> {
503 pub fn name<'data, R: ReadRef<'data>>(
505 &self,
506 endian: Endian,
507 strings: StringTable<'data, R>,
508 ) -> Result<&'data [u8]> {
509 strings
510 .get(self.vna_name.get(endian))
511 .read_error("Invalid ELF vna_name")
512 }
513}