31
31
#include "libunwind_ext.h"
32
32
#include "unwind.h"
33
33
34
- #if !defined(_LIBUNWIND_ARM_EHABI ) && !defined(__USING_SJLJ_EXCEPTIONS__ )
34
+ #if !defined(_LIBUNWIND_ARM_EHABI ) && !defined(__USING_SJLJ_EXCEPTIONS__ ) && \
35
+ !defined(__wasm__ )
35
36
36
37
#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
37
38
43
44
// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we
44
45
// directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using
45
46
// a regular function call to avoid pushing to CET shadow stack again.
46
- #if !defined(_LIBUNWIND_USE_CET )
47
+ #if !defined(_LIBUNWIND_USE_CET ) && !defined( _LIBUNWIND_USE_GCS )
47
48
#define __unw_phase2_resume (cursor , fn ) \
48
49
do { \
49
50
(void)fn; \
71
72
__asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \
72
73
"d"(cetJumpAddress)); \
73
74
} while (0)
75
+ #elif defined(_LIBUNWIND_TARGET_AARCH64 )
76
+ #define __cet_ss_step_size 8
77
+ #define __unw_phase2_resume (cursor , fn ) \
78
+ do { \
79
+ _LIBUNWIND_POP_CET_SSP((fn)); \
80
+ void *cetRegContext = __libunwind_cet_get_registers((cursor)); \
81
+ void *cetJumpAddress = __libunwind_cet_get_jump_target(); \
82
+ __asm__ volatile("mov x0, %0\n\t" \
83
+ "br %1\n\t" \
84
+ : \
85
+ : "r"(cetRegContext), "r"(cetJumpAddress) \
86
+ : "x0"); \
87
+ } while (0)
74
88
#endif
75
89
76
90
static _Unwind_Reason_Code
@@ -169,6 +183,10 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
169
183
}
170
184
extern int __unw_step_stage2 (unw_cursor_t * );
171
185
186
+ #if defined(_LIBUNWIND_USE_GCS )
187
+ // Enable the GCS target feature to permit gcspop instructions to be used.
188
+ __attribute__((target ("gcs" )))
189
+ #endif
172
190
static _Unwind_Reason_Code
173
191
unwind_phase2 (unw_context_t * uc , unw_cursor_t * cursor , _Unwind_Exception * exception_object ) {
174
192
__unw_init_local (cursor , uc );
@@ -179,8 +197,12 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
179
197
// uc is initialized by __unw_getcontext in the parent frame. The first stack
180
198
// frame walked is unwind_phase2.
181
199
unsigned framesWalked = 1 ;
182
- #ifdef _LIBUNWIND_USE_CET
200
+ #if defined( _LIBUNWIND_USE_CET )
183
201
unsigned long shadowStackTop = _get_ssp ();
202
+ #elif defined(_LIBUNWIND_USE_GCS )
203
+ unsigned long shadowStackTop = 0 ;
204
+ if (__chkfeat (_CHKFEAT_GCS ))
205
+ shadowStackTop = (unsigned long )__gcspr ();
184
206
#endif
185
207
// Walk each frame until we reach where search phase said to stop.
186
208
while (true) {
@@ -237,7 +259,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
237
259
// against return address stored in CET shadow stack, if the 2 addresses don't
238
260
// match, it means return address in normal stack has been corrupted, we return
239
261
// _URC_FATAL_PHASE2_ERROR.
240
- #ifdef _LIBUNWIND_USE_CET
262
+ #if defined( _LIBUNWIND_USE_CET ) || defined( _LIBUNWIND_USE_GCS )
241
263
if (shadowStackTop != 0 ) {
242
264
unw_word_t retInNormalStack ;
243
265
__unw_get_reg (cursor , UNW_REG_IP , & retInNormalStack );
@@ -305,6 +327,10 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
305
327
return _URC_FATAL_PHASE2_ERROR ;
306
328
}
307
329
330
+ #if defined(_LIBUNWIND_USE_GCS )
331
+ // Enable the GCS target feature to permit gcspop instructions to be used.
332
+ __attribute__((target ("gcs" )))
333
+ #endif
308
334
static _Unwind_Reason_Code
309
335
unwind_phase2_forced (unw_context_t * uc , unw_cursor_t * cursor ,
310
336
_Unwind_Exception * exception_object ,
0 commit comments