///|
/// ELF compression header for sections marked with `SHF_COMPRESSED`.
///
/// The parser returns this header together with the remaining compressed
/// payload bytes. It does not perform decompression; callers choose the
/// decompressor matching `ch_type` such as `ELFCOMPRESS_ZLIB` or
/// `ELFCOMPRESS_ZSTD`.
pub(all) struct CompressionHeader {
/// Compression algorithm identifier (`ELFCOMPRESS_*`).
ch_type : UInt
/// Uncompressed section size in bytes.
ch_size : UInt64
/// Required alignment of the uncompressed data.
ch_addralign : UInt64
} derive(Debug, Eq)
///|
impl ParseAt for CompressionHeader with parse_at(endian, class, offset, data) {
let end = checked_add(offset, CompressionHeader::size_for(class))
let record = slice_checked(data, offset, end)
let header = match (class, endian) {
(ELF32, Little) =>
match record {
[u32le(ch_type), u32le(ch_size32), u32le(ch_addralign32)] =>
{
ch_type,
ch_size: ch_size32.to_uint64(),
ch_addralign: ch_addralign32.to_uint64(),
}
_ => raise SliceReadError(offset, end)
}
(ELF32, Big) =>
match record {
[u32be(ch_type), u32be(ch_size32), u32be(ch_addralign32)] =>
{
ch_type,
ch_size: ch_size32.to_uint64(),
ch_addralign: ch_addralign32.to_uint64(),
}
_ => raise SliceReadError(offset, end)
}
(ELF64, Little) =>
match record {
[u32le(ch_type), u32le(_reserved), u64le(ch_size), u64le(ch_addralign)] =>
{ ch_type, ch_size, ch_addralign }
_ => raise SliceReadError(offset, end)
}
(ELF64, Big) =>
match record {
[u32be(ch_type), u32be(_reserved), u64be(ch_size), u64be(ch_addralign)] =>
{ ch_type, ch_size, ch_addralign }
_ => raise SliceReadError(offset, end)
}
}
(header, end)
}
///|
/// Size in bytes of an ELF compression header for the given class.
pub fn CompressionHeader::size_for(class : Class) -> Int {
match class {
ELF32 => 12
ELF64 => 24
}
}