use crate::{
containers::Table,
error::{PewterError, Result},
io::{ReadData, WriteData},
pe::{coff::CoffFileHeader, optional_header::OptionalHeader},
};
use super::ParseSectionData;
use crate::{string::String, vec::Vec};
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct ExportTableDataDirectory {
pub export_directory_table: ExportDirectory,
pub export_address_table: Table<ExportAddress>,
pub name_pointer_table: Table<ExportNamePointer>,
pub export_ordinal_table: Table<ExportOrtinal>,
pub export_name_table: Table<String>,
}
impl ParseSectionData for ExportTableDataDirectory {
fn parse(
section_data: &[u8],
sections: &super::Sections,
_: &OptionalHeader,
_: &CoffFileHeader,
) -> Result<Self> {
let export_directory_table = ExportDirectory::read(&mut section_data.as_ref())?;
let export_address_table_data = sections
.find_rva_data(export_directory_table.export_address_table as usize)
.ok_or_else(|| {
PewterError::invalid_image_format(
"Failed to map export_address_table_data inside image",
)
})?;
let name_pointer_table_data = sections
.find_rva_data(export_directory_table.export_address_table as usize)
.ok_or_else(|| {
PewterError::invalid_image_format(
"Failed to map name_pointer_table_data inside image",
)
})?;
let export_ordinal_table_data = sections
.find_rva_data(export_directory_table.export_address_table as usize)
.ok_or_else(|| {
PewterError::invalid_image_format(
"Failed to map export_ordinal_table_data inside image",
)
})?;
let export_name_data = sections
.find_rva_data(export_directory_table.name_rva as usize)
.ok_or_else(|| {
PewterError::invalid_image_format(
"Failed to map export_ordinal_table_data inside image",
)
})?;
let export_name_table = {
let mut values =
Vec::with_capacity(export_directory_table.number_of_name_pointers as usize);
let mut offset = 0;
for _ in 0..export_directory_table.number_of_name_pointers as usize {
let current_str_start = &export_name_data[offset..];
let null_term_pos = current_str_start.iter().position(|c| *c == 0).unwrap_or(0);
values.push(String::from_utf8_lossy(¤t_str_start[..null_term_pos]).into());
offset += null_term_pos;
}
Table(values)
};
Ok(Self {
export_address_table: Table::new_linear(
&mut export_address_table_data.as_ref(),
export_directory_table.address_table_entries as usize,
)?,
name_pointer_table: Table::new_linear(
&mut name_pointer_table_data.as_ref(),
export_directory_table.number_of_name_pointers as usize,
)?,
export_ordinal_table: Table::new_linear(
&mut export_ordinal_table_data.as_ref(),
export_directory_table.number_of_name_pointers as usize,
)?,
export_name_table,
export_directory_table,
})
}
}
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct ExportDirectory {
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: u32,
pub name_pointer_rva: u32,
pub ordinal_table_rva: u32,
}
impl ReadData for ExportDirectory {
fn read(reader: &mut impl crate::io::Reader) -> Result<Self> {
Ok(Self {
export_flags: reader.read()?,
time_date_stamp: reader.read()?,
major_version: reader.read()?,
minor_version: reader.read()?,
name_rva: reader.read()?,
ordinal_base: reader.read()?,
address_table_entries: reader.read()?,
number_of_name_pointers: reader.read()?,
export_address_table: reader.read()?,
name_pointer_rva: reader.read()?,
ordinal_table_rva: reader.read()?,
})
}
}
impl WriteData for ExportDirectory {
fn write_to(self, writer: &mut impl crate::io::Writer) -> Result<()> {
writer.write(self.export_flags)?;
writer.write(self.time_date_stamp)?;
writer.write(self.major_version)?;
writer.write(self.minor_version)?;
writer.write(self.name_rva)?;
writer.write(self.ordinal_base)?;
writer.write(self.address_table_entries)?;
writer.write(self.number_of_name_pointers)?;
writer.write(self.export_address_table)?;
writer.write(self.name_pointer_rva)?;
writer.write(self.ordinal_table_rva)?;
Ok(())
}
}
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct ExportAddress {
pub export_rva: u32,
pub forwarder_rva: u32,
}
impl ReadData for ExportAddress {
fn read(reader: &mut impl crate::io::Reader) -> crate::error::Result<Self> {
Ok(Self {
export_rva: reader.read()?,
forwarder_rva: reader.read()?,
})
}
}
impl WriteData for ExportAddress {
fn write_to(self, writer: &mut impl crate::io::Writer) -> crate::error::Result<()> {
writer.write(self.export_rva)?;
writer.write(self.forwarder_rva)?;
Ok(())
}
}
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct ExportNamePointer(pub u32);
impl ReadData for ExportNamePointer {
fn read(reader: &mut impl crate::io::Reader) -> crate::error::Result<Self> {
Ok(Self(reader.read()?))
}
}
impl WriteData for ExportNamePointer {
fn write_to(self, writer: &mut impl crate::io::Writer) -> crate::error::Result<()> {
writer.write(self.0)?;
Ok(())
}
}
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct ExportOrtinal(pub u16);
impl ReadData for ExportOrtinal {
fn read(reader: &mut impl crate::io::Reader) -> crate::error::Result<Self> {
Ok(Self(reader.read()?))
}
}
impl WriteData for ExportOrtinal {
fn write_to(self, writer: &mut impl crate::io::Writer) -> crate::error::Result<()> {
writer.write(self.0)?;
Ok(())
}
}
#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct ExportName(pub u16);
impl ReadData for ExportName {
fn read(reader: &mut impl crate::io::Reader) -> crate::error::Result<Self> {
Ok(Self(reader.read()?))
}
}
impl WriteData for ExportName {
fn write_to(self, writer: &mut impl crate::io::Writer) -> crate::error::Result<()> {
writer.write(self.0)?;
Ok(())
}
}