use anyhow::Result;
use crate::{loader::pe::PE, module::Permissions, VA};
pub fn find_pe_exports(pe: &PE) -> Result<Vec<VA>> {
let base_address = match pe.header.optional_header {
Some(opt) => opt.windows_fields.image_base,
_ => 0x40_0000,
};
let exports: Vec<VA> = pe
.pe()?
.exports
.iter()
.filter(|&exp| exp.reexport.is_none())
.map(|exp| base_address + exp.rva as u64)
.filter(|&va| {
pe.module.probe_va(va, Permissions::X)
})
.collect();
Ok(exports)
}
#[cfg(test)]
mod tests {
use crate::rsrc::*;
use anyhow::Result;
#[test]
fn k32() -> Result<()> {
let buf = get_buf(Rsrc::K32);
let pe = crate::loader::pe::PE::from_bytes(&buf)?;
let fns = crate::analysis::pe::exports::find_pe_exports(&pe)?;
assert_eq!(1445, fns.len());
Ok(())
}
#[test]
fn tiny() -> Result<()> {
let buf = get_buf(Rsrc::TINY);
let pe = crate::loader::pe::PE::from_bytes(&buf)?;
let fns = crate::analysis::pe::exports::find_pe_exports(&pe)?;
assert_eq!(0, fns.len());
Ok(())
}
#[test]
fn nop() -> Result<()> {
let buf = get_buf(Rsrc::NOP);
let pe = crate::loader::pe::PE::from_bytes(&buf)?;
let fns = crate::analysis::pe::exports::find_pe_exports(&pe)?;
assert_eq!(0, fns.len());
Ok(())
}
#[test]
fn mimi() -> Result<()> {
let buf = get_buf(Rsrc::MIMI);
let pe = crate::loader::pe::PE::from_bytes(&buf)?;
let fns = crate::analysis::pe::exports::find_pe_exports(&pe)?;
assert_eq!(0, fns.len());
Ok(())
}
}