Skip to content

Commit c5f6535

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 c5f6535

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

src/unwinder/sentry_unwinder_libbacktrace.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,115 @@
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
23+
sentry__unwind_stack_libbacktrace_libnuwind(
24+
const sentry_ucontext_t *uctx, void **ptrs, size_t max_frames)
25+
{
26+
unw_context_t ctx;
27+
if (unw_getcontext(&ctx))
28+
return 0;
29+
30+
unw_cursor_t cursor;
31+
if (unw_init_local(&cursor, &ctx))
32+
return 0;
33+
34+
# if defined(__x86_64__)
35+
if (unw_set_reg(&cursor, UNW_X86_64_RAX,
36+
uctx->user_context->uc_mcontext->__ss.__rax)
37+
|| unw_set_reg(&cursor, UNW_X86_64_RDX,
38+
uctx->user_context->uc_mcontext->__ss.__rdx)
39+
|| unw_set_reg(&cursor, UNW_X86_64_RCX,
40+
uctx->user_context->uc_mcontext->__ss.__rcx)
41+
|| unw_set_reg(&cursor, UNW_X86_64_RBX,
42+
uctx->user_context->uc_mcontext->__ss.__rbx)
43+
|| unw_set_reg(&cursor, UNW_X86_64_RSI,
44+
uctx->user_context->uc_mcontext->__ss.__rsi)
45+
|| unw_set_reg(&cursor, UNW_X86_64_RDI,
46+
uctx->user_context->uc_mcontext->__ss.__rdi)
47+
|| unw_set_reg(&cursor, UNW_X86_64_RBP,
48+
uctx->user_context->uc_mcontext->__ss.__rbp)
49+
|| unw_set_reg(&cursor, UNW_X86_64_RSP,
50+
uctx->user_context->uc_mcontext->__ss.__rsp)
51+
|| unw_set_reg(
52+
&cursor, UNW_X86_64_R8, uctx->user_context->uc_mcontext->__ss.__r8)
53+
|| unw_set_reg(
54+
&cursor, UNW_X86_64_R9, uctx->user_context->uc_mcontext->__ss.__r9)
55+
|| unw_set_reg(&cursor, UNW_X86_64_R10,
56+
uctx->user_context->uc_mcontext->__ss.__r10)
57+
|| unw_set_reg(&cursor, UNW_X86_64_R11,
58+
uctx->user_context->uc_mcontext->__ss.__r11)
59+
|| unw_set_reg(&cursor, UNW_X86_64_R12,
60+
uctx->user_context->uc_mcontext->__ss.__r12)
61+
|| unw_set_reg(&cursor, UNW_X86_64_R13,
62+
uctx->user_context->uc_mcontext->__ss.__r13)
63+
|| unw_set_reg(&cursor, UNW_X86_64_R14,
64+
uctx->user_context->uc_mcontext->__ss.__r14)
65+
|| unw_set_reg(&cursor, UNW_X86_64_R15,
66+
uctx->user_context->uc_mcontext->__ss.__r15)
67+
|| unw_set_reg(
68+
&cursor, UNW_REG_IP, uctx->user_context->uc_mcontext->__ss.__rip))
69+
return 0;
70+
71+
# elif defined(__arm64__)
72+
for (size_t i = 0;
73+
i < ARRAY_SIZE(uctx->user_context->uc_mcontext->__ss.__x); ++i) {
74+
if (unw_set_reg(&cursor, UNW_AARCH64_X0 + i,
75+
uctx->user_context->uc_mcontext->__ss.__x[i])) {
76+
return 0;
77+
}
78+
}
79+
80+
if (unw_set_reg(
81+
&cursor, UNW_AARCH64_FP, uctx->user_context->uc_mcontext->__ss.__fp)
82+
|| unw_set_reg(
83+
&cursor, UNW_AARCH64_LR, uctx->user_context->uc_mcontext->__ss.__lr)
84+
|| unw_set_reg(
85+
&cursor, UNW_AARCH64_SP, uctx->user_context->uc_mcontext->__ss.__sp)
86+
|| unw_set_reg(
87+
&cursor, UNW_REG_IP, uctx->user_context->uc_mcontext->__ss.__pc))
88+
return 0;
89+
90+
# endif
91+
92+
size_t n = 0;
93+
for (int err = 1; err >= 0 && n < max_frames; err = unw_step(&cursor)) {
94+
unw_word_t ip;
95+
if (unw_get_reg(&cursor, UNW_REG_IP, &ip)) {
96+
break;
97+
}
98+
99+
# if defined(__arm64__)
100+
// Strip pointer authentication, for some reason ptrauth_strip() not
101+
// working
102+
// https://developer.apple.com/documentation/security/preparing_your_app_to_work_with_pointer_authentication
103+
ip &= 0x7fffffffffffull;
104+
# endif
105+
106+
ptrs[n++] = (void *)ip;
107+
108+
// last frame
109+
if (err == 0) {
110+
break;
111+
}
112+
}
113+
114+
return n;
115+
}
116+
#endif
117+
13118
size_t
14119
sentry__unwind_stack_libbacktrace(
15120
void *addr, const sentry_ucontext_t *uctx, void **ptrs, size_t max_frames)
@@ -23,7 +128,12 @@ sentry__unwind_stack_libbacktrace(
23128
#endif
24129
return 0;
25130
} else if (uctx) {
131+
#ifdef HAS_LIBUNWIND
132+
return sentry__unwind_stack_libbacktrace_libnuwind(
133+
uctx, ptrs, max_frames);
134+
#else
26135
return 0;
136+
#endif
27137
}
28138
#ifdef HAS_EXECINFO_H
29139
return (size_t)backtrace(ptrs, (int)max_frames);

0 commit comments

Comments
 (0)