Skip to content

feat(native): add remote DWARF unwinding + symbol names for Linux#1747

Open
jpnurmi wants to merge 14 commits into
masterfrom
jpnurmi/feat/native/libunwind-remote
Open

feat(native): add remote DWARF unwinding + symbol names for Linux#1747
jpnurmi wants to merge 14 commits into
masterfrom
jpnurmi/feat/native/libunwind-remote

Conversation

@jpnurmi
Copy link
Copy Markdown
Collaborator

@jpnurmi jpnurmi commented May 22, 2026

Add libunwind remote unwinding support to the native backend's crash daemon, enabling DWARF-based stack walking and symbol name resolution for all threads (not just the crashing thread) on Linux.

  • Re-add upstream libunwind src/ptrace/ (_UPT_* accessors)
  • Add unwind_remote CMake target with G-prefix + ptrace sources, only built when SENTRY_BACKEND=native on Linux
  • New sentry_remote_unwind.c using unw_init_remote() + unw_get_proc_name()
  • Integrate into daemon's build_stacktrace_for_thread() with fallback to pre-captured backtrace and FP-walking
Before After
before after

See also:

Add libunwind remote unwinding support to the native backend's crash
daemon, enabling DWARF-based stack walking and symbol name resolution
for all threads (not just the crashing thread) on Linux.

- Re-add upstream libunwind src/ptrace/ (_UPT_* accessors)
- Add `unwind_remote` CMake target with G-prefix + ptrace sources,
  only built when SENTRY_BACKEND=native on Linux
- New sentry_remote_unwind.c using unw_init_remote() + unw_get_proc_name()
- Integrate into daemon's build_stacktrace_for_thread() with fallback
  to pre-captured backtrace and FP-walking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread src/backends/native/sentry_crash_daemon.c Outdated
Comment thread src/backends/native/sentry_crash_daemon.c Outdated
Comment thread src/backends/native/sentry_crash_daemon.c Outdated
Comment thread src/backends/native/sentry_crash_daemon.c
jpnurmi added 2 commits May 25, 2026 09:34
Only free the captured stack buffer once a remote-unwind stacktrace is
actually returned. If remote unwinding yields frames but all are filtered,
the fallback stacktrace paths still need to own and clean up the buffer.
Avoid reserving the remote unwind frame buffer on the daemon stack. If the
allocation fails, remote unwinding is skipped and the existing fallback
stacktrace paths continue to run.
Comment thread src/backends/native/sentry_crash_daemon.c
Comment thread src/backends/native/sentry_crash_daemon.c
jpnurmi added 4 commits May 25, 2026 11:05
Move the Linux remote libunwind implementation under src/unwinder and route it
through sentry_unwinder.c, matching the existing local unwinder backend
selection pattern.

Expose a backend-neutral sentry__unwind_stack_from_thread() entry point for the
daemon while keeping the libunwind-specific implementation private to the
backend file.
Skip remote thread unwinding for the crashed Linux thread when the signal
handler already captured a backtrace. This keeps the signal-frame-aware
ucontext unwind as the primary stacktrace and avoids replacing it with a
potentially partial remote unwind from the handler wait state.

Make sentry_unwinder.h self-contained now that sentry_unwinder.c includes it
for remote unwinder dispatch.
Comment thread src/unwinder/sentry_unwinder_libunwind_remote.c
Document that frame trust tracks the unwind source rather than the emitted
frame index, so filtered initial frames do not cause subsequent CFI frames to
be labeled as context frames.
Comment thread src/unwinder/sentry_unwinder_libunwind_remote.c
jpnurmi added 4 commits May 25, 2026 12:09
Skip daemon-side ptrace unwinding for the crashed Linux thread so
PTRACE_DETACH cannot resume it while crash processing is still running.
The crashed thread continues to use the saved fault context and any
pre-captured backtrace.
After attaching to a thread, require waitpid() to report a stopped
tracee before entering libunwind's remote unwinder. This avoids calling
unw_init_remote() when the attach/wait race reports a non-stopped thread.
Add the arm32 generic libunwind sources and target definitions to the
vendored unwind_remote target so daemon-side remote unwinding is built
consistently with the local arm32 unwinder.
The regular sentry target compiles the Linux thread-unwind dispatcher
without the daemon-only remote unwinder backend enabled. Mark the
dispatcher arguments as intentionally unused so Clang -Werror builds do
not fail in that configuration.
Comment thread src/backends/native/sentry_crash_daemon.c Outdated
Non-crashed Linux threads discovered by the daemon only have a TID and a
zero-filled ucontext. Do not attach a registers object to successfully
remote-unwound stacktraces for those threads.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 95db646. Configure here.

Comment thread src/backends/native/sentry_crash_daemon.c
Capture register values from the initial libunwind cursor for remote
Linux stack walking and attach them to the produced stacktrace.

Keep the remote thread unwinder API aligned with sentry_unwind_stack by
returning the frame count directly, with registers passed as optional
side metadata.
@jpnurmi jpnurmi changed the title wip(native): add remote DWARF unwinding + symbol names for Linux feat(native): add remote DWARF unwinding + symbol names for Linux May 25, 2026
@github-actions
Copy link
Copy Markdown

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 4cf3b68

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant