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+
13100size_t
14101sentry__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