Line data Source code
1 : use std::marker::PhantomData;
2 : use std::pin::Pin;
3 :
4 : use crate::common::{into_optional, AsFFI, FromFFI};
5 : use crate::declare_iterator;
6 : use crate::generic;
7 : use lief_ffi as ffi;
8 :
9 : use super::commands::Dylib;
10 : use super::{BindingInfo, ExportInfo};
11 :
12 : /// Structure that represents a Symbol in a Mach-O file.
13 : ///
14 : /// A Mach-O symbol can come from:
15 : /// 1. The symbols command (LC_SYMTAB / SymbolCommand)
16 : /// 2. The Dyld Export trie
17 : /// 3. The Dyld Symbol bindings
18 : pub struct Symbol<'a> {
19 : ptr: cxx::UniquePtr<ffi::MachO_Symbol>,
20 : _owner: PhantomData<&'a ()>,
21 : }
22 :
23 : #[allow(non_camel_case_types)]
24 463034 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
25 : pub enum Category {
26 : NONE,
27 : LOCAL,
28 : EXTERNAL,
29 : UNDEFINED,
30 : INDIRECT_ABS,
31 : INDIRECT_LOCAL,
32 : INDIRECT_ABS_LOCAL,
33 : UNKNOWN(u32),
34 : }
35 :
36 : impl From<u32> for Category {
37 463034 : fn from(value: u32) -> Self {
38 463034 : match value {
39 113451 : 0x00000000 => Category::NONE,
40 196963 : 0x00000001 => Category::LOCAL,
41 90974 : 0x00000002 => Category::EXTERNAL,
42 61646 : 0x00000003 => Category::UNDEFINED,
43 0 : 0x00000004 => Category::INDIRECT_ABS,
44 0 : 0x00000005 => Category::INDIRECT_LOCAL,
45 0 : 0x00000006 => Category::INDIRECT_ABS_LOCAL,
46 0 : _ => Category::UNKNOWN(value),
47 : }
48 463034 : }
49 : }
50 :
51 : #[allow(non_camel_case_types)]
52 463034 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
53 : pub enum Origin {
54 : DYLD_EXPORT,
55 : DYLD_BIND,
56 : LC_SYMTAB,
57 : UNKNOWN(u32),
58 : }
59 :
60 : impl From<u32> for Origin {
61 463034 : fn from(value: u32) -> Self {
62 463034 : match value {
63 53820 : 0x00000001 => Origin::DYLD_EXPORT,
64 59631 : 0x00000002 => Origin::DYLD_BIND,
65 349583 : 0x00000003 => Origin::LC_SYMTAB,
66 0 : _ => Origin::UNKNOWN(value),
67 : }
68 463034 : }
69 : }
70 :
71 : /// Symbol type as defined by `nlist_xx.n_type & N_TYPE`
72 : #[allow(non_camel_case_types)]
73 0 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
74 : pub enum Type {
75 : /// The symbol is undefined
76 : UNDEFINED,
77 : /// The symbol is absolute
78 : ABSOLUTE_SYM,
79 : /// The symbol is defined in a specific section
80 : SECTION,
81 : /// The symbol is undefined and the image is using a prebound value
82 : PREBOUND,
83 : /// The symbol is defined to be the same as another symbol
84 : INDIRECT,
85 : UNKNOWN(u32),
86 : }
87 :
88 : impl From<u32> for Type {
89 0 : fn from(value: u32) -> Self {
90 0 : match value {
91 0 : 0x0 => Type::UNDEFINED,
92 0 : 0x2 => Type::ABSOLUTE_SYM,
93 0 : 0xe => Type::SECTION,
94 0 : 0xc => Type::PREBOUND,
95 0 : 0xa => Type::INDIRECT,
96 0 : _ => Type::UNKNOWN(value),
97 : }
98 0 : }
99 : }
100 :
101 : impl From<Type> for u32 {
102 0 : fn from(value: Type) -> u32 {
103 0 : match value {
104 0 : Type::UNDEFINED => 0x0,
105 0 : Type::ABSOLUTE_SYM => 0x2,
106 0 : Type::SECTION => 0xe,
107 0 : Type::PREBOUND => 0xc,
108 0 : Type::INDIRECT => 0xa,
109 0 : Type::UNKNOWN(v) => v,
110 : }
111 0 : }
112 : }
113 :
114 : impl Symbol<'_> {
115 463034 : pub fn get_type(&self) -> u8 {
116 463034 : self.ptr.get_type()
117 463034 : }
118 :
119 : /// It returns the number of sections in which this symbol can be found.
120 : /// If the symbol can't be found in any section, it returns 0 (`NO_SECT`)
121 463034 : pub fn numberof_sections(&self) -> u8 {
122 463034 : self.ptr.numberof_sections()
123 463034 : }
124 :
125 : /// Return information about the symbol
126 463034 : pub fn description(&self) -> u16 {
127 463034 : self.ptr.description()
128 463034 : }
129 :
130 : /// Return the origin of the symbol: from `LC_SYMTAB` from the Dyld information, ...
131 463034 : pub fn origin(&self) -> Origin {
132 463034 : Origin::from(self.ptr.origin())
133 463034 : }
134 :
135 : /// Category of the symbol according to the `LC_DYSYMTAB` command
136 463034 : pub fn category(&self) -> Category {
137 463034 : Category::from(self.ptr.category())
138 463034 : }
139 :
140 : /// Export info associated with this symbol (if any)
141 463034 : pub fn export_info(&self) -> Option<ExportInfo<'_>> {
142 463034 : into_optional(self.ptr.export_info())
143 463034 : }
144 :
145 : /// Binding info associated with this symbol (if any)
146 463034 : pub fn binding_info(&self) -> Option<BindingInfo<'_>> {
147 463034 : into_optional(self.ptr.binding_info())
148 463034 : }
149 :
150 : /// Return the library in which this symbol is defined (if any)
151 463034 : pub fn library(&self) -> Option<Dylib<'_>> {
152 463034 : into_optional(self.ptr.library())
153 463034 : }
154 :
155 : /// Whether this symbol is external
156 0 : pub fn is_external(&self) -> bool {
157 0 : self.ptr.is_external()
158 0 : }
159 :
160 : /// Return the library ordinal for this symbol. A negative ordinal indicates
161 : /// a special value (e.g., -1 for `SELF_LIBRARY`, -2 for `MAIN_EXECUTABLE`)
162 0 : pub fn library_ordinal(&self) -> i32 {
163 0 : self.ptr.library_ordinal()
164 0 : }
165 :
166 : /// Try to demangle the symbol or return an empty string if it is not possible
167 335296 : pub fn demangled_name(&self) -> String {
168 335296 : self.ptr.demangled_name().to_string()
169 335296 : }
170 : }
171 :
172 : impl std::fmt::Debug for Symbol<'_> {
173 463034 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
174 463034 : let base = self as &dyn generic::Symbol;
175 463034 : f.debug_struct("Symbol")
176 463034 : .field("base", &base)
177 463034 : .field("type", &self.get_type())
178 463034 : .field("numberof_sections", &self.numberof_sections())
179 463034 : .field("description", &self.description())
180 463034 : .field("origin", &self.origin())
181 463034 : .field("category", &self.category())
182 463034 : .field("export_info", &self.export_info())
183 463034 : .field("binding_info", &self.binding_info())
184 463034 : .field("library", &self.library())
185 463034 : .finish()
186 463034 : }
187 : }
188 :
189 : impl<'a> FromFFI<ffi::MachO_Symbol> for Symbol<'a> {
190 525304 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Symbol>) -> Self {
191 525304 : Self {
192 525304 : ptr,
193 525304 : _owner: PhantomData,
194 525304 : }
195 525304 : }
196 : }
197 :
198 : impl AsFFI<ffi::MachO_Symbol> for Symbol<'_> {
199 0 : fn as_ffi(&self) -> &ffi::MachO_Symbol {
200 0 : self.ptr.as_ref().unwrap()
201 0 : }
202 :
203 0 : fn as_mut_ffi(&mut self) -> Pin<&mut ffi::MachO_Symbol> {
204 0 : self.ptr.pin_mut()
205 0 : }
206 : }
207 :
208 : impl generic::Symbol for Symbol<'_> {
209 1451372 : fn as_generic(&self) -> &ffi::AbstractSymbol {
210 1451372 : self.ptr.as_ref().unwrap().as_ref()
211 1451372 : }
212 :
213 0 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
214 0 : unsafe {
215 0 : Pin::new_unchecked({
216 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
217 0 : as *mut ffi::AbstractSymbol)
218 0 : .as_mut()
219 0 : .unwrap()
220 0 : })
221 0 : }
222 0 : }
223 : }
224 :
225 335296 : declare_iterator!(
226 335296 : Symbols,
227 335296 : Symbol<'a>,
228 335296 : ffi::MachO_Symbol,
229 335296 : ffi::MachO_Binary,
230 335296 : ffi::MachO_Binary_it_symbols
231 335296 : );
|