-
Notifications
You must be signed in to change notification settings - Fork 248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support zstd-compressed ELF sections. #626
Changes from all commits
d6ab680
b0ae948
8d94e0d
e5473c3
fbfaf5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,9 @@ use super::{gimli, Context, Endian, EndianSlice, Mapping, Stash, Vec}; | |
use alloc::sync::Arc; | ||
use core::convert::{TryFrom, TryInto}; | ||
use core::str; | ||
use object::elf::{ELFCOMPRESS_ZLIB, ELF_NOTE_GNU, NT_GNU_BUILD_ID, SHF_COMPRESSED}; | ||
use object::elf::{ | ||
ELFCOMPRESS_ZLIB, ELFCOMPRESS_ZSTD, ELF_NOTE_GNU, NT_GNU_BUILD_ID, SHF_COMPRESSED, | ||
}; | ||
use object::read::elf::{CompressionHeader, FileHeader, SectionHeader, SectionTable, Sym}; | ||
use object::read::StringTable; | ||
use object::{BigEndian, Bytes, NativeEndian}; | ||
|
@@ -213,22 +215,30 @@ impl<'a> Object<'a> { | |
let mut data = Bytes(section.data(self.endian, self.data).ok()?); | ||
|
||
// Check for DWARF-standard (gABI) compression, i.e., as generated | ||
// by ld's `--compress-debug-sections=zlib-gabi` flag. | ||
// by ld's `--compress-debug-sections=zlib-gabi` and | ||
// `--compress-debug-sections=zstd` flags. | ||
let flags: u64 = section.sh_flags(self.endian).into(); | ||
if (flags & u64::from(SHF_COMPRESSED)) == 0 { | ||
// Not compressed. | ||
return Some(data.0); | ||
} | ||
|
||
let header = data.read::<<Elf as FileHeader>::CompressionHeader>().ok()?; | ||
if header.ch_type(self.endian) != ELFCOMPRESS_ZLIB { | ||
// Zlib compression is the only known type. | ||
return None; | ||
match header.ch_type(self.endian) { | ||
ELFCOMPRESS_ZLIB => { | ||
let size = usize::try_from(header.ch_size(self.endian)).ok()?; | ||
let buf = stash.allocate(size); | ||
decompress_zlib(data.0, buf)?; | ||
return Some(buf); | ||
} | ||
ELFCOMPRESS_ZSTD => { | ||
let size = usize::try_from(header.ch_size(self.endian)).ok()?; | ||
let buf = stash.allocate(size); | ||
decompress_zstd(data.0, buf)?; | ||
return Some(buf); | ||
} | ||
_ => return None, // Unknown compression type. | ||
Comment on lines
+227
to
+240
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, the actual implementation seems basically fine. |
||
} | ||
let size = usize::try_from(header.ch_size(self.endian)).ok()?; | ||
let buf = stash.allocate(size); | ||
decompress_zlib(data.0, buf)?; | ||
return Some(buf); | ||
} | ||
|
||
// Check for the nonstandard GNU compression format, i.e., as generated | ||
|
@@ -347,6 +357,40 @@ fn decompress_zlib(input: &[u8], output: &mut [u8]) -> Option<()> { | |
} | ||
} | ||
|
||
fn decompress_zstd(mut input: &[u8], mut output: &mut [u8]) -> Option<()> { | ||
use ruzstd::frame::ReadFrameHeaderError; | ||
use ruzstd::frame_decoder::FrameDecoderError; | ||
use ruzstd::io::Read; | ||
|
||
while !input.is_empty() { | ||
let mut decoder = match ruzstd::StreamingDecoder::new(&mut input) { | ||
Ok(decoder) => decoder, | ||
Err(FrameDecoderError::ReadFrameHeaderError(ReadFrameHeaderError::SkipFrame { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mmmmmmm... that sure is a pattern that is being matched... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed. |
||
length, | ||
.. | ||
})) => { | ||
input = &input.get(length as usize..)?; | ||
continue; | ||
} | ||
Err(_) => return None, | ||
}; | ||
loop { | ||
let bytes_written = decoder.read(output).ok()?; | ||
if bytes_written == 0 { | ||
break; | ||
} | ||
output = &mut output[bytes_written..]; | ||
} | ||
} | ||
|
||
if !output.is_empty() { | ||
// Lengths didn't match, something is wrong. | ||
return None; | ||
} | ||
|
||
Some(()) | ||
} | ||
|
||
const DEBUG_PATH: &[u8] = b"/usr/lib/debug"; | ||
|
||
fn debug_path_exists() -> bool { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, why are we bumping this? I kinda think we should just bump ahead to a recent ubuntu if we gotta?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--compress-debug-sections=zstd is only available in the binutils/etc that ships with 24.04, not with 20.04 or 22.04.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And no chance of installing that stuff on ubuntu 20 without exploding the world, huh?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be scared to try :)
If rust-lld propagates out to the stable branches I think it'll just work there though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh cool. Can you give that a whirl against our CI for nightly + ubuntu 20.04, then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like that's rust-lang/rust#120953
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
huh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...wait, can we just install lld and test with that or something? (not sure if that actually works out with all the versions involved...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rust-lang/rust#125642 is also good lmao.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to rust-lang/rust#124129 we can just use
-Zlinker-features=-lld
but I feel like rust-lld should be fixed.