mer/symbol.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
use crate::{section::SectionType, Elf};
use bit_field::BitField;
use scroll::Pread;
pub enum SymbolBinding {
/// Only visible inside the object file that defines it.
Local,
/// Global symbol - visible to all object files.
Global,
/// Global scope, but with a lower precedence than global symbols.
Weak,
/// Environment-specific use.
Os(u8),
/// Processor-specific use.
Proc(u8),
}
pub enum SymbolType {
NoType,
Object,
Func,
Section,
File,
Os(u8),
Proc(u8),
}
#[derive(Pread)]
#[repr(C)]
pub struct Symbol {
/// The offset into the string table, in bytes, to the symbol name. If this is `0`, the symbol
/// doesn't have a name.
pub name: u32,
pub info: u8,
/// Reserved. Must be `0`.
_other: u8,
pub section_table_index: u16,
pub value: u64,
pub size: u64,
}
impl Symbol {
pub fn binding(&self) -> SymbolBinding {
let binding = self.info.get_bits(4..8);
match binding {
0 => SymbolBinding::Local,
1 => SymbolBinding::Global,
2 => SymbolBinding::Weak,
10..=12 => SymbolBinding::Os(binding),
13..=15 => SymbolBinding::Proc(binding),
_ => panic!("Invalid symbol binding: {}", binding),
}
}
pub fn symbol_type(&self) -> SymbolType {
let symbol_type = self.info.get_bits(0..4);
match symbol_type {
0 => SymbolType::NoType,
1 => SymbolType::Object,
2 => SymbolType::Func,
3 => SymbolType::Section,
4 => SymbolType::File,
10..=12 => SymbolType::Os(symbol_type),
13..=15 => SymbolType::Proc(symbol_type),
_ => panic!("Invalid symbol type: {}", symbol_type),
}
}
pub fn name<'a>(&self, elf: &'a Elf) -> Option<&'a str> {
if self.name == 0 {
return None;
}
match &elf.symbol_table {
/*
* NOTE: This is unreachable because we can't create symbols without a symbol table.
*/
None => unreachable!(),
Some(ref symbol_table) => {
/*
* NOTE: the `link` field of the symbol table contains the index of the string
* table that contains the names of the symbols.
*/
let string_table = elf.sections().nth(symbol_table.link as usize).unwrap();
if string_table.section_type() != SectionType::StrTab {
return None;
}
crate::from_utf8_null_terminated(&string_table.data(elf)?[(self.name as usize)..]).ok()
}
}
}
}