]> git.proxmox.com Git - rustc.git/blame - vendor/object-0.26.2/src/read/pe/section.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / vendor / object-0.26.2 / src / read / pe / section.rs
CommitLineData
17df50a5
XL
1use core::marker::PhantomData;
2use core::{cmp, iter, result, slice, str};
3
4use crate::endian::LittleEndian as LE;
5use crate::pe;
6use crate::read::{
7 self, CompressedData, CompressedFileRange, ObjectSection, ObjectSegment, ReadError, ReadRef,
8 Relocation, Result, SectionFlags, SectionIndex, SectionKind,
9};
10
11use super::{ImageNtHeaders, PeFile, SectionTable};
12
13/// An iterator over the loadable sections of a `PeFile32`.
14pub type PeSegmentIterator32<'data, 'file, R = &'data [u8]> =
15 PeSegmentIterator<'data, 'file, pe::ImageNtHeaders32, R>;
16/// An iterator over the loadable sections of a `PeFile64`.
17pub type PeSegmentIterator64<'data, 'file, R = &'data [u8]> =
18 PeSegmentIterator<'data, 'file, pe::ImageNtHeaders64, R>;
19
20/// An iterator over the loadable sections of a `PeFile`.
21#[derive(Debug)]
22pub struct PeSegmentIterator<'data, 'file, Pe, R = &'data [u8]>
23where
24 Pe: ImageNtHeaders,
25 R: ReadRef<'data>,
26{
27 pub(super) file: &'file PeFile<'data, Pe, R>,
136023e0 28 pub(super) iter: slice::Iter<'data, pe::ImageSectionHeader>,
17df50a5
XL
29}
30
31impl<'data, 'file, Pe, R> Iterator for PeSegmentIterator<'data, 'file, Pe, R>
32where
33 Pe: ImageNtHeaders,
34 R: ReadRef<'data>,
35{
36 type Item = PeSegment<'data, 'file, Pe, R>;
37
38 fn next(&mut self) -> Option<Self::Item> {
39 self.iter.next().map(|section| PeSegment {
40 file: self.file,
41 section,
42 })
43 }
44}
45
46/// A loadable section of a `PeFile32`.
47pub type PeSegment32<'data, 'file, R = &'data [u8]> =
48 PeSegment<'data, 'file, pe::ImageNtHeaders32, R>;
49/// A loadable section of a `PeFile64`.
50pub type PeSegment64<'data, 'file, R = &'data [u8]> =
51 PeSegment<'data, 'file, pe::ImageNtHeaders64, R>;
52
53/// A loadable section of a `PeFile`.
54#[derive(Debug)]
55pub struct PeSegment<'data, 'file, Pe, R = &'data [u8]>
56where
57 Pe: ImageNtHeaders,
58 R: ReadRef<'data>,
59{
60 file: &'file PeFile<'data, Pe, R>,
136023e0 61 section: &'data pe::ImageSectionHeader,
17df50a5
XL
62}
63
64impl<'data, 'file, Pe, R> PeSegment<'data, 'file, Pe, R>
65where
66 Pe: ImageNtHeaders,
67 R: ReadRef<'data>,
68{
69 fn bytes(&self) -> Result<&'data [u8]> {
70 self.section
71 .pe_data(self.file.data)
72 .read_error("Invalid PE section offset or size")
73 }
74}
75
76impl<'data, 'file, Pe, R> read::private::Sealed for PeSegment<'data, 'file, Pe, R>
77where
78 Pe: ImageNtHeaders,
79 R: ReadRef<'data>,
80{
81}
82
83impl<'data, 'file, Pe, R> ObjectSegment<'data> for PeSegment<'data, 'file, Pe, R>
84where
85 Pe: ImageNtHeaders,
86 R: ReadRef<'data>,
87{
88 #[inline]
89 fn address(&self) -> u64 {
90 u64::from(self.section.virtual_address.get(LE)).wrapping_add(self.file.common.image_base)
91 }
92
93 #[inline]
94 fn size(&self) -> u64 {
95 u64::from(self.section.virtual_size.get(LE))
96 }
97
98 #[inline]
99 fn align(&self) -> u64 {
100 self.file.section_alignment()
101 }
102
103 #[inline]
104 fn file_range(&self) -> (u64, u64) {
105 let (offset, size) = self.section.pe_file_range();
106 (u64::from(offset), u64::from(size))
107 }
108
109 fn data(&self) -> Result<&'data [u8]> {
110 self.bytes()
111 }
112
113 fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
114 Ok(read::util::data_range(
115 self.bytes()?,
116 self.address(),
117 address,
118 size,
119 ))
120 }
121
122 #[inline]
123 fn name(&self) -> Result<Option<&str>> {
124 let name = self.section.name(self.file.common.symbols.strings())?;
125 Ok(Some(
126 str::from_utf8(name)
127 .ok()
128 .read_error("Non UTF-8 PE section name")?,
129 ))
130 }
131}
132
133/// An iterator over the sections of a `PeFile32`.
134pub type PeSectionIterator32<'data, 'file, R = &'data [u8]> =
135 PeSectionIterator<'data, 'file, pe::ImageNtHeaders32, R>;
136/// An iterator over the sections of a `PeFile64`.
137pub type PeSectionIterator64<'data, 'file, R = &'data [u8]> =
138 PeSectionIterator<'data, 'file, pe::ImageNtHeaders64, R>;
139
140/// An iterator over the sections of a `PeFile`.
141#[derive(Debug)]
142pub struct PeSectionIterator<'data, 'file, Pe, R = &'data [u8]>
143where
144 'data: 'file,
145 Pe: ImageNtHeaders,
146 R: ReadRef<'data>,
147{
148 pub(super) file: &'file PeFile<'data, Pe, R>,
136023e0 149 pub(super) iter: iter::Enumerate<slice::Iter<'data, pe::ImageSectionHeader>>,
17df50a5
XL
150}
151
152impl<'data, 'file, Pe, R> Iterator for PeSectionIterator<'data, 'file, Pe, R>
153where
154 Pe: ImageNtHeaders,
155 R: ReadRef<'data>,
156{
157 type Item = PeSection<'data, 'file, Pe, R>;
158
159 fn next(&mut self) -> Option<Self::Item> {
160 self.iter.next().map(|(index, section)| PeSection {
161 file: self.file,
162 index: SectionIndex(index + 1),
163 section,
164 })
165 }
166}
167
168/// A section of a `PeFile32`.
169pub type PeSection32<'data, 'file, R = &'data [u8]> =
170 PeSection<'data, 'file, pe::ImageNtHeaders32, R>;
171/// A section of a `PeFile64`.
172pub type PeSection64<'data, 'file, R = &'data [u8]> =
173 PeSection<'data, 'file, pe::ImageNtHeaders64, R>;
174
175/// A section of a `PeFile`.
176#[derive(Debug)]
177pub struct PeSection<'data, 'file, Pe, R = &'data [u8]>
178where
179 'data: 'file,
180 Pe: ImageNtHeaders,
181 R: ReadRef<'data>,
182{
183 pub(super) file: &'file PeFile<'data, Pe, R>,
184 pub(super) index: SectionIndex,
136023e0 185 pub(super) section: &'data pe::ImageSectionHeader,
17df50a5
XL
186}
187
188impl<'data, 'file, Pe, R> PeSection<'data, 'file, Pe, R>
189where
190 Pe: ImageNtHeaders,
191 R: ReadRef<'data>,
192{
193 fn bytes(&self) -> Result<&'data [u8]> {
194 self.section
195 .pe_data(self.file.data)
196 .read_error("Invalid PE section offset or size")
197 }
198}
199
200impl<'data, 'file, Pe, R> read::private::Sealed for PeSection<'data, 'file, Pe, R>
201where
202 Pe: ImageNtHeaders,
203 R: ReadRef<'data>,
204{
205}
206
207impl<'data, 'file, Pe, R> ObjectSection<'data> for PeSection<'data, 'file, Pe, R>
208where
209 Pe: ImageNtHeaders,
210 R: ReadRef<'data>,
211{
212 type RelocationIterator = PeRelocationIterator<'data, 'file, R>;
213
214 #[inline]
215 fn index(&self) -> SectionIndex {
216 self.index
217 }
218
219 #[inline]
220 fn address(&self) -> u64 {
221 u64::from(self.section.virtual_address.get(LE)).wrapping_add(self.file.common.image_base)
222 }
223
224 #[inline]
225 fn size(&self) -> u64 {
226 u64::from(self.section.virtual_size.get(LE))
227 }
228
229 #[inline]
230 fn align(&self) -> u64 {
231 self.file.section_alignment()
232 }
233
234 #[inline]
235 fn file_range(&self) -> Option<(u64, u64)> {
236 let (offset, size) = self.section.pe_file_range();
237 if size == 0 {
238 None
239 } else {
240 Some((u64::from(offset), u64::from(size)))
241 }
242 }
243
244 fn data(&self) -> Result<&'data [u8]> {
245 self.bytes()
246 }
247
248 fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
249 Ok(read::util::data_range(
250 self.bytes()?,
251 self.address(),
252 address,
253 size,
254 ))
255 }
256
257 #[inline]
258 fn compressed_file_range(&self) -> Result<CompressedFileRange> {
259 Ok(CompressedFileRange::none(self.file_range()))
260 }
261
262 #[inline]
263 fn compressed_data(&self) -> Result<CompressedData<'data>> {
264 self.data().map(CompressedData::none)
265 }
266
267 #[inline]
268 fn name(&self) -> Result<&str> {
269 let name = self.section.name(self.file.common.symbols.strings())?;
270 str::from_utf8(name)
271 .ok()
272 .read_error("Non UTF-8 PE section name")
273 }
274
275 #[inline]
276 fn segment_name(&self) -> Result<Option<&str>> {
277 Ok(None)
278 }
279
280 #[inline]
281 fn kind(&self) -> SectionKind {
282 self.section.kind()
283 }
284
285 fn relocations(&self) -> PeRelocationIterator<'data, 'file, R> {
286 PeRelocationIterator(PhantomData)
287 }
288
289 fn flags(&self) -> SectionFlags {
290 SectionFlags::Coff {
291 characteristics: self.section.characteristics.get(LE),
292 }
293 }
294}
295
296impl<'data> SectionTable<'data> {
297 /// Return the data at the given virtual address in a PE file.
298 pub fn pe_data_at<R: ReadRef<'data>>(&self, data: R, va: u32) -> Option<&'data [u8]> {
299 self.iter()
300 .filter_map(|section| section.pe_data_at(data, va))
301 .next()
302 }
303}
304
305impl pe::ImageSectionHeader {
306 /// Return the offset and size of the section in a PE file.
307 ///
308 /// Returns `None` for sections that have no data in the file.
309 pub fn pe_file_range(&self) -> (u32, u32) {
310 // Pointer and size will be zero for uninitialized data; we don't need to validate this.
311 let offset = self.pointer_to_raw_data.get(LE);
312 let size = cmp::min(self.virtual_size.get(LE), self.size_of_raw_data.get(LE));
313 (offset, size)
314 }
315
316 /// Return the section data in a PE file.
317 pub fn pe_data<'data, R: ReadRef<'data>>(&self, data: R) -> result::Result<&'data [u8], ()> {
318 let (offset, size) = self.pe_file_range();
319 data.read_bytes_at(offset.into(), size.into())
320 }
321
322 /// Return the data at the given virtual address if this section contains it.
323 pub fn pe_data_at<'data, R: ReadRef<'data>>(&self, data: R, va: u32) -> Option<&'data [u8]> {
324 let section_va = self.virtual_address.get(LE);
325 let offset = va.checked_sub(section_va)?;
326 let section_data = self.pe_data(data).ok()?;
327 section_data.get(offset as usize..)
328 }
329}
330
331/// An iterator over the relocations in an `PeSection`.
332#[derive(Debug)]
333pub struct PeRelocationIterator<'data, 'file, R = &'data [u8]>(
334 PhantomData<(&'data (), &'file (), R)>,
335);
336
337impl<'data, 'file, R> Iterator for PeRelocationIterator<'data, 'file, R> {
338 type Item = (u64, Relocation);
339
340 fn next(&mut self) -> Option<Self::Item> {
341 None
342 }
343}