Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libunwind] Add GCS support for AArch64 #99335

Merged
merged 4 commits into from
Aug 4, 2024

Conversation

john-brawn-arm
Copy link
Collaborator

AArch64 GCS (Guarded Control Stack) is similar enough to CET that we can re-use the existing code that is guarded by _LIBUNWIND_USE_CET, so long as we also add defines to locate the GCS stack and pop the entries from it. We also need the jumpto function to exit using br instead of ret, to prevent it from popping the GCS stack.

GCS support is enabled using the LIBUNWIND_ENABLE_GCS cmake option. This enables -mbranch-protection=standard, which enables GCS. For the places we need to use GCS instructions we use the target attribute, as there's not a command-line option to enable a specific architecture extension.

AArch64 GCS (Guarded Control Stack) is similar enough to CET that we
can re-use the existing code that is guarded by _LIBUNWIND_USE_CET,
so long as we also add defines to locate the GCS stack and pop the
entries from it. We also need the jumpto function to exit using br
instead of ret, to prevent it from popping the GCS stack.

GCS support is enabled using the LIBUNWIND_ENABLE_GCS cmake option.
This enables -mbranch-protection=standard, which enables GCS. For
the places we need to use GCS instructions we use the target
attribute, as there's not a command-line option to enable a specific
architecture extension.
@john-brawn-arm john-brawn-arm requested a review from a team as a code owner July 17, 2024 15:02
@llvmbot
Copy link
Collaborator

llvmbot commented Jul 17, 2024

@llvm/pr-subscribers-libunwind

Author: John Brawn (john-brawn-arm)

Changes

AArch64 GCS (Guarded Control Stack) is similar enough to CET that we can re-use the existing code that is guarded by _LIBUNWIND_USE_CET, so long as we also add defines to locate the GCS stack and pop the entries from it. We also need the jumpto function to exit using br instead of ret, to prevent it from popping the GCS stack.

GCS support is enabled using the LIBUNWIND_ENABLE_GCS cmake option. This enables -mbranch-protection=standard, which enables GCS. For the places we need to use GCS instructions we use the target attribute, as there's not a command-line option to enable a specific architecture extension.


Full diff: https://github.com/llvm/llvm-project/pull/99335.diff

9 Files Affected:

  • (modified) libunwind/CMakeLists.txt (+8)
  • (modified) libunwind/src/Registers.hpp (+7)
  • (modified) libunwind/src/UnwindLevel1.c (+28)
  • (modified) libunwind/src/UnwindRegistersRestore.S (+1-1)
  • (modified) libunwind/src/cet_unwind.h (+19)
  • (modified) libunwind/test/CMakeLists.txt (+1)
  • (modified) libunwind/test/configs/llvm-libunwind-merged.cfg.in (+3)
  • (modified) libunwind/test/configs/llvm-libunwind-shared.cfg.in (+3)
  • (modified) libunwind/test/configs/llvm-libunwind-static.cfg.in (+3)
diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt
index b22ade0a7d71e..28d67b0fef92c 100644
--- a/libunwind/CMakeLists.txt
+++ b/libunwind/CMakeLists.txt
@@ -37,6 +37,7 @@ if (LIBUNWIND_BUILD_32_BITS)
 endif()
 
 option(LIBUNWIND_ENABLE_CET "Build libunwind with CET enabled." OFF)
