Line data Source code
1 : //! PE section module
2 :
3 : use std::marker::PhantomData;
4 :
5 : use crate::coff;
6 : use crate::common::{into_optional, AsFFI, FromFFI};
7 : use crate::declare_iterator;
8 : use crate::generic;
9 : use crate::to_slice;
10 : use bitflags::bitflags;
11 : use lief_ffi as ffi;
12 : use std::pin::Pin;
13 :
14 : /// This structure defines a regular PE section.
15 : ///
16 : /// Note that it implements the trait [`generic::Section`] which provides additional
17 : /// functions.
18 : pub struct Section<'a> {
19 : ptr: cxx::UniquePtr<ffi::PE_Section>,
20 : _owner: PhantomData<&'a ffi::PE_Binary>,
21 : }
22 :
23 0 : bitflags! {
24 21684 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
25 0 : pub struct Characteristics: u32 {
26 0 : const TYPE_NO_PAD = 0x8;
27 0 : const CNT_CODE = 0x20;
28 0 : const CNT_INITIALIZED_DATA = 0x40;
29 0 : const CNT_UNINITIALIZED_DATA = 0x80;
30 0 : const LNK_OTHER = 0x100;
31 0 : const LNK_INFO = 0x200;
32 0 : const LNK_REMOVE = 0x800;
33 0 : const LNK_COMDAT = 0x1000;
34 0 : const GPREL = 0x8000;
35 0 : const MEM_PURGEABLE = 0x10000;
36 0 : const MEM_16BIT = 0x20000;
37 0 : const MEM_LOCKED = 0x40000;
38 0 : const MEM_PRELOAD = 0x80000;
39 0 : const ALIGN_1BYTES = 0x100000;
40 0 : const ALIGN_2BYTES = 0x200000;
41 0 : const ALIGN_4BYTES = 0x300000;
42 0 : const ALIGN_8BYTES = 0x400000;
43 0 : const ALIGN_16BYTES = 0x500000;
44 0 : const ALIGN_32BYTES = 0x600000;
45 0 : const ALIGN_64BYTES = 0x700000;
46 0 : const ALIGN_128BYTES = 0x800000;
47 0 : const ALIGN_256BYTES = 0x900000;
48 0 : const ALIGN_512BYTES = 0xa00000;
49 0 : const ALIGN_1024BYTES = 0xb00000;
50 0 : const ALIGN_2048BYTES = 0xc00000;
51 0 : const ALIGN_4096BYTES = 0xd00000;
52 0 : const ALIGN_8192BYTES = 0xe00000;
53 0 : const LNK_NRELOC_OVFL = 0x1000000;
54 0 : const MEM_DISCARDABLE = 0x2000000;
55 0 : const MEM_NOT_CACHED = 0x4000000;
56 0 : const MEM_NOT_PAGED = 0x8000000;
57 0 : const MEM_SHARED = 0x10000000;
58 0 : const MEM_EXECUTE = 0x20000000;
59 0 : const MEM_READ = 0x40000000;
60 0 : const MEM_WRITE = 0x80000000;
61 0 : }
62 0 : }
63 :
64 : impl From<u32> for Characteristics {
65 21684 : fn from(value: u32) -> Self {
66 21684 : Characteristics::from_bits_truncate(value)
67 21684 : }
68 : }
69 : impl From<Characteristics> for u32 {
70 0 : fn from(value: Characteristics) -> Self {
71 0 : value.bits()
72 0 : }
73 : }
74 : impl std::fmt::Display for Characteristics {
75 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
76 0 : bitflags::parser::to_writer(self, f)
77 0 : }
78 : }
79 :
80 : impl Section<'_> {
81 : /// Create a new Section
82 0 : pub fn new() -> Section<'static> {
83 0 : Section::from_ffi(lief_ffi::PE_Section::create())
84 0 : }
85 :
86 : /// Create a new Section with the given name
87 0 : pub fn new_with_name(name: &str) -> Section<'static> {
88 0 : Section::from_ffi(lief_ffi::PE_Section::create_with_name(name.to_string()))
89 0 : }
90 :
91 : /// Create a new Section with the given name and content
92 0 : pub fn new_with_content(name: &str, content: &[u8]) -> Section<'static> {
93 0 : unsafe {
94 0 : Section::from_ffi(lief_ffi::PE_Section::create_with_content(
95 0 : name.to_string(),
96 0 : content.as_ptr(),
97 0 : content.len(),
98 0 : ))
99 0 : }
100 0 : }
101 :
102 : /// Return the size of the data in the section.
103 8229 : pub fn sizeof_raw_data(&self) -> u32 {
104 8229 : self.ptr.sizeof_raw_data()
105 8229 : }
106 :
107 : /// Return the size of the data when mapped in memory
108 : ///
109 : /// If this value is greater than [`Section::sizeof_raw_data`], the section is zero-padded.
110 8229 : pub fn virtual_size(&self) -> u32 {
111 8229 : self.ptr.virtual_size()
112 8229 : }
113 :
114 : /// The offset of the section data in the PE file
115 8229 : pub fn pointerto_raw_data(&self) -> u32 {
116 8229 : self.ptr.pointerto_raw_data()
117 8229 : }
118 :
119 : /// The file pointer to the beginning of the COFF relocation entries for the section.
120 : /// This is set to zero for executable images or if there are no relocations.
121 : ///
122 : /// For modern PE binaries, this value is usually set to 0 as the relocations are managed by
123 : /// [`crate::pe::Relocation`].
124 8229 : pub fn pointerto_relocation(&self) -> u32 {
125 8229 : self.ptr.pointerto_relocation()
126 8229 : }
127 :
128 : /// The file pointer to the beginning of line-number entries for the section.
129 : /// This is set to zero if there are no COFF line numbers. This value should be zero for an
130 : /// image because COFF debugging information is deprecated and modern debug information relies
131 : /// on the PDB files.
132 8229 : pub fn pointerto_line_numbers(&self) -> u32 {
133 8229 : self.ptr.pointerto_line_numbers()
134 8229 : }
135 :
136 : /// No longer used in recent PE binaries produced by Visual Studio
137 8229 : pub fn numberof_relocations(&self) -> u16 {
138 8229 : self.ptr.numberof_relocations()
139 8229 : }
140 :
141 : /// No longer used in recent PE binaries produced by Visual Studio
142 8229 : pub fn numberof_line_numbers(&self) -> u16 {
143 8229 : self.ptr.numberof_line_numbers()
144 8229 : }
145 :
146 : /// Characteristics of the section: it provides information about
147 : /// the permissions of the section when mapped. It can also provide
148 : /// information about the *purpose* of the section (contain code, BSS-like, ...)
149 8229 : pub fn characteristics(&self) -> Characteristics {
150 8229 : Characteristics::from(self.ptr.characteristics())
151 8229 : }
152 :
153 : /// Content of the section's padding area
154 1976 : pub fn padding(&self) -> &[u8] {
155 1976 : to_slice!(self.ptr.padding());
156 1976 : }
157 :
158 : /// True if the section can be discarded as needed.
159 : ///
160 : /// This is typically the case for debug-related sections
161 0 : pub fn is_discardable(&self) -> bool {
162 0 : self.ptr.is_discardable()
163 0 : }
164 :
165 : /// Return the COFF string associated with the section's name (or a None)
166 : ///
167 : /// This coff string is usually present for long section names whose length
168 : /// does not fit in the 8 bytes allocated by the PE format.
169 1976 : pub fn coff_string(&self) -> Option<coff::String<'_>> {
170 1976 : into_optional(self.ptr.coff_string())
171 1976 : }
172 :
173 : /// Set the virtual size of the section
174 0 : pub fn set_virtual_size(&mut self, virtual_size: u32) {
175 0 : self.ptr.pin_mut().set_virtual_size(virtual_size);
176 0 : }
177 : }
178 :
179 : impl std::fmt::Debug for Section<'_> {
180 8229 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181 8229 : let base = self as &dyn generic::Section;
182 8229 : f.debug_struct("Section")
183 8229 : .field("base", &base)
184 8229 : .field("sizeof_raw_data", &self.sizeof_raw_data())
185 8229 : .field("virtual_size", &self.virtual_size())
186 8229 : .field("pointerto_raw_data", &self.pointerto_raw_data())
187 8229 : .field("pointerto_relocation", &self.pointerto_relocation())
188 8229 : .field("pointerto_line_numbers", &self.pointerto_line_numbers())
189 8229 : .field("numberof_relocations", &self.numberof_relocations())
190 8229 : .field("numberof_line_numbers", &self.numberof_line_numbers())
191 8229 : .field("characteristics", &self.characteristics())
192 8229 : .finish()
193 8229 : }
194 : }
195 :
196 : impl<'a> FromFFI<ffi::PE_Section> for Section<'a> {
197 8294 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Section>) -> Self {
198 8294 : Section {
199 8294 : ptr,
200 8294 : _owner: PhantomData,
201 8294 : }
202 8294 : }
203 : }
204 :
205 : impl<'a> AsFFI<ffi::PE_Section> for Section<'a> {
206 0 : fn as_ffi(&self) -> &ffi::PE_Section {
207 0 : self.ptr.as_ref().unwrap()
208 0 : }
209 :
210 0 : fn as_mut_ffi(&mut self) -> std::pin::Pin<&mut ffi::PE_Section> {
211 0 : self.ptr.pin_mut()
212 0 : }
213 : }
214 :
215 : impl generic::Section for Section<'_> {
216 32981 : fn as_generic(&self) -> &ffi::AbstractSection {
217 32981 : self.ptr.as_ref().unwrap().as_ref()
218 32981 : }
219 :
220 0 : fn as_generic_mut(&mut self) -> Pin<&mut ffi::AbstractSection> {
221 0 : unsafe {
222 0 : Pin::new_unchecked({
223 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSection
224 0 : as *mut ffi::AbstractSection)
225 0 : .as_mut()
226 0 : .unwrap()
227 0 : })
228 0 : }
229 0 : }
230 : }
231 :
232 1976 : declare_iterator!(
233 1976 : Sections,
234 1976 : Section<'a>,
235 1976 : ffi::PE_Section,
236 1976 : ffi::PE_Binary,
237 1976 : ffi::PE_Binary_it_sections
238 1976 : );
|