summaryrefslogtreecommitdiffstats
path: root/third_party/rust/goblin/src/elf/compression_header.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/goblin/src/elf/compression_header.rs')
-rw-r--r--third_party/rust/goblin/src/elf/compression_header.rs275
1 files changed, 275 insertions, 0 deletions
diff --git a/third_party/rust/goblin/src/elf/compression_header.rs b/third_party/rust/goblin/src/elf/compression_header.rs
new file mode 100644
index 0000000000..1dd7aa1362
--- /dev/null
+++ b/third_party/rust/goblin/src/elf/compression_header.rs
@@ -0,0 +1,275 @@
+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