+option(LIBUNWIND_ENABLE_GCS "Build libunwind with GCS enabled." OFF)
 option(LIBUNWIND_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON)
 option(LIBUNWIND_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
 option(LIBUNWIND_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
@@ -188,6 +189,13 @@ if (LIBUNWIND_ENABLE_CET)
   endif()
 endif()
 
+if (LIBUNWIND_ENABLE_GCS)
+  add_compile_flags_if_supported(-mbranch-protection=standard)
+  if (NOT CXX_SUPPORTS_MBRANCH_PROTECTION_EQ_STANDARD_FLAG)
+    message(SEND_ERROR "Compiler doesn't support GCS -mbranch-protection option!")
+  endif()
+endif()
+
 if (WIN32)
   # The headers lack matching dllexport attributes (_LIBUNWIND_EXPORT);
   # silence the warning instead of cluttering the headers (which aren't
diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp
index d11ddb3426d52..0fc2a683a7fa4 100644
--- a/libunwind/src/Registers.hpp
+++ b/libunwind/src/Registers.hpp
@@ -1815,6 +1815,13 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {
 /// process.
 class _LIBUNWIND_HIDDEN Registers_arm64;
 extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
+
+#if defined(_LIBUNWIND_USE_CET)
+extern "C" void *__libunwind_cet_get_jump_target() {
+  return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto);
+}
+#endif
+
 class _LIBUNWIND_HIDDEN Registers_arm64 {
 public:
   Registers_arm64();
diff --git a/libunwind/src/UnwindLevel1.c b/libunwind/src/UnwindLevel1.c
index 48e7bc3b9e00e..67a324947cbf1 100644
--- a/libunwind/src/UnwindLevel1.c
+++ b/libunwind/src/UnwindLevel1.c
@@ -72,6 +72,19 @@
     __asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext),                  \
                      "d"(cetJumpAddress));                                     \
   } while (0)
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+#define __cet_ss_step_size 8
+#define __unw_phase2_resume(cursor, fn)                                        \
+  do {                                                                         \
+    _LIBUNWIND_POP_CET_SSP((fn));                                              \
+    void *cetRegContext = __libunwind_cet_get_registers((cursor));             \
+    void *cetJumpAddress = __libunwind_cet_get_jump_target();                  \
+    __asm__ volatile("mov x0, %0\n\t"                                          \
+                     "br %1\n\t"                                               \
+                     :                                                         \
+                     : "r"(cetRegContext), "r"(cetJumpAddress)                 \
+                     : "x0");                                                  \
+  } while (0)
 #endif
 
 static _Unwind_Reason_Code
@@ -170,6 +183,10 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
 }
 extern int __unw_step_stage2(unw_cursor_t *);
 
+#if defined(_LIBUNWIND_USE_CET) && defined(_LIBUNWIND_TARGET_AARCH64)
+// Enable the GCS target feature to permit GCS instructions to be used.
+__attribute__((target("gcs")))
+#endif
 static _Unwind_Reason_Code
 unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
   __unw_init_local(cursor, uc);
@@ -181,7 +198,14 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
   // frame walked is unwind_phase2.
   unsigned framesWalked = 1;
 #ifdef _LIBUNWIND_USE_CET
+#if defined(_LIBUNWIND_TARGET_I386) || defined(_LIBUNWIND_TARGET_X86_64)
   unsigned long shadowStackTop = _get_ssp();
+#elif defined(_LIBUNWIND_TARGET_AARCH64)
+  unsigned long shadowStackTop = 0;
+  if (__chkfeat(_CHKFEAT_GCS)) {
+    shadowStackTop = (unsigned long)__gcspr();
+  }
+#endif
 #endif
   // Walk each frame until we reach where search phase said to stop.
   while (true) {
@@ -306,6 +330,10 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
   return _URC_FATAL_PHASE2_ERROR;
 }
 
+#if defined(_LIBUNWIND_USE_CET) && defined(_LIBUNWIND_TARGET_AARCH64)
+// Enable the GCS target feature to permit GCS instructions to be used.
+__attribute__((target("gcs")))
+#endif
 static _Unwind_Reason_Code
 unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
                      _Unwind_Exception *exception_object,
diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S
index 67d9e05711898..e1d6e17549880 100644
--- a/libunwind/src/UnwindRegistersRestore.S
+++ b/libunwind/src/UnwindRegistersRestore.S
@@ -680,7 +680,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
   ldr    x16,     [x0, #0x0F8]
   ldp    x0, x1,  [x0, #0x000]  // restore x0,x1
   mov    sp,x16                 // restore sp
-  ret    x30                    // jump to pc
+  br     x30                    // jump to pc
 
 #elif defined(__arm__) && !defined(__APPLE__)
 
diff --git a/libunwind/src/cet_unwind.h b/libunwind/src/cet_unwind.h
index c364ed3e12feb..404f94551d78e 100644
--- a/libunwind/src/cet_unwind.h
+++ b/libunwind/src/cet_unwind.h
@@ -35,6 +35,25 @@
   } while (0)
 #endif
 
+// On AArch64 we use _LIBUNWIND_USE_CET to indicate that GCS is supported. We
+// need to guard any use of GCS instructions with __chkfeat though, as GCS may
+// not be enabled.
+#if defined(_LIBUNWIND_TARGET_AARCH64) && defined(__ARM_FEATURE_GCS_DEFAULT)
+#define _LIBUNWIND_USE_CET 1
+#include <arm_acle.h>
+
+#define _LIBUNWIND_POP_CET_SSP(x)                                              \
+  do {                                                                         \
+    if (__chkfeat(_CHKFEAT_GCS)) {                                             \
+      unsigned int tmp = (x);                                                  \
+      while (tmp--) {                                                          \
+        __gcspopm();                                                           \
+      }                                                                        \
+    }                                                                          \
+  } while (0)
+
+#endif
+
 extern void *__libunwind_cet_get_registers(unw_cursor_t *);
 extern void *__libunwind_cet_get_jump_target(void);
 
diff --git a/libunwind/test/CMakeLists.txt b/libunwind/test/CMakeLists.txt
index 19f055f6f93ff..c7b1b3d01d8c7 100644
--- a/libunwind/test/CMakeLists.txt
+++ b/libunwind/test/CMakeLists.txt
@@ -9,6 +9,7 @@ macro(pythonize_bool var)
 endmacro()
 
 pythonize_bool(LIBUNWIND_ENABLE_CET)
+pythonize_bool(LIBUNWIND_ENABLE_GCS)
 pythonize_bool(LIBUNWIND_ENABLE_THREADS)
 pythonize_bool(LIBUNWIND_USES_ARM_EHABI)
 
diff --git a/libunwind/test/configs/llvm-libunwind-merged.cfg.in b/libunwind/test/configs/llvm-libunwind-merged.cfg.in
index 38b79840c9fe2..fafe12962b428 100644
--- a/libunwind/test/configs/llvm-libunwind-merged.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-merged.cfg.in
@@ -11,6 +11,9 @@ link_flags = []
 if @LIBUNWIND_ENABLE_CET@:
     compile_flags.append('-fcf-protection=full')
 
+if @LIBUNWIND_ENABLE_GCS@:
+    compile_flags.append('-mbranch-protection=standard')
+
 # On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker.
 if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'):
     link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@')
diff --git a/libunwind/test/configs/llvm-libunwind-shared.cfg.in b/libunwind/test/configs/llvm-libunwind-shared.cfg.in
index 13896aeb13bc4..f3e40928b525d 100644
--- a/libunwind/test/configs/llvm-libunwind-shared.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-shared.cfg.in
@@ -10,6 +10,9 @@ link_flags = []
 if @LIBUNWIND_ENABLE_CET@:
     compile_flags.append('-fcf-protection=full')
 
+if @LIBUNWIND_ENABLE_GCS@:
+    compile_flags.append('-mbranch-protection=standard')
+
 # On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker.
 if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'):
     link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@')
diff --git a/libunwind/test/configs/llvm-libunwind-static.cfg.in b/libunwind/test/configs/llvm-libunwind-static.cfg.in
index 50b64dc665a5a..a3a65ae82591b 100644
--- a/libunwind/test/configs/llvm-libunwind-static.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-static.cfg.in
@@ -13,6 +13,9 @@ if @LIBUNWIND_ENABLE_THREADS@:
 if @LIBUNWIND_ENABLE_CET@:
     compile_flags.append('-fcf-protection=full')
 
+if @LIBUNWIND_ENABLE_GCS@:
+    compile_flags.append('-mbranch-protection=standard')
+
 # On ELF platforms, link tests with -Wl,--export-dynamic if supported by the linker.
 if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'):
     link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@')

Copy link

github-actions bot commented Jul 17, 2024

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff 554febd3aad8d7cea7b8f8f6124d691031fb618c c776eafd1f45fac3b63ae3370cd8dd75b411d289 --extensions h,c,hpp -- libunwind/src/Registers.hpp libunwind/src/UnwindCursor.hpp libunwind/src/UnwindLevel1.c libunwind/src/cet_unwind.h
View the diff from clang-format here.
diff --git a/libunwind/src/UnwindLevel1.c b/libunwind/src/UnwindLevel1.c
index 7e785f4d31..d3755a0e8d 100644
--- a/libunwind/src/UnwindLevel1.c
+++ b/libunwind/src/UnwindLevel1.c
@@ -188,7 +188,8 @@ extern int __unw_step_stage2(unw_cursor_t *);
 __attribute__((target("gcs")))
 #endif
 static _Unwind_Reason_Code
-unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
+unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
+              _Unwind_Exception *exception_object) {
   __unw_init_local(cursor, uc);
 
   _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
@@ -333,8 +334,8 @@ __attribute__((target("gcs")))
 #endif
 static _Unwind_Reason_Code
 unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
-                     _Unwind_Exception *exception_object,
-                     _Unwind_Stop_Fn stop, void *stop_parameter) {
+                     _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,
+                     void *stop_parameter) {
   __unw_init_local(cursor, uc);
 
   // uc is initialized by __unw_getcontext in the parent frame. The first stack
@@ -440,7 +441,6 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
   return _URC_FATAL_PHASE2_ERROR;
 }
 
