rustrust-cargodebug-symbolsdebug-information

When to use symbol stripping in Rust release builds?


Stripping debug info in the release profile reduces my crate's binary size by a third (from 1.9 MB to 1.3 MB). This is what I added:

[profile.release]
strip = true
# or strip = "symbols"

Why is stripping disabled by default in the release profile?

I read the section on strip cargo option but I'm still a bit unsure about its internals.

Are there any cons of always using it in the release profile - perhaps only increasing compilation time?


Solution

  • Debug info is, well, information that is useful in debugging. In particular, certain parts of the binary are mapped to source code in a way that helps you debug a --release binary.

    For example, given this code:

    fn main() {
      foo();
    }
    
    #[inline(never)]
    fn foo() {
      panic!("hello");
    }
    

    The stacktrace with debug info included looks like this (running RUST_BACKTRACE=full cargo run --release):

    ...
    
      12:     0x563a420d5c5c - std::sys_common::backtrace::__rust_end_short_backtrace::h356ecf2a7ec67271
                                   at /rustc/060e47f74a91b28c3db28d80a6a9d6841ca51026/library/std/src/sys_common/backtrace.rs:138:18
      13:     0x563a420d7162 - rust_begin_unwind
                                   at /rustc/060e47f74a91b28c3db28d80a6a9d6841ca51026/library/std/src/panicking.rs:584:5
      14:     0x563a420c0833 - core::panicking::panic_fmt::h9555dfef52eae25e
                                   at /rustc/060e47f74a91b28c3db28d80a6a9d6841ca51026/library/core/src/panicking.rs:142:14
      15:     0x563a420c0b59 - playground::foo::h556d88610d3b7d1f
      16:     0x563a420c0b06 - playground::main::h2eebec7531673915
      17:     0x563a420c0af3 - std::sys_common::backtrace::__rust_begin_short_backtrace::haa748201e9438a0f
      18:     0x563a420c0b99 - std::rt::lang_start::{{closure}}::h605b074d393b11eb
      19:     0x563a420d19bf - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::hed7373fa9659f259
                                   at /rustc/060e47f74a91b28c3db28d80a6a9d6841ca51026/library/core/src/ops/function.rs:280:13
      20:     0x563a420d19bf - std::panicking::try::do_call::h60869ea5a827d812
                                   at /rustc/060e47f74a91b28c3db28d80a6a9d6841ca51026/library/std/src/panicking.rs:492:40
      21:     0x563a420d19bf - std::panicking::try::he306a2f2634a9efa
                                   at /rustc/060e47f74a91b28c3db28d80a6a9d6841ca51026/library/std/src/panicking.rs:456:19
      22:     0x563a420d19bf - std::panic::catch_unwind::hd1d792c621528cfe
                                   at /rustc/060e47f74a91b28c3db28d80a6a9d6841ca51026/library/std/src/panic.rs:137:14
    
    ...
    

    Without debug info, it looks like this:

       0:     0x55d165a94750 - <unknown>
       1:     0x55d165aaf00e - <unknown>
       2:     0x55d165a92575 - <unknown>
       3:     0x55d165a95ea3 - <unknown>
       4:     0x55d165a95b8f - <unknown>
       5:     0x55d165a9654a - <unknown>
       6:     0x55d165a96401 - <unknown>
       7:     0x55d165a94c5c - <unknown>
       8:     0x55d165a96162 - <unknown>
       9:     0x55d165a7f833 - <unknown>
      10:     0x55d165a7fb49 - <unknown>
      11:     0x55d165a7faf6 - <unknown>
      12:     0x55d165a7fb83 - <unknown>
      13:     0x55d165a7fb99 - <unknown>
      14:     0x55d165a909bf - <unknown>
      15:     0x55d165a7fb72 - <unknown>
      16:     0x7fddc5a16237 - __libc_start_call_main
      17:     0x7fddc5a162f5 - __libc_start_main_impl
      18:     0x55d165a7fa21 - <unknown>
      19:                0x0 - <unknown>
    

    As a rule of thumb, I leave it on (i.e. I don't strip debug info) unless I really really care about binary size.