Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using libunwind for mac, since backtrace do not expect thread context… #1088

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions src/unwinder/sentry_unwinder_libbacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,115 @@
# define HAS_EXECINFO_H
#endif

#if defined(SENTRY_PLATFORM_MACOS) && defined(MAC_OS_X_VERSION_10_6)
# define HAS_LIBUNWIND
#endif

#ifdef HAS_EXECINFO_H
# include <execinfo.h>
#endif

#ifdef HAS_LIBUNWIND
# include <libunwind.h>

# define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])

static size_t
sentry__unwind_stack_libbacktrace_libnuwind(
const sentry_ucontext_t *uctx, void **ptrs, size_t max_frames)
{
unw_context_t ctx;
if (unw_getcontext(&ctx))
return 0;

unw_cursor_t cursor;
if (unw_init_local(&cursor, &ctx))
return 0;

# if defined(__x86_64__)
if (unw_set_reg(&cursor, UNW_X86_64_RAX,
uctx->user_context->uc_mcontext->__ss.__rax)
|| unw_set_reg(&cursor, UNW_X86_64_RDX,
uctx->user_context->uc_mcontext->__ss.__rdx)
|| unw_set_reg(&cursor, UNW_X86_64_RCX,
uctx->user_context->uc_mcontext->__ss.__rcx)
|| unw_set_reg(&cursor, UNW_X86_64_RBX,
uctx->user_context->uc_mcontext->__ss.__rbx)
|| unw_set_reg(&cursor, UNW_X86_64_RSI,
uctx->user_context->uc_mcontext->__ss.__rsi)
|| unw_set_reg(&cursor, UNW_X86_64_RDI,
uctx->user_context->uc_mcontext->__ss.__rdi)
|| unw_set_reg(&cursor, UNW_X86_64_RBP,
uctx->user_context->uc_mcontext->__ss.__rbp)
|| unw_set_reg(&cursor, UNW_X86_64_RSP,
uctx->user_context->uc_mcontext->__ss.__rsp)
|| unw_set_reg(
&cursor, UNW_X86_64_R8, uctx->user_context->uc_mcontext->__ss.__r8)
|| unw_set_reg(
&cursor, UNW_X86_64_R9, uctx->user_context->uc_mcontext->__ss.__r9)
|| unw_set_reg(&cursor, UNW_X86_64_R10,
uctx->user_context->uc_mcontext->__ss.__r10)
|| unw_set_reg(&cursor, UNW_X86_64_R11,
uctx->user_context->uc_mcontext->__ss.__r11)
|| unw_set_reg(&cursor, UNW_X86_64_R12,
uctx->user_context->uc_mcontext->__ss.__r12)
|| unw_set_reg(&cursor, UNW_X86_64_R13,
uctx->user_context->uc_mcontext->__ss.__r13)
|| unw_set_reg(&cursor, UNW_X86_64_R14,
uctx->user_context->uc_mcontext->__ss.__r14)
|| unw_set_reg(&cursor, UNW_X86_64_R15,
uctx->user_context->uc_mcontext->__ss.__r15)
|| unw_set_reg(
&cursor, UNW_REG_IP, uctx->user_context->uc_mcontext->__ss.__rip))
return 0;

# elif defined(__arm64__)
for (size_t i = 0;
i < ARRAY_SIZE(uctx->user_context->uc_mcontext->__ss.__x); ++i) {
if (unw_set_reg(&cursor, UNW_AARCH64_X0 + i,
uctx->user_context->uc_mcontext->__ss.__x[i])) {
return 0;
}
}

if (unw_set_reg(
&cursor, UNW_AARCH64_FP, uctx->user_context->uc_mcontext->__ss.__fp)
|| unw_set_reg(
&cursor, UNW_AARCH64_LR, uctx->user_context->uc_mcontext->__ss.__lr)
|| unw_set_reg(
&cursor, UNW_AARCH64_SP, uctx->user_context->uc_mcontext->__ss.__sp)
|| unw_set_reg(
&cursor, UNW_REG_IP, uctx->user_context->uc_mcontext->__ss.__pc))
return 0;

# endif

size_t n = 0;
for (int err = 1; err >= 0 && n < max_frames; err = unw_step(&cursor)) {
unw_word_t ip;
if (unw_get_reg(&cursor, UNW_REG_IP, &ip)) {
break;
}

# if defined(__arm64__)
// Strip pointer authentication, for some reason ptrauth_strip() not
// working
// https://developer.apple.com/documentation/security/preparing_your_app_to_work_with_pointer_authentication
ip &= 0x7fffffffffffull;
# endif

ptrs[n++] = (void *)ip;

// last frame
if (err == 0) {
break;
}
}

return n;
}
#endif

size_t
sentry__unwind_stack_libbacktrace(
void *addr, const sentry_ucontext_t *uctx, void **ptrs, size_t max_frames)
Expand All @@ -23,7 +128,12 @@ sentry__unwind_stack_libbacktrace(
#endif
return 0;
} else if (uctx) {
#ifdef HAS_LIBUNWIND
return sentry__unwind_stack_libbacktrace_libnuwind(
uctx, ptrs, max_frames);
#else
return 0;
#endif
}
#ifdef HAS_EXECINFO_H
return (size_t)backtrace(ptrs, (int)max_frames);
Expand Down
Loading