Line data Source code
1 : //! PE section module
2 :
3 : use std::marker::PhantomData;
4 :
5 : use lief_ffi as ffi;
6 :
7 : use crate::declare_iterator;
8 : use crate::to_slice;
9 : use crate::{common::FromFFI, generic};
10 : use super::coff;
11 : use bitflags::bitflags;
12 : use crate::common::into_optional;
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 6330 : #[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 :
65 : impl From<u32> for Characteristics {
66 6330 : fn from(value: u32) -> Self {
67 6330 : Characteristics::from_bits_truncate(value)
68 6330 : }
69 : }
70 : impl From<Characteristics> for u32 {
71 0 : fn from(value: Characteristics) -> Self {
72 0 : value.bits()
73 0 : }
74 : }
75 : impl std::fmt::Display for Characteristics {
76 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
77 0 : bitflags::parser::to_writer(self, f)
78 0 : }
79 : }
80 :
81 : impl Section<'_> {
82 : /// Return the size of the data in the section.
83 6330 : pub fn sizeof_raw_data(&self) -> u32 {
84 6330 : self.ptr.sizeof_raw_data()
85 6330 : }
86 :
87 : /// Return the size of the data when mapped in memory
88 : ///
89 : /// If this value is greater than [`Section::sizeof_raw_data`], the section is zero-padded.
90 6330 : pub fn virtual_size(&self) -> u32 {
91 6330 : self.ptr.virtual_size()
92 6330 : }
93 :
94 : /// The offset of the section data in the PE file
95 6330 : pub fn pointerto_raw_data(&self) -> u32 {
96 6330 : self.ptr.pointerto_raw_data()
97 6330 : }
98 :
99 : /// The file pointer to the beginning of the COFF relocation entries for the section.
100 : /// This is set to zero for executable images or if there are no relocations.
101 : ///
102 : /// For modern PE binaries, this value is usually set to 0 as the relocations are managed by
103 : /// [`crate::pe::Relocation`].
104 6330 : pub fn pointerto_relocation(&self) -> u32 {
105 6330 : self.ptr.pointerto_relocation()
106 6330 : }
107 :
108 : /// The file pointer to the beginning of line-number entries for the section.
109 : /// This is set to zero if there are no COFF line numbers. This value should be zero for an
110 : /// image because COFF debugging information is deprecated and modern debug information relies
111 : /// on the PDB files.
112 6330 : pub fn pointerto_line_numbers(&self) -> u32 {
113 6330 : self.ptr.pointerto_line_numbers()
114 6330 : }
115 :
116 : /// No longer used in recent PE binaries produced by Visual Studio
117 6330 : pub fn numberof_relocations(&self) -> u16 {
118 6330 : self.ptr.numberof_relocations()
119 6330 : }
120 :
121 : /// No longer used in recent PE binaries produced by Visual Studio
122 6330 : pub fn numberof_line_numbers(&self) -> u16 {
123 6330 : self.ptr.numberof_line_numbers()
124 6330 : }
125 :
126 : /// Characteristics of the section: it provides information about
127 : /// the permissions of the section when mapped. It can also provide
128 : /// information about the *purpose* of the section (contain code, BSS-like, ...)
129 6330 : pub fn characteristics(&self) -> Characteristics {
130 6330 : Characteristics::from(self.ptr.characteristics())
131 6330 : }
132 :
133 : /// Content of the section's padding area
134 1520 : pub fn padding(&self) -> &[u8] {
135 1520 : to_slice!(self.ptr.padding());
136 1520 : }
137 :
138 : /// True if the section can be discarded as needed.
139 : ///
140 : /// This is typically the case for debug-related sections
141 0 : pub fn is_discardable(&self) -> bool {
142 0 : self.ptr.is_discardable()
143 0 : }
144 :
145 : /// Return the COFF string associated with the section's name (or a None)
146 : ///
147 : /// This coff string is usually present for long section names whose length
148 : /// does not fit in the 8 bytes allocated by the PE format.
149 1520 : pub fn coff_string(&self) -> Option<coff::String> {
150 1520 : into_optional(self.ptr.coff_string())
151 1520 : }
152 : }
153 :
154 : impl std::fmt::Debug for Section<'_> {
155 6330 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 6330 : let base = self as &dyn generic::Section;
157 6330 : f.debug_struct("Section")
158 6330 : .field("base", &base)
159 6330 : .field("sizeof_raw_data", &self.sizeof_raw_data())
160 6330 : .field("virtual_size", &self.virtual_size())
161 6330 : .field("pointerto_raw_data", &self.pointerto_raw_data())
162 6330 : .field("pointerto_relocation", &self.pointerto_relocation())
163 6330 : .field("pointerto_line_numbers", &self.pointerto_line_numbers())
164 6330 : .field("numberof_relocations", &self.numberof_relocations())
165 6330 : .field("numberof_line_numbers", &self.numberof_line_numbers())
166 6330 : .field("characteristics", &self.characteristics())
167 6330 : .finish()
168 6330 : }
169 : }
170 :
171 : impl<'a> FromFFI<ffi::PE_Section> for Section<'a> {
172 6360 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Section>) -> Self {
173 6360 : Section {
174 6360 : ptr,
175 6360 : _owner: PhantomData,
176 6360 : }
177 6360 : }
178 : }
179 :
180 : impl generic::Section for Section<'_> {
181 25320 : fn as_generic(&self) -> &ffi::AbstractSection {
182 25320 : self.ptr.as_ref().unwrap().as_ref()
183 25320 : }
184 : }
185 :
186 1520 : declare_iterator!(
187 1520 : Sections,
188 1520 : Section<'a>,
189 1520 : ffi::PE_Section,
190 1520 : ffi::PE_Binary,
191 1520 : ffi::PE_Binary_it_sections
192 1520 : );
|