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}