diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0103a099..d95466cb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,6 +22,12 @@ jobs: rust: beta - os: ubuntu-20.04 rust: nightly + - os: ubuntu-24.04 + rust: stable + - os: ubuntu-24.04 + rust: beta + - os: ubuntu-24.04 + rust: nightly - os: macos-latest rust: stable - os: macos-latest @@ -48,6 +54,12 @@ jobs: - run: echo RUSTFLAGS=-Dwarnings >> $GITHUB_ENV shell: bash + # Starting with Ubuntu 22.04 libc6-dbg is needed. + - name: Install libc debug info + run: sudo apt-get install -y libc6-dbg + shell: bash + if: contains(matrix.os, 'ubuntu-24.04') + # full fidelity of backtraces on 32-bit msvc requires frame pointers, so # enable that for our tests - name: Force frame pointers @@ -80,6 +92,11 @@ jobs: if: contains(matrix.os, 'ubuntu') env: RUSTFLAGS: "-C link-arg=-Wl,--compress-debug-sections=zlib" + - run: cargo test + if: contains(matrix.os, 'ubuntu-24.04') || + (contains(matrix.os, 'ubuntu') && contains(matrix.rust, 'nightly')) + env: + RUSTFLAGS: "-C link-arg=-Wl,--compress-debug-sections=zstd" # Test that, on macOS, packed/unpacked debuginfo both work - run: cargo clean && cargo test @@ -248,7 +265,7 @@ jobs: with: submodules: true - name: Install Rust - run: rustup update 1.65.0 --no-self-update && rustup default 1.65.0 + run: rustup update 1.73.0 --no-self-update && rustup default 1.73.0 - run: cargo build miri: diff --git a/Cargo.lock b/Cargo.lock index 37556f3f..0ce03e15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,6 +27,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", + "ruzstd", "windows-bindgen", ] @@ -43,9 +44,16 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", + "ruzstd", "serde", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "cc" version = "1.0.99" @@ -206,6 +214,15 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "ruzstd" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5022b253619b1ba797f243056276bed8ed1a73b0f5a7ce7225d524067644bf8f" +dependencies = [ + "byteorder", +] + [[package]] name = "ryu" version = "1.0.18" diff --git a/Cargo.toml b/Cargo.toml index ec298d07..4782c50d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ autoexamples = true autotests = true edition = "2021" exclude = ["/ci/"] -rust-version = "1.65.0" +rust-version = "1.73.0" [workspace] members = ['crates/cpp_smoke_test', 'crates/as-if-std'] @@ -40,6 +40,7 @@ cpp_demangle = { default-features = false, version = "0.4.0", optional = true, f [target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies] miniz_oxide = { version = "0.7.0", default-features = false } +ruzstd = { version = "0.7.0", default-features = false } addr2line = { version = "0.24.0", default-features = false } libc = { version = "0.2.146", default-features = false } diff --git a/crates/as-if-std/Cargo.toml b/crates/as-if-std/Cargo.toml index 3590f4d1..d2136394 100644 --- a/crates/as-if-std/Cargo.toml +++ b/crates/as-if-std/Cargo.toml @@ -18,6 +18,7 @@ libc = { version = "0.2.146", default-features = false } [target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies] miniz_oxide = { version = "0.7.0", optional = true, default-features = false } +ruzstd = { version = "0.7.0", optional = true, default-features = false } addr2line = { version = "0.24.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies.object] @@ -32,7 +33,7 @@ windows-bindgen = "0.56" [features] default = ['backtrace'] -backtrace = ['addr2line', 'miniz_oxide', 'object'] +backtrace = ['addr2line', 'miniz_oxide', 'object', 'ruzstd'] std = [] [lints.rust] diff --git a/src/symbolize/gimli/elf.rs b/src/symbolize/gimli/elf.rs index 906a3005..056d42f6 100644 --- a/src/symbolize/gimli/elf.rs +++ b/src/symbolize/gimli/elf.rs @@ -7,7 +7,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}; @@ -170,7 +172,8 @@ 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. @@ -178,14 +181,21 @@ impl<'a> Object<'a> { } let header = data.read::<::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. } - 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 @@ -304,6 +314,13 @@ fn decompress_zlib(input: &[u8], output: &mut [u8]) -> Option<()> { } } +fn decompress_zstd(input: &[u8], output: &mut [u8]) -> Option<()> { + use ruzstd::io::Read; + + let mut decoder = ruzstd::StreamingDecoder::new(input).ok()?; + decoder.read_exact(output).ok() +} + const DEBUG_PATH: &[u8] = b"/usr/lib/debug"; fn debug_path_exists() -> bool {