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 bitflags::bitflags;
11 :
12 : /// This structure defines a regular PE section.
13 : ///
14 : /// Note that it implements the trait [`generic::Section`] which provides additional
15 : /// functions.
16 : pub struct Section<'a> {
17 : ptr: cxx::UniquePtr<ffi::PE_Section>,
18 : _owner: PhantomData<&'a ffi::PE_Binary>,
19 : }
20 :
21 0 : bitflags! {
22 2144 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
23 0 : pub struct Characteristics: u64 {
24 0 : const TYPE_NO_PAD = 0x8;
25 0 : const CNT_CODE = 0x20;
26 0 : const CNT_INITIALIZED_DATA = 0x40;
27 0 : const CNT_UNINITIALIZED_DATA = 0x80;
28 0 : const LNK_OTHER = 0x100;
29 0 : const LNK_INFO = 0x200;
30 0 : const LNK_REMOVE = 0x800;
31 0 : const LNK_COMDAT = 0x1000;
32 0 : const GPREL = 0x8000;
33 0 : const MEM_PURGEABLE = 0x10000;
34 0 : const MEM_16BIT = 0x20000;
35 0 : const MEM_LOCKED = 0x40000;
36 0 : const MEM_PRELOAD = 0x80000;
37 0 : const ALIGN_1BYTES = 0x100000;
38 0 : const ALIGN_2BYTES = 0x200000;
39 0 : const ALIGN_4BYTES = 0x300000;
40 0 : const ALIGN_8BYTES = 0x400000;
41 0 : const ALIGN_16BYTES = 0x500000;
42 0 : const ALIGN_32BYTES = 0x600000;
43 0 : const ALIGN_64BYTES = 0x700000;
44 0 : const ALIGN_128BYTES = 0x800000;
45 0 : const ALIGN_256BYTES = 0x900000;
46 0 : const ALIGN_512BYTES = 0xa00000;
47 0 : const ALIGN_1024BYTES = 0xb00000;
48 0 : const ALIGN_2048BYTES = 0xc00000;
49 0 : const ALIGN_4096BYTES = 0xd00000;
50 0 : const ALIGN_8192BYTES = 0xe00000;
51 0 : const LNK_NRELOC_OVFL = 0x1000000;
52 0 : const MEM_DISCARDABLE = 0x2000000;
53 0 : const MEM_NOT_CACHED = 0x4000000;
54 0 : const MEM_NOT_PAGED = 0x8000000;
55 0 : const MEM_SHARED = 0x10000000;
56 0 : const MEM_EXECUTE = 0x20000000;
57 0 : const MEM_READ = 0x40000000;
58 0 : const MEM_WRITE = 0x80000000;
59 0 : }
60 0 : }
61 :
62 :
63 : impl From<u64> for Characteristics {
64 2144 : fn from(value: u64) -> Self {
65 2144 : Characteristics::from_bits_truncate(value)
66 2144 : }
67 : }
68 : impl From<Characteristics> for u64 {
69 0 : fn from(value: Characteristics) -> Self {
70 0 : value.bits()
71 0 : }
72 : }
73 : impl std::fmt::Display for Characteristics {
74 0 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
75 0 : bitflags::parser::to_writer(self, f)
76 0 : }
77 : }
78 :
79 : impl Section<'_> {
80 : /// Return the size of the data in the section.
81 2144 : pub fn sizeof_raw_data(&self) -> u32 {
82 2144 : self.ptr.sizeof_raw_data()
83 2144 : }
84 :
85 : /// Return the size of the data when mapped in memory
86 : ///
87 : /// If this value is greater than [`Section::sizeof_raw_data`], the section is zero-padded.
88 2144 : pub fn virtual_size(&self) -> u32 {
89 2144 : self.ptr.virtual_size()
90 2144 : }
91 :
92 : /// The offset of the section data in the PE file
93 2144 : pub fn pointerto_raw_data(&self) -> u32 {
94 2144 : self.ptr.pointerto_raw_data()
95 2144 : }
96 :
97 : /// The file pointer to the beginning of the COFF relocation entries for the section.
98 : /// This is set to zero for executable images or if there are no relocations.
99 : ///
100 : /// For modern PE binaries, this value is usually set to 0 as the relocations are managed by
101 : /// [`crate::pe::Relocation`].
102 2144 : pub fn pointerto_relocation(&self) -> u32 {
103 2144 : self.ptr.pointerto_relocation()
104 2144 : }
105 :
106 : /// The file pointer to the beginning of line-number entries for the section.
107 : /// This is set to zero if there are no COFF line numbers. This value should be zero for an
108 : /// image because COFF debugging information is deprecated and modern debug information relies
109 : /// on the PDB files.
110 2144 : pub fn pointerto_line_numbers(&self) -> u32 {
111 2144 : self.ptr.pointerto_line_numbers()
112 2144 : }
113 :
114 : /// No longer used in recent PE binaries produced by Visual Studio
115 2144 : pub fn numberof_relocations(&self) -> u32 {
116 2144 : self.ptr.numberof_relocations()
117 2144 : }
118 :
119 : /// No longer used in recent PE binaries produced by Visual Studio
120 2144 : pub fn numberof_line_numbers(&self) -> u32 {
121 2144 : self.ptr.numberof_line_numbers()
122 2144 : }
123 :
124 : /// Characteristics of the section: it provides information about
125 : /// the permissions of the section when mapped. It can also provide
126 : /// information about the *purpose* of the section (contain code, BSS-like, ...)
127 2144 : pub fn characteristics(&self) -> Characteristics {
128 2144 : Characteristics::from(self.ptr.characteristics())
129 2144 : }
130 :
131 : /// Content of the section's padding area
132 672 : pub fn padding(&self) -> &[u8] {
133 672 : to_slice!(self.ptr.padding());
134 672 : }
135 : }
136 :
137 : impl std::fmt::Debug for Section<'_> {
138 2144 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 2144 : let base = self as &dyn generic::Section;
140 2144 : f.debug_struct("Section")
141 2144 : .field("base", &base)
142 2144 : .field("sizeof_raw_data", &self.sizeof_raw_data())
143 2144 : .field("virtual_size", &self.virtual_size())
144 2144 : .field("pointerto_raw_data", &self.pointerto_raw_data())
145 2144 : .field("pointerto_relocation", &self.pointerto_relocation())
146 2144 : .field("pointerto_line_numbers", &self.pointerto_line_numbers())
147 2144 : .field("numberof_relocations", &self.numberof_relocations())
148 2144 : .field("numberof_line_numbers", &self.numberof_line_numbers())
149 2144 : .field("characteristics", &self.characteristics())
150 2144 : .finish()
151 2144 : }
152 : }
153 :
154 : impl<'a> FromFFI<ffi::PE_Section> for Section<'a> {
155 2168 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_Section>) -> Self {
156 2168 : Section {
157 2168 : ptr,
158 2168 : _owner: PhantomData,
159 2168 : }
160 2168 : }
161 : }
162 :
163 : impl generic::Section for Section<'_> {
164 8576 : fn as_generic(&self) -> &ffi::AbstractSection {
165 8576 : self.ptr.as_ref().unwrap().as_ref()
166 8576 : }
167 : }
168 :
169 672 : declare_iterator!(
170 672 : Sections,
171 672 : Section<'a>,
172 672 : ffi::PE_Section,
173 672 : ffi::PE_Binary,
174 672 : ffi::PE_Binary_it_sections
175 672 : );
|