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