Skip to content
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

libunwind is compiled even with panic_immediate_abort #6358

Open
yuki0iq opened this issue Feb 18, 2024 · 6 comments
Open

libunwind is compiled even with panic_immediate_abort #6358

yuki0iq opened this issue Feb 18, 2024 · 6 comments
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug.

Comments

@yuki0iq
Copy link

yuki0iq commented Feb 18, 2024

Version and platform

$ cargo tree
tokio-no-backtrace-test v0.1.0 (/home/yuki/kek/pubnix/__TEMP)
└── tokio v1.36.0 (https://github.com/tokio-rs/tokio#b32826bc)
    └── pin-project-lite v0.2.13
$ rustc --version --verbose
rustc 1.78.0-nightly (6672c16af 2024-02-17)
binary: rustc
commit-hash: 6672c16afcd4db8acdf08a6984fd4107bf07632c
commit-date: 2024-02-17
host: x86_64-unknown-linux-musl
release: 1.78.0-nightly
LLVM version: 18.1.0
$ uname -a
Linux reimu 6.7.4-arch1-1 #1 SMP PREEMPT_DYNAMIC Mon, 05 Feb 2024 22:07:49 +0000 x86_64 GNU/Linux

Note that I use Arch Linux as a host system and musl-rust is from alpine chroot.

# uname -a
Linux reimu 6.7.4-arch1-1 #1 SMP PREEMPT_DYNAMIC Mon, 05 Feb 2024 22:07:49 +0000 x86_64 Linux

Description
I use agressive rust code minification for one of my projects and panic_immediate_abort to disable unwinding to make executable smaller. However, this crate does not provide a simple way of disabling (or rather not enabling) unwinding.

The simplest example I can think of is

// in Cargo.toml:
// [dependencies]
// tokio = { git = "https://github.com/tokio-rs/tokio", features = ["rt"], default-features = false }

fn main() {
    tokio::runtime::Builder::new_current_thread()
        .build()
        .unwrap()
        .block_on(async {
            println!("hello world");
        });
}

Let's define some environment variables so I won't have to type them in every code block

RUSTFLAGS="-Copt-level=z -Ccodegen-units=1 -Cembed-bitcode -Clto=fat -Cpanic=abort -Zlocation-detail=none"

# to be passed between `cargo` and `build`
CARGOOPTS="+nightly -Zbuild-std=std,core,alloc,panic_abort -Zbuild-std-features=panic_immediate_abort"

If I compile the binary as I always do, I get 67 kilobytes of output. That looks like too much for something this simple...

$ RUSTFLAGS="... -Cstrip=symbols" cargo ... build --release --target x86_64-unknown-linux-musl
   Compiling core v0.0.0 (/home/yuki/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core)
   [...]
   Compiling tokio v1.36.0 (https://github.com/tokio-rs/tokio#b32826bc)
   Compiling tokio-no-backtrace-test v0.1.0 (/home/yuki/tokio-no-backtrace-test)
    Finished release [optimized] target(s) in 23.58s
$ ls -al target/x86_64-unknown-linux-musl/release/tokio-no-backtrace-test
-rwxr-xr-x 2 yuki yuki 67728 Feb 18 23:12 target/x86_64-unknown-linux-musl/release/tokio-no-backtrace-test

I expected somewhat smaller executable and dug into cargo bloat output. Note that I'm not stripping the binary here for cargo bloat to actually work

$ RUSTFLAGS="..." cargo ... bloat --release --target x86_64-unknown-linux-musl
    Finished release [optimized] target(s) in 0.02s
    Analyzing target/x86_64-unknown-linux-musl/release/tokio-no-backtrace-test

 File  .text     Size                   Crate Name
 1.0%   6.1%  19.7KiB               [Unknown] _ZN9libunwind10CFI_ParserINS_17LocalAddressSpaceEE20parseFDEInstructionsERS1_RKNS2_8FDE_InfoERKNS2_8CIE_InfoEmiPNS2_10PrologInfoE
 0.9%   5.5%  17.9KiB                     std std::backtrace_rs::symbolize::gimli::Cache::with_global
 0.8%   5.0%  16.3KiB                     std std::backtrace_rs::symbolize::gimli::Context::new
 0.6%   3.5%  11.3KiB                     std addr2line::ResUnit<R>::find_function_or_location::{{closure}}
 0.5%   2.7%   8.8KiB tokio_no_backtrace_test tokio_no_backtrace_test::main
 0.4%   2.7%   8.6KiB                     std miniz_oxide::inflate::core::decompress
 0.4%   2.7%   8.6KiB                     std gimli::read::dwarf::Unit<R>::new
 0.4%   2.4%   7.7KiB                     std addr2line::Lines::parse
 0.3%   1.8%   5.9KiB                     std std::backtrace_rs::symbolize::gimli::libs_dl_iterate_phdr::callback
 0.3%   1.6%   5.3KiB                     std gimli::read::abbrev::Abbreviations::insert
 0.3%   1.5%   5.0KiB                     std gimli::read::unit::parse_attribute
 0.2%   1.3%   4.3KiB               [Unknown] _ZN9libunwind17DwarfInstructionsINS_17LocalAddressSpaceENS_16Registers_x86_64EE13stepWithDwarfERS1_mmRS2_Rbb
 0.2%   1.2%   4.0KiB                     std addr2line::function::Function<R>::parse_children
 0.2%   1.2%   3.9KiB               [Unknown] _ZN9libunwind17DwarfInstructionsINS_17LocalAddressSpaceENS_16Registers_x86_64EE18evaluateExpressionEmRS1_RKS2_m
 0.2%   1.1%   3.7KiB                     std gimli::read::rnglists::RngListIter<R>::next
 0.2%   1.1%   3.5KiB               [Unknown] main
 0.2%   1.0%   3.2KiB                     std <&T as core::fmt::Display>::fmt
 0.2%   1.0%   3.2KiB                     std core::slice::sort::recurse
 0.2%   1.0%   3.1KiB                     std gimli::read::abbrev::DebugAbbrev<R>::abbreviations
 0.2%   0.9%   3.0KiB                     std std::backtrace_rs::symbolize::gimli::elf::<impl std::backtrace_rs::symbolize::gimli::Mapping>::new_debug
 9.1%  53.7% 174.8KiB                         And 682 smaller methods. Use -n N to show more.
16.9% 100.0% 325.7KiB                         .text section size, the file size is 1.9MiB

This is... interesting. If we look at what cargo bloat has to say for crates, we'll see

$ RUSTFLAGS="..." cargo ... bloat --release --target x86_64-unknown-linux-musl --crates
    Finished release [optimized] target(s) in 0.02s
    Analyzing target/x86_64-unknown-linux-musl/release/tokio-no-backtrace-test

 File  .text     Size Crate
11.6%  68.7% 223.7KiB std
 4.2%  24.9%  81.1KiB [Unknown]
 0.5%   3.0%   9.8KiB tokio_no_backtrace_test
 0.4%   2.2%   7.3KiB tokio
16.9% 100.0% 325.7KiB .text section size, the file size is 1.9MiB

Note: numbers above are a result of guesswork. They are not 100% correct and never will be.

Judging by cargo bloat output, [Unknown] and std should mostly be libunwind and something related to them. I wonder now if it is possible to disable unwinding, possibly by making some features opt-in and default.

@yuki0iq yuki0iq added A-tokio Area: The main tokio crate C-bug Category: This is a bug. labels Feb 18, 2024
@Darksonn
Copy link
Contributor

However, this crate does not provide a simple way of disabling (or rather not enabling) unwinding.

What are you asking us to do? The panic=abort property should work fine with Tokio.

@yuki0iq
Copy link
Author

yuki0iq commented Feb 18, 2024

panic=abort is passed through RUSTFLAGS, but libunwind is still linked into the executable

And I'm asking for ability to disable unwinding

@Darksonn
Copy link
Contributor

What, concretely, do you want us to do to disable unwinding? I could be mistaken, but to my knowledge, there's nothing that Tokio needs to do and it should just work.

@yuki0iq
Copy link
Author

yuki0iq commented Feb 18, 2024

It is probably related to catching panics and something like this. I know that these is a runtime ability to disable panic silencing (which is behind a tokio_unstable feature gate), but this probably wouldn't help. There could be more places like this, but grep'ing sources gives little to no clue where to fix, only a reference to tokio/src/runtime/trace/

Further investigation is probably needed

@Darksonn
Copy link
Contributor

I mean, one example of how we don't have to do anything is that catch_unwind becomes a no-op when you set panic=abort. (It still needs libunwind, but that's for printing the backtrace, not for unwinding.)

@yuki0iq
Copy link
Author

yuki0iq commented Feb 18, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

2 participants