1 | use crate::read::{self, Error, ReadError as _}; |
2 | use crate::{endian, CompressedFileRange, CompressionFormat, ReadRef, U32Bytes}; |
3 | |
4 | // Attempt to parse the the CompressedFileRange for a section using the GNU-style |
5 | // inline compression header format. This is used by the Go compiler in Mach-O files |
6 | // as well as by the GNU linker in some ELF files. |
7 | pub(super) fn compressed_file_range<'data, R: ReadRef<'data>>( |
8 | file_data: R, |
9 | section_offset: u64, |
10 | section_size: u64, |
11 | ) -> read::Result<CompressedFileRange> { |
12 | let mut offset = section_offset; |
13 | // Assume ZLIB-style uncompressed data is no more than 4GB to avoid accidentally |
14 | // huge allocations. This also reduces the chance of accidentally matching on a |
15 | // .debug_str that happens to start with "ZLIB". |
16 | let header = file_data |
17 | .read_bytes(&mut offset, 8) |
18 | .read_error("GNU compressed section is too short" )?; |
19 | if header != b"ZLIB \0\0\0\0" { |
20 | return Err(Error("Invalid GNU compressed section header" )); |
21 | } |
22 | let uncompressed_size = file_data |
23 | .read::<U32Bytes<_>>(&mut offset) |
24 | .read_error("GNU compressed section is too short" )? |
25 | .get(endian::BigEndian) |
26 | .into(); |
27 | let compressed_size = section_size |
28 | .checked_sub(offset - section_offset) |
29 | .read_error("GNU compressed section is too short" )?; |
30 | Ok(CompressedFileRange { |
31 | format: CompressionFormat::Zlib, |
32 | offset, |
33 | compressed_size, |
34 | uncompressed_size, |
35 | }) |
36 | } |
37 | |