Line data Source code
1 : use lief_ffi as ffi;
2 : use std::fmt;
3 : use crate::declare_iterator;
4 : use std::marker::PhantomData;
5 : use crate::common::{FromFFI, into_optional};
6 :
7 : /// Structure which represents an entry defined in the `DT_VERSYM`
8 : /// dynamic entry
9 : pub struct SymbolVersion<'a> {
10 : ptr: cxx::UniquePtr<ffi::ELF_SymbolVersion>,
11 : _owner: PhantomData<&'a ffi::ELF_Binary>
12 : }
13 :
14 : impl SymbolVersion<'_> {
15 : /// Value associated with the symbol
16 : ///
17 : /// If the given [`SymbolVersion`] doesn't have [`SymbolVersion::symbol_version_auxiliary`]:
18 : ///
19 : /// * `0` means **Local**
20 : /// * `1` means **Global**
21 36704 : pub fn value(&self) -> u16 {
22 36704 : self.ptr.value()
23 36704 : }
24 :
25 : /// SymbolVersionAux associated with the current Version if any.
26 36704 : pub fn symbol_version_auxiliary(&self) -> Option<SymbolVersionAux> {
27 36704 : into_optional(self.ptr.symbol_version_auxiliary())
28 36704 : }
29 : }
30 :
31 : impl fmt::Debug for SymbolVersion<'_> {
32 36704 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 36704 : f.debug_struct("SymbolVersion")
34 36704 : .field("value", &self.value())
35 36704 : .field("symbol_version_auxiliary", &self.symbol_version_auxiliary())
36 36704 : .finish()
37 36704 : }
38 : }
39 :
40 : impl FromFFI<ffi::ELF_SymbolVersion> for SymbolVersion<'_> {
41 36704 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersion>) -> Self {
42 36704 : Self {
43 36704 : ptr,
44 36704 : _owner: PhantomData
45 36704 : }
46 36704 : }
47 : }
48 :
49 : pub struct SymbolVersionAux<'a> {
50 : ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAux>,
51 : _owner: PhantomData<&'a ()>
52 : }
53 :
54 :
55 : impl SymbolVersionAux<'_> {
56 20328 : pub fn name(&self) -> String {
57 20328 : self.ptr.name().to_string()
58 20328 : }
59 : }
60 :
61 : impl fmt::Debug for SymbolVersionAux<'_> {
62 20328 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 20328 : f.debug_struct("SymbolVersionAux")
64 20328 : .field("name", &self.name())
65 20328 : .finish()
66 20328 : }
67 : }
68 :
69 : impl FromFFI<ffi::ELF_SymbolVersionAux> for SymbolVersionAux<'_> {
70 20328 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAux>) -> Self {
71 20328 : Self {
72 20328 : ptr,
73 20328 : _owner: PhantomData
74 20328 : }
75 20328 : }
76 : }
77 :
78 : pub struct SymbolVersionAuxRequirement<'a> {
79 : ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAuxRequirement>,
80 : _owner: PhantomData<&'a ()>
81 : }
82 :
83 : impl SymbolVersionAuxRequirement<'_> {
84 : /// Hash value of the dependency name (use ELF hashing function)
85 368 : pub fn hash(&self) -> u32 {
86 368 : self.ptr.hash()
87 368 : }
88 : /// Bitmask of flags
89 368 : pub fn flags(&self) -> u16 {
90 368 : self.ptr.flags()
91 368 : }
92 :
93 : /// It returns the unique version index for the file which is used in the
94 : /// version symbol table. If the highest bit (bit 15) is set this
95 : /// is a hidden symbol which cannot be referenced from outside the
96 : /// object.
97 368 : pub fn other(&self) -> u16 {
98 368 : self.ptr.other()
99 368 : }
100 :
101 :
102 : /// Symbol's aux name (e.g. ``GLIBC_2.2.5``)
103 0 : pub fn name(&self) -> String {
104 0 : self.ptr.name().to_string()
105 0 : }
106 :
107 : }
108 :
109 : impl fmt::Debug for SymbolVersionAuxRequirement<'_> {
110 368 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 368 : f.debug_struct("SymbolVersionAuxRequirement")
112 368 : .field("hash", &self.hash())
113 368 : .field("flags", &self.flags())
114 368 : .field("other", &self.other())
115 368 : .finish()
116 368 : }
117 : }
118 :
119 : impl FromFFI<ffi::ELF_SymbolVersionAuxRequirement> for SymbolVersionAuxRequirement<'_> {
120 368 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAuxRequirement>) -> Self {
121 368 : Self {
122 368 : ptr,
123 368 : _owner: PhantomData
124 368 : }
125 368 : }
126 : }
127 :
128 : /// Structure which represents an entry defined in `DT_VERDEF` or `.gnu.version_d`
129 : pub struct SymbolVersionDefinition<'a> {
130 : ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionDefinition>,
131 : _owner: PhantomData<&'a ()>
132 : }
133 :
134 :
135 : impl SymbolVersionDefinition<'_> {
136 : /// Version revision
137 : ///
138 : /// This field should always have the value `1`. It will be changed
139 : /// if the versioning implementation has to be changed in an incompatible way.
140 24 : pub fn version(&self) -> u16 {
141 24 : self.ptr.version()
142 24 : }
143 :
144 : /// Version information
145 24 : pub fn flags(&self) -> u16 {
146 24 : self.ptr.flags()
147 24 : }
148 :
149 : /// Version index
150 : /// Numeric value used as an index in the [`SymbolVersion`] table
151 24 : pub fn ndx(&self) -> u16 {
152 24 : self.ptr.ndx()
153 24 : }
154 :
155 : /// Hash value of the symbol's name (using ELF hash function)
156 24 : pub fn hash(&self) -> u32 {
157 24 : self.ptr.hash()
158 24 : }
159 :
160 : /// Iterator over the [`SymbolVersionAux`] associated with this entry
161 24 : pub fn auxiliary_symbols(&self) -> DefAuxiliarySymbols {
162 24 : DefAuxiliarySymbols::new(self.ptr.sym_aux())
163 24 : }
164 : }
165 :
166 : impl fmt::Debug for SymbolVersionDefinition<'_> {
167 24 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 24 : f.debug_struct("SymbolVersionDefinition")
169 24 : .field("version", &self.version())
170 24 : .field("flags", &self.flags())
171 24 : .field("ndx", &self.ndx())
172 24 : .field("hash", &self.hash())
173 24 : .finish()
174 24 : }
175 : }
176 :
177 : impl FromFFI<ffi::ELF_SymbolVersionDefinition> for SymbolVersionDefinition<'_> {
178 24 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionDefinition>) -> Self {
179 24 : Self {
180 24 : ptr,
181 24 : _owner: PhantomData
182 24 : }
183 24 : }
184 : }
185 :
186 :
187 : /// Structure which represents an entry in the ``DT_VERNEED`` or ``.gnu.version_r`` table
188 : pub struct SymbolVersionRequirement<'a> {
189 : ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionRequirement>,
190 : _owner: PhantomData<&'a ()>
191 : }
192 :
193 : impl SymbolVersionRequirement<'_> {
194 : /// Version revision
195 : ///
196 : /// This field should always have the value `1`. It will be changed
197 : /// if the versioning implementation has to be changed in an incompatible way.
198 120 : pub fn version(&self) -> u16 {
199 120 : self.ptr.version()
200 120 : }
201 :
202 : /// Number of auxiliary entries
203 120 : pub fn cnt(&self) -> u32 {
204 120 : self.ptr.cnt()
205 120 : }
206 :
207 : /// Return the library name associated with this requirement (e.g. `libc.so.6`)
208 120 : pub fn name(&self) -> String {
209 120 : self.ptr.name().to_string()
210 120 : }
211 :
212 : /// Auxiliary entries as an iterator over [`SymbolVersionAuxRequirement`]
213 120 : pub fn auxiliary_symbols(&self) -> AuxiliarySymbols {
214 120 : AuxiliarySymbols::new(self.ptr.auxiliary_symbols())
215 120 : }
216 : }
217 :
218 : impl fmt::Debug for SymbolVersionRequirement<'_> {
219 120 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 120 : f.debug_struct("SymbolVersionRequirement")
221 120 : .field("verison", &self.version())
222 120 : .field("cnt", &self.cnt())
223 120 : .field("name", &self.name())
224 120 : .finish()
225 120 : }
226 : }
227 :
228 : impl FromFFI<ffi::ELF_SymbolVersionRequirement> for SymbolVersionRequirement<'_> {
229 120 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionRequirement>) -> Self {
230 120 : Self {
231 120 : ptr,
232 120 : _owner: PhantomData,
233 120 : }
234 120 : }
235 : }
236 :
237 368 : declare_iterator!(
238 368 : AuxiliarySymbols,
239 368 : SymbolVersionAuxRequirement<'a>,
240 368 : ffi::ELF_SymbolVersionAuxRequirement,
241 368 : ffi::ELF_SymbolVersionRequirement,
242 368 : ffi::ELF_SymbolVersionRequirement_it_auxiliary_symbols
243 368 : );
244 24 : declare_iterator!(
245 24 : DefAuxiliarySymbols,
246 24 : SymbolVersionAux<'a>,
247 24 : ffi::ELF_SymbolVersionAux,
248 24 : ffi::ELF_SymbolVersionDefinition,
249 24 : ffi::ELF_SymbolVersionDefinition_it_auxiliary_symbols
250 24 : );
251 :
|