1use core::fmt::Debug;
2use core::mem;
3
4use crate::endian::{LittleEndian as LE, U16Bytes};
5use crate::pe;
6use crate::pod::Pod;
7use crate::read::{Bytes, ReadError, Result};
8
9use super::ImageNtHeaders;
10
11#[derive(Debug, Clone)]
15pub struct ImportTable<'data> {
16 section_data: Bytes<'data>,
17 section_address: u32,
18 import_address: u32,
19}
20
21impl<'data> ImportTable<'data> {
22 pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self {
32 ImportTable {
33 section_data: Bytes(section_data),
34 section_address,
35 import_address,
36 }
37 }
38
39 pub fn descriptors(&self) -> Result<ImportDescriptorIterator<'data>> {
41 let offset = self.import_address.wrapping_sub(self.section_address);
42 let mut data = self.section_data;
43 data.skip(offset as usize)
44 .read_error("Invalid PE import descriptor address")?;
45 Ok(ImportDescriptorIterator { data, null: false })
46 }
47
48 pub fn name(&self, address: u32) -> Result<&'data [u8]> {
52 self.section_data
53 .read_string_at(address.wrapping_sub(self.section_address) as usize)
54 .read_error("Invalid PE import descriptor name")
55 }
56
57 pub fn thunks(&self, address: u32) -> Result<ImportThunkList<'data>> {
62 let offset = address.wrapping_sub(self.section_address);
63 let mut data = self.section_data;
64 data.skip(offset as usize)
65 .read_error("Invalid PE import thunk table address")?;
66 Ok(ImportThunkList { data })
67 }
68
69 pub fn import<Pe: ImageNtHeaders>(&self, thunk: Pe::ImageThunkData) -> Result<Import<'data>> {
71 if thunk.is_ordinal() {
72 Ok(Import::Ordinal(thunk.ordinal()))
73 } else {
74 let (hint, name) = self.hint_name(thunk.address())?;
75 Ok(Import::Name(hint, name))
76 }
77 }
78
79 pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> {
85 let offset = address.wrapping_sub(self.section_address);
86 let mut data = self.section_data;
87 data.skip(offset as usize)
88 .read_error("Invalid PE import thunk address")?;
89 let hint = data
90 .read::<U16Bytes<LE>>()
91 .read_error("Missing PE import thunk hint")?
92 .get(LE);
93 let name = data
94 .read_string()
95 .read_error("Missing PE import thunk name")?;
96 Ok((hint, name))
97 }
98}
99
100#[derive(Debug, Clone)]
102pub struct ImportDescriptorIterator<'data> {
103 data: Bytes<'data>,
104 null: bool,
105}
106
107impl<'data> ImportDescriptorIterator<'data> {
108 pub fn next(&mut self) -> Result<Option<&'data pe::ImageImportDescriptor>> {
112 if self.null {
113 return Ok(None);
114 }
115 let result = self
116 .data
117 .read::<pe::ImageImportDescriptor>()
118 .read_error("Missing PE null import descriptor");
119 match result {
120 Ok(import_desc) => {
121 if import_desc.is_null() {
122 self.null = true;
123 Ok(None)
124 } else {
125 Ok(Some(import_desc))
126 }
127 }
128 Err(e) => {
129 self.null = true;
130 Err(e)
131 }
132 }
133 }
134}
135
136impl<'data> Iterator for ImportDescriptorIterator<'data> {
137 type Item = Result<&'data pe::ImageImportDescriptor>;
138
139 fn next(&mut self) -> Option<Self::Item> {
140 self.next().transpose()
141 }
142}
143
144#[derive(Debug, Clone)]
148pub struct ImportThunkList<'data> {
149 data: Bytes<'data>,
150}
151
152impl<'data> ImportThunkList<'data> {
153 pub fn get<Pe: ImageNtHeaders>(&self, index: usize) -> Result<Pe::ImageThunkData> {
155 let thunk = self
156 .data
157 .read_at(index * mem::size_of::<Pe::ImageThunkData>())
158 .read_error("Invalid PE import thunk index")?;
159 Ok(*thunk)
160 }
161
162 pub fn next<Pe: ImageNtHeaders>(&mut self) -> Result<Option<Pe::ImageThunkData>> {
166 let thunk = self
167 .data
168 .read::<Pe::ImageThunkData>()
169 .read_error("Missing PE null import thunk")?;
170 if thunk.address() == 0 {
171 Ok(None)
172 } else {
173 Ok(Some(*thunk))
174 }
175 }
176}
177
178#[derive(Debug, Clone, Copy)]
180pub enum Import<'data> {
181 Ordinal(u16),
183 Name(u16, &'data [u8]),
187}
188
189#[allow(missing_docs)]
191pub trait ImageThunkData: Debug + Pod {
192 fn raw(self) -> u64;
194
195 fn is_ordinal(self) -> bool;
197
198 fn ordinal(self) -> u16;
202
203 fn address(self) -> u32;
207}
208
209impl ImageThunkData for pe::ImageThunkData64 {
210 fn raw(self) -> u64 {
211 self.0.get(LE)
212 }
213
214 fn is_ordinal(self) -> bool {
215 self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG64 != 0
216 }
217
218 fn ordinal(self) -> u16 {
219 self.0.get(LE) as u16
220 }
221
222 fn address(self) -> u32 {
223 self.0.get(LE) as u32 & 0x7fff_ffff
224 }
225}
226
227impl ImageThunkData for pe::ImageThunkData32 {
228 fn raw(self) -> u64 {
229 self.0.get(LE).into()
230 }
231
232 fn is_ordinal(self) -> bool {
233 self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG32 != 0
234 }
235
236 fn ordinal(self) -> u16 {
237 self.0.get(LE) as u16
238 }
239
240 fn address(self) -> u32 {
241 self.0.get(LE) & 0x7fff_ffff
242 }
243}
244
245#[derive(Debug, Clone)]
250pub struct DelayLoadImportTable<'data> {
251 section_data: Bytes<'data>,
252 section_address: u32,
253 import_address: u32,
254}
255
256impl<'data> DelayLoadImportTable<'data> {
257 pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self {
267 DelayLoadImportTable {
268 section_data: Bytes(section_data),
269 section_address,
270 import_address,
271 }
272 }
273
274 pub fn descriptors(&self) -> Result<DelayLoadDescriptorIterator<'data>> {
276 let offset = self.import_address.wrapping_sub(self.section_address);
277 let mut data = self.section_data;
278 data.skip(offset as usize)
279 .read_error("Invalid PE delay-load import descriptor address")?;
280 Ok(DelayLoadDescriptorIterator { data, null: false })
281 }
282
283 pub fn name(&self, address: u32) -> Result<&'data [u8]> {
287 self.section_data
288 .read_string_at(address.wrapping_sub(self.section_address) as usize)
289 .read_error("Invalid PE import descriptor name")
290 }
291
292 pub fn thunks(&self, address: u32) -> Result<ImportThunkList<'data>> {
301 let offset = address.wrapping_sub(self.section_address);
302 let mut data = self.section_data;
303 data.skip(offset as usize)
304 .read_error("Invalid PE delay load import thunk table address")?;
305 Ok(ImportThunkList { data })
306 }
307
308 pub fn import<Pe: ImageNtHeaders>(&self, thunk: Pe::ImageThunkData) -> Result<Import<'data>> {
310 if thunk.is_ordinal() {
311 Ok(Import::Ordinal(thunk.ordinal()))
312 } else {
313 let (hint, name) = self.hint_name(thunk.address())?;
314 Ok(Import::Name(hint, name))
315 }
316 }
317
318 pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> {
324 let offset = address.wrapping_sub(self.section_address);
325 let mut data = self.section_data;
326 data.skip(offset as usize)
327 .read_error("Invalid PE delay load import thunk address")?;
328 let hint = data
329 .read::<U16Bytes<LE>>()
330 .read_error("Missing PE delay load import thunk hint")?
331 .get(LE);
332 let name = data
333 .read_string()
334 .read_error("Missing PE delay load import thunk name")?;
335 Ok((hint, name))
336 }
337}
338
339#[derive(Debug, Clone)]
341pub struct DelayLoadDescriptorIterator<'data> {
342 data: Bytes<'data>,
343 null: bool,
344}
345
346impl<'data> DelayLoadDescriptorIterator<'data> {
347 pub fn next(&mut self) -> Result<Option<&'data pe::ImageDelayloadDescriptor>> {
351 if self.null {
352 return Ok(None);
353 }
354 let result = self
355 .data
356 .read::<pe::ImageDelayloadDescriptor>()
357 .read_error("Missing PE null delay-load import descriptor");
358 match result {
359 Ok(import_desc) => {
360 if import_desc.is_null() {
361 self.null = true;
362 Ok(None)
363 } else {
364 Ok(Some(import_desc))
365 }
366 }
367 Err(e) => {
368 self.null = true;
369 Err(e)
370 }
371 }
372 }
373}
374
375impl<'data> Iterator for DelayLoadDescriptorIterator<'data> {
376 type Item = Result<&'data pe::ImageDelayloadDescriptor>;
377
378 fn next(&mut self) -> Option<Self::Item> {
379 self.next().transpose()
380 }
381}