chore(sentry): pin sentry-native 0.16.5, and the crash daemon walks ARM32 frame chains - #64
Merged
Merged
Conversation
…RM32 frame chains
The pin moves 0.13.9 → 0.16.5. Two things this repo hand-wrote against 0.13.9 are
upstream now and leave the patch: the non-regular-file guard when reading
/proc/<pid>/maps entries as ELF (sentry__elf_open), and the ptrace snapshot of
the other threads — #1747's per-thread remote libunwind unwinding replaces it
with DWARF frames and symbol names. Also gone: previous-handler chaining and the
flush_scope fields (release, dist, environment, sdk, event_id), which upstream
fills. The patch shrinks from 600 lines to what upstream does not do.
What it still does, and why:
- process_vm_readv wrapper for glibc 2.12 (also needed by the daemon now).
- ARM32 registers in the event, and a frame-pointer walk that reads BOTH
ARM32 frame records. GCC's `push {..,fp,lr}; add fp,sp,#N` leaves fp on the
LR slot ([fp-4] saved fp, [fp] return); rustc/LLVM leaves it on the saved-fp
slot ([fp] saved fp, [fp+4] return). The old patch hard-coded the GCC shape,
so a crash in Rust — nearly every crash — walked one frame and reported a
saved fp as a return address. Candidates are judged against the crashed
process's mappings, recorded with permission bits while maps is parsed:
return address in an executable, non-writable mapping; saved fp above the
current frame in a writable one. Fail closed when the mapping snapshot is
incomplete or differs on a second read after the stack copy. Both halves
are upstream PRs (getsentry/sentry-native#2052, #2053) and drop out of the
patch once a pinned release contains them.
- Pointer-width stack reads with a subtraction range check.
- 32-frame cap for non-crashed threads (the 256 KiB record ceiling), the 30 s
handler budget, and the two webOS-only signal-handler escapes.
libsentry and our C are built with -funwind-tables so the remote unwinder gets
through them (it stopped at threadpool_thread before).
Device-verified on the debug install: SIGSEGV and SIGABRT → envelope → import
(queued=1 rejected=0, native_wins=1) → flushed → visible in the Sentry project
with sdk.version 0.16.5; crashed thread `crash_on_purpose ← plex_run ←
__libc_start_main`; a GCC-built noinline chain `leaf ← f2 ← f1 ←
__libc_start_main`. fwcompat matrix unchanged (OK 4.4.2→11.2.0); both binaries
still need only GLIBC_2.12.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Approval recommended
The version pin, patch adjustments, build flags, and accompanying docs/tests are consistent and appear internally coherent for the intended webOS ARM32 crash-walk behavior.
Pull request overview
This PR updates the vendored Sentry Native crash handler integration to a pinned sentry-native 0.16.5 release, reducing the downstream webOS/ARM32 patch surface by dropping functionality that has moved upstream and keeping only the remaining webOS/ARM32-specific crash-walk requirements (notably ARM32 frame-chain correctness and glibc 2.12 compatibility).
Changes:
- Pin sentry-native to 0.16.5 in the build script and update the downstream
webos-arm32.patchaccordingly. - Improve ARM32 crash-walk reliability: pointer-width stack reads, dual frame-record shape support, mapping-snapshot verification, and a longer handler wait budget for cold crashes.
- Align build flags and documentation/examples with the new pinned version and unwinding requirements.
File summaries
| File | Description |
|---|---|
| vendor/sentry-native/webos-arm32.patch | Updates the downstream webOS/ARM32 patch for sentry-native 0.16.5, keeping only non-upstreamed webOS/ARM32 crash-walk behavior and compatibility shims. |
| rust-modules/src/telemetry/native.rs | Updates the representative native event/schema preview and tests to report sdk.version 0.16.5. |
| Makefile | Adds -funwind-tables to C compilation flags to support remote DWARF unwinding paths. |
| docs/agent-reference.md | Updates the crash-forensics architecture notes to reflect the new upstream/unpatched behavior and the 0.16.5 pin. |
| ci/build-sentry-native.sh | Pins the build to 0.16.5, updates SHA256, and sets explicit C flags for unwind tables + frame pointers in the cross build. |
| .agents/skills/crash-triage/SKILL.md | Updates the crash triage skill text to match the new crash-daemon unwinding behavior and limits. |
Review details
- Files reviewed: 5/6 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The pin moves 0.13.9 → 0.16.5. Two things this repo hand-wrote against 0.13.9 are
upstream now and leave the patch: the non-regular-file guard when reading
/proc//maps entries as ELF (sentry__elf_open), and the ptrace snapshot of
the other threads — #1747's per-thread remote libunwind unwinding replaces it
with DWARF frames and symbol names. Also gone: previous-handler chaining and the
flush_scope fields (release, dist, environment, sdk, event_id), which upstream
fills. The patch shrinks from 600 lines to what upstream does not do.
What it still does, and why:
ARM32 frame records. GCC's
push {..,fp,lr}; add fp,sp,#Nleaves fp on theLR slot ([fp-4] saved fp, [fp] return); rustc/LLVM leaves it on the saved-fp
slot ([fp] saved fp, [fp+4] return). The old patch hard-coded the GCC shape,
so a crash in Rust — nearly every crash — walked one frame and reported a
saved fp as a return address. Candidates are judged against the crashed
process's mappings, recorded with permission bits while maps is parsed:
return address in an executable, non-writable mapping; saved fp above the
current frame in a writable one. Fail closed when the mapping snapshot is
incomplete or differs on a second read after the stack copy. Both halves
are upstream PRs (fix(native): read frame records at pointer width in the crash daemon's FP walk getsentry/sentry-native#2052, #2053) and drop out of the
patch once a pinned release contains them.
handler budget, and the two webOS-only signal-handler escapes.
libsentry and our C are built with -funwind-tables so the remote unwinder gets
through them (it stopped at threadpool_thread before).
Device-verified on the debug install: SIGSEGV and SIGABRT → envelope → import
(queued=1 rejected=0, native_wins=1) → flushed → visible in the Sentry project
with sdk.version 0.16.5; crashed thread
crash_on_purpose ← plex_run ← __libc_start_main; a GCC-built noinline chainleaf ← f2 ← f1 ← __libc_start_main. fwcompat matrix unchanged (OK 4.4.2→11.2.0); both binariesstill need only GLIBC_2.12.
🤖 Generated with Claude Code