Line data Source code
1 : use lief_ffi as ffi;
2 : use std::fmt;
3 : use std::pin::Pin;
4 : use std::marker::PhantomData;
5 :
6 : use crate::common::{FromFFI, into_optional};
7 : use crate::declare_iterator;
8 : use crate::generic;
9 : use crate::elf::Section;
10 : use super::SymbolVersion;
11 :
12 : /// Structure which reprents an ELF symbol
13 : pub struct Symbol<'a> {
14 : ptr: cxx::UniquePtr<ffi::ELF_Symbol>,
15 : _owner: PhantomData<&'a ffi::ELF_Binary>
16 : }
17 :
18 : #[allow(non_camel_case_types)]
19 39588 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
20 : pub enum Binding {
21 : /// Local symbol
22 : LOCAL,
23 : /// Global symbol
24 : GLOBAL,
25 : /// Weak symbol
26 : WEAK,
27 : /// Unique symbol
28 : GNU_UNIQUE,
29 : UNKNOWN(u32),
30 : }
31 :
32 : impl Binding {
33 39588 : pub fn from_value(value: u32) -> Self {
34 39588 : match value {
35 4692 : 0x00000000 => Binding::LOCAL,
36 28968 : 0x00000001 => Binding::GLOBAL,
37 5808 : 0x00000002 => Binding::WEAK,
38 120 : 0x0000000a => Binding::GNU_UNIQUE,
39 0 : _ => Binding::UNKNOWN(value),
40 :
41 : }
42 39588 : }
43 : }
44 :
45 :
46 : #[allow(non_camel_case_types)]
47 39588 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
48 : /// Type of the symbol. This enum matches the `STT_xxx` values of the ELF
49 : /// specs
50 : pub enum Type {
51 : /// Symbol's type is not specified
52 : NOTYPE,
53 : /// Symbol is a data object (variable, array, etc.)
54 : OBJECT,
55 : /// Symbol is executable code (function, etc.)
56 : FUNC,
57 : /// Symbol refers to a section
58 : SECTION,
59 : /// Local, absolute symbol that refers to a file
60 : FILE,
61 : /// An uninitialized common block
62 : COMMON,
63 : /// Thread local data object
64 : TLS,
65 : /// GNU indirect function
66 : GNU_IFUNC,
67 : UNKNOWN(u32),
68 : }
69 :
70 : impl Type {
71 39588 : pub fn from_value(value: u32) -> Self {
72 39588 : match value {
73 5496 : 0x00000000 => Type::NOTYPE,
74 9576 : 0x00000001 => Type::OBJECT,
75 23700 : 0x00000002 => Type::FUNC,
76 660 : 0x00000003 => Type::SECTION,
77 84 : 0x00000004 => Type::FILE,
78 0 : 0x00000005 => Type::COMMON,
79 72 : 0x00000006 => Type::TLS,
80 0 : 0x0000000a => Type::GNU_IFUNC,
81 0 : _ => Type::UNKNOWN(value),
82 :
83 : }
84 39588 : }
85 : }
86 :
87 :
88 : #[allow(non_camel_case_types)]
89 39588 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
90 : /// Visibility of the symbol. This enum matches the `STV_xxx` values of the
91 : /// official ELF specs
92 : pub enum Visibility {
93 : /// Visibility is specified by binding type
94 : DEFAULT,
95 : /// Defined by processor supplements
96 : INTERNAL,
97 : /// Not visible to other components
98 : HIDDEN,
99 : /// Visible in other components but not preemptable
100 : PROTECTED,
101 : UNKNOWN(u32),
102 : }
103 :
104 : impl Visibility {
105 39588 : pub fn from_value(value: u32) -> Self {
106 39588 : match value {
107 39312 : 0x00000000 => Visibility::DEFAULT,
108 0 : 0x00000001 => Visibility::INTERNAL,
109 228 : 0x00000002 => Visibility::HIDDEN,
110 0 : 0x00000003 => Visibility::PROTECTED,
111 48 : _ => Visibility::UNKNOWN(value),
112 :
113 : }
114 39588 : }
115 : }
116 :
117 : impl Symbol<'_> {
118 : /// The symbol's type provides a general classification for the associated entity
119 39588 : pub fn get_type(&self) -> Type {
120 39588 : Type::from_value(self.ptr.get_type())
121 39588 : }
122 :
123 : /// The symbol's binding determines the linkage visibility and behavior
124 39588 : pub fn binding(&self) -> Binding {
125 39588 : Binding::from_value(self.ptr.binding())
126 39588 : }
127 :
128 : /// This member specifies the symbol's type and binding attributes.
129 39588 : pub fn information(&self) -> u8 {
130 39588 : self.ptr.information()
131 39588 : }
132 :
133 : /// Alias for [`Symbol::visibility`]
134 39588 : pub fn other(&self) -> u8 {
135 39588 : self.ptr.other()
136 39588 : }
137 :
138 : /// ELF Section index associated with the symbol
139 39588 : pub fn section_idx(&self) -> u16 {
140 39588 : self.ptr.section_idx()
141 39588 : }
142 :
143 : /// Symbol visibility
144 39588 : pub fn visibility(&self) -> Visibility {
145 39588 : Visibility::from_value(self.ptr.visibility())
146 39588 : }
147 :
148 : /// Section associated with the symbol (if any)
149 39588 : pub fn section(&self) -> Option<Section<'_>> {
150 39588 : into_optional(self.ptr.section())
151 39588 : }
152 :
153 : /// Return the SymbolVersion associated with this symbol (if any)
154 39588 : pub fn symbol_version(&self) -> Option<SymbolVersion<'_>> {
155 39588 : into_optional(self.ptr.symbol_version())
156 39588 : }
157 :
158 : /// Try to demangle the symbol or return an empty string if it is not possible
159 9612 : pub fn demangled_name(&self) -> String {
160 9612 : self.ptr.demangled_name().to_string()
161 9612 : }
162 : }
163 :
164 : impl fmt::Debug for Symbol<'_> {
165 39588 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 39588 : let base = self as &dyn generic::Symbol;
167 39588 : f.debug_struct("Symbol")
168 39588 : .field("base", &base)
169 39588 : .field("type", &self.get_type())
170 39588 : .field("binding", &self.binding())
171 39588 : .field("information", &self.information())
172 39588 : .field("other", &self.other())
173 39588 : .field("section_idx", &self.section_idx())
174 39588 : .field("visibility", &self.visibility())
175 39588 : .field("section", &self.section())
176 39588 : .field("symbol_version", &self.symbol_version())
177 39588 : .finish()
178 39588 : }
179 : }
180 :
181 : impl FromFFI<ffi::ELF_Symbol> for Symbol<'_> {
182 39612 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Symbol>) -> Self {
183 39612 : Self {
184 39612 : ptr,
185 39612 : _owner: PhantomData
186 39612 : }
187 39612 : }
188 : }
189 :
190 : impl generic::Symbol for Symbol<'_> {
191 147600 : fn as_generic(&self) -> &ffi::AbstractSymbol {
192 147600 : self.ptr.as_ref().unwrap().as_ref()
193 147600 : }
194 :
195 0 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
196 0 : unsafe {
197 0 : Pin::new_unchecked({
198 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
199 0 : as *mut ffi::AbstractSymbol)
200 0 : .as_mut()
201 0 : .unwrap()
202 0 : })
203 0 : }
204 0 : }
205 : }
206 :
207 : impl fmt::Display for Symbol<'_> {
208 9612 : fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
209 9612 : write!(f, "{}", self.ptr.to_string())
210 9612 : }
211 : }
212 :
213 9612 : declare_iterator!(DynamicSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_dynamic_symbols);
214 3168 : declare_iterator!(ExportedSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_exported_symbols);
215 5880 : declare_iterator!(ImportedSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_imported_symbols);
216 1056 : declare_iterator!(SymtabSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_symtab_symbols);
|