/// A version definition or requirement. /// /// This is derived from entries in the [`elf::SHT_GNU_VERDEF`] and [`elf::SHT_GNU_VERNEED`] sections. #[derive(Debug, Default, Clone, Copy)] pubstruct Version<'data> {
name: &'data [u8],
hash: u32, // Used to keep track of valid indices in `VersionTable`.
valid: bool,
file: Option<&'data [u8]>,
}
impl<'data> Version<'data> { /// Return the version name. pubfn name(&self) -> &'data [u8] { self.name
}
/// Return hash of the version name. pubfn hash(&self) -> u32 { self.hash
}
/// Return the filename of the library containing this version. /// /// This is the `vn_file` field of the associated entry in [`elf::SHT_GNU_VERNEED`]. /// or `None` if the version info was parsed from a [`elf::SHT_GNU_VERDEF`] section. pubfn file(&self) -> Option<&'data [u8]> { self.file
}
}
/// A table of version definitions and requirements. /// /// It allows looking up the version information for a given symbol index. /// /// This is derived from entries in the [`elf::SHT_GNU_VERSYM`], [`elf::SHT_GNU_VERDEF`] /// and [`elf::SHT_GNU_VERNEED`] sections. /// /// Returned by [`SectionTable::versions`](super::SectionTable::versions). #[derive(Debug, Clone)] pubstruct VersionTable<'data, Elf: FileHeader> {
symbols: &'data [elf::Versym<Elf::Endian>],
versions: Vec<Version<'data>>,
}
impl<'data, Elf: FileHeader> VersionTable<'data, Elf> { /// Parse the version sections. pubfn parse<R: ReadRef<'data>>(
endian: Elf::Endian,
versyms: &'data [elf::Versym<Elf::Endian>],
verdefs: Option<VerdefIterator<'data, Elf>>,
verneeds: Option<VerneedIterator<'data, Elf>>,
strings: StringTable<'data, R>,
) -> Result<Self> { letmut max_index = 0; iflet Some(mut verdefs) = verdefs.clone() { whilelet Some((verdef, _)) = verdefs.next()? { if verdef.vd_flags.get(endian) & elf::VER_FLG_BASE != 0 { continue;
} let index = verdef.vd_ndx.get(endian) & elf::VERSYM_VERSION; if max_index < index {
max_index = index;
}
}
} iflet Some(mut verneeds) = verneeds.clone() { whilelet Some((_, mut vernauxs)) = verneeds.next()? { whilelet Some(vernaux) = vernauxs.next()? { let index = vernaux.vna_other.get(endian) & elf::VERSYM_VERSION; if max_index < index {
max_index = index;
}
}
}
}
// Indices should be sequential, but this could be up to // 32k * size_of::<Version>() if max_index is bad. letmut versions = vec![Version::default(); max_index as usize + 1];
/// Return true if the version table is empty. pubfn is_empty(&self) -> bool { self.symbols.is_empty()
}
/// Return version index for a given symbol index. pubfn version_index(&self, endian: Elf::Endian, index: SymbolIndex) -> VersionIndex { let version_index = matchself.symbols.get(index.0) {
Some(x) => x.0.get(endian), // Ideally this would be VER_NDX_LOCAL for undefined symbols, // but currently there are no checks that need this distinction.
None => elf::VER_NDX_GLOBAL,
};
VersionIndex(version_index)
}
/// Return version information for a given symbol version index. /// /// Returns `Ok(None)` for local and global versions. /// Returns `Err(_)` if index is invalid. pubfn version(&self, index: VersionIndex) -> Result<Option<&Version<'data>>> { if index.index() <= elf::VER_NDX_GLOBAL { return Ok(None);
} self.versions
.get(usize::from(index.index()))
.filter(|version| version.valid)
.read_error("Invalid ELF symbol version index")
.map(Some)
}
/// Return true if the given symbol index satisfies the requirements of `need`. /// /// Returns false for any error. /// /// Note: this function hasn't been fully tested and is likely to be incomplete. pubfn matches(
&self,
endian: Elf::Endian,
index: SymbolIndex,
need: Option<&Version<'_>>,
) -> bool { let version_index = self.version_index(endian, index); let def = matchself.version(version_index) {
Ok(def) => def,
Err(_) => returnfalse,
}; match (def, need) {
(Some(def), Some(need)) => need.hash == def.hash && need.name == def.name,
(None, Some(_need)) => { // Version must be present if needed. false
}
(Some(_def), None) => { // For a dlsym call, use the newest version. // TODO: if not a dlsym call, then use the oldest version.
!version_index.is_hidden()
}
(None, None) => true,
}
}
}
/// An iterator for the entries in an ELF [`elf::SHT_GNU_VERDEF`] section. #[derive(Debug, Clone)] pubstruct VerdefIterator<'data, Elf: FileHeader> {
endian: Elf::Endian,
data: Bytes<'data>,
}
/// An iterator for the auxiliary records for an entry in an ELF [`elf::SHT_GNU_VERDEF`] section. #[derive(Debug, Clone)] pubstruct VerdauxIterator<'data, Elf: FileHeader> {
endian: Elf::Endian,
data: Bytes<'data>,
count: u16,
}
/// An iterator for the entries in an ELF [`elf::SHT_GNU_VERNEED`] section. #[derive(Debug, Clone)] pubstruct VerneedIterator<'data, Elf: FileHeader> {
endian: Elf::Endian,
data: Bytes<'data>,
}
/// An iterator for the auxiliary records for an entry in an ELF [`elf::SHT_GNU_VERNEED`] section. #[derive(Debug, Clone)] pubstruct VernauxIterator<'data, Elf: FileHeader> {
endian: Elf::Endian,
data: Bytes<'data>,
count: u16,
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.