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 scroll_derive::Pread;
use bit_field::BitField;
use crate::{Elf, section::SectionType};
pub enum SymbolBinding {
Local,
Global,
Weak,
Os(u8),
Proc(u8),
}
pub enum SymbolType {
NoType,
Object,
Func,
Section,
File,
Os(u8),
Proc(u8),
}
#[derive(Pread)]
#[repr(C)]
pub struct Symbol {
pub name: u32,
pub info: u8,
_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 {
None => unreachable!(),
Some(ref symbol_table) => {
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()
}
}
}
}