1use std::{fmt, iter, mem, slice};
45
46use crate::{Error, Result};
47use crate::util::CStr;
48
49use super::image::*;
50use super::Pe;
51
52pub use crate::wrap::imports::Import;
55
56fn import_from_va<'a, P: Pe<'a>>(pe: P, &va: &'a Va) -> Result<Import<'a>> {
61 if va & IMAGE_ORDINAL_FLAG == 0 {
62 let rva = va as Rva;
64 let hint = pe.derva::<u16>(rva)?;
65 let name = pe.derva_c_str(rva + 2)?;
66 Ok(Import::ByName { hint: *hint as usize, name })
67 }
68 else {
69 Ok(Import::ByOrdinal { ord: va as Ordinal })
70 }
71}
72
73#[derive(Copy, Clone)]
79pub struct Imports<'a, P> {
80 pe: P,
81 image: &'a [IMAGE_IMPORT_DESCRIPTOR],
82}
83impl<'a, P: Pe<'a>> Imports<'a, P> {
84 pub(crate) fn try_from(pe: P) -> Result<Imports<'a, P>> {
85 let datadir = pe.data_directory().get(IMAGE_DIRECTORY_ENTRY_IMPORT).ok_or(Error::Bounds)?;
86 let image = pe.derva_slice_f(datadir.VirtualAddress, |image: &IMAGE_IMPORT_DESCRIPTOR| image.is_null())?;
87 Ok(Imports { pe, image })
88 }
89 pub fn pe(&self) -> P {
91 self.pe
92 }
93 pub fn image(&self) -> &'a [IMAGE_IMPORT_DESCRIPTOR] {
95 self.image
96 }
97 pub fn iter(&self) -> Iter<'a, P> {
99 Iter {
100 pe: self.pe,
101 iter: self.image.iter(),
102 }
103 }
104}
105impl<'a, P: Pe<'a>> IntoIterator for Imports<'a, P> {
106 type Item = Desc<'a, P>;
107 type IntoIter = Iter<'a, P>;
108 fn into_iter(self) -> Iter<'a, P> {
109 self.iter()
110 }
111}
112impl<'a, P: Pe<'a>> fmt::Debug for Imports<'a, P> {
113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114 f.debug_list()
115 .entries(self.into_iter())
116 .finish()
117 }
118}
119
120#[derive(Copy, Clone)]
126pub struct IAT<'a, P> {
127 pe: P,
128 image: &'a [Va],
129}
130impl<'a, P: Pe<'a>> IAT<'a, P> {
131 pub(crate) fn try_from(pe: P) -> Result<IAT<'a, P>> {
132 let datadir = pe.data_directory().get(IMAGE_DIRECTORY_ENTRY_IAT).ok_or(Error::Bounds)?;
133 let image = pe.derva_slice(datadir.VirtualAddress, datadir.Size as usize / mem::size_of::<Va>())?;
135 Ok(IAT { pe, image })
136 }
137 pub fn pe(&self) -> P {
139 self.pe
140 }
141 pub fn image(&self) -> &'a [Va] {
143 self.image
144 }
145 pub fn iter(&self) -> iter::Map<slice::Iter<'a, Va>, impl Clone + FnMut(&'a Va) -> (&'a Va, Result<Import<'a>>)> {
149 let pe = self.pe;
150 self.image.iter().map(move |va| (va, import_from_va(pe, va)))
151 }
152}
153impl<'a, P: Pe<'a>> fmt::Debug for IAT<'a, P> {
154 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155 f.debug_struct("IAT")
156 .field("iat.len", &self.image.len())
157 .finish()
158 }
159}
160
161#[derive(Clone)]
164pub struct Iter<'a, P> {
165 pe: P,
166 iter: slice::Iter<'a, IMAGE_IMPORT_DESCRIPTOR>,
167}
168impl<'a, P: Pe<'a>> Iter<'a, P> {
169 pub fn image(&self) -> &'a [IMAGE_IMPORT_DESCRIPTOR] {
170 self.iter.as_slice()
171 }
172}
173impl<'a, P: Pe<'a>> Iterator for Iter<'a, P> {
174 type Item = Desc<'a, P>;
175 fn next(&mut self) -> Option<Desc<'a, P>> {
176 self.iter.next().map(|image| Desc { pe: self.pe, image })
177 }
178 fn size_hint(&self) -> (usize, Option<usize>) {
179 self.iter.size_hint()
180 }
181 fn count(self) -> usize {
182 self.iter.count()
183 }
184 fn nth(&mut self, n: usize) -> Option<Desc<'a, P>> {
185 self.iter.nth(n).map(|image| Desc { pe: self.pe, image })
186 }
187}
188impl<'a, P: Pe<'a>> DoubleEndedIterator for Iter<'a, P> {
189 fn next_back(&mut self) -> Option<Desc<'a, P>> {
190 self.iter.next_back().map(|image| Desc { pe: self.pe, image })
191 }
192}
193impl<'a, P: Pe<'a>> ExactSizeIterator for Iter<'a, P> {}
194impl<'a, P: Pe<'a>> iter::FusedIterator for Iter<'a, P> {}
195
196#[derive(Copy, Clone)]
200pub struct Desc<'a, P> {
201 pe: P,
202 image: &'a IMAGE_IMPORT_DESCRIPTOR,
203}
204impl<'a, P: Pe<'a>> Desc<'a, P> {
205 pub fn pe(&self) -> P {
207 self.pe
208 }
209 pub fn image(&self) -> &'a IMAGE_IMPORT_DESCRIPTOR {
211 self.image
212 }
213 pub fn dll_name(&self) -> Result<&'a CStr> {
215 self.pe.derva_c_str(self.image.Name)
216 }
217 pub fn iat(&self) -> Result<slice::Iter<'a, Va>> {
224 let slice = self.pe.derva_slice_s(self.image.FirstThunk, 0)?;
225 Ok(slice.iter())
226 }
227 pub fn int(&self) -> Result<iter::Map<slice::Iter<'a, Va>, impl Clone + FnMut(&'a Va) -> Result<Import<'a>>>> {
229 let slice = self.pe.derva_slice_s(self.image.OriginalFirstThunk, 0)?;
230 let pe = self.pe;
231 Ok(slice.iter().map(move |va| import_from_va(pe, va)))
232 }
233}
234impl<'a, P: Pe<'a>> fmt::Debug for Desc<'a, P> {
235 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236 f.debug_struct("Imports")
237 .field("dll_name", &format_args!("{:?}", self.dll_name()))
238 .field("iat.len", &format_args!("{:?}", &self.iat().map(|iter| iter.len())))
239 .field("int.len", &format_args!("{:?}", &self.int().map(|iter| iter.len())))
240 .finish()
241 }
242}
243
244#[cfg(feature = "serde")]
263mod serde {
264 use crate::util::serde_helper::*;
265 use super::{Pe, Imports, IAT, Desc};
266
267 impl<'a, P: Pe<'a>> Serialize for Imports<'a, P> {
268 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
269 serializer.collect_seq(self.into_iter())
270 }
271 }
272 impl<'a, P: Pe<'a>> Serialize for IAT<'a, P> {
273 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
274 let iat = self.iter().filter_map(|(_va, import)| import.ok());
275 serializer.collect_seq(iat)
276 }
277 }
278 impl<'a, P: Pe<'a>> Serialize for Desc<'a, P> {
279 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
280 let mut state = serializer.serialize_struct("Desc", 2)?;
281 state.serialize_field("dll_name", &self.dll_name().ok())?;
282 let int = self.int().map(|int| {
283 SerdeIter(int.filter_map(|import| {
284 import.ok()
285 }))
286 });
287 state.serialize_field("int", &int.ok())?;
288 state.end()
289 }
290 }
291}
292
293#[cfg(test)]
296pub(crate) fn test<'a, P: Pe<'a>>(pe: P) -> Result<()> {
297 let imports = pe.imports()?;
298 let _ = format!("{:?}", imports);
299
300 for desc in imports {
301 let _ = format!("{:?}", desc);
302 let _dll_name = desc.dll_name();
303 for _ in desc.iat() {}
304 for _ in desc.int() {}
305 }
306
307 let iat = pe.iat()?;
308 for (va, import) in iat.iter() {
309 let _ = format!("{:?}", import);
310 if import.is_ok() {
311 assert_eq!(import_from_va(pe, va), import);
312 }
313 }
314
315 Ok(())
316}