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 269376 : #[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 269376 : fn from(value: u32) -> Self {
37 269376 : match value {
38 69816 : 0x00000000 => Category::NONE,
39 111008 : 0x00000001 => Category::LOCAL,
40 55952 : 0x00000002 => Category::EXTERNAL,
41 32600 : 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 269376 : }
48 : }
49 :
50 : #[allow(non_camel_case_types)]
51 269376 : #[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 269376 : fn from(value: u32) -> Self {
61 269376 : match value {
62 33120 : 0x00000001 => Origin::DYLD_EXPORT,
63 36696 : 0x00000002 => Origin::DYLD_BIND,
64 199560 : 0x00000003 => Origin::LC_SYMTAB,
65 0 : _ => Origin::UNKNOWN(value),
66 : }
67 269376 : }
68 : }
69 :
70 : impl Symbol<'_> {
71 269376 : pub fn get_type(&self) -> u8 {
72 269376 : self.ptr.get_type()
73 269376 : }
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 269376 : pub fn numberof_sections(&self) -> u8 {
78 269376 : self.ptr.numberof_sections()
79 269376 : }
80 :
81 : /// Return information about the symbol
82 269376 : pub fn description(&self) -> u16 {
83 269376 : self.ptr.description()
84 269376 : }
85 :
86 : /// Return the origin of the symbol: from `LC_SYMTAB` from the Dyld information, ...
87 269376 : pub fn origin(&self) -> Origin {
88 269376 : Origin::from(self.ptr.origin())
89 269376 : }
90 :
91 : /// Category of the symbol according to the `LC_DYSYMTAB` command
92 269376 : pub fn category(&self) -> Category {
93 269376 : Category::from(self.ptr.category())
94 269376 : }
95 :
96 : /// Export info associated with this symbol (if any)
97 269376 : pub fn export_info(&self) -> Option<ExportInfo> {
98 269376 : into_optional(self.ptr.export_info())
99 269376 : }
100 :
101 : /// Binding info associated with this symbol (if any)
102 269376 : pub fn binding_info(&self) -> Option<BindingInfo> {
103 269376 : into_optional(self.ptr.binding_info())
104 269376 : }
105 :
106 : /// Return the library in which this symbol is defined (if any)
107 269376 : pub fn library(&self) -> Option<Dylib> {
108 269376 : into_optional(self.ptr.library())
109 269376 : }
110 :
111 : /// Try to demangle the symbol or return an empty string if it is not possible
112 193760 : pub fn demangled_name(&self) -> String {
113 193760 : self.ptr.demangled_name().to_string()
114 193760 : }
115 : }
116 :
117 : impl std::fmt::Debug for Symbol<'_> {
118 269376 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 269376 : let base = self as &dyn generic::Symbol;
120 269376 : f.debug_struct("Symbol")
121 269376 : .field("base", &base)
122 269376 : .field("type", &self.get_type())
123 269376 : .field("numberof_sections", &self.numberof_sections())
124 269376 : .field("description", &self.description())
125 269376 : .field("origin", &self.origin())
126 269376 : .field("category", &self.category())
127 269376 : .field("export_info", &self.export_info())
128 269376 : .field("binding_info", &self.binding_info())
129 269376 : .field("library", &self.library())
130 269376 : .finish()
131 269376 : }
132 : }
133 :
134 : impl<'a> FromFFI<ffi::MachO_Symbol> for Symbol<'a> {
135 303040 : fn from_ffi(ptr: cxx::UniquePtr<ffi::MachO_Symbol>) -> Self {
136 303040 : Self {
137 303040 : ptr,
138 303040 : _owner: PhantomData,
139 303040 : }
140 303040 : }
141 : }
142 :
143 : impl generic::Symbol for Symbol<'_> {
144 841792 : fn as_generic(&self) -> &ffi::AbstractSymbol {
145 841792 : self.ptr.as_ref().unwrap().as_ref()
146 841792 : }
147 : }
148 :
149 193760 : declare_iterator!(
150 193760 : Symbols,
151 193760 : Symbol<'a>,
152 193760 : ffi::MachO_Symbol,
153 193760 : ffi::MachO_Binary,
154 193760 : ffi::MachO_Binary_it_symbols
155 193760 : );
|