Skip to content

Commit 5a591e0

Browse files
committed
Using libunwind for mac, since backtrace do not expect thread context (i.e. working just with current thread)
1 parent 4e61614 commit 5a591e0

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

src/unwinder/sentry_unwinder_libbacktrace.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,97 @@
66
# define HAS_EXECINFO_H
77
#endif
88

9+
#if defined(SENTRY_PLATFORM_MACOS) && defined(MAC_OS_X_VERSION_10_6)
10+
# define HAS_LIBUNWIND
11+
#endif
12+
913
#ifdef HAS_EXECINFO_H
1014
# include <execinfo.h>
1115
#endif
1216

17+
#ifdef HAS_LIBUNWIND
18+
# include <libunwind.h>
19+
20+
#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0])
21+
22+
static size_t sentry__unwind_stack_libbacktrace_libnuwind(const sentry_ucontext_t *uctx, void **ptrs, size_t max_frames)
23+
{
24+
unw_context_t ctx;
25+
if (unw_getcontext(&ctx))
26+
return 0;
27+
28+
unw_cursor_t cursor;
29+
if (unw_init_local(&cursor, &ctx))
30+
return 0;
31+
32+
#if defined(__x86_64__)
33+
if (unw_set_reg(&cursor, UNW_X86_64_RAX, uctx->user_context->uc_mcontext->__ss.__rax) ||
34+
unw_set_reg(&cursor, UNW_X86_64_RDX, uctx->user_context->uc_mcontext->__ss.__rdx) ||
35+
unw_set_reg(&cursor, UNW_X86_64_RCX, uctx->user_context->uc_mcontext->__ss.__rcx) ||
36+
unw_set_reg(&cursor, UNW_X86_64_RBX, uctx->user_context->uc_mcontext->__ss.__rbx) ||
37+
unw_set_reg(&cursor, UNW_X86_64_RSI, uctx->user_context->uc_mcontext->__ss.__rsi) ||
38+
unw_set_reg(&cursor, UNW_X86_64_RDI, uctx->user_context->uc_mcontext->__ss.__rdi) ||
39+
unw_set_reg(&cursor, UNW_X86_64_RBP, uctx->user_context->uc_mcontext->__ss.__rbp) ||
40+
unw_set_reg(&cursor, UNW_X86_64_RSP, uctx->user_context->uc_mcontext->__ss.__rsp) ||
41+
unw_set_reg(&cursor, UNW_X86_64_R8, uctx->user_context->uc_mcontext->__ss.__r8) ||
42+
unw_set_reg(&cursor, UNW_X86_64_R9, uctx->user_context->uc_mcontext->__ss.__r9) ||
43+
unw_set_reg(&cursor, UNW_X86_64_R10, uctx->user_context->uc_mcontext->__ss.__r10) ||
44+
unw_set_reg(&cursor, UNW_X86_64_R11, uctx->user_context->uc_mcontext->__ss.__r11) ||
45+
unw_set_reg(&cursor, UNW_X86_64_R12, uctx->user_context->uc_mcontext->__ss.__r12) ||
46+
unw_set_reg(&cursor, UNW_X86_64_R13, uctx->user_context->uc_mcontext->__ss.__r13) ||
47+
unw_set_reg(&cursor, UNW_X86_64_R14, uctx->user_context->uc_mcontext->__ss.__r14) ||
48+
unw_set_reg(&cursor, UNW_X86_64_R15, uctx->user_context->uc_mcontext->__ss.__r15) ||
49+
unw_set_reg(&cursor, UNW_REG_IP, uctx->user_context->uc_mcontext->__ss.__rip)
50+
)
51+
return 0;
52+
53+
#elif defined(__arm64__)
54+
for(size_t i = 0; i < ARRAY_SIZE(uctx->user_context->uc_mcontext->__ss.__x); ++i)
55+
{
56+
if (unw_set_reg(&cursor, UNW_AARCH64_X0 + i, uctx->user_context->uc_mcontext->__ss.__x[i]))
57+
{
58+
return 0;
59+
}
60+
}
61+
62+
if (unw_set_reg(&cursor, UNW_AARCH64_FP, uctx->user_context->uc_mcontext->__ss.__fp) ||
63+
unw_set_reg(&cursor, UNW_AARCH64_LR, uctx->user_context->uc_mcontext->__ss.__lr) ||
64+
unw_set_reg(&cursor, UNW_AARCH64_SP, uctx->user_context->uc_mcontext->__ss.__sp) ||
65+
unw_set_reg(&cursor, UNW_REG_IP, uctx->user_context->uc_mcontext->__ss.__pc)
66+
)
67+
return 0;
68+
69+
#endif
70+
71+
size_t n = 0;
72+
for(int err = 1; err >= 0 && n < max_frames; err = unw_step(&cursor))
73+
{
74+
unw_word_t ip;
75+
if (unw_get_reg(&cursor, UNW_REG_IP, &ip))
76+
{
77+
break;
78+
}
79+
80+
#if defined(__arm64__)
81+
// Strip pointer authentication, for some reason ptrauth_strip() not working
82+
// https://developer.apple.com/documentation/security/preparing_your_app_to_work_with_pointer_authentication
83+
ip &= 0x7fffffffffffull;
84+
#endif
85+
86+
ptrs[n++] = (void *)ip;
87+
88+
// last frame
89+
if (err == 0)
90+
{
91+
break;
92+
}
93+
}
94+
95+
return n;
96+
}
97+
#endif
98+
99+
13100
size_t
14101
sentry__unwind_stack_libbacktrace(
15102
void *addr, const sentry_ucontext_t *uctx, void **ptrs, size_t max_frames)
@@ -23,7 +110,11 @@ sentry__unwind_stack_libbacktrace(
23110
#endif
24111
return 0;
25112
} else if (uctx) {
113+
#ifdef HAS_LIBUNWIND
114+
return sentry__unwind_stack_libbacktrace_libnuwind(uctx, ptrs, max_frames);
115+
#else
26116
return 0;
117+
#endif
27118
}
28119
#ifdef HAS_EXECINFO_H
29120
return (size_t)backtrace(ptrs, (int)max_frames);

0 commit comments

Comments
 (0)