summaryrefslogtreecommitdiffstats
path: root/third_party/rust/goblin/src/pe/data_directories.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/goblin/src/pe/data_directories.rs')
-rw-r--r--third_party/rust/goblin/src/pe/data_directories.rs175
1 files changed, 111 insertions, 64 deletions
diff --git a/third_party/rust/goblin/src/pe/data_directories.rs b/third_party/rust/goblin/src/pe/data_directories.rs
index 265e4e27f7..e65db5953d 100644
--- a/third_party/rust/goblin/src/pe/data_directories.rs
+++ b/third_party/rust/goblin/src/pe/data_directories.rs
@@ -1,5 +1,8 @@
use crate::error;
-use scroll::{Pread, Pwrite, SizeWith};
+use scroll::{
+ ctx::{self},
+ Pread, Pwrite, SizeWith,
+};
#[repr(C)]
#[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, SizeWith)]
@@ -13,14 +16,86 @@ const NUM_DATA_DIRECTORIES: usize = 16;
impl DataDirectory {
pub fn parse(bytes: &[u8], offset: &mut usize) -> error::Result<Self> {
- let dd = bytes.gread_with(offset, scroll::LE)?;
- Ok(dd)
+ Ok(bytes.gread_with(offset, scroll::LE)?)
+ }
+}
+
+#[derive(Debug, PartialEq, Copy, Clone)]
+pub enum DataDirectoryType {
+ ExportTable,
+ ImportTable,
+ ResourceTable,
+ ExceptionTable,
+ CertificateTable,
+ BaseRelocationTable,
+ DebugTable,
+ Architecture,
+ GlobalPtr,
+ TlsTable,
+ LoadConfigTable,
+ BoundImportTable,
+ ImportAddressTable,
+ DelayImportDescriptor,
+ ClrRuntimeHeader,
+}
+
+impl TryFrom<usize> for DataDirectoryType {
+ type Error = error::Error;
+ fn try_from(value: usize) -> Result<Self, Self::Error> {
+ Ok(match value {
+ 0 => Self::ExportTable,
+ 1 => Self::ImportTable,
+ 2 => Self::ResourceTable,
+ 3 => Self::ExceptionTable,
+ 4 => Self::CertificateTable,
+ 5 => Self::BaseRelocationTable,
+ 6 => Self::DebugTable,
+ 7 => Self::Architecture,
+ 8 => Self::GlobalPtr,
+ 9 => Self::TlsTable,
+ 10 => Self::LoadConfigTable,
+ 11 => Self::BoundImportTable,
+ 12 => Self::ImportAddressTable,
+ 13 => Self::DelayImportDescriptor,
+ 14 => Self::ClrRuntimeHeader,
+ _ => {
+ return Err(error::Error::Malformed(
+ "Wrong data directory index number".into(),
+ ))
+ }
+ })
}
}
#[derive(Debug, PartialEq, Copy, Clone, Default)]
pub struct DataDirectories {
- pub data_directories: [Option<DataDirectory>; NUM_DATA_DIRECTORIES],
+ pub data_directories: [Option<(usize, DataDirectory)>; NUM_DATA_DIRECTORIES],
+}
+
+impl ctx::TryIntoCtx<scroll::Endian> for DataDirectories {
+ type Error = error::Error;
+
+ fn try_into_ctx(self, bytes: &mut [u8], ctx: scroll::Endian) -> Result<usize, Self::Error> {
+ let offset = &mut 0;
+ for opt_dd in self.data_directories {
+ if let Some((dd_offset, dd)) = opt_dd {
+ bytes.pwrite_with(dd, dd_offset, ctx)?;
+ *offset += dd_offset;
+ } else {
+ bytes.gwrite(&[0; SIZEOF_DATA_DIRECTORY][..], offset)?;
+ }
+ }
+ Ok(NUM_DATA_DIRECTORIES * SIZEOF_DATA_DIRECTORY)
+ }
+}
+
+macro_rules! build_dd_getter {
+ ($dd_name:tt, $index:tt) => {
+ pub fn $dd_name(&self) -> Option<&DataDirectory> {
+ let idx = $index;
+ self.data_directories[idx].as_ref().map(|(_, dd)| dd)
+ }
+ };
}
impl DataDirectories {
@@ -37,70 +112,42 @@ impl DataDirectories {
let dd = if dd.virtual_address == 0 && dd.size == 0 {
None
} else {
- Some(dd)
+ Some((*offset, dd))
};
*dir = dd;
}
Ok(DataDirectories { data_directories })
}
- pub fn get_export_table(&self) -> &Option<DataDirectory> {
- let idx = 0;
- &self.data_directories[idx]
- }
- pub fn get_import_table(&self) -> &Option<DataDirectory> {
- let idx = 1;
- &self.data_directories[idx]
- }
- pub fn get_resource_table(&self) -> &Option<DataDirectory> {
- let idx = 2;
- &self.data_directories[idx]
- }
- pub fn get_exception_table(&self) -> &Option<DataDirectory> {
- let idx = 3;
- &self.data_directories[idx]
- }
- pub fn get_certificate_table(&self) -> &Option<DataDirectory> {
- let idx = 4;
- &self.data_directories[idx]
- }
- pub fn get_base_relocation_table(&self) -> &Option<DataDirectory> {
- let idx = 5;
- &self.data_directories[idx]
- }
- pub fn get_debug_table(&self) -> &Option<DataDirectory> {
- let idx = 6;
- &self.data_directories[idx]
- }
- pub fn get_architecture(&self) -> &Option<DataDirectory> {
- let idx = 7;
- &self.data_directories[idx]
- }
- pub fn get_global_ptr(&self) -> &Option<DataDirectory> {
- let idx = 8;
- &self.data_directories[idx]
- }
- pub fn get_tls_table(&self) -> &Option<DataDirectory> {
- let idx = 9;
- &self.data_directories[idx]
- }
- pub fn get_load_config_table(&self) -> &Option<DataDirectory> {
- let idx = 10;
- &self.data_directories[idx]
- }
- pub fn get_bound_import_table(&self) -> &Option<DataDirectory> {
- let idx = 11;
- &self.data_directories[idx]
- }
- pub fn get_import_address_table(&self) -> &Option<DataDirectory> {
- let idx = 12;
- &self.data_directories[idx]
- }
- pub fn get_delay_import_descriptor(&self) -> &Option<DataDirectory> {
- let idx = 13;
- &self.data_directories[idx]
- }
- pub fn get_clr_runtime_header(&self) -> &Option<DataDirectory> {
- let idx = 14;
- &self.data_directories[idx]
+
+ build_dd_getter!(get_export_table, 0);
+ build_dd_getter!(get_import_table, 1);
+ build_dd_getter!(get_resource_table, 2);
+ build_dd_getter!(get_exception_table, 3);
+ build_dd_getter!(get_certificate_table, 4);
+ build_dd_getter!(get_base_relocation_table, 5);
+ build_dd_getter!(get_debug_table, 6);
+ build_dd_getter!(get_architecture, 7);
+ build_dd_getter!(get_global_ptr, 8);
+ build_dd_getter!(get_tls_table, 9);
+ build_dd_getter!(get_load_config_table, 10);
+ build_dd_getter!(get_bound_import_table, 11);
+ build_dd_getter!(get_import_address_table, 12);
+ build_dd_getter!(get_delay_import_descriptor, 13);
+ build_dd_getter!(get_clr_runtime_header, 14);
+
+ pub fn dirs(&self) -> impl Iterator<Item = (DataDirectoryType, DataDirectory)> {
+ self.data_directories
+ .into_iter()
+ .enumerate()
+ // (Index, Option<DD>) -> Option<(Index, DD)> -> (DDT, DD)
+ .filter_map(|(i, o)|
+ // We should not have invalid indexes.
+ // Indeed: `data_directories: &[_; N]` where N is the number
+ // of data directories.
+ // The `TryFrom` trait for integers to DataDirectoryType
+ // takes into account the N possible data directories.
+ // Therefore, the unwrap can never fail as long as Rust guarantees
+ // on types are honored.
+ o.map(|(_, v)| (i.try_into().unwrap(), v)))
}
}