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 38748 : #[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 38748 : pub fn from_value(value: u32) -> Self {
34 38748 : match value {
35 4524 : 0x00000000 => Binding::LOCAL,
36 28632 : 0x00000001 => Binding::GLOBAL,
37 5472 : 0x00000002 => Binding::WEAK,
38 120 : 0x0000000a => Binding::GNU_UNIQUE,
39 0 : _ => Binding::UNKNOWN(value),
40 :
41 : }
42 38748 : }
43 : }
44 :
45 :
46 : #[allow(non_camel_case_types)]
47 38748 : #[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 38748 : pub fn from_value(value: u32) -> Self {
72 38748 : match value {
73 4992 : 0x00000000 => Type::NOTYPE,
74 9528 : 0x00000001 => Type::OBJECT,
75 23412 : 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 38748 : }
85 : }
86 :
87 :
88 : #[allow(non_camel_case_types)]
89 38748 : #[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 38748 : pub fn from_value(value: u32) -> Self {
106 38748 : match value {
107 38472 : 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 38748 : }
115 : }
116 :
117 : impl Symbol<'_> {
118 : /// The symbol's type provides a general classification for the associated entity
119 38748 : pub fn get_type(&self) -> Type {
120 38748 : Type::from_value(self.ptr.get_type())
121 38748 : }
122 :
123 : /// The symbol's binding determines the linkage visibility and behavior
124 38748 : pub fn binding(&self) -> Binding {
125 38748 : Binding::from_value(self.ptr.binding())
126 38748 : }
127 :
128 : /// This member specifies the symbol's type and binding attributes.
129 38748 : pub fn information(&self) -> u8 {
130 38748 : self.ptr.information()
131 38748 : }
132 :
133 : /// Alias for [`Symbol::visibility`]
134 38748 : pub fn other(&self) -> u8 {
135 38748 : self.ptr.other()
136 38748 : }
137 :
138 : /// ELF Section index associated with the symbol
139 38748 : pub fn section_idx(&self) -> u16 {
140 38748 : self.ptr.section_idx()
141 38748 : }
142 :
143 : /// Symbol visibility
144 38748 : pub fn visibility(&self) -> Visibility {
145 38748 : Visibility::from_value(self.ptr.visibility())
146 38748 : }
147 :
148 : /// Section associated with the symbol (if any)
149 38748 : pub fn section(&self) -> Option<Section> {
150 38748 : into_optional(self.ptr.section())
151 38748 : }
152 :
153 : /// Return the SymbolVersion associated with this symbol (if any)
154 38748 : pub fn symbol_version(&self) -> Option<SymbolVersion> {
155 38748 : into_optional(self.ptr.symbol_version())
156 38748 : }
157 :
158 : /// Try to demangle the symbol or return an empty string if it is not possible
159 9324 : pub fn demangled_name(&self) -> String {
160 9324 : self.ptr.demangled_name().to_string()
161 9324 : }
162 : }
163 :
164 : impl fmt::Debug for Symbol<'_> {
165 38748 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 38748 : let base = self as &dyn generic::Symbol;
167 38748 : f.debug_struct("Symbol")
168 38748 : .field("base", &base)
169 38748 : .field("type", &self.get_type())
170 38748 : .field("binding", &self.binding())
171 38748 : .field("information", &self.information())
172 38748 : .field("other", &self.other())
173 38748 : .field("section_idx", &self.section_idx())
174 38748 : .field("visibility", &self.visibility())
175 38748 : .field("section", &self.section())
176 38748 : .field("symbol_version", &self.symbol_version())
177 38748 : .finish()
178 38748 : }
179 : }
180 :
181 : impl FromFFI<ffi::ELF_Symbol> for Symbol<'_> {
182 38772 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Symbol>) -> Self {
183 38772 : Self {
184 38772 : ptr,
185 38772 : _owner: PhantomData
186 38772 : }
187 38772 : }
188 : }
189 :
190 : impl generic::Symbol for Symbol<'_> {
191 144216 : fn as_generic(&self) -> &ffi::AbstractSymbol {
192 144216 : self.ptr.as_ref().unwrap().as_ref()
193 144216 : }
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 9324 : fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
209 9324 : write!(f, "{}", self.ptr.to_string())
210 9324 : }
211 : }
212 :
213 9324 : declare_iterator!(DynamicSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_dynamic_symbols);
214 3096 : declare_iterator!(ExportedSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_exported_symbols);
215 5832 : 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);
|