1use core::fmt::Debug;
2use core::mem;
3
4use crate::endian::{LittleEndian as LE, U16};
5use crate::pe;
6use crate::pod::Pod;
7use crate::read::{Bytes, ReadError, ReadRef, Result};
8
9use super::{ImageNtHeaders, SectionTable};
10
11#[derive(Debug, Clone)]
15pub struct ImportTable<'data> {
16 import_address: u32,
17 import_section_data: Bytes<'data>,
18 import_section_address: u32,
19 name_section_data: Bytes<'data>,
20 name_section_address: u32,
21}
22
23impl<'data> ImportTable<'data> {
24 pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self {
34 ImportTable {
35 import_address,
36 import_section_data: Bytes(section_data),
37 import_section_address: section_address,
38 name_section_data: Bytes(section_data),
39 name_section_address: section_address,
40 }
41 }
42
43 pub fn from_sections<R: ReadRef<'data>>(
55 data: R,
56 sections: &SectionTable<'data>,
57 import_address: u32,
58 ) -> Result<Self> {
59 let (section_data, section_address) = sections
60 .pe_data_containing(data, import_address)
61 .read_error("Invalid import data dir virtual address")?;
62 let mut imports = Self::new(section_data, section_address, import_address);
63
64 if let Ok(mut descriptors) = imports.descriptors() {
73 if let Ok(Some(descriptor)) = descriptors.next() {
74 if let Some((name_section_data, name_section_address)) =
75 sections.pe_data_containing(data, descriptor.name.get(LE))
76 {
77 imports.name_section_data = Bytes(name_section_data);
78 imports.name_section_address = name_section_address;
79 }
80 }
81 }
82 Ok(imports)
83 }
84
85 pub fn descriptors(&self) -> Result<ImportDescriptorIterator<'data>> {
87 let offset = self
88 .import_address
89 .wrapping_sub(self.import_section_address);
90 let mut data = self.import_section_data;
91 data.skip(offset as usize)
92 .read_error("Invalid PE import descriptor address")?;
93 Ok(ImportDescriptorIterator { data, null: false })
94 }
95
96 pub fn name(&self, address: u32) -> Result<&'data [u8]> {
100 self.name_section_data
101 .read_string_at(address.wrapping_sub(self.name_section_address) as usize)
102 .read_error("Invalid PE import descriptor name")
103 }
104
105 pub fn thunks(&self, address: u32) -> Result<ImportThunkList<'data>> {
110 let offset = address.wrapping_sub(self.import_section_address);
111 let mut data = self.import_section_data;
112 data.skip(offset as usize)
113 .read_error("Invalid PE import thunk table address")?;
114 Ok(ImportThunkList { data })
115 }
116
117 pub fn import<Pe: ImageNtHeaders>(&self, thunk: Pe::ImageThunkData) -> Result<Import<'data>> {
119 if thunk.is_ordinal() {
120 Ok(Import::Ordinal(thunk.ordinal()))
121 } else {
122 let (hint, name) = self.hint_name(thunk.address())?;
123 Ok(Import::Name(hint, name))
124 }
125 }
126
127 pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> {
133 let offset = address.wrapping_sub(self.name_section_address);
134 let mut data = self.name_section_data;
135 data.skip(offset as usize)
136 .read_error("Invalid PE import thunk address")?;
137 let hint = data
138 .read::<U16<LE>>()
139 .read_error("Missing PE import thunk hint")?
140 .get(LE);
141 let name = data
142 .read_string()
143 .ok()
144 .filter(|s| !s.is_empty())
145 .read_error("Missing PE import thunk name")?;
146 Ok((hint, name))
147 }
148}
149
150#[derive(Debug, Clone)]
152pub struct ImportDescriptorIterator<'data> {
153 data: Bytes<'data>,
154 null: bool,
155}
156
157impl<'data> ImportDescriptorIterator<'data> {
158 pub fn next(&mut self) -> Result<Option<&'data pe::ImageImportDescriptor>> {
162 if self.null {
163 return Ok(None);
164 }
165 let result = self
166 .data
167 .read::<pe::ImageImportDescriptor>()
168 .read_error("Missing PE null import descriptor");
169 match result {
170 Ok(import_desc) => {
171 if import_desc.is_null() {
172 self.null = true;
173 Ok(None)
174 } else {
175 Ok(Some(import_desc))
176 }
177 }
178 Err(e) => {
179 self.null = true;
180 Err(e)
181 }
182 }
183 }
184}
185
186impl<'data> Iterator for ImportDescriptorIterator<'data> {
187 type Item = Result<&'data pe::ImageImportDescriptor>;
188
189 fn next(&mut self) -> Option<Self::Item> {
190 self.next().transpose()
191 }
192}
193
194#[derive(Debug, Clone)]
198pub struct ImportThunkList<'data> {
199 data: Bytes<'data>,
200}
201
202impl<'data> ImportThunkList<'data> {
203 pub fn get<Pe: ImageNtHeaders>(&self, index: usize) -> Result<Pe::ImageThunkData> {
205 let thunk = self
206 .data
207 .read_at(index * mem::size_of::<Pe::ImageThunkData>())
208 .read_error("Invalid PE import thunk index")?;
209 Ok(*thunk)
210 }
211
212 pub fn next<Pe: ImageNtHeaders>(&mut self) -> Result<Option<Pe::ImageThunkData>> {
216 let thunk = self
217 .data
218 .read::<Pe::ImageThunkData>()
219 .read_error("Missing PE null import thunk")?;
220 if thunk.address() == 0 {
221 Ok(None)
222 } else {
223 Ok(Some(*thunk))
224 }
225 }
226}
227
228#[derive(Debug, Clone, Copy)]
230pub enum Import<'data> {
231 Ordinal(u16),
233 Name(u16, &'data [u8]),
237}
238
239#[allow(missing_docs)]
241pub trait ImageThunkData: Debug + Pod {
242 fn raw(self) -> u64;
244
245 fn is_ordinal(self) -> bool;
247
248 fn ordinal(self) -> u16;
252
253 fn address(self) -> u32;
257}
258
259impl ImageThunkData for pe::ImageThunkData64 {
260 fn raw(self) -> u64 {
261 self.0.get(LE)
262 }
263
264 fn is_ordinal(self) -> bool {
265 self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG64 != 0
266 }
267
268 fn ordinal(self) -> u16 {
269 self.0.get(LE) as u16
270 }
271
272 fn address(self) -> u32 {
273 self.0.get(LE) as u32 & 0x7fff_ffff
274 }
275}
276
277impl ImageThunkData for pe::ImageThunkData32 {
278 fn raw(self) -> u64 {
279 self.0.get(LE).into()
280 }
281
282 fn is_ordinal(self) -> bool {
283 self.0.get(LE) & pe::IMAGE_ORDINAL_FLAG32 != 0
284 }
285
286 fn ordinal(self) -> u16 {
287 self.0.get(LE) as u16
288 }
289
290 fn address(self) -> u32 {
291 self.0.get(LE) & 0x7fff_ffff
292 }
293}
294
295#[derive(Debug, Clone)]
300pub struct DelayLoadImportTable<'data> {
301 section_data: Bytes<'data>,
302 section_address: u32,
303 import_address: u32,
304}
305
306impl<'data> DelayLoadImportTable<'data> {
307 pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self {
317 DelayLoadImportTable {
318 section_data: Bytes(section_data),
319 section_address,
320 import_address,
321 }
322 }
323
324 pub fn descriptors(&self) -> Result<DelayLoadDescriptorIterator<'data>> {
326 let offset = self.import_address.wrapping_sub(self.section_address);
327 let mut data = self.section_data;
328 data.skip(offset as usize)
329 .read_error("Invalid PE delay-load import descriptor address")?;
330 Ok(DelayLoadDescriptorIterator { data, null: false })
331 }
332
333 pub fn name(&self, address: u32) -> Result<&'data [u8]> {
337 self.section_data
338 .read_string_at(address.wrapping_sub(self.section_address) as usize)
339 .read_error("Invalid PE import descriptor name")
340 }
341
342 pub fn thunks(&self, address: u32) -> Result<ImportThunkList<'data>> {
351 let offset = address.wrapping_sub(self.section_address);
352 let mut data = self.section_data;
353 data.skip(offset as usize)
354 .read_error("Invalid PE delay load import thunk table address")?;
355 Ok(ImportThunkList { data })
356 }
357
358 pub fn import<Pe: ImageNtHeaders>(&self, thunk: Pe::ImageThunkData) -> Result<Import<'data>> {
360 if thunk.is_ordinal() {
361 Ok(Import::Ordinal(thunk.ordinal()))
362 } else {
363 let (hint, name) = self.hint_name(thunk.address())?;
364 Ok(Import::Name(hint, name))
365 }
366 }
367
368 pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> {
374 let offset = address.wrapping_sub(self.section_address);
375 let mut data = self.section_data;
376 data.skip(offset as usize)
377 .read_error("Invalid PE delay load import thunk address")?;
378 let hint = data
379 .read::<U16<LE>>()
380 .read_error("Missing PE delay load import thunk hint")?
381 .get(LE);
382 let name = data
383 .read_string()
384 .ok()
385 .filter(|s| !s.is_empty())
386 .read_error("Missing PE delay load import thunk name")?;
387 Ok((hint, name))
388 }
389}
390
391#[derive(Debug, Clone)]
393pub struct DelayLoadDescriptorIterator<'data> {
394 data: Bytes<'data>,
395 null: bool,
396}
397
398impl<'data> DelayLoadDescriptorIterator<'data> {
399 pub fn next(&mut self) -> Result<Option<&'data pe::ImageDelayloadDescriptor>> {
403 if self.null {
404 return Ok(None);
405 }
406 let result = self
407 .data
408 .read::<pe::ImageDelayloadDescriptor>()
409 .read_error("Missing PE null delay-load import descriptor");
410 match result {
411 Ok(import_desc) => {
412 if import_desc.is_null() {
413 self.null = true;
414 Ok(None)
415 } else {
416 Ok(Some(import_desc))
417 }
418 }
419 Err(e) => {
420 self.null = true;
421 Err(e)
422 }
423 }
424 }
425}
426
427impl<'data> Iterator for DelayLoadDescriptorIterator<'data> {
428 type Item = Result<&'data pe::ImageDelayloadDescriptor>;
429
430 fn next(&mut self) -> Option<Self::Item> {
431 self.next().transpose()
432 }
433}