-
 /// Called by __cxa_throw.  Only returns if there is a fatal error.
 _LIBUNWIND_EXPORT _Unwind_Reason_Code
 _Unwind_RaiseException(_Unwind_Exception *exception_object) {

libunwind/src/cet_unwind.h Outdated Show resolved Hide resolved
libunwind/src/cet_unwind.h Outdated Show resolved Hide resolved
libunwind/src/UnwindLevel1.c Outdated Show resolved Hide resolved
@john-brawn-arm
Copy link
Collaborator Author

Ping

@john-brawn-arm john-brawn-arm added this to the LLVM 19.X Release milestone Aug 2, 2024
@john-brawn-arm
Copy link
Collaborator Author

Sorry to pester you about this, but would it be possible to get this approved in time for LLVM19 RC2 on Monday? This is the last piece of GCS work and it would be nice to have it all in a single LLVM release.

Copy link
Member

@MaskRay MaskRay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Sorry for the delay.

Q: Is there a way to play with the GCS feature in a VM? Do you have setup instructions?

#elif defined(_LIBUNWIND_USE_GCS)
unsigned long shadowStackTop = 0;
if (__chkfeat(_CHKFEAT_GCS)) {
shadowStackTop = (unsigned long)__gcspr();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the brace can be dropped

@@ -170,6 +183,10 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
}
extern int __unw_step_stage2(unw_cursor_t *);

#if defined(_LIBUNWIND_USE_GCS)
// Enable the GCS target feature to permit GCS instructions to be used.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be useful to elaborate what instructions need to use the GCS version.

@tru
Copy link
Collaborator

tru commented Aug 4, 2024

This seems to add a new feature, is it really relevant for a backport?

@john-brawn-arm
Copy link
Collaborator Author

LGTM. Sorry for the delay.

Q: Is there a way to play with the GCS feature in a VM? Do you have setup instructions?

https://git.yoctoproject.org/meta-arm/log/?h=testing/gcs is a demonstration embedded linux that support GCS, including an emulator capable of running it. https://git.yoctoproject.org/meta-arm/tree/meta-arm-gcs/README?h=testing/gcs is the instructions for building and running it.

@john-brawn-arm john-brawn-arm merged commit b32aac4 into llvm:main Aug 4, 2024
7 of 10 checks passed
@john-brawn-arm
Copy link
Collaborator Author

This seems to add a new feature, is it really relevant for a backport?

This is the last piece of work to enable GCS in the LLVM toolchain (clang and lld support went in a while ago), and I was hoping to get everything in to LLVM 19. It would be rather annoying to have this last part slip to LLVM 20.

The way GCS works is that the -mbranch-protection=standard command-line option marks generated objects with the GCS property, and lld then sets the GCS property on the output if all inputs have it, which then indicates to the operating system to enable GCS on that process. Without GCS support in libunwind that means it won't have the GCS property so anything that links with libunwind will have GCS disabled.

Though having said all this, I marked this for LLVM 19 as my reading of https://discourse.llvm.org/t/update-on-llvm-19-x-releases/80511 was that new features are still ok before RC2, but re-reading it it's a bit ambiguous: it says "New features will have to wait until LLVM 20 at this point" and my reading of that was that "this point" means RC2, so new features before RC2 is fine, but if "this point" meant "right now" that means new features aren't OK. If that's the case the it's reasonable for this to not go in RC2.

@john-brawn-arm
Copy link
Collaborator Author

/cherry-pick b32aac4

llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Aug 4, 2024
AArch64 GCS (Guarded Control Stack) is similar enough to CET that we can
re-use the existing code that is guarded by _LIBUNWIND_USE_CET, so long
as we also add defines to locate the GCS stack and pop the entries from
it. We also need the jumpto function to exit using br instead of ret, to
prevent it from popping the GCS stack.

GCS support is enabled using the LIBUNWIND_ENABLE_GCS cmake option. This
enables -mbranch-protection=standard, which enables GCS. For the places
we need to use GCS instructions we use the target attribute, as there's
not a command-line option to enable a specific architecture extension.

(cherry picked from commit b32aac4)
@llvmbot
Copy link
Collaborator

llvmbot commented Aug 4, 2024

/pull-request #101888

@nico
Copy link
Contributor

nico commented Aug 4, 2024

Looks like this breaks building on Android: https://ci.chromium.org/ui/p/chromium/builders/try/android-arm64-rel/680348/overview

@tru
Copy link
Collaborator

tru commented Aug 5, 2024

Though having said all this, I marked this for LLVM 19 as my reading of https://discourse.llvm.org/t/update-on-llvm-19-x-releases/80511 was that new features are still ok before RC2, but re-reading it it's a bit ambiguous: it says "New features will have to wait until LLVM 20 at this point" and my reading of that was that "this point" means RC2, so new features before RC2 is fine, but if "this point" meant "right now" that means new features aren't OK. If that's the case the it's reasonable for this to not go in RC2.

I am fine with it going into RC2 if it's part of a on-going work as you explained and that it doesn't create any big issues. Unfortunately with nico's latest comment it seems like this is breaking some build configurations and I am cutting RC2 now, I don't feel comfortable to merge it before that has been investigated. I can probably be convinced to take it in RC3 if it's really helpful to do so and it have been working without any problems.

@john-brawn-arm
Copy link
Collaborator Author

Looks like this breaks building on Android: https://ci.chromium.org/ui/p/chromium/builders/try/android-arm64-rel/680348/overview

Looks like Android here is being built with clang-llvmorg-19-init-14561-gecea8371-3004.tar.xz which looks like it's built from commit ecea8371 which is after 40d5c2b (which made -mbranch-protection=standard enable GCS) but before 3a14ffb (which added GCS intrinsics to arm_acle.h).

@nico
Copy link
Contributor

nico commented Aug 5, 2024

That sounds believable.

We did update our compiler just an hour or so ago, so it's possible it will work for us now.

However, it suggests that the assumption defined(__ARM_FEATURE_GCS_DEFAULT) => arm_acle.h has __chkfeat() isn't valid in this snippet in libunwind/src/cet_unwind.h (https://github.com/llvm/llvm-project/pull/99335/files#diff-7c503795ceadc957122b87cbf0dff76624c0576c291268226952dd822c75ea6eR41)

#if defined(_LIBUNWIND_TARGET_AARCH64) && defined(__ARM_FEATURE_GCS_DEFAULT)
#define _LIBUNWIND_USE_GCS 1
#include <arm_acle.h>

#define _LIBUNWIND_POP_CET_SSP(x)                                              \
  do {                                                                         \
    if (__chkfeat(_CHKFEAT_GCS)) {   

@john-brawn-arm
Copy link
Collaborator Author

#101973 for being more careful about enabling GCS.

@@ -680,7 +680,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
ldr x16, [x0, #0x0F8]
ldp x0, x1, [x0, #0x000] // restore x0,x1
mov sp,x16 // restore sp
ret x30 // jump to pc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the application is compiled with BTI then br x30 will cause an exception as it jumps to a non landing pad instruction.
(We only generate landing pads for return-twice locations but a normal catch block won't get it)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you're right, and actually the way I've adjusted __unw_phase2_resume also means we need to change the BTI instruction in __libunwind_Registers_arm64_jumpto to BTI JC. I'll fix this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#102322 should fix this

banach-space pushed a commit to banach-space/llvm-project that referenced this pull request Aug 7, 2024
AArch64 GCS (Guarded Control Stack) is similar enough to CET that we can
re-use the existing code that is guarded by _LIBUNWIND_USE_CET, so long
as we also add defines to locate the GCS stack and pop the entries from
it. We also need the jumpto function to exit using br instead of ret, to
prevent it from popping the GCS stack.

GCS support is enabled using the LIBUNWIND_ENABLE_GCS cmake option. This
enables -mbranch-protection=standard, which enables GCS. For the places
we need to use GCS instructions we use the target attribute, as there's
not a command-line option to enable a specific architecture extension.
@john-brawn-arm
Copy link
Collaborator Author

/cherry-pick b32aac4 c649194 3952910

llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Aug 12, 2024
AArch64 GCS (Guarded Control Stack) is similar enough to CET that we can
re-use the existing code that is guarded by _LIBUNWIND_USE_CET, so long
as we also add defines to locate the GCS stack and pop the entries from
it. We also need the jumpto function to exit using br instead of ret, to
prevent it from popping the GCS stack.

GCS support is enabled using the LIBUNWIND_ENABLE_GCS cmake option. This
enables -mbranch-protection=standard, which enables GCS. For the places
we need to use GCS instructions we use the target attribute, as there's
not a command-line option to enable a specific architecture extension.

(cherry picked from commit b32aac4)
@john-brawn-arm john-brawn-arm deleted the libunwind_gcs branch August 14, 2024 09:45
kstoimenov pushed a commit to kstoimenov/llvm-project that referenced this pull request Aug 15, 2024
AArch64 GCS (Guarded Control Stack) is similar enough to CET that we can
re-use the existing code that is guarded by _LIBUNWIND_USE_CET, so long
as we also add defines to locate the GCS stack and pop the entries from
it. We also need the jumpto function to exit using br instead of ret, to
prevent it from popping the GCS stack.

GCS support is enabled using the LIBUNWIND_ENABLE_GCS cmake option. This
enables -mbranch-protection=standard, which enables GCS. For the places
we need to use GCS instructions we use the target attribute, as there's
not a command-line option to enable a specific architecture extension.
tru pushed a commit to llvmbot/llvm-project that referenced this pull request Aug 20, 2024
AArch64 GCS (Guarded Control Stack) is similar enough to CET that we can
re-use the existing code that is guarded by _LIBUNWIND_USE_CET, so long
as we also add defines to locate the GCS stack and pop the entries from
it. We also need the jumpto function to exit using br instead of ret, to
prevent it from popping the GCS stack.

GCS support is enabled using the LIBUNWIND_ENABLE_GCS cmake option. This
enables -mbranch-protection=standard, which enables GCS. For the places
we need to use GCS instructions we use the target attribute, as there's
not a command-line option to enable a specific architecture extension.

(cherry picked from commit b32aac4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

7 participants