Line data Source code
1 : use std::marker::PhantomData;
2 : use std::pin::Pin;
3 :
4 : use crate::common::{into_optional, 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 404268 : #[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 404268 : fn from(value: u32) -> Self {
38 404268 : match value {
39 104724 : 0x00000000 => Category::NONE,
40 166680 : 0x00000001 => Category::LOCAL,
41 83952 : 0x00000002 => Category::EXTERNAL,
42 48912 : 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 404268 : }
49 : }
50 :
51 : #[allow(non_camel_case_types)]
52 404268 : #[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 404268 : fn from(value: u32) -> Self {
62 404268 : match value {
63 49680 : 0x00000001 => Origin::DYLD_EXPORT,
64 55044 : 0x00000002 => Origin::DYLD_BIND,
65 299544 : 0x00000003 => Origin::LC_SYMTAB,
66 0 : _ => Origin::UNKNOWN(value),
67 : }
68 404268 : }
69 : }
70 :
71 : impl Symbol<'_> {
72 404268 : pub fn get_type(&self) -> u8 {
73 404268 : self.ptr.get_type()
74 404268 : }
75 :
76 : /// It returns the number of sections in which this symbol can be found.
77 : /// If the symbol can't be found in any section, it returns 0 (`NO_SECT`)
78 404268 : pub fn numberof_sections(&self) -> u8 {
79 404268 : self.ptr.numberof_sections()
80 404268 : }
81 :
82 : /// Return information about the symbol
83 404268 : pub fn description(&self) -> u16 {
84 404268 : self.ptr.description()
85 404268 : }
86 :
87 : /// Return the origin of the symbol: from `LC_SYMTAB` from the Dyld information, ...
88 404268 : pub fn origin(&self) -> Origin {
89 404268 : Origin::from(self.ptr.origin())
90 404268 : }
91 :
92 : /// Category of the symbol according to the `LC_DYSYMTAB` command
93 404268 : pub fn category(&self) -> Category {
94 404268 : Category::from(self.ptr.category())
95 404268 : }
96 :
97 : /// Export info associated with this symbol (if any)
98 404268 : pub fn export_info(&self) -> Option<ExportInfo> {
99 404268 : into_optional(self.ptr.export_info())
100 404268 : }
101 :
102 : /// Binding info associated with this symbol (if any)
103 404268 : pub fn binding_info(&self) -> Option<BindingInfo> {
104 404268 : into_optional(self.ptr.binding_info())
105 404268 : }
106 :
107 : /// Return the library in which this symbol is defined (if any)
108 404268 : pub fn library(&self) -> Option<Dylib> {
109 404268 : into_optional(self.ptr.library())
110 404268 : }
111 :
112 : /// Try to demangle the symbol or return an empty string if it is not possible
113 290832 : pub fn demangled_name(&self) -> String {
114 290832 : self.ptr.demangled_name().to_string()
115 290832 : }
116 : }
117 :
118 : impl std::fmt::Debug for Symbol<'_> {
119 404268 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 404268 : let base = self as &dyn generic::Symbol;
121 404268 : f.debug_struct("Symbol")
122 404268 : .field("base", &base)
123 404268 : .field("type", &self.get_type())
124 404268 : .field("numberof_sections", &self.numberof_sections())
125 404268 : .field("description", &self.description())
126 404268 : .field("origin", &self.origin())
127 404268 : .field("category", &self.category())
128 404268 : .field("export_info", &self.export_info())
129 404268 : .field("binding_info", &self.binding_info())
130 404268 : .field("library", &self.library())
131 404268 : .finish()
132 404268 : }
133 : }
134 :
135 : impl<'a> FromFFI<ffi::MachO_Symbol> for Symbol<'a> {
136 454788 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Symbol>) -> Self {
137 454788 : Self {
138 454788 : ptr,
139 454788 : _owner: PhantomData,
140 454788 : }
141 454788 : }
142 : }
143 :
144 : impl generic::Symbol for Symbol<'_> {
145 1263324 : fn as_generic(&self) -> &ffi::AbstractSymbol {
146 1263324 : self.ptr.as_ref().unwrap().as_ref()
147 1263324 : }
148 :
149 0 : fn as_pin_mut_generic(&mut self) -> Pin<&mut ffi::AbstractSymbol> {
150 0 : unsafe {
151 0 : Pin::new_unchecked({
152 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSymbol
153 0 : as *mut ffi::AbstractSymbol)
154 0 : .as_mut()
155 0 : .unwrap()
156 0 : })
157 0 : }
158 0 : }
159 : }
160 :
161 290832 : declare_iterator!(
162 290832 : Symbols,
163 290832 : Symbol<'a>,
164 290832 : ffi::MachO_Symbol,
165 290832 : ffi::MachO_Binary,
166 290832 : ffi::MachO_Binary_it_symbols
167 290832 : );
|