Line data Source code
1 : //! COFF section module
2 :
3 : use super::Relocation;
4 : use super::Symbol;
5 : use crate::coff;
6 : use crate::common::into_optional;
7 : use crate::common::FromFFI;
8 : use crate::declare_iterator;
9 : use crate::generic;
10 : use crate::pe;
11 : use std::marker::PhantomData;
12 : use std::pin::Pin;
13 :
14 : use lief_ffi as ffi;
15 :
16 : pub struct Section<'a> {
17 : ptr: cxx::UniquePtr<ffi::COFF_Section>,
18 : _owner: PhantomData<&'a ffi::COFF_Binary>,
19 : }
20 :
21 : impl FromFFI<ffi::COFF_Section> for Section<'_> {
22 25571 : fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_Section>) -> Self {
23 25571 : Self {
24 25571 : ptr,
25 25571 : _owner: PhantomData,
26 25571 : }
27 25571 : }
28 : }
29 :
30 : impl Section<'_> {
31 : /// Return the size of the data in the section.
32 13455 : pub fn sizeof_raw_data(&self) -> u32 {
33 13455 : self.ptr.sizeof_raw_data()
34 13455 : }
35 :
36 : /// Return the size of the data when mapped in memory (should be 0)
37 13455 : pub fn virtual_size(&self) -> u32 {
38 13455 : self.ptr.virtual_size()
39 13455 : }
40 :
41 : /// Offset to the section's content
42 13455 : pub fn pointerto_raw_data(&self) -> u32 {
43 13455 : self.ptr.pointerto_raw_data()
44 13455 : }
45 :
46 : /// Offset to the relocation table
47 13455 : pub fn pointerto_relocation(&self) -> u32 {
48 13455 : self.ptr.pointerto_relocation()
49 13455 : }
50 :
51 : /// The file pointer to the beginning of line-number entries for the section.
52 : ///
53 : /// This is set to zero if there are no COFF line numbers.
54 : /// This value should be zero for an image because COFF debugging information
55 : /// is deprecated and modern debug information relies on the PDB files.
56 13455 : pub fn pointerto_line_numbers(&self) -> u32 {
57 13455 : self.ptr.pointerto_line_numbers()
58 13455 : }
59 :
60 : /// Number of relocations.
61 : ///
62 : /// <div class="warning">
63 : /// If the number of relocations is greater than 0xFFFF (maximum value for 16-bits integer),
64 : /// then the number of relocations is stored in the virtual address attribute.
65 : /// </div>
66 13455 : pub fn numberof_relocations(&self) -> u16 {
67 13455 : self.ptr.numberof_relocations()
68 13455 : }
69 :
70 : /// Number of line number entries (if any).
71 13455 : pub fn numberof_line_numbers(&self) -> u16 {
72 13455 : self.ptr.numberof_line_numbers()
73 13455 : }
74 :
75 : /// Characteristics of the section: it provides information about
76 : /// the permissions of the section when mapped. It can also provide
77 : /// information about the *purpose* of the section (contain code, BSS-like, ...)
78 13455 : pub fn characteristics(&self) -> pe::section::Characteristics {
79 13455 : pe::section::Characteristics::from(self.ptr.characteristics())
80 13455 : }
81 :
82 : /// True if the section can be discarded as needed.
83 : ///
84 : /// This is typically the case for debug-related sections
85 0 : pub fn is_discardable(&self) -> bool {
86 0 : self.ptr.is_discardable()
87 0 : }
88 :
89 : /// Whether there is a large number of relocations whose number need to be stored in the
90 : /// virtual address attribute
91 0 : pub fn has_extended_relocations(&self) -> bool {
92 0 : self.ptr.has_extended_relocations()
93 0 : }
94 :
95 : /// Iterator over the relocations associated with this section
96 4355 : pub fn relocations(&self) -> Relocations<'_> {
97 4355 : Relocations::new(self.ptr.relocations())
98 4355 : }
99 :
100 : /// Iterator over the symbols associated with this section
101 4355 : pub fn symbols(&self) -> Symbols<'_> {
102 4355 : Symbols::new(self.ptr.symbols())
103 4355 : }
104 :
105 : /// Return comdat information (only if the section has the
106 : /// [`crate::pe::section::Characteristics::LNK_COMDAT`] characteristic)
107 4355 : pub fn comdat_info(&self) -> Option<ComdatInfo<'_>> {
108 4355 : into_optional(self.ptr.comdat_info())
109 4355 : }
110 :
111 : /// Return the COFF string associated with the section's name (or a None)
112 : ///
113 : /// This coff string is usually present for long section names whose length
114 : /// does not fit in the 8 bytes allocated by the COFF format.
115 0 : pub fn coff_string(&self) -> Option<coff::String<'_>> {
116 0 : into_optional(self.ptr.coff_string())
117 0 : }
118 : }
119 :
120 : impl generic::Section for Section<'_> {
121 65936 : fn as_generic(&self) -> &ffi::AbstractSection {
122 65936 : self.ptr.as_ref().unwrap().as_ref()
123 65936 : }
124 :
125 0 : fn as_generic_mut(&mut self) -> Pin<&mut ffi::AbstractSection> {
126 0 : unsafe {
127 0 : Pin::new_unchecked({
128 0 : (self.ptr.as_ref().unwrap().as_ref() as *const ffi::AbstractSection
129 0 : as *mut ffi::AbstractSection)
130 0 : .as_mut()
131 0 : .unwrap()
132 0 : })
133 0 : }
134 0 : }
135 : }
136 :
137 : impl std::fmt::Debug for Section<'_> {
138 13455 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 13455 : let base = self as &dyn generic::Section;
140 13455 : f.debug_struct("Section")
141 13455 : .field("base", &base)
142 13455 : .field("sizeof_raw_data", &self.sizeof_raw_data())
143 13455 : .field("virtual_size", &self.virtual_size())
144 13455 : .field("pointerto_raw_data", &self.pointerto_raw_data())
145 13455 : .field("pointerto_relocation", &self.pointerto_relocation())
146 13455 : .field("pointerto_line_numbers", &self.pointerto_line_numbers())
147 13455 : .field("numberof_relocations", &self.numberof_relocations())
148 13455 : .field("numberof_line_numbers", &self.numberof_line_numbers())
149 13455 : .field("characteristics", &self.characteristics())
150 13455 : .finish()
151 13455 : }
152 : }
153 :
154 : impl std::fmt::Display for Section<'_> {
155 13455 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
156 13455 : write!(f, "{}", self.ptr.to_string())
157 13455 : }
158 : }
159 :
160 : /// This structure wraps comdat information which is composed of the symbol
161 : /// associated with the comdat section and its selection flag
162 : pub struct ComdatInfo<'a> {
163 : ptr: cxx::UniquePtr<ffi::COFF_Section_ComdataInfo>,
164 : _owner: PhantomData<&'a ffi::COFF_Binary>,
165 : }
166 :
167 : impl ComdatInfo<'_> {
168 2795 : pub fn symbol(&self) -> Option<Symbol<'_>> {
169 2795 : into_optional(self.ptr.symbol())
170 2795 : }
171 :
172 2795 : pub fn kind(&self) -> coff::symbol::ComdatSelection {
173 2795 : coff::symbol::ComdatSelection::from(self.ptr.kind())
174 2795 : }
175 : }
176 :
177 : impl FromFFI<ffi::COFF_Section_ComdataInfo> for ComdatInfo<'_> {
178 2795 : fn from_ffi(ptr: cxx::UniquePtr<ffi::COFF_Section_ComdataInfo>) -> Self {
179 2795 : Self {
180 2795 : ptr,
181 2795 : _owner: PhantomData,
182 2795 : }
183 2795 : }
184 : }
185 :
186 : impl std::fmt::Debug for ComdatInfo<'_> {
187 2795 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 2795 : f.debug_struct("ComdatInfo")
189 2795 : .field("symbol", &self.symbol())
190 2795 : .field("kind", &self.kind())
191 2795 : .finish()
192 2795 : }
193 : }
194 :
195 0 : declare_iterator!(
196 0 : Relocations,
197 0 : Relocation<'a>,
198 0 : ffi::COFF_Relocation,
199 0 : ffi::COFF_Section,
200 0 : ffi::COFF_Section_it_relocations
201 0 : );
202 :
203 9100 : declare_iterator!(
204 9100 : Symbols,
205 9100 : Symbol<'a>,
206 9100 : ffi::COFF_Symbol,
207 9100 : ffi::COFF_Section,
208 9100 : ffi::COFF_Section_it_symbols
209 9100 : );
|