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