macro_rules! elf_compression_header { () => { use plain; // Declare that this is a plain type. unsafe impl plain::Plain for CompressionHeader {} impl ::core::fmt::Debug for CompressionHeader { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { f.debug_struct("CompressionHeader") .field("ch_type", &self.ch_type) .field("ch_size", &format_args!("0x{:x}", self.ch_size)) .field("ch_addralign", &format_args!("0x{:x}", self.ch_addralign)) .finish() } } }; } /// ZLIB/DEFLATE algorithm. pub const ELFCOMPRESS_ZLIB: u32 = 1; /// Start of OS-specific. pub const ELFCOMPRESS_LOOS: u32 = 0x6000_0000; /// End of OS-specific. pub const ELFCOMPRESS_HIOS: u32 = 0x6fff_ffff; /// Start of processor-specific. pub const ELFCOMPRESS_LOPROC: u32 = 0x7000_0000; /// End of processor-specific. pub const ELFCOMPRESS_HIPROC: u32 = 0x7fff_ffff; macro_rules! elf_compression_header_std_impl { ($size:ty) => { #[cfg(test)] mod tests { use super::*; #[test] fn size_of() { assert_eq!(::std::mem::size_of::(), SIZEOF_CHDR); } } if_alloc! { use crate::elf::compression_header::CompressionHeader as ElfCompressionHeader; use plain::Plain; if_std! { use crate::error::Result; use std::fs::File; use std::io::{Read, Seek}; use std::io::SeekFrom::Start; } impl From for ElfCompressionHeader { fn from(ch: CompressionHeader) -> Self { ElfCompressionHeader { ch_type: ch.ch_type, ch_size: u64::from(ch.ch_size), ch_addralign: u64::from(ch.ch_addralign), } } } impl CompressionHeader { pub fn from_bytes(bytes: &[u8]) -> CompressionHeader { let mut chdr = CompressionHeader::default(); chdr.copy_from_bytes(bytes).expect("buffer is too short for header"); chdr } #[cfg(feature = "std")] pub fn from_fd(fd: &mut File, offset: u64) -> Result { let mut chdr = CompressionHeader::default(); fd.seek(Start(offset))?; unsafe { fd.read_exact(plain::as_mut_bytes(&mut chdr))?; } Ok(chdr) } } } // end if_alloc }; } #[cfg(feature = "alloc")] use scroll::{Pread, Pwrite, SizeWith}; pub mod compression_header32 { pub use crate::elf::compression_header::*; #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Default)] #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))] /// The compression header is used at the start of SHF_COMPRESSED sections pub struct CompressionHeader { /// Compression format pub ch_type: u32, /// Uncompressed data size pub ch_size: u32, /// Uncompressed data alignment pub ch_addralign: u32, } elf_compression_header!(); pub const SIZEOF_CHDR: usize = 12; elf_compression_header_std_impl!(u32); if_alloc! { impl From for CompressionHeader { fn from(ch: ElfCompressionHeader) -> Self { CompressionHeader { ch_type: ch.ch_type, ch_size: ch.ch_size as u32, ch_addralign: ch.ch_addralign as u32, } } } } } pub mod compression_header64 { pub use crate::elf::compression_header::*; #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Default)] #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))] /// The compression header is used at the start of SHF_COMPRESSED sections pub struct CompressionHeader { /// Compression format pub ch_type: u32, pub ch_reserved: u32, /// Uncompressed data size pub ch_size: u64, /// Uncompressed data alignment pub ch_addralign: u64, } elf_compression_header!(); pub const SIZEOF_CHDR: usize = 24; elf_compression_header_std_impl!(u64); if_alloc! { impl From for CompressionHeader { fn from(ch: ElfCompressionHeader) -> Self { CompressionHeader { ch_type: ch.ch_type, ch_reserved: 0, ch_size: ch.ch_size as u64, ch_addralign: ch.ch_addralign as u64, } } } } } /////////////////////////////// // Std/analysis/Unified Structs /////////////////////////////// if_alloc! { #[cfg(feature = "endian_fd")] use crate::error; use core::fmt; use core::result; use scroll::ctx; use crate::container::{Container, Ctx}; #[derive(Default, PartialEq, Clone)] /// A unified CompressionHeader - convertable to and from 32-bit and 64-bit variants pub struct CompressionHeader { /// Compression format pub ch_type: u32, /// Uncompressed data size pub ch_size: u64, /// Uncompressed data alignment pub ch_addralign: u64, } impl CompressionHeader { /// Return the size of the underlying compression header, given a `container` #[inline] pub fn size(ctx: Ctx) -> usize { use scroll::ctx::SizeWith; Self::size_with(&ctx) } pub fn new() -> Self { CompressionHeader { ch_type: 0, ch_size: 0, ch_addralign: 2 << 8, } } /// Parse a compression header from `bytes` at `offset`, using the given `ctx` #[cfg(feature = "endian_fd")] pub fn parse(bytes: &[u8], mut offset: usize, ctx: Ctx) -> error::Result { use scroll::Pread; bytes.gread_with(&mut offset, ctx) } } impl fmt::Debug for CompressionHeader { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("CompressionHeader") .field("ch_type", &self.ch_type) .field("ch_size", &format_args!("0x{:x}", self.ch_size)) .field("ch_addralign", &format_args!("0x{:x}", self.ch_addralign)) .finish() } } impl ctx::SizeWith for CompressionHeader { fn size_with( &Ctx { container, .. }: &Ctx) -> usize { match container { Container::Little => { compression_header32::SIZEOF_CHDR }, Container::Big => { compression_header64::SIZEOF_CHDR }, } } } impl<'a> ctx::TryFromCtx<'a, Ctx> for CompressionHeader { type Error = crate::error::Error; fn try_from_ctx(bytes: &'a [u8], Ctx {container, le}: Ctx) -> result::Result<(Self, usize), Self::Error> { use scroll::Pread; let res = match container { Container::Little => { (bytes.pread_with::(0, le)?.into(), compression_header32::SIZEOF_CHDR) }, Container::Big => { (bytes.pread_with::(0, le)?.into(), compression_header64::SIZEOF_CHDR) } }; Ok(res) } } impl ctx::TryIntoCtx for CompressionHeader { type Error = crate::error::Error; fn try_into_ctx(self, bytes: &mut [u8], Ctx {container, le}: Ctx) -> result::Result { use scroll::Pwrite; match container { Container::Little => { let chdr: compression_header32::CompressionHeader = self.into(); Ok(bytes.pwrite_with(chdr, 0, le)?) }, Container::Big => { let chdr: compression_header64::CompressionHeader = self.into(); Ok(bytes.pwrite_with(chdr, 0, le)?) } } } } impl ctx::IntoCtx for CompressionHeader { fn into_ctx(self, bytes: &mut [u8], Ctx {container, le}: Ctx) { use scroll::Pwrite; match container { Container::Little => { let chdr: compression_header32::CompressionHeader = self.into(); bytes.pwrite_with(chdr, 0, le).unwrap(); }, Container::Big => { let chdr: compression_header64::CompressionHeader = self.into(); bytes.pwrite_with(chdr, 0, le).unwrap(); } } } } } // end if_alloc