diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6ed2863cf..ca8a4b81c 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 @@ -85,6 +97,10 @@ jobs: if: contains(matrix.os, 'ubuntu') env: RUSTFLAGS: "-C link-arg=-Wl,--compress-debug-sections=zlib-gnu" + - run: cargo test + if: contains(matrix.os, 'ubuntu-24.04') + env: + RUSTFLAGS: "-C link-arg=-Wl,--compress-debug-sections=zstd" # Test that, on macOS, packed/unpacked debuginfo both work - run: cargo clean && cargo test diff --git a/Cargo.lock b/Cargo.lock index 52472f32e..d22781de3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", + "zstd", ] [[package]] @@ -46,6 +47,7 @@ dependencies = [ "rustc-demangle", "serde", "winapi", + "zstd", ] [[package]] @@ -53,6 +55,10 @@ name = "cc" version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +dependencies = [ + "jobserver", + "libc", +] [[package]] name = "cfg-if" @@ -87,6 +93,15 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +[[package]] +name = "jobserver" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + [[package]] name = "libc" version = "0.2.147" @@ -127,6 +142,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "proc-macro2" version = "1.0.66" @@ -209,3 +230,31 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "zstd" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index bf8cf869d..941f7a0ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,12 +39,21 @@ cpp_demangle = { default-features = false, version = "0.4.0", optional = true, f "alloc", ] } -[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies] -miniz_oxide = { version = "0.7.0", default-features = false } +# MSVC uses PDB, not DWARF. But UWP doesn't allow for APIs gimli (via addr2line) uses, +# so skip that too. +[target.'cfg(not(any(target_env = "msvc", target_vendor = "uwp")))'.dependencies] addr2line = { version = "0.22.0", default-features = false } libc = { version = "0.2.146", default-features = false } -[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies.object] +# Windows uses PE, not ELF, so libraries for ELF compression are unnecessary. +[target.'cfg(not(windows))'.dependencies] +miniz_oxide = { version = "0.7.0", default-features = false } + +# Also used for ELF compression, but doesn't build on illumos in CI. +[target.'cfg(not(any(windows, target_os = "illumos")))'.dependencies] +zstd = { version = "= 0.13.0", default-features = false } + +[target.'cfg(not(any(target_env = "msvc", target_vendor = "uwp")))'.dependencies.object] version = "0.35.0" default-features = false features = ['read_core', 'elf', 'macho', 'pe', 'xcoff', 'unaligned', 'archive'] diff --git a/ci/docker/arm-linux-androideabi/Dockerfile b/ci/docker/arm-linux-androideabi/Dockerfile index 7471dcb73..e2fb5e08a 100644 --- a/ci/docker/arm-linux-androideabi/Dockerfile +++ b/ci/docker/arm-linux-androideabi/Dockerfile @@ -15,4 +15,5 @@ ENV PATH=$PATH:/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin # TODO: run tests in an emulator eventually ENV CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=armv7a-linux-androideabi19-clang \ + CC=armv7a-linux-androideabi19-clang \ CARGO_TARGET_ARM_LINUX_ANDROIDEABI_RUNNER=echo diff --git a/ci/docker/armv7-linux-androideabi/Dockerfile b/ci/docker/armv7-linux-androideabi/Dockerfile index 543fcd243..a251e2dc3 100644 --- a/ci/docker/armv7-linux-androideabi/Dockerfile +++ b/ci/docker/armv7-linux-androideabi/Dockerfile @@ -15,4 +15,5 @@ ENV PATH=$PATH:/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin # TODO: run tests in an emulator eventually ENV CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=armv7a-linux-androideabi19-clang \ + CC=armv7a-linux-androideabi19-clang \ CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_RUNNER=echo diff --git a/ci/docker/i686-linux-android/Dockerfile b/ci/docker/i686-linux-android/Dockerfile index 61cb9d075..bfac4f015 100644 --- a/ci/docker/i686-linux-android/Dockerfile +++ b/ci/docker/i686-linux-android/Dockerfile @@ -15,4 +15,5 @@ ENV PATH=$PATH:/android-toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin # TODO: run tests in an emulator eventually ENV CARGO_TARGET_I686_LINUX_ANDROID_LINKER=i686-linux-android19-clang \ + CC=i686-linux-android19-clang \ CARGO_TARGET_I686_LINUX_ANDROID_RUNNER=echo diff --git a/crates/as-if-std/Cargo.toml b/crates/as-if-std/Cargo.toml index b451c024a..73e3ce5fa 100644 --- a/crates/as-if-std/Cargo.toml +++ b/crates/as-if-std/Cargo.toml @@ -14,13 +14,18 @@ bench = false [dependencies] cfg-if = "1.0" rustc-demangle = "0.1.21" + +[target.'cfg(not(any(target_env = "msvc", target_vendor = "uwp")))'.dependencies] libc = { version = "0.2.146", default-features = false } +addr2line = { version = "0.22.0", optional = true, default-features = false } -[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies] +[target.'cfg(not(windows))'.dependencies] miniz_oxide = { version = "0.7.0", optional = true, default-features = false } -addr2line = { version = "0.22.0", optional = true, default-features = false } -[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies.object] +[target.'cfg(not(any(windows, target_os = "illumos")))'.dependencies] +zstd = { version = "= 0.13.0", optional = true, default-features = false } + +[target.'cfg(not(any(target_env = "msvc", target_vendor = "uwp")))'.dependencies.object] version = "0.35.0" default-features = false optional = true @@ -32,7 +37,7 @@ cc = "1.0.90" [features] default = ['backtrace'] -backtrace = ['addr2line', 'miniz_oxide', 'object'] +backtrace = ['addr2line', 'miniz_oxide', 'object', 'zstd'] std = [] [lints.rust] diff --git a/src/symbolize/gimli/elf.rs b/src/symbolize/gimli/elf.rs index 906a30054..20f2d3f7e 100644 --- a/src/symbolize/gimli/elf.rs +++ b/src/symbolize/gimli/elf.rs @@ -7,6 +7,8 @@ use super::{gimli, Context, Endian, EndianSlice, Mapping, Stash, Vec}; use alloc::sync::Arc; use core::convert::{TryFrom, TryInto}; use core::str; +#[cfg(not(target_os = "illumos"))] +use object::elf::ELFCOMPRESS_ZSTD; use object::elf::{ELFCOMPRESS_ZLIB, ELF_NOTE_GNU, NT_GNU_BUILD_ID, SHF_COMPRESSED}; use object::read::elf::{CompressionHeader, FileHeader, SectionHeader, SectionTable, Sym}; use object::read::StringTable; @@ -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,22 @@ 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); + } + #[cfg(not(target_os = "illumos"))] + 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 +315,11 @@ fn decompress_zlib(input: &[u8], output: &mut [u8]) -> Option<()> { } } +#[cfg(not(target_os = "illumos"))] +fn decompress_zstd(input: &[u8], output: &mut [u8]) -> Option<()> { + zstd::stream::copy_decode(input, output).ok() +} + const DEBUG_PATH: &[u8] = b"/usr/lib/debug"; fn debug_path_exists() -> bool {