Skip to content

Small ReleaseSafe binaries with backtraces #18520

@matklad

Description

@matklad

Problem: for TigerBetele, we want our release binary to be relatively small and self-contained, but we also want to see at least a minimal backtrace on assert faliures, overflow errors, indexing out of bounds and such.

As far as I am aware:

  • No combination of Zig build flags gets us the desired result: either a binary is huge, or the stacktrace is absent
  • This should be theoretically possible, as Rust does that

Specifically (non-expert, might be talking nonsense here), I think including frame pointers, and debug symbols (but not the entire of debug info) should give both a small executable, and a reasonable stack trace.

Here's a reproducible log of my experiments:

https://github.com/matklad/repros/tree/7d0c1a081d969ac040625445059dcc6574ad2bdf/zig-stack-trace

This is what I tried:

  1. Baseline, just ReleaseSafe: huge binary because of debuginfo, good backtrace
  2. module.omit_frame_pointer = false; module.strip = false;: small file, but no backtrace at all
  3. addObjCopy step with .strip = .debug: small file, but bad backtrace:
thread 33065 panic: integer overflow
Unwind information for `exe:0x10318a0` was not available, trace may be incomplete

???:?:?: 0x100c274 in ??? (exe)
???:?:?: 0x100bbc8 in ??? (exe)
???:?:?: 0x100bbb8 in ??? (exe)
???:?:?: 0x100bb93 in ??? (exe)
???:?:?: 0x100ba41 in ??? (exe)

In comparison, here's what Rust gives with strip=debuginfo:

thread 'main' panicked at ./main.rs:3:5:
attempt to multiply with overflow
stack backtrace:
   0: rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::panicking::panic
   3: main::foo
   4: main::bar
   5: main::main

I think 3) is what I want big-picture wise, but a few details prevent it from being actually useful:

  • having names, and not just addresses, would be great.
  • it would be great to have line number information for the root failure. I think we can get that for asserts, by providing our own assert using @src(), but that's also important for things like arithmertic overflows
  • The build.zig incantaiton with separate ObjCopy invocation to get the desired behavior is gnarly. I'd love to just module.strip = .strip_debuginfo_keep_symbols. See the repo linked above for build.zig.

Metadata

Metadata

Assignees

No one assigned

    Labels

    debug-infoDebug information of binary generated by Zig is not as expected.enhancementSolving this issue will likely involve adding new logic or components to the codebase.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions