Revision control
Copy as Markdown
Other Tools
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::<CompressionHeader>(), 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<CompressionHeader> 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<CompressionHeader> {
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<ElfCompressionHeader> 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<ElfCompressionHeader> 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<CompressionHeader> {
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<Ctx> 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::<compression_header32::CompressionHeader>(0, le)?.into(), compression_header32::SIZEOF_CHDR)
},
Container::Big => {
(bytes.pread_with::<compression_header64::CompressionHeader>(0, le)?.into(), compression_header64::SIZEOF_CHDR)
}
};
Ok(res)
}
}
impl ctx::TryIntoCtx<Ctx> for CompressionHeader {
type Error = crate::error::Error;
fn try_into_ctx(self, bytes: &mut [u8], Ctx {container, le}: Ctx) -> result::Result<usize, Self::Error> {
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<Ctx> 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