xref: /freebsd/contrib/llvm-project/libunwind/src/shadow_stack_unwind.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //
8*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
9*700637cbSDimitry Andric 
10*700637cbSDimitry Andric #ifndef LIBUNWIND_SHADOW_STACK_UNWIND_H
11*700637cbSDimitry Andric #define LIBUNWIND_SHADOW_STACK_UNWIND_H
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "libunwind.h"
14*700637cbSDimitry Andric 
15*700637cbSDimitry Andric // Currently, CET is implemented on Linux x86 platforms.
16*700637cbSDimitry Andric #if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__)
17*700637cbSDimitry Andric #define _LIBUNWIND_USE_CET 1
18*700637cbSDimitry Andric #endif
19*700637cbSDimitry Andric 
20*700637cbSDimitry Andric #if defined(_LIBUNWIND_USE_CET)
21*700637cbSDimitry Andric #include <cet.h>
22*700637cbSDimitry Andric #include <immintrin.h>
23*700637cbSDimitry Andric 
24*700637cbSDimitry Andric #define _LIBUNWIND_POP_SHSTK_SSP(x)                                            \
25*700637cbSDimitry Andric   do {                                                                         \
26*700637cbSDimitry Andric     unsigned long ssp = _get_ssp();                                            \
27*700637cbSDimitry Andric     if (ssp != 0) {                                                            \
28*700637cbSDimitry Andric       unsigned int tmp = (x);                                                  \
29*700637cbSDimitry Andric       while (tmp > 255) {                                                      \
30*700637cbSDimitry Andric         _inc_ssp(255);                                                         \
31*700637cbSDimitry Andric         tmp -= 255;                                                            \
32*700637cbSDimitry Andric       }                                                                        \
33*700637cbSDimitry Andric       _inc_ssp(tmp);                                                           \
34*700637cbSDimitry Andric     }                                                                          \
35*700637cbSDimitry Andric   } while (0)
36*700637cbSDimitry Andric #endif
37*700637cbSDimitry Andric 
38*700637cbSDimitry Andric // On AArch64 we use _LIBUNWIND_USE_GCS to indicate that GCS is supported. We
39*700637cbSDimitry Andric // need to guard any use of GCS instructions with __chkfeat though, as GCS may
40*700637cbSDimitry Andric // not be enabled.
41*700637cbSDimitry Andric #if defined(_LIBUNWIND_TARGET_AARCH64) && defined(__ARM_FEATURE_GCS_DEFAULT)
42*700637cbSDimitry Andric #include <arm_acle.h>
43*700637cbSDimitry Andric 
44*700637cbSDimitry Andric // We can only use GCS if arm_acle.h defines the GCS intrinsics.
45*700637cbSDimitry Andric #ifdef _CHKFEAT_GCS
46*700637cbSDimitry Andric #define _LIBUNWIND_USE_GCS 1
47*700637cbSDimitry Andric #endif
48*700637cbSDimitry Andric 
49*700637cbSDimitry Andric #define _LIBUNWIND_POP_SHSTK_SSP(x)                                            \
50*700637cbSDimitry Andric   do {                                                                         \
51*700637cbSDimitry Andric     if (__chkfeat(_CHKFEAT_GCS)) {                                             \
52*700637cbSDimitry Andric       unsigned tmp = (x);                                                      \
53*700637cbSDimitry Andric       while (tmp--)                                                            \
54*700637cbSDimitry Andric         __gcspopm();                                                           \
55*700637cbSDimitry Andric     }                                                                          \
56*700637cbSDimitry Andric   } while (0)
57*700637cbSDimitry Andric 
58*700637cbSDimitry Andric #endif
59*700637cbSDimitry Andric 
60*700637cbSDimitry Andric extern void *__libunwind_shstk_get_registers(unw_cursor_t *);
61*700637cbSDimitry Andric extern void *__libunwind_shstk_get_jump_target(void);
62*700637cbSDimitry Andric 
63*700637cbSDimitry Andric #endif
64