1349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric // 8349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 9349cc55cSDimitry Andric 10349cc55cSDimitry Andric #ifndef LIBUNWIND_CET_UNWIND_H 11349cc55cSDimitry Andric #define LIBUNWIND_CET_UNWIND_H 12349cc55cSDimitry Andric 13349cc55cSDimitry Andric #include "libunwind.h" 14349cc55cSDimitry Andric 15349cc55cSDimitry Andric // Currently, CET is implemented on Linux x86 platforms. 16349cc55cSDimitry Andric #if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__) 17349cc55cSDimitry Andric #define _LIBUNWIND_USE_CET 1 18349cc55cSDimitry Andric #endif 19349cc55cSDimitry Andric 20349cc55cSDimitry Andric #if defined(_LIBUNWIND_USE_CET) 21349cc55cSDimitry Andric #include <cet.h> 22349cc55cSDimitry Andric #include <immintrin.h> 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric #define _LIBUNWIND_POP_CET_SSP(x) \ 25349cc55cSDimitry Andric do { \ 26349cc55cSDimitry Andric unsigned long ssp = _get_ssp(); \ 27349cc55cSDimitry Andric if (ssp != 0) { \ 28349cc55cSDimitry Andric unsigned int tmp = (x); \ 29349cc55cSDimitry Andric while (tmp > 255) { \ 30349cc55cSDimitry Andric _inc_ssp(255); \ 31349cc55cSDimitry Andric tmp -= 255; \ 32349cc55cSDimitry Andric } \ 33349cc55cSDimitry Andric _inc_ssp(tmp); \ 34349cc55cSDimitry Andric } \ 35349cc55cSDimitry Andric } while (0) 36349cc55cSDimitry Andric #endif 37349cc55cSDimitry Andric 38*62987288SDimitry Andric // On AArch64 we use _LIBUNWIND_USE_GCS to indicate that GCS is supported. We 39*62987288SDimitry Andric // need to guard any use of GCS instructions with __chkfeat though, as GCS may 40*62987288SDimitry Andric // not be enabled. 41*62987288SDimitry Andric #if defined(_LIBUNWIND_TARGET_AARCH64) && defined(__ARM_FEATURE_GCS_DEFAULT) 42*62987288SDimitry Andric #include <arm_acle.h> 43*62987288SDimitry Andric 44*62987288SDimitry Andric // We can only use GCS if arm_acle.h defines the GCS intrinsics. 45*62987288SDimitry Andric #ifdef _CHKFEAT_GCS 46*62987288SDimitry Andric #define _LIBUNWIND_USE_GCS 1 47*62987288SDimitry Andric #endif 48*62987288SDimitry Andric 49*62987288SDimitry Andric #define _LIBUNWIND_POP_CET_SSP(x) \ 50*62987288SDimitry Andric do { \ 51*62987288SDimitry Andric if (__chkfeat(_CHKFEAT_GCS)) { \ 52*62987288SDimitry Andric unsigned tmp = (x); \ 53*62987288SDimitry Andric while (tmp--) \ 54*62987288SDimitry Andric __gcspopm(); \ 55*62987288SDimitry Andric } \ 56*62987288SDimitry Andric } while (0) 57*62987288SDimitry Andric 58*62987288SDimitry Andric #endif 59*62987288SDimitry Andric 60349cc55cSDimitry Andric extern void *__libunwind_cet_get_registers(unw_cursor_t *); 6181ad6265SDimitry Andric extern void *__libunwind_cet_get_jump_target(void); 62349cc55cSDimitry Andric 63349cc55cSDimitry Andric #endif 64