1use std::{fmt, ops};
57
58use crate::{Error, Result};
59use crate::util::CStr;
60
61use super::image::*;
62use super::imports::Import;
63use super::Pe;
64
65pub use crate::wrap::exports::Export;
68
69#[derive(Copy, Clone)]
75pub struct Exports<'a, P> {
76 pe: P,
77 datadir: &'a IMAGE_DATA_DIRECTORY,
78 image: &'a IMAGE_EXPORT_DIRECTORY,
79}
80impl<'a, P: Pe<'a>> Exports<'a, P> {
81 pub(crate) fn try_from(pe: P) -> Result<Exports<'a, P>> {
82 let datadir = pe.data_directory().get(IMAGE_DIRECTORY_ENTRY_EXPORT).ok_or(Error::Bounds)?;
83 let image = pe.derva(datadir.VirtualAddress)?;
84 Ok(Exports { pe, datadir, image })
85 }
86 pub fn pe(&self) -> P {
88 self.pe
89 }
90 pub fn image(&self) -> &'a IMAGE_EXPORT_DIRECTORY {
92 self.image
93 }
94 pub fn dll_name(&self) -> Result<&'a CStr> {
96 self.pe.derva_c_str(self.image.Name)
97 }
98 pub fn ordinal_base(&self) -> Ordinal {
100 self.image.Base as Ordinal
101 }
102 pub fn functions(&self) -> Result<&'a [Rva]> {
104 self.pe.derva_slice(self.image.AddressOfFunctions, self.image.NumberOfFunctions as usize)
105 }
106 pub fn names(&self) -> Result<&'a [Rva]> {
112 self.pe.derva_slice(self.image.AddressOfNames, self.image.NumberOfNames as usize)
113 }
114 pub fn name_indices(&self) -> Result<&'a [u16]> {
118 self.pe.derva_slice(self.image.AddressOfNameOrdinals, self.image.NumberOfNames as usize)
119 }
120 pub fn by(&self) -> Result<By<'a, P>> {
124 let functions = match self.functions() {
125 Ok(functions) => functions,
126 Err(Error::Null) => &[],
127 Err(e) => return Err(e),
128 };
129 let names = match self.names() {
130 Ok(names) => names,
131 Err(Error::Null) => &[],
132 Err(e) => return Err(e),
133 };
134 let name_indices = match self.name_indices() {
135 Ok(name_indices) => name_indices,
136 Err(Error::Null) => &[],
137 Err(e) => return Err(e),
138 };
139 Ok(By { exp: *self, functions, names, name_indices })
140 }
141 fn is_forwarded(&self, rva: Rva) -> bool {
142 rva >= self.datadir.VirtualAddress && rva < self.datadir.VirtualAddress + self.datadir.Size
144 }
145 pub(crate) fn symbol_from_rva(&self, rva: &'a Rva) -> Result<Export<'a>> {
146 if *rva == 0 {
147 Err(Error::Null)
148 }
149 else if self.is_forwarded(*rva) {
150 let fwd = self.pe.derva_c_str(*rva)?;
151 Ok(Export::Forward(fwd))
152 }
153 else {
154 Ok(Export::Symbol(rva))
155 }
156 }
157}
158impl<'a, P: Pe<'a>> fmt::Debug for Exports<'a, P> {
159 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160 match self.by() {
161 Ok(by) => by.fmt(f),
162 Err(err) => err.fmt(f),
163 }
164 }
165}
166
167#[derive(Copy, Clone)]
171pub struct By<'a, P> {
172 exp: Exports<'a, P>,
173 functions: &'a [Rva],
174 names: &'a [Rva],
175 name_indices: &'a [u16],
176}
177impl<'a, P: Pe<'a>> ops::Deref for By<'a, P> {
178 type Target = Exports<'a, P>;
179 fn deref(&self) -> &Exports<'a, P> {
180 &self.exp
181 }
182}
183impl<'a, P: Pe<'a>> By<'a, P> {
184 pub fn functions(&self) -> &'a [Rva] {
186 self.functions
187 }
188 pub fn names(&self) -> &'a [Rva] {
194 self.names
195 }
196 pub fn name_indices(&self) -> &'a [u16] {
200 self.name_indices
201 }
202 pub fn check_sorted(&self) -> Result<bool> {
209 let mut last = CStr::empty();
210 for (name, _export) in self.iter_names() {
211 let name = name?;
212 if last > name {
213 return Ok(false);
214 }
215 last = name;
216 }
217 Ok(true)
218 }
219 pub fn ordinal(&self, ordinal: Ordinal) -> Result<Export<'a>> {
221 let base = self.exp.image.Base;
222 if (ordinal as u32) < base {
223 Err(Error::Bounds)
224 }
225 else {
226 let index = (ordinal as u32 - base) as usize;
227 self.index(index)
228 }
229 }
230 pub fn name_linear<S: AsRef<[u8]> + ?Sized>(&self, name: &S) -> Result<Export<'a>> {
237 self.name_linear_(name.as_ref())
238 }
239 fn name_linear_(&self, name: &[u8]) -> Result<Export<'a>> {
240 for hint in 0..self.names.len() {
241 match self.name_of_hint(hint) {
242 Ok(name_it) if name_it == name => return self.hint(hint),
243 _ => (),
244 }
245 }
246 Err(Error::Null)
247 }
248 pub fn name<S: AsRef<[u8]> + ?Sized>(&self, name: &S) -> Result<Export<'a>> {
252 self.name_(name.as_ref())
253 }
254 fn name_(&self, name: &[u8]) -> Result<Export<'a>> {
255 let mut lower_bound = 0;
257 let mut upper_bound = self.names.len();
258 while lower_bound != upper_bound {
259 let i = lower_bound + (upper_bound - lower_bound) / 2;
260 let name_rva = self.names[i];
261 let name_it = self.exp.pe.derva_c_str(name_rva)?.as_ref();
262 use std::cmp::Ordering::*;
263 match name.cmp(name_it) {
264 Less => upper_bound = i,
265 Greater => lower_bound = i + 1,
266 Equal => {
267 let &index = self.name_indices.get(i).ok_or(Error::Bounds)?;
268 return self.index(index as usize);
269 },
270 };
271 }
272 Err(Error::Null)
274 }
275 pub fn import(&self, import: Import) -> Result<Export<'a>> {
277 match import {
278 Import::ByName { hint, name } => {
279 self.hint_name_(hint, name)
280 },
281 Import::ByOrdinal { ord } => {
282 self.ordinal(ord)
283 }
284 }
285 }
286 pub fn index(&self, index: usize) -> Result<Export<'a>> {
288 let rva = self.functions.get(index).ok_or(Error::Bounds)?;
289 self.exp.symbol_from_rva(rva)
290 }
291 pub fn hint(&self, hint: usize) -> Result<Export<'a>> {
293 let &index = self.name_indices.get(hint).ok_or(Error::Bounds)?;
294 self.index(index as usize)
295 }
296 pub fn hint_name<S: AsRef<[u8]> + ?Sized>(&self, hint: usize, name: &S) -> Result<Export<'a>> {
298 self.hint_name_(hint, name.as_ref())
299 }
300 fn hint_name_(&self, hint: usize, name: &[u8]) -> Result<Export<'a>> {
301 if let Ok(export) = self.hint(hint) {
303 if let Ok(export_name) = self.name_of_hint(hint) {
305 if export_name == name {
306 return Ok(export);
307 }
308 }
309 }
310 self.name(name)
312 }
313 pub fn name_of_hint(&self, hint: usize) -> Result<&'a CStr> {
315 let &name_rva = self.names.get(hint).ok_or(Error::Bounds)?;
316 self.exp.pe.derva_c_str(name_rva)
317 }
318 pub fn name_lookup(&self, index: usize) -> Result<Import<'a>> {
325 match self.name_indices.iter().position(|&i| i as usize == index) {
327 Some(hint) => {
328 let name_rva = self.names[hint];
330 let name = self.exp.pe.derva_c_str(name_rva)?;
331 Ok(Import::ByName { hint, name })
332 },
333 None => {
334 let ord = (index as u32 + self.exp.image.Base) as Ordinal;
336 Ok(Import::ByOrdinal { ord })
337 },
338 }
339 }
340 pub fn iter<'s>(&'s self) -> impl 's + Clone + Iterator<Item = Result<Export<'a>>> {
346 self.functions.iter().map(move |rva| self.symbol_from_rva(rva))
347 }
348 pub fn iter_names<'s>(&'s self) -> impl 's + Clone + Iterator<Item = (Result<&'a CStr>, Result<Export<'a>>)> {
350 (0..self.names().len() as u32)
351 .map(move |hint| (
352 self.name_of_hint(hint as usize),
353 self.hint(hint as usize),
354 ))
355 }
356 pub fn iter_name_indices<'s>(&'s self) -> impl 's + Clone + Iterator<Item = (Result<&'a CStr>, usize)> {
358 (0..self.names().len() as u32)
359 .map(move |hint| (
360 self.name_of_hint(hint as usize),
361 self.name_indices[hint as usize] as usize,
362 ))
363 }
364}
365impl<'a, P: Pe<'a>> fmt::Debug for By<'a, P> {
366 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
367 f.debug_struct("Exports")
368 .field("dll_name", &format_args!("{:?}", self.dll_name()))
369 .field("time_date_stamp", &self.image.TimeDateStamp)
370 .field("version", &self.image.Version)
371 .field("ordinal_base", &self.ordinal_base())
372 .field("functions.len", &self.functions().len())
373 .field("names.len", &self.names.len())
374 .finish()
375 }
376}
377
378pub trait GetProcAddress<'a, T>: Pe<'a> {
382 fn get_export(self, name: T) -> Result<Export<'a>>;
386 #[inline(never)]
392 fn get_proc_address(self, name: T) -> Result<Va> {
393 self.rva_to_va(self.get_export(name)?.symbol().ok_or(Error::Null)?)
394 }
395}
396impl<'a, P: Pe<'a>> GetProcAddress<'a, Ordinal> for P {
397 fn get_export(self, name: Ordinal) -> Result<Export<'a>> {
398 self.exports()?.by()?.ordinal(name)
399 }
400}
401impl<'b, 'a, P: Pe<'a>> GetProcAddress<'a, Import<'b>> for P {
402 fn get_export(self, name: Import<'b>) -> Result<Export<'a>> {
403 self.exports()?.by()?.import(name)
404 }
405}
406impl<'b, 'a, P: Pe<'a>, S: AsRef<[u8]> + ?Sized> GetProcAddress<'a, &'b S> for P {
407 fn get_export(self, name: &'b S) -> Result<Export<'a>> {
408 self.exports()?.by()?.name(name)
409 }
410}
411
412#[cfg(feature = "serde")]
429mod serde {
430 use crate::util::serde_helper::*;
431 use super::{Pe, Exports, By};
432
433 impl<'a, P: Pe<'a>> Serialize for Exports<'a, P> {
434 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
435 self.by().ok().serialize(serializer)
436 }
437 }
438 impl<'a, P: Pe<'a>> Serialize for By<'a, P> {
439 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
440 let mut state = serializer.serialize_struct("Exports", 6)?;
441 state.serialize_field("dll_name", &self.dll_name().ok())?;
442 state.serialize_field("time_date_stamp", &self.image.TimeDateStamp)?;
443 state.serialize_field("version", &self.image.Version)?;
444 state.serialize_field("ordinal_base", &self.ordinal_base())?;
445 state.serialize_field("functions", &self.functions())?;
446 let names = self.iter_name_indices().filter_map(|(name, index)| {
447 name.ok().and_then(|name| name.to_str().ok()).map(|name| (name, index))
448 });
449 state.serialize_field("names", &SerdeKV(names))?;
450 state.end()
451 }
452 }
453}
454
455#[cfg(test)]
458pub(crate) fn test<'a, P: Pe<'a>>(pe: P) -> Result<()> {
459 let by = pe.exports()?.by()?;
460 let _ = format!("{:?}", by);
461
462 let _dll_name = by.dll_name();
463 let _ordinal_base = by.ordinal_base();
464
465 let sorted = by.check_sorted()?;
467
468 use std::collections::HashMap;
470 let mut occurances = HashMap::<_, i32>::new();
471 for (name, _) in by.iter_names() {
472 if let Ok(name) = name {
473 *occurances.entry(name).or_default() += 1;
474 }
475 }
476
477 for (hint, (name, export)) in by.iter_names().enumerate() {
478 assert_eq!(name, by.name_of_hint(hint));
481 assert_eq!(export, by.hint(hint));
482
483 if let Ok(name) = name {
484 let unique = occurances[name] == 1;
486
487 if unique {
489 assert_eq!(export, by.name_linear(name));
490 if sorted {
491 assert_eq!(export, by.name(name));
492 }
493 }
494
495 assert_eq!(export, by.hint_name(hint, name));
497 assert_eq!(export, by.import(Import::ByName { hint, name }));
498 if sorted && unique {
499 assert_eq!(export, by.hint_name(0, name));
500 assert_eq!(export, by.import(Import::ByName { hint: 0, name }));
501 }
502 }
503 }
504 Ok(())
505}