/// === Sym bindings === /// Local symbol. pubconst STB_LOCAL: u8 = 0; /// Global symbol. pubconst STB_GLOBAL: u8 = 1; /// Weak symbol. pubconst STB_WEAK: u8 = 2; /// Number of defined types.. pubconst STB_NUM: u8 = 3; /// Start of OS-specific. pubconst STB_LOOS: u8 = 10; /// Unique symbol.. pubconst STB_GNU_UNIQUE: u8 = 10; /// End of OS-specific. pubconst STB_HIOS: u8 = 12; /// Start of processor-specific. pubconst STB_LOPROC: u8 = 13; /// End of processor-specific. pubconst STB_HIPROC: u8 = 15;
/// === Sym types === /// Symbol type is unspecified. pubconst STT_NOTYPE: u8 = 0; /// Symbol is a data object. pubconst STT_OBJECT: u8 = 1; /// Symbol is a code object. pubconst STT_FUNC: u8 = 2; /// Symbol associated with a section. pubconst STT_SECTION: u8 = 3; /// Symbol's name is file name. pubconst STT_FILE: u8 = 4; /// Symbol is a common data object. pubconst STT_COMMON: u8 = 5; /// Symbol is thread-local data object. pubconst STT_TLS: u8 = 6; /// Number of defined types. pubconst STT_NUM: u8 = 7; /// Start of OS-specific. pubconst STT_LOOS: u8 = 10; /// Symbol is indirect code object. pubconst STT_GNU_IFUNC: u8 = 10; /// End of OS-specific. pubconst STT_HIOS: u8 = 12; /// Start of processor-specific. pubconst STT_LOPROC: u8 = 13; /// End of processor-specific. pubconst STT_HIPROC: u8 = 15;
/// === Sym visibility === /// Default: Visibility is specified by the symbol's binding type pubconst STV_DEFAULT: u8 = 0; /// Internal: use of this attribute is currently reserved. pubconst STV_INTERNAL: u8 = 1; /// Hidden: Not visible to other components, necessarily protected. Binding scope becomes local /// when the object is included in an executable or shared object. pubconst STV_HIDDEN: u8 = 2; /// Protected: Symbol defined in current component is visible in other components, but cannot be preempted. /// Any reference from within the defining component must be resolved to the definition in that /// component. pubconst STV_PROTECTED: u8 = 3; /// Exported: ensures a symbol remains global, cannot be demoted or eliminated by any other symbol /// visibility technique. pubconst STV_EXPORTED: u8 = 4; /// Singleton: ensures a symbol remains global, and that a single instance of the definition is /// bound to by all references within a process. Cannot be demoted or eliminated. pubconst STV_SINGLETON: u8 = 5; /// Eliminate: extends the hidden attribute. Not written in any symbol table of a dynamic /// executable or shared object. pubconst STV_ELIMINATE: u8 = 6;
/// Get the ST bind. /// /// This is the first four bits of the "info" byte. #[inline] pubfn st_bind(info: u8) -> u8 {
info >> 4
}
/// Get the ST type. /// /// This is the last four bits of the "info" byte. #[inline] pubfn st_type(info: u8) -> u8 {
info & 0xf
}
/// Get the ST visibility. /// /// This is the last three bits of the "other" byte. #[inline] pubfn st_visibility(other: u8) -> u8 {
other & 0x7
}
/// Is this information defining an import? #[inline] pubfn is_import(info: u8, value: u64) -> bool { let bind = st_bind(info);
bind == STB_GLOBAL && value == 0
}
/// Convenience function to get the &'static str type from the symbols `st_info`. #[inline] pubfn get_type(info: u8) -> &'static str {
type_to_str(st_type(info))
}
/// Get the string for some bind. #[inline] pubfn bind_to_str(typ: u8) -> &'static str { match typ {
STB_LOCAL => "LOCAL",
STB_GLOBAL => "GLOBAL",
STB_WEAK => "WEAK",
STB_NUM => "NUM",
STB_GNU_UNIQUE => "GNU_UNIQUE",
_ => "UNKNOWN_STB",
}
}
/// Get the string for some type. #[inline] pubfn type_to_str(typ: u8) -> &'static str { match typ {
STT_NOTYPE => "NOTYPE",
STT_OBJECT => "OBJECT",
STT_FUNC => "FUNC",
STT_SECTION => "SECTION",
STT_FILE => "FILE",
STT_COMMON => "COMMON",
STT_TLS => "TLS",
STT_NUM => "NUM",
STT_GNU_IFUNC => "GNU_IFUNC",
_ => "UNKNOWN_STT",
}
}
/// Get the string for some visibility #[inline] pubfn visibility_to_str(typ: u8) -> &'static str { match typ {
STV_DEFAULT => "DEFAULT",
STV_INTERNAL => "INTERNAL",
STV_HIDDEN => "HIDDEN",
STV_PROTECTED => "PROTECTED",
STV_EXPORTED => "EXPORTED",
STV_SINGLETON => "SINGLETON",
STV_ELIMINATE => "ELIMINATE",
_ => "UNKNOWN_STV",
}
}
impl From<ElfSym> for Sym { #[inline] fn from(sym: ElfSym) -> Self {
Sym {
st_name: sym.st_name as u32,
st_info: sym.st_info,
st_other: sym.st_other,
st_shndx: sym.st_shndx as u16,
st_value: sym.st_value as $size,
st_size: sym.st_size as $size,
}
}
}
impl fmt::Debug for Sym { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let bind = st_bind(self.st_info); let typ = st_type(self.st_info); let vis = st_visibility(self.st_other);
f.debug_struct("Sym")
.field("st_name", &self.st_name)
.field("st_value", &format_args!("{:x}", self.st_value))
.field("st_size", &self.st_size)
.field( "st_info",
&format_args!( "{:x} {} {}", self.st_info,
bind_to_str(bind),
type_to_str(typ)
),
)
.field( "st_other",
&format_args!("{} {}", self.st_other, visibility_to_str(vis)),
)
.field("st_shndx", &self.st_shndx)
.finish()
}
}
/// # Safety /// /// This function creates a `Sym` slice directly from a raw pointer #[inline] pubunsafefn from_raw<'a>(symp: *const Sym, count: usize) -> &'a [Sym] {
slice::from_raw_parts(symp, count)
}
if_std! { usecrate::error::Result;
use std::fs::File; use std::io::{Read, Seek}; use std::io::SeekFrom::Start;
pubfn from_fd(fd: &mut File, offset: usize, count: usize) -> Result<Vec<Sym>> { // TODO: AFAIK this shouldn't work, since i pass in a byte size... letmut syms = vec![Sym::default(); count];
fd.seek(Start(offset as u64))?; unsafe {
fd.read_exact(plain::as_mut_bytes(&mut *syms))?;
}
syms.dedup();
Ok(syms)
}
}
};
}
#[cfg(feature = "alloc")] use scroll::{Pread, Pwrite, SizeWith};
pubmod sym32 { pubusecrate::elf::sym::*;
#[repr(C)] #[derive(Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))] /// 32-bit Sym - used for both static and dynamic symbol information in a binary pubstruct Sym { /// Symbol name (string tbl index) pub st_name: u32, /// Symbol value pub st_value: u32, /// Symbol size pub st_size: u32, /// Symbol type and binding pub st_info: u8, /// Symbol visibility pub st_other: u8, /// Section index pub st_shndx: u16,
}
// Declare that the type is plain. unsafeimpl plain::Plain for Sym {}
#[repr(C)] #[derive(Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))] /// 64-bit Sym - used for both static and dynamic symbol information in a binary pubstruct Sym { /// Symbol name (string tbl index) pub st_name: u32, /// Symbol type and binding pub st_info: u8, /// Symbol visibility pub st_other: u8, /// Section index pub st_shndx: u16, /// Symbol value pub st_value: u64, /// Symbol size pub st_size: u64,
}
// Declare that the type is plain. unsafeimpl plain::Plain for Sym {}
usecrate::container::{Container, Ctx}; #[cfg(feature = "alloc")] usecrate::error::Result; #[cfg(feature = "alloc")] use alloc::vec::Vec; use core::fmt; use scroll::ctx; use scroll::ctx::SizeWith;
#[derive(Clone, Copy, PartialEq, Default)] /// A unified Sym definition - convertible to and from 32-bit and 64-bit variants pubstruct Sym { pub st_name: usize, pub st_info: u8, pub st_other: u8, pub st_shndx: usize, pub st_value: u64, pub st_size: u64,
}
impl Sym { #[inline] pubfn size(container: Container) -> usize { Self::size_with(&Ctx::from(container))
} /// Checks whether this `Sym` has `STB_GLOBAL`/`STB_WEAK` bind and a `st_value` of 0 #[inline] pubfn is_import(&self) -> bool { let bind = self.st_bind();
(bind == STB_GLOBAL || bind == STB_WEAK) && self.st_value == 0
} /// Checks whether this `Sym` has type `STT_FUNC` #[inline] pubfn is_function(&self) -> bool {
st_type(self.st_info) == STT_FUNC
} /// Get the ST bind. /// /// This is the first four bits of the "info" byte. #[inline] pubfn st_bind(&self) -> u8 { self.st_info >> 4
} /// Get the ST type. /// /// This is the last four bits of the "info" byte. #[inline] pubfn st_type(&self) -> u8 {
st_type(self.st_info)
} /// Get the ST visibility. /// /// This is the last three bits of the "other" byte. #[inline] pubfn st_visibility(&self) -> u8 {
st_visibility(self.st_other)
} #[cfg(feature = "endian_fd")] /// Parse `count` vector of ELF symbols from `offset` pubfn parse(bytes: &[u8], mut offset: usize, count: usize, ctx: Ctx) -> Result<Vec<Sym>> { if count > bytes.len() / Sym::size_with(&ctx) { return Err(crate::error::Error::BufferTooShort(count, "symbols"));
} letmut syms = Vec::with_capacity(count); for _ in0..count { let sym = bytes.gread_with(&mut offset, ctx)?;
syms.push(sym);
}
Ok(syms)
}
}
impl fmt::Debug for Sym { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let bind = self.st_bind(); let typ = self.st_type(); let vis = self.st_visibility();
f.debug_struct("Sym")
.field("st_name", &self.st_name)
.field( "st_info",
&format_args!( "0x{:x} {} {}", self.st_info,
bind_to_str(bind),
type_to_str(typ)
),
)
.field( "st_other",
&format_args!("{} {}", self.st_other, visibility_to_str(vis)),
)
.field("st_shndx", &self.st_shndx)
.field("st_value", &format_args!("0x{:x}", self.st_value))
.field("st_size", &self.st_size)
.finish()
}
}
impl<'a> Symtab<'a> { /// Parse a table of `count` ELF symbols from `offset`. pubfn parse(bytes: &'a [u8], offset: usize, count: usize, ctx: Ctx) -> Result<Symtab<'a>> { let size = count
.checked_mul(Sym::size_with(&ctx))
.ok_or_else(|| crate::error::Error::Malformed(
format!("Too many ELF symbols (offset {:#x}, count {})", offset, count)
))?; // TODO: make this a better error message when too large let bytes = bytes.pread_with(offset, size)?;
Ok(Symtab { bytes, count, ctx, start: offset, end: offset+size })
}
/// Try to parse a single symbol from the binary, at `index`. #[inline] pubfn get(&self, index: usize) -> Option<Sym> { if index >= self.count {
None
} else {
Some(self.bytes.pread_with(index * Sym::size_with(&self.ctx), self.ctx).unwrap())
}
}
/// The number of symbols in the table. #[inline] pubfn len(&self) -> usize { self.count
}
/// The offset of symbol table in elf #[inline] pubfn offset(&self) -> usize { self.start
}
/// The ctx of symbol table #[inline] pubfn ctx(&self) -> &Ctx {
&self.ctx
}
/// Returns true if table has no symbols. #[inline] pubfn is_empty(&self) -> bool { self.count == 0
}
/// Iterate over all symbols. #[inline] pubfn iter(&self) -> SymIterator<'a> { self.into_iter()
}
/// Parse all symbols into a vector. pubfn to_vec(&self) -> Vec<Sym> { self.iter().collect()
}
}
impl<'a, 'b> IntoIterator for &'b Symtab<'a> { type Item = <SymIterator<'a> as Iterator>::Item; type IntoIter = SymIterator<'a>;
/// An iterator over symbols in an ELF symbol table pubstruct SymIterator<'a> {
bytes: &'a [u8],
offset: usize,
index: usize,
count: usize,
ctx: Ctx,
}
impl<'a> Iterator for SymIterator<'a> { type Item = Sym;
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.