feat: server-side symbolication of frames #3

Merged
Breadway merged 2 commits from feature/symbolication into main 2026-10-11 20:15:46 +08:00
Owner

Closes BUG-4

Stacked on #2 (fingerprint). Part of ECO-EP1. Depends on the release pipeline publishing symbols (ECO-67) to be useful in production.

What

  • symbolicate.rs: resolves frames that carry build_id + module-relative offset but no symbol, against <symbol_dir>/<xx>/<build-id>.debug (BREADBUG_SYMBOL_DIR, default <data>/symbols), using addr2line / gimli / object. Function (demangled), file and line.
  • Falls back to the ELF symbol table only for an address inside a sized function symbol; otherwise it is unresolved rather than a confident wrong nearest-symbol answer.
  • Defensive: build-ids must be lowercase hex before becoming path components (traversal impossible), size-capped files, memory-safe parsers only, parser panics caught, build-host paths cut to three components so usernames in CI paths never reach storage.
  • Only the top 24 frames per stack are resolved (deeper frames cannot change the fingerprint).
  • Resolved symbols are stored in the report copy and feed fingerprinting, so a stripped client and a client that already had symbols land in the same cluster.
  • Missing symbols are recorded per build-id (migration 3: count, first/last seen) so gaps in the symbol store are visible in triage.

Tests

  • 9 unit tests, including a real binary compiled with rustc -g and a GNU build-id: function, file and line resolve; already-symbolised frames untouched; missing symbols reported; hostile build-ids never touch the filesystem; corrupt or directory "symbol files" do not panic; unmapped addresses stay unresolved; top-frame cap.
  • 3 HTTP integration tests: stripped report is symbolicated and clusters with a client-symbolised one; missing symbols recorded and the report still stored; hostile build-ids accepted as data but never looked up.
  • clippy -D warnings clean.

Notes

  • Offsets are module-relative virtual addresses (what dladdr arithmetic gives for a PIE binary). The client side that fills offset is BREAD-16/17.
  • Symbol files come from our own CI but are still treated as untrusted input.
Closes BUG-4 Stacked on #2 (fingerprint). Part of ECO-EP1. Depends on the release pipeline publishing symbols (ECO-67) to be useful in production. ## What - `symbolicate.rs`: resolves frames that carry `build_id` + module-relative `offset` but no symbol, against `<symbol_dir>/<xx>/<build-id>.debug` (`BREADBUG_SYMBOL_DIR`, default `<data>/symbols`), using addr2line / gimli / object. Function (demangled), file and line. - Falls back to the ELF symbol table only for an address inside a sized function symbol; otherwise it is unresolved rather than a confident wrong nearest-symbol answer. - Defensive: build-ids must be lowercase hex before becoming path components (traversal impossible), size-capped files, memory-safe parsers only, parser panics caught, build-host paths cut to three components so usernames in CI paths never reach storage. - Only the top 24 frames per stack are resolved (deeper frames cannot change the fingerprint). - Resolved symbols are stored in the report copy and feed fingerprinting, so a stripped client and a client that already had symbols land in the same cluster. - Missing symbols are recorded per build-id (migration 3: count, first/last seen) so gaps in the symbol store are visible in triage. ## Tests - 9 unit tests, including a real binary compiled with `rustc -g` and a GNU build-id: function, file and line resolve; already-symbolised frames untouched; missing symbols reported; hostile build-ids never touch the filesystem; corrupt or directory "symbol files" do not panic; unmapped addresses stay unresolved; top-frame cap. - 3 HTTP integration tests: stripped report is symbolicated and clusters with a client-symbolised one; missing symbols recorded and the report still stored; hostile build-ids accepted as data but never looked up. - clippy `-D warnings` clean. ## Notes - Offsets are module-relative virtual addresses (what `dladdr` arithmetic gives for a PIE binary). The client side that fills `offset` is BREAD-16/17. - Symbol files come from our own CI but are still treated as untrusted input.
feat: server-side symbolication of frames
All checks were successful
check / check (push) Successful in 51s
fc1efbbdd2
Frames with a build-id and module-relative offset but no symbol are resolved
against the release symbol store (<dir>/<xx>/<build-id>.debug) to function,
file and line using addr2line/gimli/object. Build-ids are validated as
lowercase hex before becoming path components, symbol files are size
capped, parser panics are caught, an address outside any sized symbol is
unresolved rather than guessed, and build-host paths are cut to three
components. Missing symbols are recorded per build-id so gaps in the symbol
store are visible. Only the top frames of each stack are resolved.

Refs BUG-4
Breadway changed target branch from feature/fingerprint to main 2026-10-11 19:47:32 +08:00
Breadway force-pushed feature/symbolication from fc1efbbdd2
All checks were successful
check / check (push) Successful in 51s
to 5684d956c0
All checks were successful
check / check (push) Successful in 54s
2026-10-11 19:55:21 +08:00
Compare
Breadway deleted branch feature/symbolication 2026-10-11 20:15:46 +08:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Breadway/breadbug-server!3
No description provided.