Line data Source code
1 : use lief_ffi as ffi;
2 :
3 : use std::{fmt, marker::PhantomData};
4 :
5 : use crate::common::FromFFI;
6 :
7 :
8 : #[allow(non_camel_case_types)]
9 64 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10 : /// The type of the underlying ELF file. This enum matches
11 : /// the semantic of `ET_NONE`, `ET_REL`, ...
12 : pub enum FileType {
13 : /// Can't be determined
14 : NONE,
15 :
16 : /// Relocatable file (or object file)
17 : REL,
18 :
19 : /// non-pie executable
20 : EXEC,
21 :
22 : /// Shared library **or** a pie-executable
23 : DYN,
24 :
25 : /// Core dump file
26 : CORE,
27 : UNKNOWN(u32),
28 : }
29 :
30 :
31 : impl FileType {
32 64 : pub fn from_value(value: u32) -> Self {
33 64 : match value {
34 0 : 0x00000000 => FileType::NONE,
35 16 : 0x00000001 => FileType::REL,
36 24 : 0x00000002 => FileType::EXEC,
37 16 : 0x00000003 => FileType::DYN,
38 8 : 0x00000004 => FileType::CORE,
39 0 : _ => FileType::UNKNOWN(value),
40 :
41 : }
42 64 : }
43 : }
44 :
45 :
46 : #[allow(non_camel_case_types)]
47 128 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
48 : /// Match the result of `Elfxx_Ehdr.e_version`
49 : pub enum Version {
50 : /// Invalid ELF version
51 : NONE,
52 :
53 : /// Current version (default)
54 : CURRENT,
55 : UNKNOWN(u32),
56 : }
57 :
58 : impl Version {
59 128 : pub fn from_value(value: u32) -> Self {
60 128 : match value {
61 0 : 0x00000000 => Version::NONE,
62 128 : 0x00000001 => Version::CURRENT,
63 0 : _ => Version::UNKNOWN(value),
64 :
65 : }
66 128 : }
67 : }
68 :
69 :
70 : #[allow(non_camel_case_types)]
71 64 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
72 : /// Match the result of `Elfxx_Ehdr.e_ident[EI_CLASS]`
73 : pub enum Class {
74 : /// Invalid class
75 : NONE,
76 :
77 : /// 32-bit objects
78 : ELF32,
79 :
80 : /// 64-bits objects
81 : ELF64,
82 : UNKNOWN(u32),
83 : }
84 :
85 : impl Class {
86 64 : pub fn from_value(value: u32) -> Self {
87 64 : match value {
88 0 : 0x00000000 => Class::NONE,
89 8 : 0x00000001 => Class::ELF32,
90 56 : 0x00000002 => Class::ELF64,
91 0 : _ => Class::UNKNOWN(value),
92 :
93 : }
94 64 : }
95 : }
96 :
97 :
98 : #[allow(non_camel_case_types)]
99 64 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
100 : /// Match the result `Elfxx_Ehdr.e_ident[EI_OSABI]`
101 : pub enum OsAbi {
102 : /// UNIX System V ABI
103 : SYSTEMV,
104 : /// HP-UX operating system
105 : HPUX,
106 : /// NetBSD
107 : NETBSD,
108 : /// GNU/Linux
109 : GNU,
110 : /// Historical alias for ELFOSABI_GNU.
111 : LINUX,
112 : /// GNU/Hurd
113 : HURD,
114 : /// Solaris
115 : SOLARIS,
116 : /// AIX
117 : AIX,
118 : /// IRIX
119 : IRIX,
120 : /// FreeBSD
121 : FREEBSD,
122 : /// TRU64 UNIX
123 : TRU64,
124 : /// Novell Modesto
125 : MODESTO,
126 : /// OpenBSD
127 : OPENBSD,
128 : /// OpenVMS
129 : OPENVMS,
130 : /// Hewlett-Packard Non-Stop Kernel
131 : NSK,
132 : /// AROS
133 : AROS,
134 : /// FenixOS
135 : FENIXOS,
136 : /// Nuxi CloudABI
137 : CLOUDABI,
138 : /// Bare-metal TMS320C6000
139 : C6000_ELFABI,
140 : /// AMD HSA runtim
141 : AMDGPU_HSA,
142 : /// Linux TMS320C6000
143 : C6000_LINUX,
144 : /// ARM
145 : ARM,
146 : /// Standalone (embedded) applicatio
147 : STANDALONE,
148 : UNKNOWN(u32),
149 : }
150 :
151 :
152 : impl OsAbi {
153 64 : pub fn from_value(value: u32) -> Self {
154 64 : match value {
155 56 : 0x00000000 => OsAbi::SYSTEMV,
156 0 : 0x00000001 => OsAbi::HPUX,
157 0 : 0x00000002 => OsAbi::NETBSD,
158 8 : 0x00000003 => OsAbi::LINUX,
159 0 : 0x00000004 => OsAbi::HURD,
160 0 : 0x00000006 => OsAbi::SOLARIS,
161 0 : 0x00000007 => OsAbi::AIX,
162 0 : 0x00000008 => OsAbi::IRIX,
163 0 : 0x00000009 => OsAbi::FREEBSD,
164 0 : 0x0000000a => OsAbi::TRU64,
165 0 : 0x0000000b => OsAbi::MODESTO,
166 0 : 0x0000000c => OsAbi::OPENBSD,
167 0 : 0x0000000d => OsAbi::OPENVMS,
168 0 : 0x0000000e => OsAbi::NSK,
169 0 : 0x0000000f => OsAbi::AROS,
170 0 : 0x00000010 => OsAbi::FENIXOS,
171 0 : 0x00000011 => OsAbi::CLOUDABI,
172 : /* 0x00000040 => OsAbi::C6000_ELFABI, */
173 0 : 0x00000040 => OsAbi::AMDGPU_HSA,
174 0 : 0x00000041 => OsAbi::C6000_LINUX,
175 0 : 0x00000061 => OsAbi::ARM,
176 0 : 0x000000ff => OsAbi::STANDALONE,
177 0 : _ => OsAbi::UNKNOWN(value),
178 :
179 : }
180 64 : }
181 : }
182 :
183 :
184 : #[allow(non_camel_case_types)]
185 64 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
186 : /// Match the result `Elfxx_Ehdr.e_ident[EI_DATA]`
187 : pub enum ElfData {
188 : /// Invalid data encodin
189 : NONE,
190 : /// 2's complement, little endian
191 : LSB,
192 : /// 2's complement, big endian
193 : MSB,
194 : UNKNOWN(u32),
195 : }
196 :
197 : impl ElfData {
198 64 : pub fn from_value(value: u32) -> Self {
199 64 : match value {
200 0 : 0x00000000 => ElfData::NONE,
201 56 : 0x00000001 => ElfData::LSB,
202 8 : 0x00000002 => ElfData::MSB,
203 0 : _ => ElfData::UNKNOWN(value),
204 :
205 : }
206 64 : }
207 : }
208 :
209 : /// Class which represents the ELF's header. This class mirrors the raw
210 : /// ELF `Elfxx_Ehdr` structure
211 : pub struct Header<'a> {
212 : ptr: cxx::UniquePtr<ffi::ELF_Header>,
213 : _owner: PhantomData<&'a ffi::ELF_Binary>
214 : }
215 :
216 : impl FromFFI<ffi::ELF_Header> for Header<'_> {
217 64 : fn from_ffi(hdr: cxx::UniquePtr<ffi::ELF_Header>) -> Self {
218 64 : Self {
219 64 : ptr: hdr,
220 64 : _owner: PhantomData
221 64 : }
222 64 : }
223 : }
224 :
225 : impl Header<'_> {
226 : /// Executable entrypoint
227 64 : pub fn entrypoint(&self) -> u64 {
228 64 : self.ptr.entrypoint()
229 64 : }
230 :
231 : /// Define the object file type. (e.g. executable, library...)
232 64 : pub fn file_type(&self) -> FileType {
233 64 : FileType::from_value(self.ptr.file_type())
234 64 : }
235 :
236 : /// Version of the object file format
237 64 : pub fn object_file_version(&self) -> Version {
238 64 : Version::from_value(self.ptr.object_file_version())
239 64 : }
240 :
241 : /// Return the object's class. `ELF64` or `ELF32`
242 64 : pub fn identity_class(&self) -> Class {
243 64 : Class::from_value(self.ptr.identity_class())
244 64 : }
245 :
246 : /// Specify the data encoding
247 64 : pub fn identity_data(&self) -> ElfData {
248 64 : ElfData::from_value(self.ptr.identity_data())
249 64 : }
250 :
251 : /// See: [`Header::object_file_version`]
252 64 : pub fn identity_version(&self) -> Version {
253 64 : Version::from_value(self.ptr.identity_version())
254 64 : }
255 :
256 : /// Identifies the version of the ABI for which the object is prepared
257 64 : pub fn identity_os_abi(&self) -> OsAbi {
258 64 : OsAbi::from_value(self.ptr.identity_os_abi())
259 64 : }
260 :
261 : /// Target architecture
262 64 : pub fn machine_type(&self) -> u32 {
263 64 : self.ptr.machine_type()
264 64 : }
265 :
266 : /// Offset of the programs table (also known as segments table)
267 64 : pub fn program_headers_offset(&self) -> u64 {
268 64 : self.ptr.program_headers_offset()
269 64 : }
270 :
271 : /// Offset of the sections table
272 64 : pub fn section_headers_offset(&self) -> u64 {
273 64 : self.ptr.section_headers_offset()
274 64 : }
275 :
276 : /// Processor-specific flags
277 64 : pub fn processor_flag(&self) -> u32 {
278 64 : self.ptr.processor_flag()
279 64 : }
280 :
281 : /// Size of the current header (i.e. `sizeof(Elfxx_Ehdr)`)
282 : /// This size should be 64 for an `ELF64` binary and 52 for an `ELF32`.
283 64 : pub fn header_size(&self) -> u32 {
284 64 : self.ptr.header_size()
285 64 : }
286 :
287 : /// Return the size of a program header (i.e. `sizeof(Elfxx_Phdr)`)
288 : /// This size should be 56 for an `ELF64` binary and 32 for an `ELF32`.
289 64 : pub fn program_header_size(&self) -> u32 {
290 64 : self.ptr.program_header_size()
291 64 : }
292 :
293 : /// Return the number of segments
294 64 : pub fn numberof_segments(&self) -> u32 {
295 64 : self.ptr.numberof_segments()
296 64 : }
297 :
298 : /// Return the size of a section header (i.e. `sizeof(Elfxx_Shdr)`)
299 : /// This size should be 64 for a ``ELF64`` binary and 40 for an ``ELF32``.
300 64 : pub fn section_header_size(&self) -> u32 {
301 64 : self.ptr.section_header_size()
302 64 : }
303 :
304 : /// Return the number of sections
305 : ///
306 : /// <div class="warning">
307 : /// This value could differ from the real number of sections
308 : /// present in the binary. It must be taken as an <i>indication</i>
309 : /// </div>
310 64 : pub fn numberof_sections(&self) -> u32 {
311 64 : self.ptr.numberof_sections()
312 64 : }
313 :
314 : /// Return the section's index which contains sections' names
315 64 : pub fn section_name_table_idx(&self) -> u32 {
316 64 : self.ptr.section_name_table_idx()
317 64 : }
318 : }
319 :
320 : impl fmt::Debug for Header<'_> {
321 64 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 64 : f.debug_struct("Header")
323 64 : .field("entrypoint", &self.entrypoint())
324 64 : .field("object_file_version", &self.object_file_version())
325 64 : .field("identity_class", &self.identity_class())
326 64 : .field("identity_os_abi", &self.identity_os_abi())
327 64 : .field("identity_data", &self.identity_data())
328 64 : .field("identity_version", &self.identity_version())
329 64 : .field("file_type", &self.file_type())
330 64 : .field("machine_type", &self.machine_type())
331 64 : .field("program_headers_offset", &self.program_headers_offset())
332 64 : .field("section_headers_offset", &self.section_headers_offset())
333 64 : .field("processor_flag", &self.processor_flag())
334 64 : .field("header_size", &self.header_size())
335 64 : .field("program_header_size", &self.program_header_size())
336 64 : .field("numberof_segments", &self.numberof_segments())
337 64 : .field("section_header_size", &self.section_header_size())
338 64 : .field("numberof_sections", &self.numberof_sections())
339 64 : .field("section_name_table_idx", &self.section_name_table_idx())
340 64 : .finish()
341 64 : }
342 : }
|