Line data Source code
1 : use std::marker::PhantomData;
2 :
3 : use crate::common::{into_optional, FromFFI};
4 : use crate::declare_iterator;
5 : use crate::generic;
6 : use lief_ffi as ffi;
7 :
8 : use super::commands::Dylib;
9 : use super::{BindingInfo, ExportInfo};
10 :
11 : /// Structure that represents a Symbol in a Mach-O file.
12 : ///
13 : /// A Mach-O symbol can come from:
14 : /// 1. The symbols command (LC_SYMTAB / SymbolCommand)
15 : /// 2. The Dyld Export trie
16 : /// 3. The Dyld Symbol bindings
17 : pub struct Symbol<'a> {
18 : ptr: cxx::UniquePtr<ffi::MachO_Symbol>,
19 : _owner: PhantomData<&'a ()>,
20 : }
21 :
22 : #[allow(non_camel_case_types)]
23 336720 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
24 : pub enum Category {
25 : NONE,
26 : LOCAL,
27 : EXTERNAL,
28 : UNDEFINED,
29 : INDIRECT_ABS,
30 : INDIRECT_LOCAL,
31 : INDIRECT_ABS_LOCAL,
32 : UNKNOWN(u32),
33 : }
34 :
35 : impl From<u32> for Category {
36 336720 : fn from(value: u32) -> Self {
37 336720 : match value {
38 87270 : 0x00000000 => Category::NONE,
39 138760 : 0x00000001 => Category::LOCAL,
40 69940 : 0x00000002 => Category::EXTERNAL,
41 40750 : 0x00000003 => Category::UNDEFINED,
42 0 : 0x00000004 => Category::INDIRECT_ABS,
43 0 : 0x00000005 => Category::INDIRECT_LOCAL,
44 0 : 0x00000006 => Category::INDIRECT_ABS_LOCAL,
45 0 : _ => Category::UNKNOWN(value),
46 : }
47 336720 : }
48 : }
49 :
50 : #[allow(non_camel_case_types)]
51 336720 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
52 : pub enum Origin {
53 : DYLD_EXPORT,
54 : DYLD_BIND,
55 : LC_SYMTAB,
56 : UNKNOWN(u32),
57 : }
58 :
59 : impl From<u32> for Origin {
60 336720 : fn from(value: u32) -> Self {
61 336720 : match value {
62 41400 : 0x00000001 => Origin::DYLD_EXPORT,
63 45870 : 0x00000002 => Origin::DYLD_BIND,
64 249450 : 0x00000003 => Origin::LC_SYMTAB,
65 0 : _ => Origin::UNKNOWN(value),
66 : }
67 336720 : }
68 : }
69 :
70 : impl Symbol<'_> {
71 336720 : pub fn get_type(&self) -> u8 {
72 336720 : self.ptr.get_type()
73 336720 : }
74 :
75 : /// It returns the number of sections in which this symbol can be found.
76 : /// If the symbol can't be found in any section, it returns 0 (`NO_SECT`)
77 336720 : pub fn numberof_sections(&self) -> u8 {
78 336720 : self.ptr.numberof_sections()
79 336720 : }
80 :
81 : /// Return information about the symbol
82 336720 : pub fn description(&self) -> u16 {
83 336720 : self.ptr.description()
84 336720 : }
85 :
86 : /// Return the origin of the symbol: from `LC_SYMTAB` from the Dyld information, ...
87 336720 : pub fn origin(&self) -> Origin {
88 336720 : Origin::from(self.ptr.origin())
89 336720 : }
90 :
91 : /// Category of the symbol according to the `LC_DYSYMTAB` command
92 336720 : pub fn category(&self) -> Category {
93 336720 : Category::from(self.ptr.category())
94 336720 : }
95 :
96 : /// Export info associated with this symbol (if any)
97 336720 : pub fn export_info(&self) -> Option<ExportInfo> {
98 336720 : into_optional(self.ptr.export_info())
99 336720 : }
100 :
101 : /// Binding info associated with this symbol (if any)
102 336720 : pub fn binding_info(&self) -> Option<BindingInfo> {
103 336720 : into_optional(self.ptr.binding_info())
104 336720 : }
105 :
106 : /// Return the library in which this symbol is defined (if any)
107 336720 : pub fn library(&self) -> Option<Dylib> {
108 336720 : into_optional(self.ptr.library())
109 336720 : }
110 :
111 : /// Try to demangle the symbol or return an empty string if it is not possible
112 242200 : pub fn demangled_name(&self) -> String {
113 242200 : self.ptr.demangled_name().to_string()
114 242200 : }
115 : }
116 :
117 : impl std::fmt::Debug for Symbol<'_> {
118 336720 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 336720 : let base = self as &dyn generic::Symbol;
120 336720 : f.debug_struct("Symbol")
121 336720 : .field("base", &base)
122 336720 : .field("type", &self.get_type())
123 336720 : .field("numberof_sections", &self.numberof_sections())
124 336720 : .field("description", &self.description())
125 336720 : .field("origin", &self.origin())
126 336720 : .field("category", &self.category())
127 336720 : .field("export_info", &self.export_info())
128 336720 : .field("binding_info", &self.binding_info())
129 336720 : .field("library", &self.library())
130 336720 : .finish()
131 336720 : }
132 : }
133 :
134 : impl<'a> FromFFI<ffi::MachO_Symbol> for Symbol<'a> {
135 378800 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Symbol>) -> Self {
136 378800 : Self {
137 378800 : ptr,
138 378800 : _owner: PhantomData,
139 378800 : }
140 378800 : }
141 : }
142 :
143 : impl generic::Symbol for Symbol<'_> {
144 1052240 : fn as_generic(&self) -> &ffi::AbstractSymbol {
145 1052240 : self.ptr.as_ref().unwrap().as_ref()
146 1052240 : }
147 : }
148 :
149 242200 : declare_iterator!(
150 242200 : Symbols,
151 242200 : Symbol<'a>,
152 242200 : ffi::MachO_Symbol,
153 242200 : ffi::MachO_Binary,
154 242200 : ffi::MachO_Binary_it_symbols
155 242200 : );
|