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 45880 : pub fn value(&self) -> u16 {
22 45880 : self.ptr.value()
23 45880 : }
24 :
25 : /// SymbolVersionAux associated with the current Version if any.
26 45880 : pub fn symbol_version_auxiliary(&self) -> Option<SymbolVersionAux> {
27 45880 : into_optional(self.ptr.symbol_version_auxiliary())
28 45880 : }
29 : }
30 :
31 : impl fmt::Debug for SymbolVersion<'_> {
32 45880 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 45880 : f.debug_struct("SymbolVersion")
34 45880 : .field("value", &self.value())
35 45880 : .field("symbol_version_auxiliary", &self.symbol_version_auxiliary())
36 45880 : .finish()
37 45880 : }
38 : }
39 :
40 : impl FromFFI<ffi::ELF_SymbolVersion> for SymbolVersion<'_> {
41 45880 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersion>) -> Self {
42 45880 : Self {
43 45880 : ptr,
44 45880 : _owner: PhantomData
45 45880 : }
46 45880 : }
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 25410 : pub fn name(&self) -> String {
57 25410 : self.ptr.name().to_string()
58 25410 : }
59 : }
60 :
61 : impl fmt::Debug for SymbolVersionAux<'_> {
62 25410 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 25410 : f.debug_struct("SymbolVersionAux")
64 25410 : .field("name", &self.name())
65 25410 : .finish()
66 25410 : }
67 : }
68 :
69 : impl FromFFI<ffi::ELF_SymbolVersionAux> for SymbolVersionAux<'_> {
70 25410 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAux>) -> Self {
71 25410 : Self {
72 25410 : ptr,
73 25410 : _owner: PhantomData
74 25410 : }
75 25410 : }
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 460 : pub fn hash(&self) -> u32 {
86 460 : self.ptr.hash()
87 460 : }
88 : /// Bitmask of flags
89 460 : pub fn flags(&self) -> u16 {
90 460 : self.ptr.flags()
91 460 : }
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 460 : pub fn other(&self) -> u16 {
98 460 : self.ptr.other()
99 460 : }
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 460 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 460 : f.debug_struct("SymbolVersionAuxRequirement")
112 460 : .field("hash", &self.hash())
113 460 : .field("flags", &self.flags())
114 460 : .field("other", &self.other())
115 460 : .finish()
116 460 : }
117 : }
118 :
119 : impl FromFFI<ffi::ELF_SymbolVersionAuxRequirement> for SymbolVersionAuxRequirement<'_> {
120 460 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionAuxRequirement>) -> Self {
121 460 : Self {
122 460 : ptr,
123 460 : _owner: PhantomData
124 460 : }
125 460 : }
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 30 : pub fn version(&self) -> u16 {
141 30 : self.ptr.version()
142 30 : }
143 :
144 : /// Version information
145 30 : pub fn flags(&self) -> u16 {
146 30 : self.ptr.flags()
147 30 : }
148 :
149 : /// Version index
150 : /// Numeric value used as an index in the [`SymbolVersion`] table
151 30 : pub fn ndx(&self) -> u16 {
152 30 : self.ptr.ndx()
153 30 : }
154 :
155 : /// Hash value of the symbol's name (using ELF hash function)
156 30 : pub fn hash(&self) -> u32 {
157 30 : self.ptr.hash()
158 30 : }
159 :
160 : /// Iterator over the [`SymbolVersionAux`] associated with this entry
161 30 : pub fn auxiliary_symbols(&self) -> DefAuxiliarySymbols {
162 30 : DefAuxiliarySymbols::new(self.ptr.sym_aux())
163 30 : }
164 : }
165 :
166 : impl fmt::Debug for SymbolVersionDefinition<'_> {
167 30 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 30 : f.debug_struct("SymbolVersionDefinition")
169 30 : .field("version", &self.version())
170 30 : .field("flags", &self.flags())
171 30 : .field("ndx", &self.ndx())
172 30 : .field("hash", &self.hash())
173 30 : .finish()
174 30 : }
175 : }
176 :
177 : impl FromFFI<ffi::ELF_SymbolVersionDefinition> for SymbolVersionDefinition<'_> {
178 30 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionDefinition>) -> Self {
179 30 : Self {
180 30 : ptr,
181 30 : _owner: PhantomData
182 30 : }
183 30 : }
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 150 : pub fn version(&self) -> u16 {
199 150 : self.ptr.version()
200 150 : }
201 :
202 : /// Number of auxiliary entries
203 150 : pub fn cnt(&self) -> u32 {
204 150 : self.ptr.cnt()
205 150 : }
206 :
207 : /// Return the library name associated with this requirement (e.g. `libc.so.6`)
208 150 : pub fn name(&self) -> String {
209 150 : self.ptr.name().to_string()
210 150 : }
211 :
212 : /// Auxiliary entries as an iterator over [`SymbolVersionAuxRequirement`]
213 150 : pub fn auxiliary_symbols(&self) -> AuxiliarySymbols {
214 150 : AuxiliarySymbols::new(self.ptr.auxiliary_symbols())
215 150 : }
216 : }
217 :
218 : impl fmt::Debug for SymbolVersionRequirement<'_> {
219 150 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 150 : f.debug_struct("SymbolVersionRequirement")
221 150 : .field("verison", &self.version())
222 150 : .field("cnt", &self.cnt())
223 150 : .field("name", &self.name())
224 150 : .finish()
225 150 : }
226 : }
227 :
228 : impl FromFFI<ffi::ELF_SymbolVersionRequirement> for SymbolVersionRequirement<'_> {
229 150 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_SymbolVersionRequirement>) -> Self {
230 150 : Self {
231 150 : ptr,
232 150 : _owner: PhantomData,
233 150 : }
234 150 : }
235 : }
236 :
237 460 : declare_iterator!(
238 460 : AuxiliarySymbols,
239 460 : SymbolVersionAuxRequirement<'a>,
240 460 : ffi::ELF_SymbolVersionAuxRequirement,
241 460 : ffi::ELF_SymbolVersionRequirement,
242 460 : ffi::ELF_SymbolVersionRequirement_it_auxiliary_symbols
243 460 : );
244 30 : declare_iterator!(
245 30 : DefAuxiliarySymbols,
246 30 : SymbolVersionAux<'a>,
247 30 : ffi::ELF_SymbolVersionAux,
248 30 : ffi::ELF_SymbolVersionDefinition,
249 30 : ffi::ELF_SymbolVersionDefinition_it_auxiliary_symbols
250 30 : );
251 :
|