summaryrefslogtreecommitdiffstats
path: root/third_party/rust/goblin/src/pe/header.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/goblin/src/pe/header.rs')
-rw-r--r--third_party/rust/goblin/src/pe/header.rs183
1 files changed, 183 insertions, 0 deletions
diff --git a/third_party/rust/goblin/src/pe/header.rs b/third_party/rust/goblin/src/pe/header.rs
new file mode 100644
index 0000000000..6318af7387
--- /dev/null
+++ b/third_party/rust/goblin/src/pe/header.rs
@@ -0,0 +1,183 @@
+use crate::alloc::vec::Vec;
+use crate::error;
+use crate::pe::{optional_header, section_table, symbol};
+use crate::strtab;
+use log::debug;
+use scroll::{Pread, Pwrite, IOread, IOwrite, SizeWith};
+
+/// DOS header present in all PE binaries
+#[repr(C)]
+#[derive(Debug, PartialEq, Copy, Clone, Default)]
+pub struct DosHeader {
+ /// Magic number: 5a4d
+ pub signature: u16,
+ /// Pointer to PE header, always at offset 0x3c
+ pub pe_pointer: u32,
+}
+
+pub const DOS_MAGIC: u16 = 0x5a4d;
+pub const PE_POINTER_OFFSET: u32 = 0x3c;
+
+impl DosHeader {
+ pub fn parse(bytes: &[u8]) -> error::Result<Self> {
+ let signature = bytes.pread_with(0, scroll::LE)
+ .map_err(|_| error::Error::Malformed(format!("cannot parse DOS signature (offset {:#x})", 0)))?;
+ let pe_pointer = bytes.pread_with(PE_POINTER_OFFSET as usize, scroll::LE)
+ .map_err(|_| error::Error::Malformed(format!("cannot parse PE header pointer (offset {:#x})", PE_POINTER_OFFSET)))?;
+ Ok (DosHeader { signature, pe_pointer })
+ }
+}
+
+/// COFF Header
+#[repr(C)]
+#[derive(Debug, PartialEq, Copy, Clone, Default, Pread, Pwrite, IOread, IOwrite, SizeWith)]
+pub struct CoffHeader {
+ /// The machine type
+ pub machine: u16,
+ pub number_of_sections: u16,
+ pub time_date_stamp: u32,
+ pub pointer_to_symbol_table: u32,
+ pub number_of_symbol_table: u32,
+ pub size_of_optional_header: u16,
+ pub characteristics: u16,
+}
+
+pub const SIZEOF_COFF_HEADER: usize = 20;
+/// PE\0\0, little endian
+pub const PE_MAGIC: u32 = 0x0000_4550;
+pub const SIZEOF_PE_MAGIC: usize = 4;
+pub const COFF_MACHINE_X86: u16 = 0x14c;
+pub const COFF_MACHINE_X86_64: u16 = 0x8664;
+
+impl CoffHeader {
+ pub fn parse(bytes: &[u8], offset: &mut usize) -> error::Result<Self> {
+ Ok(bytes.gread_with(offset, scroll::LE)?)
+ }
+
+ /// Parse the COFF section headers.
+ ///
+ /// For COFF, these immediately follow the COFF header. For PE, these immediately follow the
+ /// optional header.
+ pub fn sections(
+ &self,
+ bytes: &[u8],
+ offset: &mut usize,
+ ) -> error::Result<Vec<section_table::SectionTable>> {
+ let nsections = self.number_of_sections as usize;
+ let mut sections = Vec::with_capacity(nsections);
+ // Note that if we are handling a BigCoff, the size of the symbol will be different!
+ let string_table_offset = self.pointer_to_symbol_table as usize
+ + symbol::SymbolTable::size(self.number_of_symbol_table as usize);
+ for i in 0..nsections {
+ let section = section_table::SectionTable::parse(bytes, offset, string_table_offset as usize)?;
+ debug!("({}) {:#?}", i, section);
+ sections.push(section);
+ }
+ Ok(sections)
+ }
+
+ /// Return the COFF symbol table.
+ pub fn symbols<'a>(
+ &self,
+ bytes: &'a [u8],
+ ) -> error::Result<symbol::SymbolTable<'a>> {
+ let offset = self.pointer_to_symbol_table as usize;
+ let number = self.number_of_symbol_table as usize;
+ symbol::SymbolTable::parse(bytes, offset, number)
+ }
+
+ /// Return the COFF string table.
+ pub fn strings<'a>(
+ &self,
+ bytes: &'a [u8],
+ ) -> error::Result<strtab::Strtab<'a>> {
+ let offset = self.pointer_to_symbol_table as usize
+ + symbol::SymbolTable::size(self.number_of_symbol_table as usize);
+ let length = bytes.pread_with::<u32>(offset, scroll::LE)? as usize;
+ Ok(strtab::Strtab::parse(bytes, offset, length, 0).unwrap())
+ }
+}
+
+#[derive(Debug, PartialEq, Copy, Clone, Default)]
+pub struct Header {
+ pub dos_header: DosHeader,
+ /// PE Magic: PE\0\0, little endian
+ pub signature: u32,
+ pub coff_header: CoffHeader,
+ pub optional_header: Option<optional_header::OptionalHeader>,
+}
+
+impl Header {
+ pub fn parse(bytes: &[u8]) -> error::Result<Self> {
+ let dos_header = DosHeader::parse(&bytes)?;
+ let mut offset = dos_header.pe_pointer as usize;
+ let signature = bytes.gread_with(&mut offset, scroll::LE)
+ .map_err(|_| error::Error::Malformed(format!("cannot parse PE signature (offset {:#x})", offset)))?;
+ let coff_header = CoffHeader::parse(&bytes, &mut offset)?;
+ let optional_header =
+ if coff_header.size_of_optional_header > 0 {
+ Some (bytes.pread::<optional_header::OptionalHeader>(offset)?)
+ }
+ else { None };
+ Ok( Header { dos_header, signature, coff_header, optional_header })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::{DOS_MAGIC, PE_MAGIC, COFF_MACHINE_X86, Header};
+
+ const CRSS_HEADER: [u8; 688] =
+ [0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
+ 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00,
+ 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
+ 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
+ 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
+ 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xaa, 0x4a, 0xc3, 0xeb, 0xee, 0x2b, 0xad, 0xb8, 0xee, 0x2b, 0xad, 0xb8, 0xee, 0x2b, 0xad, 0xb8,
+ 0xee, 0x2b, 0xac, 0xb8, 0xfe, 0x2b, 0xad, 0xb8, 0x33, 0xd4, 0x66, 0xb8, 0xeb, 0x2b, 0xad, 0xb8,
+ 0x33, 0xd4, 0x63, 0xb8, 0xea, 0x2b, 0xad, 0xb8, 0x33, 0xd4, 0x7a, 0xb8, 0xed, 0x2b, 0xad, 0xb8,
+ 0x33, 0xd4, 0x64, 0xb8, 0xef, 0x2b, 0xad, 0xb8, 0x33, 0xd4, 0x61, 0xb8, 0xef, 0x2b, 0xad, 0xb8,
+ 0x52, 0x69, 0x63, 0x68, 0xee, 0x2b, 0xad, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x05, 0x00, 0xd9, 0x8f, 0x15, 0x52, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x02, 0x01, 0x0b, 0x01, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x06, 0x00, 0x03, 0x00, 0x06, 0x00, 0x03, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xe4, 0xab, 0x00, 0x00, 0x01, 0x00, 0x40, 0x05,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3c, 0x30, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0xb8, 0x22, 0x00, 0x00,
+ 0x00, 0x50, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x10, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00,
+ 0x24, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60,
+ 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc0, 0x2e, 0x69, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00,
+ 0xf8, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40,
+ 0x2e, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x2e, 0x72, 0x65, 0x6c, 0x6f, 0x63, 0x00, 0x00,
+ 0x86, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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 crss_header () {
+ let header = Header::parse(&&CRSS_HEADER[..]).unwrap();
+ assert!(header.dos_header.signature == DOS_MAGIC);
+ assert!(header.signature == PE_MAGIC);
+ assert!(header.coff_header.machine == COFF_MACHINE_X86);
+ println!("header: {:?}", &header);
+ }
+}