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 552 : #[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 : /// Platform architecture compatibility info
36 : ARM_ARCHEXT,
37 : ARM_EXIDX,
38 : ARM_UNWIND,
39 : AARCH64_MEMTAG_MTE,
40 : /// Register usage information
41 : MIPS_REGINFO,
42 : /// Runtime procedure table.
43 : MIPS_RTPROC,
44 : /// Options segment.
45 : MIPS_OPTIONS,
46 : /// Abiflags segment.
47 : MIPS_ABIFLAGS,
48 : RISCV_ATTRIBUTES,
49 : UNKNOWN(u64),
50 : }
51 :
52 : impl Type {
53 1104 : pub fn from_value(value: u64) -> Self {
54 1104 : match value {
55 16 : 0x00000000 => Type::PT_NULL,
56 480 : 0x00000001 => Type::LOAD,
57 80 : 0x00000002 => Type::DYNAMIC,
58 64 : 0x00000003 => Type::INTERP,
59 112 : 0x00000004 => Type::NOTE,
60 0 : 0x00000005 => Type::SHLIB,
61 64 : 0x00000006 => Type::PHDR,
62 16 : 0x00000007 => Type::TLS,
63 80 : 0x6474e550 => Type::GNU_EH_FRAME,
64 80 : 0x6474e551 => Type::GNU_STACK,
65 16 : 0x6474e553 => Type::GNU_PROPERTY,
66 64 : 0x6474e552 => Type::GNU_RELRO,
67 0 : 0x270000000 => Type::ARM_ARCHEXT,
68 0 : 0x270000001 => Type::ARM_EXIDX,
69 0 : 0x470000002 => Type::AARCH64_MEMTAG_MTE,
70 16 : 0x670000000 => Type::MIPS_REGINFO,
71 0 : 0x670000001 => Type::MIPS_RTPROC,
72 0 : 0x670000002 => Type::MIPS_OPTIONS,
73 16 : 0x670000003 => Type::MIPS_ABIFLAGS,
74 0 : 0x870000003 => Type::RISCV_ATTRIBUTES,
75 0 : _ => Type::UNKNOWN(value),
76 :
77 : }
78 1104 : }
79 : }
80 :
81 :
82 :
83 0 : bitflags! {
84 0 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
85 0 : pub struct Flags: u32 {
86 0 : const NONE = 0x0;
87 0 : const X = 0x1;
88 0 : const W = 0x2;
89 0 : const R = 0x4;
90 0 : }
91 0 : }
92 :
93 :
94 : impl Flags {
95 0 : pub fn from_value(value: u32) -> Self {
96 0 : Flags::from_bits_truncate(value)
97 0 : }
98 : }
99 :
100 : /// Structure which reprents an ELF segment
101 : pub struct Segment<'a> {
102 : ptr: cxx::UniquePtr<ffi::ELF_Segment>,
103 : _owner: PhantomData<&'a ffi::ELF_Binary>
104 : }
105 :
106 : impl fmt::Debug for Segment<'_> {
107 552 : fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 552 : f.debug_struct("Segment")
109 552 : .field("p_type", &self.p_type())
110 552 : .field("flags", &self.flags())
111 552 : .field("file_offset", &self.file_offset())
112 552 : .field("virtual_address", &self.virtual_address())
113 552 : .field("physical_address", &self.physical_address())
114 552 : .field("physical_size", &self.physical_size())
115 552 : .field("virtual_size", &self.virtual_size())
116 552 : .field("alignment", &self.alignment())
117 552 : .finish()
118 552 : }
119 : }
120 :
121 : impl FromFFI<ffi::ELF_Segment> for Segment<'_> {
122 568 : fn from_ffi(ptr: cxx::UniquePtr<ffi::ELF_Segment>) -> Self {
123 568 : Segment {
124 568 : ptr,
125 568 : _owner: PhantomData
126 568 : }
127 568 : }
128 : }
129 :
130 : impl<'a> Segment<'a> {
131 : /// Content of the segment as a slice of bytes
132 32 : pub fn content(&self) -> &[u8] {
133 32 : to_slice!(self.ptr.content());
134 32 : }
135 :
136 : /// The segment's type (LOAD, DYNAMIC, ...)
137 1104 : pub fn p_type(&self) -> Type {
138 1104 : Type::from_value(self.ptr.stype())
139 1104 : }
140 :
141 : /// The flag permissions associated with this segment
142 552 : pub fn flags(&self) -> u32 {
143 552 : self.ptr.flags()
144 552 : }
145 :
146 : /// The file offset of the data associated with this segment
147 552 : pub fn file_offset(&self) -> u64 {
148 552 : self.ptr.file_offset()
149 552 : }
150 :
151 : /// The virtual address of the segment.
152 552 : pub fn virtual_address(&self) -> u64 {
153 552 : self.ptr.virtual_address()
154 552 : }
155 : /// The physical address of the segment.
156 : /// This value is not really relevant on systems like Linux or Android.
157 : /// On the other hand, Qualcomm trustlets might use this value.
158 : ///
159 : /// Usually this value matches [`Segment::virtual_address`]
160 552 : pub fn physical_address(&self) -> u64 {
161 552 : self.ptr.physical_address()
162 552 : }
163 :
164 : /// The **file** size of the data associated with this segment
165 552 : pub fn physical_size(&self) -> u64 {
166 552 : self.ptr.physical_size()
167 552 : }
168 :
169 : /// The in-memory size of this segment.
170 : /// Usually, if the `.bss` segment is wrapped by this segment
171 : /// then, virtual_size is larger than physical_size
172 552 : pub fn virtual_size(&self) -> u64 {
173 552 : self.ptr.virtual_size()
174 552 : }
175 :
176 : /// The offset alignment of the segment
177 552 : pub fn alignment(&self) -> u64 {
178 552 : self.ptr.alignment()
179 552 : }
180 : }
181 :
182 : impl fmt::Display for Segment<'_> {
183 552 : fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
184 552 : write!(f, "{}", self.ptr.to_string())
185 552 : }
186 : }
187 :
188 552 : declare_iterator!(Segments, Segment<'a>, ffi::ELF_Segment, ffi::ELF_Binary, ffi::ELF_Binary_it_segments);
|