Line data Source code
1 : use bitflags::bitflags;
2 : use lief_ffi as ffi;
3 : use std::fmt;
4 : use std::marker::PhantomData;
5 :
6 : use crate::common::FromFFI;
7 : use crate::{declare_iterator, to_slice};
8 :
9 : #[allow(non_camel_case_types)]
10 1183 : #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
11 : pub enum Type {
12 : /// Unused segment
13 : PT_NULL,
14 : /// Loadable segment
15 : LOAD,
16 : /// Dynamic linking information.
17 : DYNAMIC,
18 : /// Interpreter pathname.
19 : INTERP,
20 : /// Auxiliary information.
21 : NOTE,
22 : /// Reserved
23 : SHLIB,
24 : /// The program header table itself.
25 : PHDR,
26 : /// The thread-local storage template.
27 : TLS,
28 : GNU_EH_FRAME,
29 : /// Indicates stack executability
30 : GNU_STACK,
31 : /// GNU property
32 : GNU_PROPERTY,
33 : /// Read-only after relocation.
34 : GNU_RELRO,
35 : PAX_FLAGS,
36 : /// Platform architecture compatibility info
37 : ARM_ARCHEXT,
38 : ARM_EXIDX,
39 : ARM_UNWIND,
40 : AARCH64_MEMTAG_MTE,
41 : /// Register usage information
42 : MIPS_REGINFO,
43 : /// Runtime procedure table.
44 : MIPS_RTPROC,
45 : /// Options segment.
46 : MIPS_OPTIONS,
47 : /// Abiflags segment.
48 : MIPS_ABIFLAGS,
49 : RISCV_ATTRIBUTES,
50 : IA_64_EXT,
51 : IA_64_UNWIND,
52 : HP_TLS,
53 : HP_CORE_NONE,
54 : HP_CORE_VERSION,
55 : HP_CORE_KERNEL,
56 : HP_CORE_COMM,
57 : HP_CORE_PROC,
58 : HP_CORE_LOADABLE,
59 : HP_CORE_STACK,
60 : HP_CORE_SHM,
61 : HP_CORE_MMF,
62 : HP_PARALLEL,
63 : HP_FASTBIND,
64 : HP_OPT_ANNOT,
65 : HP_HSL_ANNOT,
66 : HP_STACK,
67 : HP_CORE_UTSNAME,
68 : UNKNOWN(u64),
69 : }
70 :
71 : impl From<u64> for Type {
72 2366 : fn from(value: u64) -> Self {
73 2366 : match value {
74 26 : 0x00000000 => Type::PT_NULL,
75 988 : 0x00000001 => Type::LOAD,
76 182 : 0x00000002 => Type::DYNAMIC,
77 104 : 0x00000003 => Type::INTERP,
78 286 : 0x00000004 => Type::NOTE,
79 0 : 0x00000005 => Type::SHLIB,
80 104 : 0x00000006 => Type::PHDR,
81 26 : 0x00000007 => Type::TLS,
82 182 : 0x6474e550 => Type::GNU_EH_FRAME,
83 182 : 0x6474e551 => Type::GNU_STACK,
84 78 : 0x6474e553 => Type::GNU_PROPERTY,
85 156 : 0x6474e552 => Type::GNU_RELRO,
86 0 : 0x65041580 => Type::PAX_FLAGS,
87 0 : 0x270000000 => Type::ARM_ARCHEXT,
88 0 : 0x270000001 => Type::ARM_EXIDX,
89 0 : 0x470000002 => Type::AARCH64_MEMTAG_MTE,
90 26 : 0x670000000 => Type::MIPS_REGINFO,
91 0 : 0x670000001 => Type::MIPS_RTPROC,
92 0 : 0x670000002 => Type::MIPS_OPTIONS,
93 26 : 0x670000003 => Type::MIPS_ABIFLAGS,
94 0 : 0x870000003 => Type::RISCV_ATTRIBUTES,
95 0 : 0xa70000000 => Type::IA_64_EXT,
96 0 : 0xa70000001 => Type::IA_64_UNWIND,
97 0 : 0x20000060000000 => Type::HP_TLS,
98 0 : 0x20000060000001 => Type::HP_CORE_NONE,
99 0 : 0x20000060000002 => Type::HP_CORE_VERSION,
100 0 : 0x20000060000003 => Type::HP_CORE_KERNEL,
101 0 : 0x20000060000004 => Type::HP_CORE_COMM,
102 0 : 0x20000060000005 => Type::HP_CORE_PROC,
103 0 : 0x20000060000006 => Type::HP_CORE_LOADABLE,
104 0 : 0x20000060000007 => Type::HP_CORE_STACK,
105 0 : 0x20000060000008 => Type::HP_CORE_SHM,
106 0 : 0x20000060000009 => Type::HP_CORE_MMF,
107 0 : 0x20000060000010 => Type::HP_PARALLEL,
108 0 : 0x20000060000011 => Type::HP_FASTBIND,
109 0 : 0x20000060000012 => Type::HP_OPT_ANNOT,
110 0 : 0x20000060000013 => Type::HP_HSL_ANNOT,
111 0 : 0x20000060000014 => Type::HP_STACK,
112 0 : 0x20000060000015 => Type::HP_CORE_UTSNAME,
113 0 : _ => Type::UNKNOWN(value),
114 : }
115 2366 : }
116 : }
117 : impl From<Type> for u64 {
118 0 : fn from(value: Type) -> u64 {
119 0 : match value {
120 0 : Type::PT_NULL => 0x00000000,
121 0 : Type::LOAD => 0x00000001,
122 0 : Type::DYNAMIC => 0x00000002,
123 0 : Type::INTERP => 0x00000003,
124 0 : Type::NOTE => 0x00000004,
125 0 : Type::SHLIB => 0x00000005,
126 0 : Type::PHDR => 0x00000006,
127 0 : Type::TLS => 0x00000007,
128 0 : Type::GNU_EH_FRAME => 0x6474e550,
129 0 : Type::GNU_STACK => 0x6474e551,
130 0 : Type::GNU_PROPERTY => 0x6474e553,
131 0 : Type::GNU_RELRO => 0x6474e552,
132 0 : Type::PAX_FLAGS => 0x65041580,
133 0 : Type::ARM_ARCHEXT => 0x270000000,
134 0 : Type::ARM_EXIDX => 0x270000001,
135 0 : Type::ARM_UNWIND => 0x270000001,
136 0 : Type::AARCH64_MEMTAG_MTE => 0x470000002,
137 0 : Type::MIPS_REGINFO => 0x670000000,
138 0 : Type::MIPS_RTPROC => 0x670000001,
139 0 : Type::MIPS_OPTIONS => 0x670000002,
140 0 : Type::MIPS_ABIFLAGS => 0x670000003,
141 0 : Type::RISCV_ATTRIBUTES => 0x870000003,
142 0 : Type::IA_64_EXT => 0xa70000000,
143 0 : Type::IA_64_UNWIND => 0xa70000001,
144 0 : Type::HP_TLS => 0x20000060000000,
145 0 : Type::HP_CORE_NONE => 0x20000060000001,
146 0 : Type::HP_CORE_VERSION => 0x20000060000002,
147 0 : Type::HP_CORE_KERNEL => 0x20000060000003,
148 0 : Type::HP_CORE_COMM => 0x20000060000004,
149 0 : Type::HP_CORE_PROC => 0x20000060000005,
150 0 : Type::HP_CORE_LOADABLE => 0x20000060000006,
151 0 : Type::HP_CORE_STACK => 0x20000060000007,
152 0 : Type::HP_CORE_SHM => 0x20000060000008,
153 0 : Type::HP_CORE_MMF => 0x20000060000009,
154 0 : Type::HP_PARALLEL => 0x20000060000010,
155 0 : Type::HP_FASTBIND => 0x20000060000011,
156 0 : Type::HP_OPT_ANNOT => 0x20000060000012,
157 0 : Type::HP_HSL_ANNOT => 0x20000060000013,
158 0 : Type::HP_STACK => 0x20000060000014,
159 0 : Type::HP_CORE_UTSNAME => 0x20000060000015,
160 0 : Type::UNKNOWN(value) => value,
161 : }
162 0 : }
163 : }
164 :
165 0 : bitflags! {
166 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
167 0 : pub struct Flags: u32 {
168 0 : const NONE = 0x0;
169 0 : const X = 0x1;
170 0 : const W = 0x2;
171 0 : const R = 0x4;
172 0 : }
173 0 : }
174 :
175 : impl Flags {
176 0 : pub fn from_value(value: u32) -> Self {
177 0 : Flags::from_bits_truncate(value)
178 0 : }
179 :
180 0 : pub fn to_value(&self) -> u32 {
181 0 : self.bits()
182 0 : }
183 : }
184 :
185 : /// Structure which represents an ELF segment
186 : pub struct Segment<'a> {
187 : pub(super) ptr: cxx::UniquePtr<ffi::ELF_Segment>,
188 : _owner: PhantomData<&'a ffi::ELF_Binary>,
189 : }
190 :
191 : impl fmt::Debug for Segment<'_> {
192 1183 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 1183 : f.debug_struct("Segment")
194 1183 : .field("p_type", &self.p_type())
195 1183 : .field("flags", &self.flags())
196 1183 : .field("file_offset", &self.file_offset())
197 1183 : .field("virtual_address", &self.virtual_address())
198 1183 : .field("physical_address", &self.physical_address())
199 1183 : .field("physical_size", &self.physical_size())
200 1183 : .field("virtual_size", &self.virtual_size())
201 1183 : .field("alignment", &self.alignment())
202 1183 : .finish()
203 1183 : }
204 : }
205 :
206 : impl FromFFI<ffi::ELF_Segment> for Segment<'_> {
207 1209 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Segment>) -> Self {
208 1209 : Segment {
209 1209 : ptr,
210 1209 : _owner: PhantomData,
211 1209 : }
212 1209 : }
213 : }
214 :
215 : impl Segment<'_> {
216 : /// Create a new segment
217 0 : pub fn new() -> Segment<'static> {
218 0 : Segment::from_ffi(lief_ffi::ELF_Segment::create())
219 0 : }
220 :
221 : /// Content of the segment as a slice of bytes
222 52 : pub fn content(&self) -> &[u8] {
223 52 : to_slice!(self.ptr.content());
224 52 : }
225 :
226 : /// The segment's type (LOAD, DYNAMIC, ...)
227 2366 : pub fn p_type(&self) -> Type {
228 2366 : Type::from(self.ptr.stype())
229 2366 : }
230 :
231 : /// The flag permissions associated with this segment
232 1183 : pub fn flags(&self) -> u32 {
233 1183 : self.ptr.flags()
234 1183 : }
235 :
236 : /// The file offset of the data associated with this segment
237 1183 : pub fn file_offset(&self) -> u64 {
238 1183 : self.ptr.file_offset()
239 1183 : }
240 :
241 : /// The virtual address of the segment.
242 1183 : pub fn virtual_address(&self) -> u64 {
243 1183 : self.ptr.virtual_address()
244 1183 : }
245 : /// The physical address of the segment.
246 : /// This value is not really relevant on systems like Linux or Android.
247 : /// On the other hand, Qualcomm trustlets might use this value.
248 : ///
249 : /// Usually this value matches [`Segment::virtual_address`]
250 1183 : pub fn physical_address(&self) -> u64 {
251 1183 : self.ptr.physical_address()
252 1183 : }
253 :
254 : /// The **file** size of the data associated with this segment
255 1183 : pub fn physical_size(&self) -> u64 {
256 1183 : self.ptr.physical_size()
257 1183 : }
258 :
259 : /// The in-memory size of this segment.
260 : /// Usually, if the `.bss` segment is wrapped by this segment
261 : /// then, virtual_size is larger than physical_size
262 1183 : pub fn virtual_size(&self) -> u64 {
263 1183 : self.ptr.virtual_size()
264 1183 : }
265 :
266 : /// The offset alignment of the segment
267 1183 : pub fn alignment(&self) -> u64 {
268 1183 : self.ptr.alignment()
269 1183 : }
270 :
271 0 : pub fn set_type(&mut self, ty: Type) {
272 0 : self.ptr.pin_mut().set_type(ty.into());
273 0 : }
274 :
275 0 : pub fn set_flags(&mut self, flags: Flags) {
276 0 : self.ptr.pin_mut().set_flags(flags.to_value())
277 0 : }
278 :
279 0 : pub fn set_file_offset(&mut self, offset: u64) {
280 0 : self.ptr.pin_mut().set_file_offset(offset);
281 0 : }
282 :
283 0 : pub fn set_virtual_address(&mut self, va: u64) {
284 0 : self.ptr.pin_mut().set_virtual_address(va);
285 0 : }
286 :
287 0 : pub fn set_physical_address(&mut self, addr: u64) {
288 0 : self.ptr.pin_mut().set_physical_address(addr);
289 0 : }
290 :
291 0 : pub fn set_virtual_size(&mut self, vsize: u64) {
292 0 : self.ptr.pin_mut().set_virtual_size(vsize);
293 0 : }
294 :
295 0 : pub fn set_alignment(&mut self, alignment: u64) {
296 0 : self.ptr.pin_mut().set_alignment(alignment);
297 0 : }
298 :
299 0 : pub fn set_content(&mut self, content: &[u8]) {
300 0 : unsafe {
301 0 : self.ptr
302 0 : .pin_mut()
303 0 : .set_content(content.as_ptr(), content.len().try_into().unwrap());
304 0 : }
305 0 : }
306 :
307 : /// Clear the content of this segment
308 0 : pub fn clear(&mut self) {
309 0 : self.ptr.pin_mut().clear()
310 0 : }
311 :
312 : /// Fill the content of this segment with the value provided in parameter
313 0 : pub fn fill(&mut self, value: u8) {
314 0 : self.ptr.pin_mut().fill(value as i8)
315 0 : }
316 : }
317 :
318 : impl fmt::Display for Segment<'_> {
319 1183 : fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
320 1183 : write!(f, "{}", self.ptr.to_string())
321 1183 : }
322 : }
323 :
324 1183 : declare_iterator!(
325 1183 : Segments,
326 1183 : Segment<'a>,
327 1183 : ffi::ELF_Segment,
328 1183 : ffi::ELF_Binary,
329 1183 : ffi::ELF_Binary_it_segments
330 1183 : );
|