Line data Source code
1 : use bitflags::bitflags;
2 : use lief_ffi as ffi;
3 : use std::fmt;
4 : use std::marker::PhantomData;
5 : use std::pin::Pin;
6 :
7 : use crate::common::FromFFI;
8 : use crate::declare_iterator;
9 : use crate::generic;
10 : use crate::to_slice;
11 :
12 : /// Structure which represents an ELF Section
13 : pub struct Section<'a> {
14 : ptr: cxx::UniquePtr<ffi::ELF_Section>,
15 : _owner: PhantomData<&'a ()>,
16 : }
17 :
18 : impl Section<'_> {
19 : /// Type of the section
20 14170 : pub fn get_type(&self) -> Type {
21 14170 : Type::from(self.ptr.get_type())
22 14170 : }
23 :
24 : /// Sections flags
25 14170 : pub fn flags(&self) -> Flags {
26 14170 : Flags::from_value(self.ptr.flags())
27 14170 : }
28 :
29 : /// Section alignment
30 14170 : pub fn alignment(&self) -> u64 {
31 14170 : self.ptr.alignment()
32 14170 : }
33 :
34 : /// Section information.
35 : /// This meaning of this value depends on the section's type
36 14170 : pub fn information(&self) -> u64 {
37 14170 : self.ptr.information()
38 14170 : }
39 :
40 : /// This function returns the size of an element in the case of a section that contains
41 : /// an array.
42 : ///
43 : /// For instance, the `.dynamic` section contains an array of DynamicEntry. As the
44 : /// size of the raw C structure of this entry is 0x10 (`sizeof(Elf64_Dyn)`)
45 : /// in an ELF64, the `entry_size` is set to this value.
46 14170 : pub fn entry_size(&self) -> u64 {
47 14170 : self.ptr.entry_size()
48 14170 : }
49 :
50 : /// Index to another section
51 14170 : pub fn link(&self) -> u64 {
52 14170 : self.ptr.link()
53 14170 : }
54 :
55 : /// Offset in the file where the content of this section is located
56 14170 : pub fn file_offset(&self) -> u64 {
57 14170 : self.ptr.file_offset()
58 14170 : }
59 :
60 : /// Original size of the section (regardless modifications)
61 14170 : pub fn original_size(&self) -> u64 {
62 14170 : self.ptr.original_size()
63 14170 : }
64 :
65 : /// Content of the section as a slice of bytes
66 3315 : pub fn content(&self) -> &[u8] {
67 3315 : to_slice!(self.ptr.content());
68 3315 : }
69 : }
70 :
71 : #[allow(non_camel_case_types)]
72 14170 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
73 : pub enum Type {
74 : /// No associated section (inactive entry)
75 : SHT_NULL,
76 : /// Program-defined contents.
77 : PROGBITS,
78 : /// Symbol table
79 : SYMTAB,
80 : /// String table
81 : STRTAB,
82 : /// Relocation entries; explicit addends.
83 : RELA,
84 : /// Symbol hash table.
85 : HASH,
86 : /// Information for dynamic linking.
87 : DYNAMIC,
88 : /// Information about the file.
89 : NOTE,
90 : /// Data occupies no space in the file.
91 : NOBITS,
92 : /// Relocation entries; no explicit addends.
93 : REL,
94 : /// Reserved
95 : SHLIB,
96 : /// Symbol table.
97 : DYNSYM,
98 : /// Pointers to initialization functions.
99 : INIT_ARRAY,
100 : /// Pointers to termination functions.
101 : FINI_ARRAY,
102 : /// Pointers to pre-init functions.
103 : PREINIT_ARRAY,
104 : /// Section group.
105 : GROUP,
106 : /// Indices for SHN_XINDEX entries.
107 : SYMTAB_SHNDX,
108 : /// Relocation entries; only offsets.
109 : RELR,
110 : /// Packed relocations (Android specific).
111 : ANDROID_REL,
112 : /// Packed relocations (Android specific).
113 : ANDROID_RELA,
114 : /// This section is used to mark symbols as address-significant.
115 : LLVM_ADDRSIG,
116 : /// New relr relocations (Android specific).
117 : ANDROID_RELR,
118 : /// Object attributes.
119 : GNU_ATTRIBUTES,
120 : /// GNU-style hash table.
121 : GNU_HASH,
122 : /// GNU version definitions.
123 : GNU_VERDEF,
124 : /// GNU version references.
125 : GNU_VERNEED,
126 : /// GNU symbol versions table.
127 : GNU_VERSYM,
128 : /// Exception Index table
129 : ARM_EXIDX,
130 : /// BPABI DLL dynamic linking pre-emption map
131 : ARM_PREEMPTMAP,
132 : /// Object file compatibility attributes
133 : ARM_ATTRIBUTES,
134 : ARM_DEBUGOVERLAY,
135 : ARM_OVERLAYSECTION,
136 : /// Link editor is to sort the entries in this section based on their sizes
137 : HEX_ORDERED,
138 : /// Unwind information
139 : X86_64_UNWIND,
140 : /// Register usage information
141 : MIPS_REGINFO,
142 : /// General options
143 : MIPS_OPTIONS,
144 : /// ABI information
145 : MIPS_ABIFLAGS,
146 : /// RISC-V Attribute
147 : RISCV_ATTRIBUTES,
148 : UNKNOWN(u64),
149 : }
150 :
151 : impl From<u64> for Type {
152 14170 : fn from(value: u64) -> Self {
153 14170 : match value {
154 117 : 0x00000000 => Type::SHT_NULL,
155 10387 : 0x00000001 => Type::PROGBITS,
156 1235 : 0x00000002 => Type::SYMTAB,
157 260 : 0x00000003 => Type::STRTAB,
158 195 : 0x00000004 => Type::RELA,
159 26 : 0x00000005 => Type::HASH,
160 104 : 0x00000006 => Type::DYNAMIC,
161 234 : 0x00000007 => Type::NOTE,
162 884 : 0x00000008 => Type::NOBITS,
163 26 : 0x00000009 => Type::REL,
164 0 : 0x0000000a => Type::SHLIB,
165 91 : 0x0000000b => Type::DYNSYM,
166 143 : 0x0000000e => Type::INIT_ARRAY,
167 78 : 0x0000000f => Type::FINI_ARRAY,
168 0 : 0x00000010 => Type::PREINIT_ARRAY,
169 65 : 0x00000011 => Type::GROUP,
170 0 : 0x00000012 => Type::SYMTAB_SHNDX,
171 0 : 0x00000013 => Type::RELR,
172 0 : 0x60000001 => Type::ANDROID_REL,
173 0 : 0x60000002 => Type::ANDROID_RELA,
174 0 : 0x6fff4c03 => Type::LLVM_ADDRSIG,
175 0 : 0x6fffff00 => Type::ANDROID_RELR,
176 13 : 0x6ffffff5 => Type::GNU_ATTRIBUTES,
177 78 : 0x6ffffff6 => Type::GNU_HASH,
178 13 : 0x6ffffffd => Type::GNU_VERDEF,
179 91 : 0x6ffffffe => Type::GNU_VERNEED,
180 91 : 0x6fffffff => Type::GNU_VERSYM,
181 0 : 0x170000001 => Type::ARM_EXIDX,
182 0 : 0x170000002 => Type::ARM_PREEMPTMAP,
183 0 : 0x170000003 => Type::ARM_ATTRIBUTES,
184 0 : 0x170000004 => Type::ARM_DEBUGOVERLAY,
185 0 : 0x170000005 => Type::ARM_OVERLAYSECTION,
186 0 : 0x270000000 => Type::HEX_ORDERED,
187 0 : 0x270000001 => Type::X86_64_UNWIND,
188 13 : 0x370000006 => Type::MIPS_REGINFO,
189 0 : 0x37000000d => Type::MIPS_OPTIONS,
190 13 : 0x37000002a => Type::MIPS_ABIFLAGS,
191 0 : 0x470000003 => Type::RISCV_ATTRIBUTES,
192 13 : _ => Type::UNKNOWN(value),
193 : }
194 14170 : }
195 : }
196 : impl From<Type> for u64 {
197 0 : fn from(value: Type) -> u64 {
198 0 : match value {
199 0 : Type::SHT_NULL => 0x00000000,
200 0 : Type::PROGBITS => 0x00000001,
201 0 : Type::SYMTAB => 0x00000002,
202 0 : Type::STRTAB => 0x00000003,
203 0 : Type::RELA => 0x00000004,
204 0 : Type::HASH => 0x00000005,
205 0 : Type::DYNAMIC => 0x00000006,
206 0 : Type::NOTE => 0x00000007,
207 0 : Type::NOBITS => 0x00000008,
208 0 : Type::REL => 0x00000009,
209 0 : Type::SHLIB => 0x0000000a,
210 0 : Type::DYNSYM => 0x0000000b,
211 0 : Type::INIT_ARRAY => 0x0000000e,
212 0 : Type::FINI_ARRAY => 0x0000000f,
213 0 : Type::PREINIT_ARRAY => 0x00000010,
214 0 : Type::GROUP => 0x00000011,
215 0 : Type::SYMTAB_SHNDX => 0x00000012,
216 0 : Type::RELR => 0x00000013,
217 0 : Type::ANDROID_REL => 0x60000001,
218 0 : Type::ANDROID_RELA => 0x60000002,
219 0 : Type::LLVM_ADDRSIG => 0x6fff4c03,
220 0 : Type::ANDROID_RELR => 0x6fffff00,
221 0 : Type::GNU_ATTRIBUTES => 0x6ffffff5,
222 0 : Type::GNU_HASH => 0x6ffffff6,
223 0 : Type::GNU_VERDEF => 0x6ffffffd,
224 0 : Type::GNU_VERNEED => 0x6ffffffe,
225 0 : Type::GNU_VERSYM => 0x6fffffff,
226 0 : Type::ARM_EXIDX => 0x170000001,
227 0 : Type::ARM_PREEMPTMAP => 0x170000002,
228 0 : Type::ARM_ATTRIBUTES => 0x170000003,
229 0 : Type::ARM_DEBUGOVERLAY => 0x170000004,
230 0 : Type::ARM_OVERLAYSECTION => 0x170000005,
231 0 : Type::HEX_ORDERED => 0x270000000,
232 0 : Type::X86_64_UNWIND => 0x270000001,
233 0 : Type::MIPS_REGINFO => 0x370000006,
234 0 : Type::MIPS_OPTIONS => 0x37000000d,
235 0 : Type::MIPS_ABIFLAGS => 0x37000002a,
236 0 : Type::RISCV_ATTRIBUTES => 0x470000003,
237 0 : Type::UNKNOWN(value) => value,
238 : }
239 0 : }
240 : }
241 :
242 0 : bitflags! {
243 14170 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
244 0 : pub struct Flags: u64 {
245 0 : const NONE = 0x0;
246 0 : const WRITE = 0x1;
247 0 : const ALLOC = 0x2;
248 0 : const EXECINSTR = 0x4;
249 0 : const MERGE = 0x10;
250 0 : const STRINGS = 0x20;
251 0 : const INFO_LINK = 0x40;
252 0 : const LINK_ORDER = 0x80;
253 0 : const OS_NONCONFORMING = 0x100;
254 0 : const GROUP = 0x200;
255 0 : const TLS = 0x400;
256 0 : const COMPRESSED = 0x800;
257 0 : const GNU_RETAIN = 0x200000;
258 0 : const EXCLUDE = 0x80000000;
259 0 : const XCORE_SHF_DP_SECTION = 0x110000000;
260 0 : const XCORE_SHF_CP_SECTION = 0x120000000;
261 0 : const X86_64_LARGE = 0x210000000;
262 0 : const HEX_GPREL = 0x310000000;
263 0 : const MIPS_NODUPES = 0x401000000;
264 0 : const MIPS_NAMES = 0x402000000;
265 0 : const MIPS_LOCAL = 0x404000000;
266 0 : const MIPS_NOSTRIP = 0x408000000;
267 0 : const MIPS_GPREL = 0x410000000;
268 0 : const MIPS_MERGE = 0x420000000;
269 0 : const MIPS_ADDR = 0x440000000;
270 0 : const MIPS_STRING = 0x480000000;
271 0 : const ARM_PURECODE = 0x520000000;
272 0 : }
273 0 : }
274 :
275 : impl Flags {
276 14170 : pub fn from_value(value: u64) -> Self {
277 14170 : Flags::from_bits_truncate(value)
278 14170 : }
279 : }
280 :
281 : impl fmt::Debug for Section<'_> {
282 14170 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
283 14170 : let base = self as &dyn generic::Section;
284 14170 : f.debug_struct("Section")
285 14170 : .field("base", &base)
286 14170 : .field("type", &self.get_type())
287 14170 : .field("flags", &self.flags())
288 14170 : .field("alignment", &self.alignment())
289 14170 : .field("information", &self.information())
290 14170 : .field("entry_size", &self.entry_size())
291 14170 : .field("link", &self.link())
292 14170 : .field("file_offset", &self.file_offset())
293 14170 : .field("original_size", &self.original_size())
294 14170 : .finish()
295 14170 : }
296 : }
297 :
298 : impl fmt::Display for Section<'_> {
299 3211 : fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
300 3211 : write!(f, "{}", self.ptr.to_string())
301 3211 : }
302 : }
303 :
304 : impl FromFFI<ffi::ELF_Section> for Section<'_> {
305 14196 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Section>) -> Self {
306 14196 : Self {
307 14196 : ptr,
308 14196 : _owner: PhantomData,
309 14196 : }
310 14196 : }
311 : }
312 :
313 : impl crate::common::AsFFI<ffi::ELF_Section> for Section<'_> {
314 0 : fn as_ffi(&self) -> &ffi::ELF_Section {
315 0 : self.ptr.as_ref().unwrap()
316 0 : }
317 :
318 0 : fn as_mut_ffi(&mut self) -> Pin<&mut ffi::ELF_Section> {
319 0 : self.ptr.pin_mut()
320 0 : }
321 : }
322 :
323 : impl generic::Section for Section<'_> {
324 72852 : fn as_generic(&self) -> &ffi::AbstractSection {
325 72852 : self.ptr.as_ref().unwrap().as_ref()
326 72852 : }
327 :
328 0 : fn as_generic_mut(&mut self) -> Pin<&mut ffi::AbstractSection> {
329 0 : unsafe {
330 0 : Pin::new_unchecked({
331 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSection
332 0 : as *mut ffi::AbstractSection)
333 0 : .as_mut()
334 0 : .unwrap()
335 0 : })
336 0 : }
337 0 : }
338 : }
339 :
340 3211 : declare_iterator!(
341 3211 : Sections,
342 3211 : Section<'a>,
343 3211 : ffi::ELF_Section,
344 3211 : ffi::ELF_Binary,
345 3211 : ffi::ELF_Binary_it_sections
346 3211 : );
|