//! Symbol versioning //! //! Implementation of the GNU symbol versioning extension according to //! [LSB Core Specification - Symbol Versioning][lsb-symver]. //! //! # Examples //! //! List the dependencies of an ELF file that have [version needed][lsb-verneed] information along //! with the versions needed for each dependency. //! ```rust //! use goblin::error::Error; //! //! pub fn show_verneed(bytes: &[u8]) -> Result<(), Error> { //! let binary = goblin::elf::Elf::parse(&bytes)?; //! //! if let Some(verneed) = binary.verneed { //! for need_file in verneed.iter() { //! println!( //! "Depend on {:?} with version(s):", //! binary.dynstrtab.get_at(need_file.vn_file) //! ); //! for need_ver in need_file.iter() { //! println!("{:?}", binary.dynstrtab.get_at(need_ver.vna_name)); //! } //! } //! } //! //! Ok(()) //! } //! ``` //! //! List the [version defined][lsb-verdef] information of an ELF file, effectively listing the version //! defined by this ELF file. //! ```rust //! use goblin::error::Error; //! //! pub fn show_verdef(bytes: &[u8]) -> Result<(), Error> { //! let binary = goblin::elf::Elf::parse(&bytes)?; //! //! if let Some(verdef) = &binary.verdef { //! for def in verdef.iter() { //! for (n, aux) in def.iter().enumerate() { //! let name = binary.dynstrtab.get_at(aux.vda_name); //! match n { //! 0 => print!("Name: {:?}", name), //! 1 => print!(" Parent: {:?}", name), //! _ => print!(", {:?}", name), //! } //! } //! print!("\n"); //! } //! } //! //! Ok(()) //! } //! ``` //! //! [lsb-symver]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html //! [lsb-verneed]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html#SYMVERRQMTS //! [lsb-verdef]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html#SYMVERDEFS
usecrate::container; usecrate::elf::section_header::{SectionHeader, SHT_GNU_VERDEF, SHT_GNU_VERNEED, SHT_GNU_VERSYM}; usecrate::error::Result; use core::iter::FusedIterator; use scroll::Pread;
/// Constant describing a local symbol, see [`Versym::is_local`]. pubconst VER_NDX_LOCAL: u16 = 0; /// Constant describing a global symbol, see [`Versym::is_global`]. pubconst VER_NDX_GLOBAL: u16 = 1; /// Bitmask to check hidden bit, see [`Versym::is_hidden`]. pubconst VERSYM_HIDDEN: u16 = 0x8000; /// Bitmask to get version information, see [`Versym::version`]. pubconst VERSYM_VERSION: u16 = 0x7fff;
// Verdef constants.
/// Bitmask to check `base` flag in [`Verdef::vd_flags`]. pubconst VER_FLG_BASE: u16 = 0x1; /// Bitmask to check `weak` flag in [`Verdef::vd_flags`]. pubconst VER_FLG_WEAK: u16 = 0x2; /// Bitmask to check `info` flag in [`Verdef::vd_flags`]. pubconst VER_FLG_INFO: u16 = 0x4;
impl Versym { /// Returns true if the symbol is local and not available outside the object according to /// [`VER_NDX_LOCAL`]. #[inline] pubfn is_local(&self) -> bool { self.vs_val == VER_NDX_LOCAL
}
/// Returns true if the symbol is defined in this object and globally available according /// to [`VER_NDX_GLOBAL`]. #[inline] pubfn is_global(&self) -> bool { self.vs_val == VER_NDX_GLOBAL
}
/// Returns true if the `hidden` bit is set according to the [`VERSYM_HIDDEN`] bitmask. #[inline] pubfn is_hidden(&self) -> bool {
(self.vs_val & VERSYM_HIDDEN) == VERSYM_HIDDEN
}
/// Returns the symbol version index according to the [`VERSYM_VERSION`] bitmask. #[inline] pubfn version(&self) -> u16 { self.vs_val & VERSYM_VERSION
}
}
do_next(self).or_else(|| { // Adjust current index to count in case of an error. self.index = self.count;
None
})
}
}
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { let len = self.count - self.index;
(0, Some(len))
}
}
impl ExactSizeIterator for VerdefIter<'_> {}
impl FusedIterator for VerdefIter<'_> {}
/// An ELF [Version Definition][lsb-verdef] entry . /// /// [lsb-verdef]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html#VERDEFENTRIES #[derive(Debug)] pubstruct Verdef<'a> { /// Version revision. This field shall be set to 1. pub vd_version: u16, /// Version information flag bitmask. pub vd_flags: u16, /// Version index numeric value referencing the SHT_GNU_versym section. pub vd_ndx: u16, /// Number of associated verdaux array entries. pub vd_cnt: u16, /// Version name hash value (ELF hash function). pub vd_hash: u32, /// Offset in bytes to a corresponding entry in an array of Elfxx_Verdaux structures. pub vd_aux: u32, /// Offset to the next verdef entry, in bytes. pub vd_next: u32,
bytes: &'a [u8],
ctx: container::Ctx,
}
impl<'a> Verdef<'a> { /// Get an iterator over the [`Verdaux`] entries of this [`Verdef`] entry. #[inline] pubfn iter(&'a self) -> VerdauxIter<'a> { self.into_iter()
}
}
impl<'a> IntoIterator for &'_ Verdef<'a> { type Item = <VerdauxIter<'a> as Iterator>::Item; type IntoIter = VerdauxIter<'a>;
do_next(self).or_else(|| { // Adjust current index to count in case of an error. self.index = self.count;
None
})
}
}
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { let len = self.count - self.index;
(0, Some(len))
}
}
impl ExactSizeIterator for VerneedIter<'_> {}
impl FusedIterator for VerneedIter<'_> {}
/// An ELF [Version Need][lsb-verneed] entry . /// /// [lsb-verneed]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html#VERNEEDFIG #[derive(Debug)] pubstruct Verneed<'a> { /// Version of structure. This value is currently set to 1, and will be reset if the versioning /// implementation is incompatibly altered. pub vn_version: u16, /// Number of associated verneed array entries. pub vn_cnt: u16, /// Offset to the file name string in the section header, in bytes. pub vn_file: usize, /// Offset to a corresponding entry in the vernaux array, in bytes. pub vn_aux: u32, /// Offset to the next verneed entry, in bytes. pub vn_next: u32,
bytes: &'a [u8],
ctx: container::Ctx,
}
impl<'a> Verneed<'a> { /// Get an iterator over the [`Vernaux`] entries of this [`Verneed`] entry. #[inline] pubfn iter(&'a self) -> VernauxIter<'a> { self.into_iter()
}
}
impl<'a> IntoIterator for &'_ Verneed<'a> { type Item = <VernauxIter<'a> as Iterator>::Item; type IntoIter = VernauxIter<'a>;
do_next(self).or_else(|| { // Adjust current index to count in case of an error. self.index = self.count;
None
})
}
}
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { let len = usize::from(self.count - self.index);
(0, Some(len))
}
}
impl ExactSizeIterator for VernauxIter<'_> {}
impl FusedIterator for VernauxIter<'_> {}
/// An ELF [Version Need Auxiliary][lsb-vernaux] entry. /// /// [lsb-vernaux]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html#VERNEEDEXTFIG #[derive(Debug)] pubstruct Vernaux { /// Dependency name hash value (ELF hash function). pub vna_hash: u32, /// Dependency information flag bitmask. pub vna_flags: u16, /// Object file version identifier used in the .gnu.version symbol version array. Bit number 15 /// controls whether or not the object is hidden; if this bit is set, the object cannot be used /// and the static linker will ignore the symbol's presence in the object. pub vna_other: u16, /// Offset to the dependency name string in the section header, in bytes. pub vna_name: usize, /// Offset to the next vernaux entry, in bytes. pub vna_next: u32,
}
#[cfg(test)] mod test { usesuper::{ElfVerdaux, ElfVerdef, ElfVernaux, ElfVerneed, ElfVersym}; usesuper::{Versym, VERSYM_HIDDEN, VER_NDX_GLOBAL, VER_NDX_LOCAL}; use core::mem::size_of;
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.