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 690 : #[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 Type {
72 1380 : pub fn from_value(value: u64) -> Self {
73 1380 : match value {
74 20 : 0x00000000 => Type::PT_NULL,
75 600 : 0x00000001 => Type::LOAD,
76 100 : 0x00000002 => Type::DYNAMIC,
77 80 : 0x00000003 => Type::INTERP,
78 140 : 0x00000004 => Type::NOTE,
79 0 : 0x00000005 => Type::SHLIB,
80 80 : 0x00000006 => Type::PHDR,
81 20 : 0x00000007 => Type::TLS,
82 100 : 0x6474e550 => Type::GNU_EH_FRAME,
83 100 : 0x6474e551 => Type::GNU_STACK,
84 20 : 0x6474e553 => Type::GNU_PROPERTY,
85 80 : 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 20 : 0x670000000 => Type::MIPS_REGINFO,
91 0 : 0x670000001 => Type::MIPS_RTPROC,
92 0 : 0x670000002 => Type::MIPS_OPTIONS,
93 20 : 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 1380 : }
117 : }
118 :
119 :
120 :
121 0 : bitflags! {
122 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
123 0 : pub struct Flags: u32 {
124 0 : const NONE = 0x0;
125 0 : const X = 0x1;
126 0 : const W = 0x2;
127 0 : const R = 0x4;
128 0 : }
129 0 : }
130 :
131 :
132 : impl Flags {
133 0 : pub fn from_value(value: u32) -> Self {
134 0 : Flags::from_bits_truncate(value)
135 0 : }
136 : }
137 :
138 : /// Structure which reprents an ELF segment
139 : pub struct Segment<'a> {
140 : ptr: cxx::UniquePtr<ffi::ELF_Segment>,
141 : _owner: PhantomData<&'a ffi::ELF_Binary>
142 : }
143 :
144 : impl fmt::Debug for Segment<'_> {
145 690 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146 690 : f.debug_struct("Segment")
147 690 : .field("p_type", &self.p_type())
148 690 : .field("flags", &self.flags())
149 690 : .field("file_offset", &self.file_offset())
150 690 : .field("virtual_address", &self.virtual_address())
151 690 : .field("physical_address", &self.physical_address())
152 690 : .field("physical_size", &self.physical_size())
153 690 : .field("virtual_size", &self.virtual_size())
154 690 : .field("alignment", &self.alignment())
155 690 : .finish()
156 690 : }
157 : }
158 :
159 : impl FromFFI<ffi::ELF_Segment> for Segment<'_> {
160 710 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Segment>) -> Self {
161 710 : Segment {
162 710 : ptr,
163 710 : _owner: PhantomData
164 710 : }
165 710 : }
166 : }
167 :
168 : impl<'a> Segment<'a> {
169 : /// Content of the segment as a slice of bytes
170 40 : pub fn content(&self) -> &[u8] {
171 40 : to_slice!(self.ptr.content());
172 40 : }
173 :
174 : /// The segment's type (LOAD, DYNAMIC, ...)
175 1380 : pub fn p_type(&self) -> Type {
176 1380 : Type::from_value(self.ptr.stype())
177 1380 : }
178 :
179 : /// The flag permissions associated with this segment
180 690 : pub fn flags(&self) -> u32 {
181 690 : self.ptr.flags()
182 690 : }
183 :
184 : /// The file offset of the data associated with this segment
185 690 : pub fn file_offset(&self) -> u64 {
186 690 : self.ptr.file_offset()
187 690 : }
188 :
189 : /// The virtual address of the segment.
190 690 : pub fn virtual_address(&self) -> u64 {
191 690 : self.ptr.virtual_address()
192 690 : }
193 : /// The physical address of the segment.
194 : /// This value is not really relevant on systems like Linux or Android.
195 : /// On the other hand, Qualcomm trustlets might use this value.
196 : ///
197 : /// Usually this value matches [`Segment::virtual_address`]
198 690 : pub fn physical_address(&self) -> u64 {
199 690 : self.ptr.physical_address()
200 690 : }
201 :
202 : /// The **file** size of the data associated with this segment
203 690 : pub fn physical_size(&self) -> u64 {
204 690 : self.ptr.physical_size()
205 690 : }
206 :
207 : /// The in-memory size of this segment.
208 : /// Usually, if the `.bss` segment is wrapped by this segment
209 : /// then, virtual_size is larger than physical_size
210 690 : pub fn virtual_size(&self) -> u64 {
211 690 : self.ptr.virtual_size()
212 690 : }
213 :
214 : /// The offset alignment of the segment
215 690 : pub fn alignment(&self) -> u64 {
216 690 : self.ptr.alignment()
217 690 : }
218 : }
219 :
220 : impl fmt::Display for Segment<'_> {
221 690 : fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
222 690 : write!(f, "{}", self.ptr.to_string())
223 690 : }
224 : }
225 :
226 690 : declare_iterator!(Segments, Segment<'a>, ffi::ELF_Segment, ffi::ELF_Binary, ffi::ELF_Binary_it_segments);
|