How to ship rust binaries with reasonable backtraces?

I have a question about rust-analyzer.

When I receive bug reports with panics, I want panic messages and backtraces to contain line numbers, so that it's easier to investigate failures.

My understanding is that lines are not always included with debug = false (at least that's my impression from local testing on Linux, I didn't investigate this thoroughly).

However, compiling with debug = 1 doesn't solve the problem:

  • on windows and macs the debuginfo is split, which is uselful for development but, not not so much during shipping
  • on Linux, this inflates (gzipped) file from 8mb to 40mb, which is not way more than I am ready to pay

Questions:

  • how do people solve this problem? Is there some blog post which investigates and documents the current state of affair?
  • is it reasonable at all that debug = 1 increases the binary size five times?

I found the human-panic crate to be on a promising path here, but there're still some missing things. You could take inspiration from that approach ?

2 Likes

The most commonly used method is to store the debuginfo separate from the binary and not ship it. When you get a backtrace with raw addresses, you then run a symbolizer like addr2line for each raw address using the debuginfo. Something like breakpad can automatically extract just the necessary debuginfo and capture just enough information during crashes for easy offline backtrace generation.

Debuginfo is big. A 5x increase is a bit big I think, but debuginfo is almost always bigger than the executable itself.

3 Likes

The current debug=1 is actually more than just line tables, also including a lot of function type information. I tried to reduce that once, but IIRC it was seen as a regression for Mozilla's crash reporter. There's a new attempt to add more explicit choices here:

https://github.com/rust-lang/rust/pull/83947

3 Likes

For ELF/DWARF targets, you might be able to get away with using strip to remove the .debug_info section in particular, and maybe a few others.

Would generating minidump/breakpad work for you? I don't have experience generating them in Rust so can't comment on how well it works.

At work in C++ we typically generate debug info for release target and then extract symbols using nm --defined-only and then use strip to remove symbols/debug info. This loses DWARF information about inlined functions (not a problem for us) but if you care about them maybe you could keep your full binaries and ship stripped ones and then use addr2line or something like Symbolic to retrieve source code locations.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.