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