summaryrefslogtreecommitdiffstats
path: root/third_party/rust/goblin/src/pe/export.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/goblin/src/pe/export.rs')
-rw-r--r--third_party/rust/goblin/src/pe/export.rs533
1 files changed, 533 insertions, 0 deletions
diff --git a/third_party/rust/goblin/src/pe/export.rs b/third_party/rust/goblin/src/pe/export.rs
new file mode 100644
index 0000000000..f892c75276
--- /dev/null
+++ b/third_party/rust/goblin/src/pe/export.rs
@@ -0,0 +1,533 @@
+use alloc::vec::Vec;
+use scroll::{Pread, Pwrite};
+
+use log::debug;
+
+use crate::error;
+
+use crate::pe::data_directories;
+use crate::pe::options;
+use crate::pe::section_table;
+use crate::pe::utils;
+
+#[repr(C)]
+#[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite)]
+pub struct ExportDirectoryTable {
+ pub export_flags: u32,
+ pub time_date_stamp: u32,
+ pub major_version: u16,
+ pub minor_version: u16,
+ pub name_rva: u32,
+ pub ordinal_base: u32,
+ pub address_table_entries: u32,
+ pub number_of_name_pointers: u32,
+ pub export_address_table_rva: u32,
+ pub name_pointer_rva: u32,
+ pub ordinal_table_rva: u32,
+}
+
+pub const SIZEOF_EXPORT_DIRECTORY_TABLE: usize = 40;
+
+impl ExportDirectoryTable {
+ pub fn parse(bytes: &[u8], offset: usize) -> error::Result<Self> {
+ let res = bytes.pread_with(offset, scroll::LE)?;
+ Ok(res)
+ }
+}
+
+#[derive(Debug)]
+pub enum ExportAddressTableEntry {
+ ExportRVA(u32),
+ ForwarderRVA(u32),
+}
+
+pub const SIZEOF_EXPORT_ADDRESS_TABLE_ENTRY: usize = 4;
+
+pub type ExportAddressTable = Vec<ExportAddressTableEntry>;
+
+/// Array of rvas into the export name table
+///
+/// Export name is defined iff pointer table has pointer to the name
+pub type ExportNamePointerTable = Vec<u32>;
+
+/// Array of indexes into the export address table.
+///
+/// Should obey the formula `idx = ordinal - ordinalbase`
+pub type ExportOrdinalTable = Vec<u16>;
+
+#[derive(Debug, Default)]
+/// Export data contains the `dll` name which other libraries can import symbols by (two-level namespace), as well as other important indexing data allowing symbol lookups
+pub struct ExportData<'a> {
+ pub name: Option<&'a str>,
+ pub export_directory_table: ExportDirectoryTable,
+ pub export_name_pointer_table: ExportNamePointerTable,
+ pub export_ordinal_table: ExportOrdinalTable,
+ pub export_address_table: ExportAddressTable,
+}
+
+impl<'a> ExportData<'a> {
+ pub fn parse(
+ bytes: &'a [u8],
+ dd: data_directories::DataDirectory,
+ sections: &[section_table::SectionTable],
+ file_alignment: u32,
+ ) -> error::Result<ExportData<'a>> {
+ Self::parse_with_opts(
+ bytes,
+ dd,
+ sections,
+ file_alignment,
+ &options::ParseOptions::default(),
+ )
+ }
+
+ pub fn parse_with_opts(
+ bytes: &'a [u8],
+ dd: data_directories::DataDirectory,
+ sections: &[section_table::SectionTable],
+ file_alignment: u32,
+ opts: &options::ParseOptions,
+ ) -> error::Result<ExportData<'a>> {
+ let export_rva = dd.virtual_address as usize;
+ let size = dd.size as usize;
+ debug!("export_rva {:#x} size {:#}", export_rva, size);
+ let export_offset = utils::find_offset_or(
+ export_rva,
+ sections,
+ file_alignment,
+ opts,
+ &format!("cannot map export_rva ({:#x}) into offset", export_rva),
+ )?;
+ let export_directory_table =
+ ExportDirectoryTable::parse(bytes, export_offset).map_err(|_| {
+ error::Error::Malformed(format!(
+ "cannot parse export_directory_table (offset {:#x})",
+ export_offset
+ ))
+ })?;
+ let number_of_name_pointers = export_directory_table.number_of_name_pointers as usize;
+ let address_table_entries = export_directory_table.address_table_entries as usize;
+
+ if number_of_name_pointers > bytes.len() {
+ return Err(error::Error::BufferTooShort(
+ number_of_name_pointers,
+ "name pointers",
+ ));
+ }
+ if address_table_entries > bytes.len() {
+ return Err(error::Error::BufferTooShort(
+ address_table_entries,
+ "address table entries",
+ ));
+ }
+
+ let export_name_pointer_table = utils::find_offset(
+ export_directory_table.name_pointer_rva as usize,
+ sections,
+ file_alignment,
+ opts,
+ )
+ .map_or(vec![], |table_offset| {
+ let mut offset = table_offset;
+ let mut table: ExportNamePointerTable = Vec::with_capacity(number_of_name_pointers);
+
+ for _ in 0..number_of_name_pointers {
+ if let Ok(name_rva) = bytes.gread_with(&mut offset, scroll::LE) {
+ table.push(name_rva);
+ } else {
+ break;
+ }
+ }
+
+ table
+ });
+
+ let export_ordinal_table = utils::find_offset(
+ export_directory_table.ordinal_table_rva as usize,
+ sections,
+ file_alignment,
+ opts,
+ )
+ .map_or(vec![], |table_offset| {
+ let mut offset = table_offset;
+ let mut table: ExportOrdinalTable = Vec::with_capacity(number_of_name_pointers);
+
+ for _ in 0..number_of_name_pointers {
+ if let Ok(name_ordinal) = bytes.gread_with(&mut offset, scroll::LE) {
+ table.push(name_ordinal);
+ } else {
+ break;
+ }
+ }
+
+ table
+ });
+
+ let export_address_table = utils::find_offset(
+ export_directory_table.export_address_table_rva as usize,
+ sections,
+ file_alignment,
+ opts,
+ )
+ .map_or(vec![], |table_offset| {
+ let mut offset = table_offset;
+ let mut table: ExportAddressTable = Vec::with_capacity(address_table_entries);
+ let export_end = export_rva + size;
+
+ for _ in 0..address_table_entries {
+ if let Ok(func_rva) = bytes.gread_with::<u32>(&mut offset, scroll::LE) {
+ if utils::is_in_range(func_rva as usize, export_rva, export_end) {
+ table.push(ExportAddressTableEntry::ForwarderRVA(func_rva));
+ } else {
+ table.push(ExportAddressTableEntry::ExportRVA(func_rva));
+ }
+ } else {
+ break;
+ }
+ }
+
+ table
+ });
+
+ let name = utils::find_offset(
+ export_directory_table.name_rva as usize,
+ sections,
+ file_alignment,
+ opts,
+ )
+ .and_then(|offset| bytes.pread(offset).ok());
+
+ Ok(ExportData {
+ name,
+ export_directory_table,
+ export_name_pointer_table,
+ export_ordinal_table,
+ export_address_table,
+ })
+ }
+}
+
+#[derive(Debug)]
+/// PE binaries have two kinds of reexports, either specifying the dll's name, or the ordinal value of the dll
+pub enum Reexport<'a> {
+ DLLName { export: &'a str, lib: &'a str },
+ DLLOrdinal { ordinal: usize, lib: &'a str },
+}
+
+impl<'a> scroll::ctx::TryFromCtx<'a, scroll::Endian> for Reexport<'a> {
+ type Error = crate::error::Error;
+ #[inline]
+ fn try_from_ctx(bytes: &'a [u8], _ctx: scroll::Endian) -> Result<(Self, usize), Self::Error> {
+ let reexport = bytes.pread::<&str>(0)?;
+ let reexport_len = reexport.len();
+ debug!("reexport: {}", &reexport);
+ for o in 0..reexport_len {
+ let c: u8 = bytes.pread(o)?;
+ debug!("reexport offset: {:#x} char: {:#x}", o, c);
+ if c == b'.' {
+ let dll: &'a str = bytes.pread_with(0, scroll::ctx::StrCtx::Length(o))?;
+ debug!("dll: {:?}", &dll);
+ if o + 1 == reexport_len {
+ break;
+ }
+ let len = reexport_len - o - 1;
+ let rest: &'a [u8] = bytes.pread_with(o + 1, len)?;
+ debug!("rest: {:?}", &rest);
+ if rest[0] == b'#' {
+ let ordinal =
+ rest.pread_with::<&str>(1, scroll::ctx::StrCtx::Length(len - 1))?;
+ let ordinal = ordinal.parse::<u32>().map_err(|_e| {
+ error::Error::Malformed(format!(
+ "Cannot parse reexport ordinal from {} bytes",
+ bytes.len()
+ ))
+ })?;
+ return Ok((
+ Reexport::DLLOrdinal {
+ ordinal: ordinal as usize,
+ lib: dll,
+ },
+ reexport_len + 1,
+ ));
+ } else {
+ let export = rest.pread_with::<&str>(0, scroll::ctx::StrCtx::Length(len))?;
+ return Ok((Reexport::DLLName { export, lib: dll }, reexport_len + 1));
+ }
+ }
+ }
+ Err(error::Error::Malformed(format!(
+ "Reexport {:#} is malformed",
+ reexport
+ )))
+ }
+}
+
+impl<'a> Reexport<'a> {
+ pub fn parse(bytes: &'a [u8], offset: usize) -> crate::error::Result<Reexport<'a>> {
+ bytes.pread(offset)
+ }
+}
+
+#[derive(Debug, Default)]
+/// An exported symbol in this binary, contains synthetic data (name offset, etc., are computed)
+pub struct Export<'a> {
+ pub name: Option<&'a str>,
+ pub offset: Option<usize>,
+ pub rva: usize,
+ pub size: usize,
+ pub reexport: Option<Reexport<'a>>,
+}
+
+#[derive(Debug, Copy, Clone)]
+struct ExportCtx<'a> {
+ pub ptr: u32,
+ pub idx: usize,
+ pub sections: &'a [section_table::SectionTable],
+ pub file_alignment: u32,
+ pub addresses: &'a ExportAddressTable,
+ pub ordinals: &'a ExportOrdinalTable,
+ pub opts: options::ParseOptions,
+}
+
+impl<'a, 'b> scroll::ctx::TryFromCtx<'a, ExportCtx<'b>> for Export<'a> {
+ type Error = error::Error;
+ #[inline]
+ fn try_from_ctx(
+ bytes: &'a [u8],
+ ExportCtx {
+ ptr,
+ idx,
+ sections,
+ file_alignment,
+ addresses,
+ ordinals,
+ opts,
+ }: ExportCtx<'b>,
+ ) -> Result<(Self, usize), Self::Error> {
+ use self::ExportAddressTableEntry::*;
+
+ let name = utils::find_offset(ptr as usize, sections, file_alignment, &opts)
+ .and_then(|offset| bytes.pread::<&str>(offset).ok());
+
+ if let Some(ordinal) = ordinals.get(idx) {
+ if let Some(rva) = addresses.get(*ordinal as usize) {
+ match *rva {
+ ExportRVA(rva) => {
+ let rva = rva as usize;
+ let offset = utils::find_offset(rva, sections, file_alignment, &opts);
+ Ok((
+ Export {
+ name,
+ offset,
+ rva,
+ reexport: None,
+ size: 0,
+ },
+ 0,
+ ))
+ }
+
+ ForwarderRVA(rva) => {
+ let rva = rva as usize;
+ let offset = utils::find_offset_or(
+ rva,
+ sections,
+ file_alignment,
+ &opts,
+ &format!(
+ "cannot map RVA ({:#x}) of export ordinal {} into offset",
+ rva, ordinal
+ ),
+ )?;
+ let reexport = Reexport::parse(bytes, offset)?;
+ Ok((
+ Export {
+ name,
+ offset: Some(offset),
+ rva,
+ reexport: Some(reexport),
+ size: 0,
+ },
+ 0,
+ ))
+ }
+ }
+ } else {
+ Err(error::Error::Malformed(format!(
+ "cannot get RVA of export ordinal {}",
+ ordinal
+ )))
+ }
+ } else {
+ Err(error::Error::Malformed(format!(
+ "cannot get ordinal of export name entry {}",
+ idx
+ )))
+ }
+ }
+}
+
+impl<'a> Export<'a> {
+ pub fn parse(
+ bytes: &'a [u8],
+ export_data: &ExportData,
+ sections: &[section_table::SectionTable],
+ file_alignment: u32,
+ ) -> error::Result<Vec<Export<'a>>> {
+ Self::parse_with_opts(
+ bytes,
+ export_data,
+ sections,
+ file_alignment,
+ &options::ParseOptions::default(),
+ )
+ }
+
+ pub fn parse_with_opts(
+ bytes: &'a [u8],
+ export_data: &ExportData,
+ sections: &[section_table::SectionTable],
+ file_alignment: u32,
+ opts: &options::ParseOptions,
+ ) -> error::Result<Vec<Export<'a>>> {
+ let pointers = &export_data.export_name_pointer_table;
+ let addresses = &export_data.export_address_table;
+ let ordinals = &export_data.export_ordinal_table;
+
+ let mut exports = Vec::with_capacity(pointers.len());
+ for (idx, &ptr) in pointers.iter().enumerate() {
+ if let Ok(export) = bytes.pread_with(
+ 0,
+ ExportCtx {
+ ptr,
+ idx,
+ sections,
+ file_alignment,
+ addresses,
+ ordinals,
+ opts: *opts,
+ },
+ ) {
+ exports.push(export);
+ }
+ }
+
+ // TODO: sort + compute size
+ Ok(exports)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use self::data_directories::*;
+ use super::*;
+
+ static CORKAMI_POCS_PE_EXPORTSDATA_EXE: [u8; 0x400] = [
+ 0x4d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x02, 0x01, 0x0b, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x80, 0x03,
+ 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2a, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20,
+ 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x66, 0x61, 0x6b, 0x65, 0x20,
+ 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x10, 0x00, 0x00,
+ 0x40, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xa0, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66,
+ 0x00, 0x6d, 0x73, 0x76, 0x63, 0x72, 0x74, 0x2e, 0x64, 0x6c, 0x6c, 0x00, 0x65, 0x78, 0x70,
+ 0x6f, 0x72, 0x74, 0x73, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x68, 0x14, 0x10, 0xf0, 0x10, 0xff, 0x15, 0x30, 0x10, 0x00, 0x10, 0x73, 0xc4, 0x04,
+ 0xc3, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ ];
+
+ #[test]
+ fn size_export_directory_table() {
+ assert_eq!(
+ ::std::mem::size_of::<ExportDirectoryTable>(),
+ SIZEOF_EXPORT_DIRECTORY_TABLE
+ );
+ }
+
+ #[test]
+ fn parse_export_table() {
+ let data_dirs =
+ DataDirectories::parse(&CORKAMI_POCS_PE_EXPORTSDATA_EXE[..], 16, &mut 0xb8).unwrap();
+ let export_table = data_dirs.get_export_table().unwrap();
+
+ assert_eq!(export_table.virtual_address, 0x10b0);
+ assert_eq!(export_table.size, 0x0);
+ }
+
+ #[test]
+ fn parse_export_directory() {
+ let data_dir = ExportDirectoryTable::parse(&CORKAMI_POCS_PE_EXPORTSDATA_EXE[..], 0x2b0);
+ assert!(data_dir.is_ok());
+
+ let data_dir = data_dir.unwrap();
+ assert_eq!(data_dir.export_flags, 0x0);
+ assert_eq!(data_dir.time_date_stamp, 0x0);
+ assert_eq!(data_dir.major_version, 0x0);
+ assert_eq!(data_dir.minor_version, 0x0);
+ assert_eq!(data_dir.name_rva, 0x0);
+ assert_eq!(data_dir.ordinal_base, 0x0);
+ assert_eq!(data_dir.address_table_entries, 0x4);
+ assert_eq!(data_dir.number_of_name_pointers, 0x0);
+ assert_eq!(data_dir.export_address_table_rva, 0x10e0);
+ assert_eq!(data_dir.name_pointer_rva, 0x0);
+ assert_eq!(data_dir.ordinal_table_rva, 0x1100);
+ }
+}