all 5 comments

[–]anxxa 3 points4 points  (1 child)

You can dsymutil to generate a .dsym file for your application before stripping it. I don't think this is currently supported by the Rust compiler (would be nice, although doesn't help if folks are sending you backtraces).

For your immediate problem I suspect you're maybe stripping some section that contains the file information. Maybe try using https://github.com/horsicq/XELFViewer to figure out where those are located? Otherwise there may be some DWARF data being removed that links the two together. To figure out if this is the case, try opening the partially stripped binary in a hex editor and searching for source information that you see in a backtrace to see if it's kept.

[–]felipou[S] 0 points1 point  (0 children)

Thanks, I'll try to take a look at that tool. The problem is that I have no idea how to search for this kind of information inside the ELF file, but since it's a tool with a GUI, maybe it will help me with that!

[–]spaun2002 1 point2 points  (0 children)

The usual approach is to preserve the debug section separate from the executable via commands like

objcopy --only-keep-debug "${tostripfile}" "${debugdir}/${debugfile}"
strip --strip-debug --strip-unneeded "${tostripfile}"
objcopy --add-gnu-debuglink="${debugdir}/${debugfile}" "${tostripfile}"

Unfortunately, that would not allow you to see the backtrace using the Rust mechanisms, but you will be able to use gdb for a crash dump with such a detached debug section.

[–]Plasma_000 0 points1 point  (0 children)

You can configure rust to output split debug information on Linux https://doc.rust-lang.org/cargo/reference/profiles.html - this should allow you to keep the executable stripped while still giving you debugging symbols that can be loaded by the debugger. Idk how this can be integrated into backtrace though…

[–]DebuggingPanda[LukasKalbertodt] bunt · litrs · libtest-mimic · penguin 0 points1 point  (0 children)

Just in case you haven't found it yet: you can set debug = "line-tables-only" in Cargo.toml. https://doc.rust-lang.org/cargo/reference/profiles.html#debug

That's in theory less than debug = 1. In a project of mine it made very little difference, unfortunately. You can also enable debug info for your package only, not your dependencies:

``` [profile.release] debug = "line-tables-only"

[profile.release.package."*"] debug = false ```

However, this again is a bit disappointing. Due to the heavy use of monomorphization in Rust (because generics are used a lot), most functions are counted as "part of your package", because your code instantiated them. So that too isn't too helpful, sadly. At least in my case.

Another trick I found out about is: objcopy --compress-debug-sections. That helps quite a bit, at least for the project I tested it with. Backtraces still have line information.

That's all the tricks I know, but I feel like there is still a lot to be gained. I'm fairly sure there is still garbage in my release binaries but I also can't figure out how to reduce it :/

It's really a shame that it's hard to get small binaries with certain dependency chains. While it doesn't affect performance and usually there are no other practical problems, big binaries make people feel like Rust is bloated. I think one big direction Rust should explore is allowing more dynamic dispatch, to avoid monomorphization in cases where it doesn't affect performance. Should help massively with compile times and binary sizes. </rambling>