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 25832 : #[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 25832 : pub fn from_value(value: u32) -> Self {
33 25832 : match value {
34 3016 : 0x00000000 => Binding::LOCAL,
35 19088 : 0x00000001 => Binding::GLOBAL,
36 3648 : 0x00000002 => Binding::WEAK,
37 80 : 0x0000000a => Binding::GNU_UNIQUE,
38 0 : _ => Binding::UNKNOWN(value),
39 :
40 : }
41 25832 : }
42 : }
43 :
44 :
45 : #[allow(non_camel_case_types)]
46 25832 : #[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 25832 : pub fn from_value(value: u32) -> Self {
71 25832 : match value {
72 3328 : 0x00000000 => Type::NOTYPE,
73 6352 : 0x00000001 => Type::OBJECT,
74 15608 : 0x00000002 => Type::FUNC,
75 440 : 0x00000003 => Type::SECTION,
76 56 : 0x00000004 => Type::FILE,
77 0 : 0x00000005 => Type::COMMON,
78 48 : 0x00000006 => Type::TLS,
79 0 : 0x0000000a => Type::GNU_IFUNC,
80 0 : _ => Type::UNKNOWN(value),
81 :
82 : }
83 25832 : }
84 : }
85 :
86 :
87 : #[allow(non_camel_case_types)]
88 25832 : #[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 25832 : pub fn from_value(value: u32) -> Self {
105 25832 : match value {
106 25648 : 0x00000000 => Visibility::DEFAULT,
107 0 : 0x00000001 => Visibility::INTERNAL,
108 152 : 0x00000002 => Visibility::HIDDEN,
109 0 : 0x00000003 => Visibility::PROTECTED,
110 32 : _ => Visibility::UNKNOWN(value),
111 :
112 : }
113 25832 : }
114 : }
115 :
116 : impl Symbol<'_> {
117 : /// The symbol's type provides a general classification for the associated entity
118 25832 : pub fn get_type(&self) -> Type {
119 25832 : Type::from_value(self.ptr.get_type())
120 25832 : }
121 :
122 : /// The symbol's binding determines the linkage visibility and behavior
123 25832 : pub fn binding(&self) -> Binding {
124 25832 : Binding::from_value(self.ptr.binding())
125 25832 : }
126 :
127 : /// This member specifies the symbol's type and binding attributes.
128 25832 : pub fn information(&self) -> u8 {
129 25832 : self.ptr.information()
130 25832 : }
131 :
132 : /// Alias for [`Symbol::visibility`]
133 25832 : pub fn other(&self) -> u8 {
134 25832 : self.ptr.other()
135 25832 : }
136 :
137 : /// ELF Section index associated with the symbol
138 25832 : pub fn section_idx(&self) -> u16 {
139 25832 : self.ptr.section_idx()
140 25832 : }
141 :
142 : /// Symbol visibility
143 25832 : pub fn visibility(&self) -> Visibility {
144 25832 : Visibility::from_value(self.ptr.visibility())
145 25832 : }
146 :
147 : /// Section associated with the symbol (if any)
148 25832 : pub fn section(&self) -> Option<Section> {
149 25832 : into_optional(self.ptr.section())
150 25832 : }
151 :
152 : /// Return the SymbolVersion associated with this symbol (if any)
153 25832 : pub fn symbol_version(&self) -> Option<SymbolVersion> {
154 25832 : into_optional(self.ptr.symbol_version())
155 25832 : }
156 :
157 : /// Try to demangle the symbol or return an empty string if it is not possible
158 6216 : pub fn demangled_name(&self) -> String {
159 6216 : self.ptr.demangled_name().to_string()
160 6216 : }
161 : }
162 :
163 : impl fmt::Debug for Symbol<'_> {
164 25832 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 25832 : let base = self as &dyn generic::Symbol;
166 25832 : f.debug_struct("Symbol")
167 25832 : .field("base", &base)
168 25832 : .field("type", &self.get_type())
169 25832 : .field("binding", &self.binding())
170 25832 : .field("information", &self.information())
171 25832 : .field("other", &self.other())
172 25832 : .field("section_idx", &self.section_idx())
173 25832 : .field("visibility", &self.visibility())
174 25832 : .field("section", &self.section())
175 25832 : .field("symbol_version", &self.symbol_version())
176 25832 : .finish()
177 25832 : }
178 : }
179 :
180 : impl FromFFI<ffi::ELF_Symbol> for Symbol<'_> {
181 25848 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Symbol>) -> Self {
182 25848 : Self {
183 25848 : ptr,
184 25848 : _owner: PhantomData
185 25848 : }
186 25848 : }
187 : }
188 :
189 : impl generic::Symbol for Symbol<'_> {
190 96144 : fn as_generic(&self) -> &ffi::AbstractSymbol {
191 96144 : self.ptr.as_ref().unwrap().as_ref()
192 96144 : }
193 : }
194 :
195 : impl fmt::Display for Symbol<'_> {
196 6216 : fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197 6216 : write!(f, "{}", self.ptr.to_string())
198 6216 : }
199 : }
200 :
201 6216 : declare_iterator!(DynamicSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_dynamic_symbols);
202 2064 : declare_iterator!(ExportedSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_exported_symbols);
203 3888 : declare_iterator!(ImportedSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_imported_symbols);
204 704 : declare_iterator!(SymtabSymbols, Symbol<'a>, ffi::ELF_Symbol, ffi::ELF_Binary, ffi::ELF_Binary_it_symtab_symbols);
|