Skip to content

Commit

Permalink
pe_exports is nostd
Browse files Browse the repository at this point in the history
  • Loading branch information
daladim committed Aug 9, 2021
1 parent 9a29d9b commit a90f2f2
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 40 deletions.
67 changes: 32 additions & 35 deletions src/read/pe/file.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use alloc::vec::Vec;
use core::fmt::Debug;
use core::{mem, str};
use std::collections::HashMap;

use core::convert::TryInto;

Expand Down Expand Up @@ -97,7 +96,7 @@ where
self.data
}

/// Returns the exports of this PE file (in no particular order)
/// Returns the exports of this PE file
///
/// See also the [`PeFile::exports`] function, which only returns the regular exports.
pub fn pe_exports(&self) -> Result<Vec<PeExport<'data>>> {
Expand Down Expand Up @@ -139,7 +138,7 @@ where
.read_error("Invalid PE export ordinal table")?;

// First, let's list all exports...
let mut exports_without_a_name = HashMap::new();
let mut exports = Vec::new();
for (i, address) in addresses.iter().enumerate() {
// Convert from an array index to an ordinal
// The MSDN documentation is wrong here, see https://stackoverflow.com/a/40001778/721832
Expand All @@ -152,64 +151,62 @@ where

// is it a regular or forwarded export?
if address < export_va || (address - export_va) >= export_size {
exports_without_a_name.insert(
ordinal,
PeExport::ByOrdinal {
ordinal: ordinal,
address: self.common.image_base.wrapping_add(address as u64),
},
);
exports.push(PeExport::ByOrdinal {
ordinal: ordinal,
address: self.common.image_base.wrapping_add(address as u64),
});
} else {
let forwarded_to = export_data
.read_string_at(address.wrapping_sub(export_va) as usize)
.read_error("Invalid target for PE forwarded export")?;
exports_without_a_name.insert(
ordinal,
PeExport::ForwardedByOrdinal {
ordinal: ordinal,
forwarded_to: forwarded_to,
},
);
exports.push(PeExport::ForwardedByOrdinal {
ordinal: ordinal,
forwarded_to: forwarded_to,
});
}
}

// Now, check whether some (or all) of them have an associated name
let mut named_exports = Vec::new();
for (name_ptr, ordinal_index) in names.iter().zip(ordinals.iter()) {
// Items in the ordinal array are biased.
// The MSDN documentation is wrong regarding this bias, see https://stackoverflow.com/a/40001778/721832
let ordinal_index = ordinal_index.get(LE) as u32;
let ordinal = ordinal_index + base_ordinal;

let name = export_data
.read_string_at(name_ptr.get(LE).wrapping_sub(export_va) as usize)
.read_error("Invalid PE export name entry")?;

match exports_without_a_name.remove(&ordinal) {
let unnamed_equivalent = exports.get(ordinal_index as usize).cloned();
match unnamed_equivalent {
Some(PeExport::ByOrdinal { ordinal, address }) => {
named_exports.push(PeExport::Regular {
name,
address,
ordinal,
})
let _ = core::mem::replace(
&mut exports[ordinal_index as usize],
PeExport::Regular {
name,
address,
ordinal,
},
);
}

Some(PeExport::ForwardedByOrdinal {
ordinal,
forwarded_to,
}) => named_exports.push(PeExport::Forwarded {
name,
ordinal,
forwarded_to,
}),
}) => {
let _ = core::mem::replace(
&mut exports[ordinal_index as usize],
PeExport::Forwarded {
name,
ordinal,
forwarded_to,
},
);
}

_ => continue, // unless ordinals are not unique in the ordinals array, this should not happen
}
}

let mut exports = named_exports;
for (_addr, unnamed_export) in exports_without_a_name.drain() {
exports.push(unnamed_export);
}

Ok(exports)
}
}
Expand Down
11 changes: 6 additions & 5 deletions src/read/pe/pe_export.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use core::fmt::Debug;

/// Possible exports from a PE file
#[derive(Clone)]
pub enum PeExport<'data> {
/// A named exported symbol from this PE file
Regular {
Expand Down Expand Up @@ -44,7 +45,7 @@ pub enum PeExport<'data> {
}

impl<'a> Debug for PeExport<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
match &self {
PeExport::Regular {
ordinal,
Expand All @@ -55,7 +56,7 @@ impl<'a> Debug for PeExport<'a> {
.field("ordinal", &ordinal)
.field(
"data",
&std::str::from_utf8(name).unwrap_or("<invalid name>"),
&core::str::from_utf8(name).unwrap_or("<invalid name>"),
)
.field("address", &address)
.finish(),
Expand All @@ -73,11 +74,11 @@ impl<'a> Debug for PeExport<'a> {
.field("ordinal", &ordinal)
.field(
"name",
&std::str::from_utf8(name).unwrap_or("<invalid name>"),
&core::str::from_utf8(name).unwrap_or("<invalid name>"),
)
.field(
"forwarded_to",
&std::str::from_utf8(forwarded_to).unwrap_or("<invalid forward name>"),
&core::str::from_utf8(forwarded_to).unwrap_or("<invalid forward name>"),
)
.finish(),
PeExport::ForwardedByOrdinal {
Expand All @@ -88,7 +89,7 @@ impl<'a> Debug for PeExport<'a> {
.field("ordinal", &ordinal)
.field(
"forwarded_to",
&std::str::from_utf8(forwarded_to).unwrap_or("<invalid forward name>"),
&core::str::from_utf8(forwarded_to).unwrap_or("<invalid forward name>"),
)
.finish(),
}
Expand Down

0 comments on commit a90f2f2

Please sign in to comment.