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+
13118size_t
14119sentry__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