1 macro_rules! elf_compression_header { 2 () => { 3 use plain; 4 // Declare that this is a plain type. 5 unsafe impl plain::Plain for CompressionHeader {} 6 7 impl ::core::fmt::Debug for CompressionHeader { 8 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { 9 f.debug_struct("CompressionHeader") 10 .field("ch_type", &self.ch_type) 11 .field("ch_size", &format_args!("0x{:x}", self.ch_size)) 12 .field("ch_addralign", &format_args!("0x{:x}", self.ch_addralign)) 13 .finish() 14 } 15 } 16 } 17 } 18 19 /// ZLIB/DEFLATE algorithm. 20 pub const ELFCOMPRESS_ZLIB: u32 = 1; 21 /// Start of OS-specific. 22 pub const ELFCOMPRESS_LOOS: u32 = 0x6000_0000; 23 /// End of OS-specific. 24 pub const ELFCOMPRESS_HIOS: u32 = 0x6fff_ffff; 25 /// Start of processor-specific. 26 pub const ELFCOMPRESS_LOPROC: u32 = 0x7000_0000; 27 /// End of processor-specific. 28 pub const ELFCOMPRESS_HIPROC: u32 = 0x7fff_ffff; 29 30 macro_rules! elf_compression_header_std_impl { ($size:ty) => { 31 32 #[cfg(test)] 33 mod tests { 34 use super::*; 35 #[test] 36 fn size_of() { 37 assert_eq!(::std::mem::size_of::<CompressionHeader>(), SIZEOF_CHDR); 38 } 39 } 40 41 if_alloc! { 42 use crate::elf::compression_header::CompressionHeader as ElfCompressionHeader; 43 44 use plain::Plain; 45 46 if_std! { 47 use crate::error::Result; 48 49 use std::fs::File; 50 use std::io::{Read, Seek}; 51 use std::io::SeekFrom::Start; 52 } 53 54 impl From<CompressionHeader> for ElfCompressionHeader { 55 fn from(ch: CompressionHeader) -> Self { 56 ElfCompressionHeader { 57 ch_type: ch.ch_type, 58 ch_size: u64::from(ch.ch_size), 59 ch_addralign: u64::from(ch.ch_addralign), 60 } 61 } 62 } 63 64 impl CompressionHeader { 65 pub fn from_bytes(bytes: &[u8]) -> CompressionHeader { 66 let mut chdr = CompressionHeader::default(); 67 chdr.copy_from_bytes(bytes).expect("buffer is too short for header"); 68 chdr 69 } 70 71 #[cfg(feature = "std")] 72 pub fn from_fd(fd: &mut File, offset: u64) -> Result<CompressionHeader> { 73 let mut chdr = CompressionHeader::default(); 74 fd.seek(Start(offset))?; 75 unsafe { 76 fd.read_exact(plain::as_mut_bytes(&mut chdr))?; 77 } 78 Ok(chdr) 79 } 80 } 81 } // end if_alloc 82 };} 83 84 #[cfg(feature = "alloc")] 85 use scroll::{Pread, Pwrite, SizeWith}; 86 87 pub mod compression_header32 { 88 pub use crate::elf::compression_header::*; 89 90 #[repr(C)] 91 #[derive(Copy, Clone, Eq, PartialEq, Default)] 92 #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))] 93 /// The compression header is used at the start of SHF_COMPRESSED sections 94 pub struct CompressionHeader { 95 /// Compression format 96 pub ch_type: u32, 97 /// Uncompressed data size 98 pub ch_size: u32, 99 /// Uncompressed data alignment 100 pub ch_addralign: u32, 101 } 102 103 elf_compression_header!(); 104 105 pub const SIZEOF_CHDR: usize = 12; 106 107 elf_compression_header_std_impl!(u32); 108 109 if_alloc! { 110 impl From<ElfCompressionHeader> for CompressionHeader { 111 fn from(ch: ElfCompressionHeader) -> Self { 112 CompressionHeader { 113 ch_type: ch.ch_type, 114 ch_size: ch.ch_size as u32, 115 ch_addralign: ch.ch_addralign as u32, 116 } 117 } 118 } 119 } 120 } 121 122 123 pub mod compression_header64 { 124 pub use crate::elf::compression_header::*; 125 126 #[repr(C)] 127 #[derive(Copy, Clone, Eq, PartialEq, Default)] 128 #[cfg_attr(feature = "alloc", derive(Pread, Pwrite, SizeWith))] 129 /// The compression header is used at the start of SHF_COMPRESSED sections 130 pub struct CompressionHeader { 131 /// Compression format 132 pub ch_type: u32, 133 pub ch_reserved: u32, 134 /// Uncompressed data size 135 pub ch_size: u64, 136 /// Uncompressed data alignment 137 pub ch_addralign: u64, 138 } 139 140 elf_compression_header!(); 141 142 pub const SIZEOF_CHDR: usize = 24; 143 144 elf_compression_header_std_impl!(u64); 145 146 if_alloc! { 147 impl From<ElfCompressionHeader> for CompressionHeader { 148 fn from(ch: ElfCompressionHeader) -> Self { 149 CompressionHeader { 150 ch_type: ch.ch_type, 151 ch_reserved: 0, 152 ch_size: ch.ch_size as u64, 153 ch_addralign: ch.ch_addralign as u64, 154 } 155 } 156 } 157 } 158 } 159 160 /////////////////////////////// 161 // Std/analysis/Unified Structs 162 /////////////////////////////// 163 164 if_alloc! { 165 #[cfg(feature = "endian_fd")] 166 use crate::error; 167 use core::fmt; 168 use core::result; 169 use scroll::ctx; 170 use crate::container::{Container, Ctx}; 171 172 #[derive(Default, PartialEq, Clone)] 173 /// A unified CompressionHeader - convertable to and from 32-bit and 64-bit variants 174 pub struct CompressionHeader { 175 /// Compression format 176 pub ch_type: u32, 177 /// Uncompressed data size 178 pub ch_size: u64, 179 /// Uncompressed data alignment 180 pub ch_addralign: u64, 181 } 182 183 impl CompressionHeader { 184 /// Return the size of the underlying compression header, given a `container` 185 #[inline] 186 pub fn size(ctx: Ctx) -> usize { 187 use scroll::ctx::SizeWith; 188 Self::size_with(&ctx) 189 } 190 pub fn new() -> Self { 191 CompressionHeader { 192 ch_type: 0, 193 ch_size: 0, 194 ch_addralign: 2 << 8, 195 } 196 } 197 /// Parse a compression header from `bytes` at `offset`, using the given `ctx` 198 #[cfg(feature = "endian_fd")] 199 pub fn parse(bytes: &[u8], mut offset: usize, ctx: Ctx) -> error::Result<CompressionHeader> { 200 use scroll::Pread; 201 bytes.gread_with(&mut offset, ctx) 202 } 203 } 204 205 impl fmt::Debug for CompressionHeader { 206 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 207 f.debug_struct("CompressionHeader") 208 .field("ch_type", &self.ch_type) 209 .field("ch_size", &format_args!("0x{:x}", self.ch_size)) 210 .field("ch_addralign", &format_args!("0x{:x}", self.ch_addralign)) 211 .finish() 212 } 213 } 214 215 impl ctx::SizeWith<Ctx> for CompressionHeader { 216 fn size_with( &Ctx { container, .. }: &Ctx) -> usize { 217 match container { 218 Container::Little => { 219 compression_header32::SIZEOF_CHDR 220 }, 221 Container::Big => { 222 compression_header64::SIZEOF_CHDR 223 }, 224 } 225 } 226 } 227 228 impl<'a> ctx::TryFromCtx<'a, Ctx> for CompressionHeader { 229 type Error = crate::error::Error; 230 fn try_from_ctx(bytes: &'a [u8], Ctx {container, le}: Ctx) -> result::Result<(Self, usize), Self::Error> { 231 use scroll::Pread; 232 let res = match container { 233 Container::Little => { 234 (bytes.pread_with::<compression_header32::CompressionHeader>(0, le)?.into(), compression_header32::SIZEOF_CHDR) 235 }, 236 Container::Big => { 237 (bytes.pread_with::<compression_header64::CompressionHeader>(0, le)?.into(), compression_header64::SIZEOF_CHDR) 238 } 239 }; 240 Ok(res) 241 } 242 } 243 244 impl ctx::TryIntoCtx<Ctx> for CompressionHeader { 245 type Error = crate::error::Error; 246 fn try_into_ctx(self, bytes: &mut [u8], Ctx {container, le}: Ctx) -> result::Result<usize, Self::Error> { 247 use scroll::Pwrite; 248 match container { 249 Container::Little => { 250 let chdr: compression_header32::CompressionHeader = self.into(); 251 Ok(bytes.pwrite_with(chdr, 0, le)?) 252 }, 253 Container::Big => { 254 let chdr: compression_header64::CompressionHeader = self.into(); 255 Ok(bytes.pwrite_with(chdr, 0, le)?) 256 } 257 } 258 } 259 } 260 impl ctx::IntoCtx<Ctx> for CompressionHeader { 261 fn into_ctx(self, bytes: &mut [u8], Ctx {container, le}: Ctx) { 262 use scroll::Pwrite; 263 match container { 264 Container::Little => { 265 let chdr: compression_header32::CompressionHeader = self.into(); 266 bytes.pwrite_with(chdr, 0, le).unwrap(); 267 }, 268 Container::Big => { 269 let chdr: compression_header64::CompressionHeader = self.into(); 270 bytes.pwrite_with(chdr, 0, le).unwrap(); 271 } 272 } 273 } 274 } 275 } // end if_alloc 276