#[cfg(feature = "std")]
pub trait ElfSym {
fn st_name(&self) -> u32;
fn st_info(&self) -> u8;
fn st_other(&self) -> u8;
fn st_shndx(&self) -> u16;
fn st_value(&self) -> u64;
fn st_size(&self) -> u64;
}
pub const STB_LOCAL: u8 = 0;
pub const STB_GLOBAL: u8 = 1;
pub const STB_WEAK: u8 = 2;
pub const STB_NUM: u8 = 3;
pub const STB_LOOS: u8 = 10;
pub const STB_GNU_UNIQUE: u8 = 10;
pub const STB_HIOS: u8 = 12;
pub const STB_LOPROC: u8 = 13;
pub const STB_HIPROC: u8 = 15;
pub const STT_NOTYPE: u8 = 0;
pub const STT_OBJECT: u8 = 1;
pub const STT_FUNC: u8 = 2;
pub const STT_SECTION: u8 = 3;
pub const STT_FILE: u8 = 4;
pub const STT_COMMON: u8 = 5;
pub const STT_TLS: u8 = 6;
pub const STT_NUM: u8 = 7;
pub const STT_LOOS: u8 = 10;
pub const STT_GNU_IFUNC: u8 = 10;
pub const STT_HIOS: u8 = 12;
pub const STT_LOPROC: u8 = 13;
pub const STT_HIPROC: u8 = 15;
#[inline]
pub fn st_bind(info: u8) -> u8 {
info >> 4
}
#[inline]
pub fn st_type(info: u8) -> u8 {
info & 0xf
}
#[inline]
pub fn is_import(info: u8, value: u64) -> bool {
let binding = st_bind(info);
binding == STB_GLOBAL && value == 0
}
pub fn get_type(info: u8) -> &'static str {
type_to_str(st_type(info))
}
#[inline]
pub fn 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",
}
}
#[inline]
pub fn 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",
}
}
macro_rules! elf_sym_impure_impl {
($from_endian:item) => {
#[cfg(feature = "std")]
pub use self::impure::*;
#[cfg(feature = "std")]
mod impure {
use super::*;
use core::fmt;
use core::slice;
use std::fs::File;
use std::io::{self, Read, Seek};
use std::io::SeekFrom::Start;
impl ElfSym for Sym {
fn st_name(&self) -> u32 {
self.st_name
}
fn st_info(&self) -> u8 {
self.st_info
}
fn st_other(&self) -> u8 {
self.st_other
}
fn st_shndx(&self) -> u16 {
self.st_shndx
}
fn st_value(&self) -> u64 {
self.st_value as u64
}
fn st_size(&self) -> u64 {
self.st_size as u64
}
}
impl Sym {
pub fn is_import(&self) -> bool {
let binding = self.st_info >> 4;
(binding == STB_GLOBAL || binding == STB_WEAK) && self.st_value == 0
}
pub fn is_function(&self) -> bool {
st_type(self.st_info) == STT_FUNC
}
}
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);
write!(f,
"st_name: {} {} {} st_other: {} st_shndx: {} st_value: {:x} st_size: {}",
self.st_name,
bind_to_str(bind),
type_to_str(typ),
self.st_other,
self.st_shndx,
self.st_value,
self.st_size)
}
}
pub unsafe fn from_raw<'a>(symp: *const Sym, count: usize) -> &'a [Sym] {
slice::from_raw_parts(symp, count)
}
pub fn from_fd<'a>(fd: &mut File, offset: usize, count: usize) -> io::Result<Vec<Sym>> {
let mut bytes = vec![0u8; count * SIZEOF_SYM];
try!(fd.seek(Start(offset as u64)));
try!(fd.read(&mut bytes));
let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr() as *mut Sym, count) };
let mut syms = Vec::with_capacity(count);
syms.extend_from_slice(bytes);
syms.dedup();
Ok(syms)
}
#[cfg(feature = "endian_fd")]
$from_endian
}
};
}