Line data Source code
1 : use lief_ffi as ffi;
2 : use bitflags::bitflags;
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 828 : #[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 1656 : fn from(value: u64) -> Self {
73 1656 : match value {
74 24 : 0x00000000 => Type::PT_NULL,
75 720 : 0x00000001 => Type::LOAD,
76 120 : 0x00000002 => Type::DYNAMIC,
77 96 : 0x00000003 => Type::INTERP,
78 168 : 0x00000004 => Type::NOTE,
79 0 : 0x00000005 => Type::SHLIB,
80 96 : 0x00000006 => Type::PHDR,
81 24 : 0x00000007 => Type::TLS,
82 120 : 0x6474e550 => Type::GNU_EH_FRAME,
83 120 : 0x6474e551 => Type::GNU_STACK,
84 24 : 0x6474e553 => Type::GNU_PROPERTY,
85 96 : 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 24 : 0x670000000 => Type::MIPS_REGINFO,
91 0 : 0x670000001 => Type::MIPS_RTPROC,
92 0 : 0x670000002 => Type::MIPS_OPTIONS,
93 24 : 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 : }
116 1656 : }
117 : }
118 : impl From<Type> for u64 {
119 0 : fn from(value: Type) -> u64 {
120 0 : match value {
121 0 : Type::PT_NULL => 0x00000000,
122 0 : Type::LOAD => 0x00000001,
123 0 : Type::DYNAMIC => 0x00000002,
124 0 : Type::INTERP => 0x00000003,
125 0 : Type::NOTE => 0x00000004,
126 0 : Type::SHLIB => 0x00000005,
127 0 : Type::PHDR => 0x00000006,
128 0 : Type::TLS => 0x00000007,
129 0 : Type::GNU_EH_FRAME => 0x6474e550,
130 0 : Type::GNU_STACK => 0x6474e551,
131 0 : Type::GNU_PROPERTY => 0x6474e553,
132 0 : Type::GNU_RELRO => 0x6474e552,
133 0 : Type::PAX_FLAGS => 0x65041580,
134 0 : Type::ARM_ARCHEXT => 0x270000000,
135 0 : Type::ARM_EXIDX => 0x270000001,
136 0 : Type::ARM_UNWIND => 0x270000001,
137 0 : Type::AARCH64_MEMTAG_MTE => 0x470000002,
138 0 : Type::MIPS_REGINFO => 0x670000000,
139 0 : Type::MIPS_RTPROC => 0x670000001,
140 0 : Type::MIPS_OPTIONS => 0x670000002,
141 0 : Type::MIPS_ABIFLAGS => 0x670000003,
142 0 : Type::RISCV_ATTRIBUTES => 0x870000003,
143 0 : Type::IA_64_EXT => 0xa70000000,
144 0 : Type::IA_64_UNWIND => 0xa70000001,
145 0 : Type::HP_TLS => 0x20000060000000,
146 0 : Type::HP_CORE_NONE => 0x20000060000001,
147 0 : Type::HP_CORE_VERSION => 0x20000060000002,
148 0 : Type::HP_CORE_KERNEL => 0x20000060000003,
149 0 : Type::HP_CORE_COMM => 0x20000060000004,
150 0 : Type::HP_CORE_PROC => 0x20000060000005,
151 0 : Type::HP_CORE_LOADABLE => 0x20000060000006,
152 0 : Type::HP_CORE_STACK => 0x20000060000007,
153 0 : Type::HP_CORE_SHM => 0x20000060000008,
154 0 : Type::HP_CORE_MMF => 0x20000060000009,
155 0 : Type::HP_PARALLEL => 0x20000060000010,
156 0 : Type::HP_FASTBIND => 0x20000060000011,
157 0 : Type::HP_OPT_ANNOT => 0x20000060000012,
158 0 : Type::HP_HSL_ANNOT => 0x20000060000013,
159 0 : Type::HP_STACK => 0x20000060000014,
160 0 : Type::HP_CORE_UTSNAME => 0x20000060000015,
161 0 : Type::UNKNOWN(value) => value,
162 : }
163 0 : }
164 : }
165 :
166 0 : bitflags! {
167 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
168 0 : pub struct Flags: u32 {
169 0 : const NONE = 0x0;
170 0 : const X = 0x1;
171 0 : const W = 0x2;
172 0 : const R = 0x4;
173 0 : }
174 0 : }
175 :
176 :
177 : impl Flags {
178 0 : pub fn from_value(value: u32) -> Self {
179 0 : Flags::from_bits_truncate(value)
180 0 : }
181 :
182 0 : pub fn to_value(&self) -> u32 {
183 0 : self.bits() as u32
184 0 : }
185 : }
186 :
187 : /// Structure which reprents an ELF segment
188 : pub struct Segment<'a> {
189 : pub(super) ptr: cxx::UniquePtr<ffi::ELF_Segment>,
190 : _owner: PhantomData<&'a ffi::ELF_Binary>
191 : }
192 :
193 : impl fmt::Debug for Segment<'_> {
194 828 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 828 : f.debug_struct("Segment")
196 828 : .field("p_type", &self.p_type())
197 828 : .field("flags", &self.flags())
198 828 : .field("file_offset", &self.file_offset())
199 828 : .field("virtual_address", &self.virtual_address())
200 828 : .field("physical_address", &self.physical_address())
201 828 : .field("physical_size", &self.physical_size())
202 828 : .field("virtual_size", &self.virtual_size())
203 828 : .field("alignment", &self.alignment())
204 828 : .finish()
205 828 : }
206 : }
207 :
208 : impl FromFFI<ffi::ELF_Segment> for Segment<'_> {
209 852 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Segment>) -> Self {
210 852 : Segment {
211 852 : ptr,
212 852 : _owner: PhantomData
213 852 : }
214 852 : }
215 : }
216 :
217 : impl Segment<'_> {
218 : /// Create a new segment
219 0 : pub fn new() -> Segment<'static> {
220 0 : Segment::from_ffi(lief_ffi::ELF_Segment::create())
221 0 : }
222 :
223 : /// Content of the segment as a slice of bytes
224 48 : pub fn content(&self) -> &[u8] {
225 48 : to_slice!(self.ptr.content());
226 48 : }
227 :
228 : /// The segment's type (LOAD, DYNAMIC, ...)
229 1656 : pub fn p_type(&self) -> Type {
230 1656 : Type::from(self.ptr.stype())
231 1656 : }
232 :
233 : /// The flag permissions associated with this segment
234 828 : pub fn flags(&self) -> u32 {
235 828 : self.ptr.flags()
236 828 : }
237 :
238 : /// The file offset of the data associated with this segment
239 828 : pub fn file_offset(&self) -> u64 {
240 828 : self.ptr.file_offset()
241 828 : }
242 :
243 : /// The virtual address of the segment.
244 828 : pub fn virtual_address(&self) -> u64 {
245 828 : self.ptr.virtual_address()
246 828 : }
247 : /// The physical address of the segment.
248 : /// This value is not really relevant on systems like Linux or Android.
249 : /// On the other hand, Qualcomm trustlets might use this value.
250 : ///
251 : /// Usually this value matches [`Segment::virtual_address`]
252 828 : pub fn physical_address(&self) -> u64 {
253 828 : self.ptr.physical_address()
254 828 : }
255 :
256 : /// The **file** size of the data associated with this segment
257 828 : pub fn physical_size(&self) -> u64 {
258 828 : self.ptr.physical_size()
259 828 : }
260 :
261 : /// The in-memory size of this segment.
262 : /// Usually, if the `.bss` segment is wrapped by this segment
263 : /// then, virtual_size is larger than physical_size
264 828 : pub fn virtual_size(&self) -> u64 {
265 828 : self.ptr.virtual_size()
266 828 : }
267 :
268 : /// The offset alignment of the segment
269 828 : pub fn alignment(&self) -> u64 {
270 828 : self.ptr.alignment()
271 828 : }
272 :
273 0 : pub fn set_type(&mut self, ty: Type) {
274 0 : self.ptr.pin_mut().set_type(ty.into());
275 0 : }
276 :
277 0 : pub fn set_flags(&mut self, flags: Flags) {
278 0 : self.ptr.pin_mut().set_flags(flags.to_value())
279 0 : }
280 :
281 0 : pub fn set_file_offset(&mut self, offset: u64) {
282 0 : self.ptr.pin_mut().set_file_offset(offset);
283 0 : }
284 :
285 0 : pub fn set_virtual_address(&mut self, va: u64) {
286 0 : self.ptr.pin_mut().set_virtual_address(va);
287 0 : }
288 :
289 0 : pub fn set_physical_address(&mut self, addr: u64) {
290 0 : self.ptr.pin_mut().set_physical_address(addr);
291 0 : }
292 :
293 0 : pub fn set_virtual_size(&mut self, vsize: u64) {
294 0 : self.ptr.pin_mut().set_virtual_size(vsize);
295 0 : }
296 :
297 0 : pub fn set_alignment(&mut self, alignment: u64) {
298 0 : self.ptr.pin_mut().set_alignment(alignment);
299 0 : }
300 :
301 0 : pub fn set_content(&mut self, content: &[u8]) {
302 0 : unsafe {
303 0 : self.ptr.pin_mut().set_content(
304 0 : content.as_ptr(),
305 0 : content.len().try_into().unwrap()
306 0 : );
307 0 : }
308 0 : }
309 : }
310 :
311 : impl fmt::Display for Segment<'_> {
312 828 : fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
313 828 : write!(f, "{}", self.ptr.to_string())
314 828 : }
315 : }
316 :
317 828 : declare_iterator!(Segments, Segment<'a>, ffi::ELF_Segment, ffi::ELF_Binary, ffi::ELF_Binary_it_segments);
|