Skip to content

[compiler-rt] Add CMake option to enable execute-only code generation on AArch64 #140555

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Il-Capitano
Copy link
Contributor

For a full toolchain supporting execute-only code generation the runtime libraries also need to be pre-compiled with it enabled. For compiler-rt this can now be enabled with the COMPILER_RT_EXECUTE_ONLY_CODE CMake option during build configuration.

The build option can only be enabled for a runtimes build of compiler-rt, because a recent version of Clang is needed to correctly compile assembly files with execute-only code support.

Related RFC: https://discourse.llvm.org/t/rfc-execute-only-code-support-for-runtime-libraries-on-aarch64/86180

… on AArch64

For a full toolchain supporting execute-only code generation the runtime
libraries also need to be pre-compiled with it enabled. For compiler-rt
this can now be enabled with the `COMPILER_RT_EXECUTE_ONLY_CODE` CMake
option during build configuration.

The build option can only be enabled for a runtimes build of
compiler-rt, because a recent version of Clang is needed to correctly
compile assembly files with execute-only code support.

Related RFC: https://discourse.llvm.org/t/rfc-execute-only-code-support-for-runtime-libraries-on-aarch64/86180
@llvmbot
Copy link
Member

llvmbot commented May 19, 2025

@llvm/pr-subscribers-xray

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Csanád Hajdú (Il-Capitano)

Changes

For a full toolchain supporting execute-only code generation the runtime libraries also need to be pre-compiled with it enabled. For compiler-rt this can now be enabled with the COMPILER_RT_EXECUTE_ONLY_CODE CMake option during build configuration.

The build option can only be enabled for a runtimes build of compiler-rt, because a recent version of Clang is needed to correctly compile assembly files with execute-only code support.

Related RFC: https://discourse.llvm.org/t/rfc-execute-only-code-support-for-runtime-libraries-on-aarch64/86180


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

15 Files Affected:

  • (modified) compiler-rt/CMakeLists.txt (+20)
  • (modified) compiler-rt/cmake/builtin-config-ix.cmake (+2)
  • (modified) compiler-rt/cmake/config-ix.cmake (+2)
  • (modified) compiler-rt/lib/builtins/CMakeLists.txt (+14-1)
  • (modified) compiler-rt/lib/builtins/assembly.h (+14-1)
  • (modified) compiler-rt/lib/fuzzer/CMakeLists.txt (+3-1)
  • (modified) compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S (+1-1)
  • (modified) compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S (+1-1)
  • (modified) compiler-rt/lib/msan/tests/CMakeLists.txt (+2)
  • (modified) compiler-rt/lib/orc/elfnix_tls.aarch64.S (+4)
  • (modified) compiler-rt/lib/orc/sysv_reenter.arm64.S (+4)
  • (modified) compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S (+1)
  • (modified) compiler-rt/lib/tsan/CMakeLists.txt (+2)
  • (modified) compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S (+2-4)
  • (modified) compiler-rt/lib/xray/xray_trampoline_AArch64.S (+1-1)
diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index 9f8e8334d75ba..0e91e419fa373 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -307,6 +307,12 @@ option(COMPILER_RT_USE_BUILTINS_LIBRARY
 
 option(COMPILER_RT_USE_ATOMIC_LIBRARY "Use compiler-rt atomic instead of libatomic" OFF)
 
+option(COMPILER_RT_EXECUTE_ONLY_CODE "Compile compiler-rt as execute-only" OFF)
+if (COMPILER_RT_EXECUTE_ONLY_CODE AND NOT LLVM_RUNTIMES_BUILD)
+  message(SEND_ERROR "COMPILER_RT_EXECUTE_ONLY_CODE is only supported "
+                     "for runtimes build of compiler-rt.")
+endif()
+
 include(config-ix)
 
 #================================
@@ -603,6 +609,20 @@ string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}
 list(APPEND COMPILER_RT_COMMON_CFLAGS ${stdlib_flag})
 list(APPEND COMPILER_RT_COMMON_LINK_FLAGS ${stdlib_flag})
 
+# Add flags for execute-only code generation.
+# We need to add to both COMPILER_RT_COMMON_CFLAGS and CMAKE_<LANG>_FLAGS.
+if (COMPILER_RT_HAS_MEXECUTE_ONLY_FLAG)
+  append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE -mexecute-only COMPILER_RT_COMMON_CFLAGS)
+  append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE -DCOMPILER_RT_EXECUTE_ONLY_CODE COMPILER_RT_COMMON_CFLAGS)
+  append_string_if(COMPILER_RT_EXECUTE_ONLY_CODE -mexecute-only CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
+  append_string_if(COMPILER_RT_EXECUTE_ONLY_CODE -DCOMPILER_RT_EXECUTE_ONLY_CODE CMAKE_ASM_FLAGS)
+elseif (COMPILER_RT_HAS_MPURE_CODE_FLAG)
+  append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE -mpure-code COMPILER_RT_COMMON_CFLAGS)
+  append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE -DCOMPILER_RT_EXECUTE_ONLY_CODE COMPILER_RT_COMMON_CFLAGS)
+  append_string_if(COMPILER_RT_EXECUTE_ONLY_CODE -mpure-code CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
+  append_string_if(COMPILER_RT_EXECUTE_ONLY_CODE -DCOMPILER_RT_EXECUTE_ONLY_CODE CMAKE_ASM_FLAGS)
+endif()
+
 # TODO: There's a lot of duplication across lib/*/tests/CMakeLists.txt files,
 # move some of the common flags to COMPILER_RT_UNITTEST_CFLAGS.
 
diff --git a/compiler-rt/cmake/builtin-config-ix.cmake b/compiler-rt/cmake/builtin-config-ix.cmake
index 8c9c84ad64bc0..82fde12d85bf0 100644
--- a/compiler-rt/cmake/builtin-config-ix.cmake
+++ b/compiler-rt/cmake/builtin-config-ix.cmake
@@ -26,6 +26,8 @@ builtin_check_c_compiler_flag("-Xclang -mcode-object-version=none" COMPILER_RT_H
 builtin_check_c_compiler_flag(-Wbuiltin-declaration-mismatch COMPILER_RT_HAS_WBUILTIN_DECLARATION_MISMATCH_FLAG)
 builtin_check_c_compiler_flag(/Zl COMPILER_RT_HAS_ZL_FLAG)
 builtin_check_c_compiler_flag(-fcf-protection=full COMPILER_RT_HAS_FCF_PROTECTION_FLAG)
+builtin_check_c_compiler_flag(-mexecute-only       COMPILER_RT_HAS_MEXECUTE_ONLY_FLAG)
+builtin_check_c_compiler_flag(-mpure-code          COMPILER_RT_HAS_MPURE_CODE_FLAG)
 
 builtin_check_c_compiler_source(COMPILER_RT_HAS_ATOMIC_KEYWORD
 "
diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index e3310b1ff0e2c..e44eeb0ab1c20 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -115,6 +115,8 @@ check_cxx_compiler_flag(--sysroot=.          COMPILER_RT_HAS_SYSROOT_FLAG)
 check_cxx_compiler_flag("-Werror -mcrc"      COMPILER_RT_HAS_MCRC_FLAG)
 check_cxx_compiler_flag(-fno-partial-inlining COMPILER_RT_HAS_FNO_PARTIAL_INLINING_FLAG)
 check_cxx_compiler_flag("-Werror -ftrivial-auto-var-init=pattern" COMPILER_RT_HAS_TRIVIAL_AUTO_INIT)
+check_cxx_compiler_flag(-mexecute-only       COMPILER_RT_HAS_MEXECUTE_ONLY_FLAG)
+check_cxx_compiler_flag(-mpure-code          COMPILER_RT_HAS_MPURE_CODE_FLAG)
 
 if(NOT WIN32 AND NOT CYGWIN)
   # MinGW warns if -fvisibility-inlines-hidden is used.
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index d9b7800a95565..3842c089c1fbf 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -885,6 +885,7 @@ else ()
       cmake_push_check_state()
       # TODO: we should probably make most of the checks in builtin-config depend on the target flags.
       set(BUILTIN_CFLAGS_${arch} ${BUILTIN_CFLAGS})
+      set(BUILTIN_DEFS_${arch} ${BUILTIN_DEFS})
       # CMAKE_REQUIRED_FLAGS must be a space separated string
       # Join BUILTIN_CFLAGS_${arch} and TARGET_${arch}_CFLAGS as a
       # space-separated string.
@@ -922,6 +923,13 @@ else ()
       if(COMPILER_RT_HAS_${arch}_BFLOAT16)
         list(APPEND ${arch}_SOURCES ${BF16_SOURCES})
       endif()
+      if (COMPILER_RT_HAS_MEXECUTE_ONLY_FLAG)
+        append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE -mexecute-only BUILTIN_CFLAGS_${arch})
+        append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE COMPILER_RT_EXECUTE_ONLY_CODE BUILTIN_DEFS_${arch})
+      elseif (COMPILER_RT_HAS_MPURE_CODE_FLAG)
+        append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE -mpure-code BUILTIN_CFLAGS_${arch})
+        append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE COMPILER_RT_EXECUTE_ONLY_CODE BUILTIN_DEFS_${arch})
+      endif()
 
       # Remove a generic C builtin when an arch-specific builtin is specified.
       filter_builtin_sources(${arch}_SOURCES ${arch})
@@ -943,7 +951,7 @@ else ()
                               ARCHS ${arch}
                               DEPS ${deps_${arch}}
                               SOURCES ${${arch}_SOURCES}
-                              DEFS ${BUILTIN_DEFS}
+                              DEFS ${BUILTIN_DEFS_${arch}}
                               CFLAGS ${BUILTIN_CFLAGS_${arch}}
                               PARENT_TARGET builtins)
       cmake_pop_check_state()
@@ -1015,6 +1023,11 @@ if (COMPILER_RT_BUILD_CRT)
   if (COMPILER_RT_HAS_FCF_PROTECTION_FLAG)
     append_list_if(COMPILER_RT_ENABLE_CET -fcf-protection=full CRT_CFLAGS)
   endif()
+  if (COMPILER_RT_HAS_MEXECUTE_ONLY_FLAG)
+    append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE -mexecute-only CRT_CFLAGS)
+  elseif (COMPILER_RT_HAS_MPURE_CODE_FLAG)
+    append_list_if(COMPILER_RT_EXECUTE_ONLY_CODE -mpure-code CRT_CFLAGS)
+  endif()
 
   foreach(arch ${BUILTIN_SUPPORTED_ARCH})
     add_compiler_rt_runtime(clang_rt.crtbegin
diff --git a/compiler-rt/lib/builtins/assembly.h b/compiler-rt/lib/builtins/assembly.h
index 385dc190369d9..2e4195d0ba6a8 100644
--- a/compiler-rt/lib/builtins/assembly.h
+++ b/compiler-rt/lib/builtins/assembly.h
@@ -71,9 +71,17 @@
 
 #endif
 
+#if defined(__aarch64__) && defined(__ELF__) &&                                \
+    defined(COMPILER_RT_EXECUTE_ONLY_CODE)
+#define TEXT_SECTION                                                           \
+  .section .text,"axy",@progbits,unique,0
+#else
+#define TEXT_SECTION                                                           \
+  .text
+#endif
+
 #if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)
 #define FUNC_ALIGN                                                             \
-  .text SEPARATOR                                                              \
   .balign 16 SEPARATOR
 #else
 #define FUNC_ALIGN
@@ -230,6 +238,7 @@
 #endif
 
 #define DEFINE_COMPILERRT_FUNCTION(name)                                       \
+  TEXT_SECTION SEPARATOR                                                       \
   DEFINE_CODE_STATE                                                            \
   FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
   .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
@@ -239,6 +248,7 @@
   FUNC_SYMBOL(SYMBOL_NAME(name)):
 
 #define DEFINE_COMPILERRT_THUMB_FUNCTION(name)                                 \
+  TEXT_SECTION SEPARATOR                                                       \
   DEFINE_CODE_STATE                                                            \
   FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
   .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
@@ -248,6 +258,7 @@
   FUNC_SYMBOL(SYMBOL_NAME(name)):
 
 #define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name)                               \
+  TEXT_SECTION SEPARATOR                                                       \
   DEFINE_CODE_STATE                                                            \
   FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
   .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
@@ -257,6 +268,7 @@
   FUNC_SYMBOL(SYMBOL_NAME(name)):
 
 #define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name)                     \
+  TEXT_SECTION SEPARATOR                                                       \
   DEFINE_CODE_STATE                                                            \
   .globl FUNC_SYMBOL(name) SEPARATOR                                           \
   SYMBOL_IS_FUNC(name) SEPARATOR                                               \
@@ -265,6 +277,7 @@
   FUNC_SYMBOL(name):
 
 #define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name)                     \
+  TEXT_SECTION SEPARATOR                                                       \
   DEFINE_CODE_STATE                                                            \
   FUNC_ALIGN                                                                   \
   .globl FUNC_SYMBOL(name) SEPARATOR                                           \
diff --git a/compiler-rt/lib/fuzzer/CMakeLists.txt b/compiler-rt/lib/fuzzer/CMakeLists.txt
index 6db24610df1f0..adfba850861ac 100644
--- a/compiler-rt/lib/fuzzer/CMakeLists.txt
+++ b/compiler-rt/lib/fuzzer/CMakeLists.txt
@@ -163,8 +163,10 @@ if(OS_NAME MATCHES "Android|Linux|Fuchsia" AND
       CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON
                  -DCMAKE_POSITION_INDEPENDENT_CODE=ON
                  -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF
+                 -DLIBCXXABI_EXECUTE_ONLY_CODE=${COMPILER_RT_EXECUTE_ONLY_CODE}
                  -DLIBCXX_ABI_NAMESPACE=__Fuzzer
-                 -DLIBCXX_ENABLE_EXCEPTIONS=OFF)
+                 -DLIBCXX_ENABLE_EXCEPTIONS=OFF
+                 -DLIBCXX_EXECUTE_ONLY_CODE=${COMPILER_RT_EXECUTE_ONLY_CODE})
     target_compile_options(RTfuzzer.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1)
     add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}-install-cmake326-workaround)
     target_compile_options(RTfuzzer_main.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1)
diff --git a/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S b/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S
index 0c0abb6de861f..75ee6bc50baa8 100644
--- a/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S
+++ b/compiler-rt/lib/hwasan/hwasan_setjmp_aarch64.S
@@ -28,7 +28,7 @@
 // stack pointer when compiling a C function.
 // Hence we have to write this function in assembly.
 
-.section .text
+TEXT_SECTION
 .file "hwasan_setjmp_aarch64.S"
 
 .global ASM_WRAPPER_NAME(setjmp)
diff --git a/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S b/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S
index fd060c51cd8e2..d38767f9378fa 100644
--- a/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S
+++ b/compiler-rt/lib/hwasan/hwasan_tag_mismatch_aarch64.S
@@ -70,7 +70,7 @@
 // clobbering the x17 register in error reports, and that the program will have
 // a runtime dependency on the __hwasan_tag_mismatch_v2 symbol therefore it will
 // fail to start up given an older (i.e. incompatible) runtime.
-.section .text
+TEXT_SECTION
 .file "hwasan_tag_mismatch_aarch64.S"
 .global __hwasan_tag_mismatch
 .type __hwasan_tag_mismatch, %function
diff --git a/compiler-rt/lib/msan/tests/CMakeLists.txt b/compiler-rt/lib/msan/tests/CMakeLists.txt
index a8500225337e6..53f570cfff27f 100644
--- a/compiler-rt/lib/msan/tests/CMakeLists.txt
+++ b/compiler-rt/lib/msan/tests/CMakeLists.txt
@@ -139,6 +139,8 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS AND
     add_custom_libcxx(libcxx_msan_${arch} ${LIBCXX_PREFIX}
       DEPS ${MSAN_RUNTIME_LIBRARIES}
       CFLAGS ${MSAN_LIBCXX_CFLAGS} ${TARGET_CFLAGS}
+      CMAKE_ARGS -DLIBCXX_EXECUTE_ONLY_CODE=${COMPILER_RT_EXECUTE_ONLY_CODE}
+                 -DLIBCXXABI_EXECUTE_ONLY_CODE=${COMPILER_RT_EXECUTE_ONLY_CODE}
       USE_TOOLCHAIN)
     set(MSAN_LIBCXX_DIR ${LIBCXX_PREFIX}/lib/)
 
diff --git a/compiler-rt/lib/orc/elfnix_tls.aarch64.S b/compiler-rt/lib/orc/elfnix_tls.aarch64.S
index 8dcdd535be8ae..22bd5b560c852 100644
--- a/compiler-rt/lib/orc/elfnix_tls.aarch64.S
+++ b/compiler-rt/lib/orc/elfnix_tls.aarch64.S
@@ -15,7 +15,11 @@
 
 #define REGISTER_SAVE_SPACE_SIZE     32 * 24
 
+#if defined(COMPILER_RT_EXECUTE_ONLY_CODE)
+        .section .text,"axy",@progbits,unique,0
+#else
         .text
+#endif
 
   // returns address of TLV in x0, all other registers preserved
   // TODO: add fast-path for repeat access
diff --git a/compiler-rt/lib/orc/sysv_reenter.arm64.S b/compiler-rt/lib/orc/sysv_reenter.arm64.S
index 74941c459d6ac..87a857c56ac61 100644
--- a/compiler-rt/lib/orc/sysv_reenter.arm64.S
+++ b/compiler-rt/lib/orc/sysv_reenter.arm64.S
@@ -13,7 +13,11 @@
 // The content of this file is arm64-only
 #if defined(__arm64__) || defined(__aarch64__)
 
+#if defined(__ELF__) && defined(COMPILER_RT_EXECUTE_ONLY_CODE)
+        .section .text,"axy",@progbits,unique,0
+#else
         .text
+#endif
 
         // Saves GPRs, calls __orc_rt_resolve
         .globl __orc_rt_sysv_reenter
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S
index cdfa6f1d7f53b..99d0aae0d2faa 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_vfork_aarch64.inc.S
@@ -5,6 +5,7 @@
 
 ASM_HIDDEN(COMMON_INTERCEPTOR_SPILL_AREA)
 
+TEXT_SECTION
 .comm _ZN14__interception10real_vforkE,8,8
 .globl ASM_WRAPPER_NAME(vfork)
 ASM_TYPE_FUNCTION(ASM_WRAPPER_NAME(vfork))
diff --git a/compiler-rt/lib/tsan/CMakeLists.txt b/compiler-rt/lib/tsan/CMakeLists.txt
index 7928116879c09..686543e15fa6c 100644
--- a/compiler-rt/lib/tsan/CMakeLists.txt
+++ b/compiler-rt/lib/tsan/CMakeLists.txt
@@ -30,6 +30,8 @@ if(COMPILER_RT_LIBCXX_PATH AND
     add_custom_libcxx(libcxx_tsan_${arch} ${LIBCXX_PREFIX}
       DEPS ${TSAN_RUNTIME_LIBRARIES}
       CFLAGS ${TARGET_CFLAGS} -fsanitize=thread
+      CMAKE_ARGS -DLIBCXX_EXECUTE_ONLY_CODE=${COMPILER_RT_EXECUTE_ONLY_CODE}
+                 -DLIBCXXABI_EXECUTE_ONLY_CODE=${COMPILER_RT_EXECUTE_ONLY_CODE}
       USE_TOOLCHAIN)
     list(APPEND libcxx_tsan_deps libcxx_tsan_${arch}-install-cmake326-workaround)
   endforeach()
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S b/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S
index 7d920bee4a2db..93ad0d663c7a8 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S
@@ -4,10 +4,8 @@
 #include "sanitizer_common/sanitizer_asm.h"
 #include "builtins/assembly.h"
 
-#if !defined(__APPLE__)
-.section .text
-#else
-.section __TEXT,__text
+TEXT_SECTION
+#if defined(__APPLE__)
 .align 3
 #endif
 
diff --git a/compiler-rt/lib/xray/xray_trampoline_AArch64.S b/compiler-rt/lib/xray/xray_trampoline_AArch64.S
index 2586def04cbb1..5d951f3821a50 100644
--- a/compiler-rt/lib/xray/xray_trampoline_AArch64.S
+++ b/compiler-rt/lib/xray/xray_trampoline_AArch64.S
@@ -37,7 +37,7 @@
 #endif
 .endm
 
-.text
+TEXT_SECTION
 .p2align 2
 .global ASM_SYMBOL(__xray_FunctionEntry)
 ASM_HIDDEN(__xray_FunctionEntry)

Copy link

github-actions bot commented May 19, 2025

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

You can test this locally with the following command:
git-clang-format --diff HEAD~1 HEAD --extensions h -- compiler-rt/lib/builtins/assembly.h
View the diff from clang-format here.
diff --git a/compiler-rt/lib/builtins/assembly.h b/compiler-rt/lib/builtins/assembly.h
index 7f3af0141..38579211d 100644
--- a/compiler-rt/lib/builtins/assembly.h
+++ b/compiler-rt/lib/builtins/assembly.h
@@ -80,16 +80,13 @@
 // differentiate the two sections. The output will therefore have two separate
 // sections named '.text', where code will be placed into the execute-only
 // '.text' section, and the implicitly-created one will be empty.
-#define TEXT_SECTION                                                           \
-  .section .text,"axy",@progbits,unique,0
+#define TEXT_SECTION .section.text, "axy", @progbits, unique, 0
 #else
-#define TEXT_SECTION                                                           \
-  .text
+#define TEXT_SECTION .text
 #endif
 
 #if defined(__arm__) || defined(__aarch64__) || defined(__arm64ec__)
-#define FUNC_ALIGN                                                             \
-  .balign 16 SEPARATOR
+#define FUNC_ALIGN .balign 16 SEPARATOR
 #else
 #define FUNC_ALIGN
 #endif
@@ -245,55 +242,45 @@
 #endif
 
 #define DEFINE_COMPILERRT_FUNCTION(name)                                       \
-  TEXT_SECTION SEPARATOR                                                       \
-  DEFINE_CODE_STATE                                                            \
-  FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
-  .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
-  SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
-  DECLARE_SYMBOL_VISIBILITY(name)                                              \
+  TEXT_SECTION SEPARATOR DEFINE_CODE_STATE FILE_LEVEL_DIRECTIVE                \
+      SEPARATOR.globl                                                          \
+      FUNC_SYMBOL(SYMBOL_NAME(name))                                           \
+          SEPARATOR SYMBOL_IS_FUNC(SYMBOL_NAME(name))                          \
+              SEPARATOR DECLARE_SYMBOL_VISIBILITY(name)                        \
   DECLARE_FUNC_ENCODING                                                        \
-  FUNC_SYMBOL(SYMBOL_NAME(name)):
+  FUNC_SYMBOL(SYMBOL_NAME(name)) :
 
 #define DEFINE_COMPILERRT_THUMB_FUNCTION(name)                                 \
-  TEXT_SECTION SEPARATOR                                                       \
-  DEFINE_CODE_STATE                                                            \
-  FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
-  .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
-  SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
-  DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR                                    \
-  .thumb_func SEPARATOR                                                        \
-  FUNC_SYMBOL(SYMBOL_NAME(name)):
+  TEXT_SECTION SEPARATOR DEFINE_CODE_STATE FILE_LEVEL_DIRECTIVE SEPARATOR      \
+      .globl                                                                   \
+      FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR SYMBOL_IS_FUNC(                 \
+          SYMBOL_NAME(name)) SEPARATOR DECLARE_SYMBOL_VISIBILITY(name)         \
+          SEPARATOR.thumb_func SEPARATOR FUNC_SYMBOL(SYMBOL_NAME(name))        \
+      :
 
 #define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name)                               \
-  TEXT_SECTION SEPARATOR                                                       \
-  DEFINE_CODE_STATE                                                            \
-  FILE_LEVEL_DIRECTIVE SEPARATOR                                               \
-  .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \
-  SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR                                  \
-  HIDDEN(SYMBOL_NAME(name)) SEPARATOR                                          \
-  DECLARE_FUNC_ENCODING                                                        \
-  FUNC_SYMBOL(SYMBOL_NAME(name)):
+  TEXT_SECTION SEPARATOR DEFINE_CODE_STATE FILE_LEVEL_DIRECTIVE                \
+      SEPARATOR.globl                                                          \
+      FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR SYMBOL_IS_FUNC(                 \
+          SYMBOL_NAME(name)) SEPARATOR HIDDEN(SYMBOL_NAME(name))               \
+          SEPARATOR DECLARE_FUNC_ENCODING FUNC_SYMBOL(SYMBOL_NAME(name))       \
+      :
 
 #define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name)                     \
-  TEXT_SECTION SEPARATOR                                                       \
-  DEFINE_CODE_STATE                                                            \
-  .globl FUNC_SYMBOL(name) SEPARATOR                                           \
-  SYMBOL_IS_FUNC(name) SEPARATOR                                               \
-  HIDDEN(name) SEPARATOR                                                       \
+  TEXT_SECTION SEPARATOR DEFINE_CODE_STATE.globl FUNC_SYMBOL(name)             \
+  SEPARATOR                                                                    \
+  SYMBOL_IS_FUNC(name) SEPARATOR HIDDEN(name)                                  \
+  SEPARATOR                                                                    \
   DECLARE_FUNC_ENCODING                                                        \
-  FUNC_SYMBOL(name):
+  FUNC_SYMBOL(name) :
 
 #define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name)                     \
-  TEXT_SECTION SEPARATOR                                                       \
-  DEFINE_CODE_STATE                                                            \
-  FUNC_ALIGN                                                                   \
-  .globl FUNC_SYMBOL(name) SEPARATOR                                           \
-  SYMBOL_IS_FUNC(name) SEPARATOR                                               \
-  DECLARE_SYMBOL_VISIBILITY_UNMANGLED(FUNC_SYMBOL(name)) SEPARATOR             \
-  DECLARE_FUNC_ENCODING                                                        \
-  FUNC_SYMBOL(name):                                                           \
-  SEPARATOR CFI_START                                                          \
-  SEPARATOR BTI_C
+  TEXT_SECTION SEPARATOR DEFINE_CODE_STATE FUNC_ALIGN.globl FUNC_SYMBOL(name)  \
+  SEPARATOR                                                                    \
+  SYMBOL_IS_FUNC(name)                                                         \
+  SEPARATOR DECLARE_SYMBOL_VISIBILITY_UNMANGLED(FUNC_SYMBOL(name))             \
+      SEPARATOR DECLARE_FUNC_ENCODING FUNC_SYMBOL(name)                        \
+      : SEPARATOR CFI_START SEPARATOR BTI_C
 
 #define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target)                         \
   .globl FUNC_SYMBOL(SYMBOL_NAME(name)) SEPARATOR                              \

Copy link
Member

@compnerd compnerd left a comment

Choose a reason for hiding this comment

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

I don't think that this properly handles MachO. Additionally, I don't understand the need for the unique flag on the section, nor the section id (0).

@Il-Capitano
Copy link
Contributor Author

I don't think that this properly handles MachO.

Can you expand on this more? MachO doesn't have execute-only code AFAIK. This is intended for AArch64 ELF targets only.

Additionally, I don't understand the need for the unique flag on the section, nor the section id (0).

unique,0 is needed because the assembler creates an implicit .text section with default flags. If we tried to just do .section .text,"axy", we'd get the following error: error: changed section flags for .text, expected: 0x6. So the execute-only .text section needs to be different from the implicit .text section. The id 0 is arbitrary, but we need to provide something anyways.

This also matches what LLVM outputs when it generates execute-only code: https://godbolt.org/z/a8xa7qsxG

@compnerd
Copy link
Member

I don't think that this properly handles MachO.

Can you expand on this more? MachO doesn't have execute-only code AFAIK. This is intended for AArch64 ELF targets only.

These macros are not ELF specific is the issue. You are changing macros that are shared across all architectures and file formats. If you could scope this down somehow to not touch these global macros, that might be easier.

Additionally, I don't understand the need for the unique flag on the section, nor the section id (0).

unique,0 is needed because the assembler creates an implicit .text section with default flags. If we tried to just do .section .text,"axy", we'd get the following error: error: changed section flags for .text, expected: 0x6. So the execute-only .text section needs to be different from the implicit .text section. The id 0 is arbitrary, but we need to provide something anyways.

This also matches what LLVM outputs when it generates execute-only code: https://godbolt.org/z/a8xa7qsxG

Ah, I see. I think that deserves a comment explaining why we need those flags are being added. I do wonder if we should simply drop the unique,0 and instead build the builtins as -ffunction-sections instead as that places the text into a separate section.

@Il-Capitano
Copy link
Contributor Author

I don't think that this properly handles MachO.

Can you expand on this more? MachO doesn't have execute-only code AFAIK. This is intended for AArch64 ELF targets only.

These macros are not ELF specific is the issue. You are changing macros that are shared across all architectures and file formats. If you could scope this down somehow to not touch these global macros, that might be easier.

The change is adding a .text or .section .text,"axy",unique,0 directive before the function definitions, which just makes sure we're in the .text section. The execute-only case is guarded by defined(__aarch64__) && defined(__ELF__), so shouldn't affect any other targets. The alternative would be to change every AArch64 assembly file individually, but I don't think that would be better.

The cases where functions are put in differently named sections don't seem to use these macros anyways.

Additionally, I don't understand the need for the unique flag on the section, nor the section id (0).

unique,0 is needed because the assembler creates an implicit .text section with default flags. If we tried to just do .section .text,"axy", we'd get the following error: error: changed section flags for .text, expected: 0x6. So the execute-only .text section needs to be different from the implicit .text section. The id 0 is arbitrary, but we need to provide something anyways.
This also matches what LLVM outputs when it generates execute-only code: https://godbolt.org/z/a8xa7qsxG

Ah, I see. I think that deserves a comment explaining why we need those flags are being added. I do wonder if we should simply drop the unique,0 and instead build the builtins as -ffunction-sections instead as that places the text into a separate section.

You're right, I'll add a comment clarifying this. For dropping unique,0 do you mean to add .section .text.name in the function definition macros? That could work to get rid of the unique,0 suffix.

@compnerd
Copy link
Member

I don't think that this properly handles MachO.

Can you expand on this more? MachO doesn't have execute-only code AFAIK. This is intended for AArch64 ELF targets only.

These macros are not ELF specific is the issue. You are changing macros that are shared across all architectures and file formats. If you could scope this down somehow to not touch these global macros, that might be easier.

The change is adding a .text or .section .text,"axy",unique,0 directive before the function definitions, which just makes sure we're in the .text section. The execute-only case is guarded by defined(__aarch64__) && defined(__ELF__), so shouldn't affect any other targets. The alternative would be to change every AArch64 assembly file individually, but I don't think that would be better.

Part of the change does impact a place where there was no use of the macro and we placed text into .section __TEXT,__text which is the proper spelling.

The cases where functions are put in differently named sections don't seem to use these macros anyways.

Additionally, I don't understand the need for the unique flag on the section, nor the section id (0).

unique,0 is needed because the assembler creates an implicit .text section with default flags. If we tried to just do .section .text,"axy", we'd get the following error: error: changed section flags for .text, expected: 0x6. So the execute-only .text section needs to be different from the implicit .text section. The id 0 is arbitrary, but we need to provide something anyways.
This also matches what LLVM outputs when it generates execute-only code: https://godbolt.org/z/a8xa7qsxG

Ah, I see. I think that deserves a comment explaining why we need those flags are being added. I do wonder if we should simply drop the unique,0 and instead build the builtins as -ffunction-sections instead as that places the text into a separate section.

You're right, I'll add a comment clarifying this. For dropping unique,0 do you mean to add .section .text.name in the function definition macros? That could work to get rid of the unique,0 suffix.

Right, that is what I was thinking. For static linking, that might also enable DCE, which can be a benefit.

@Il-Capitano
Copy link
Contributor Author

Part of the change does impact a place where there was no use of the macro and we placed text into .section __TEXT,__text which is the proper spelling.

Is there a meaningful difference between .text and .section __TEXT,__text? From what I found, and my local testing, the former is an alias of the latter. There are instances in compiler-rt, where .text is used on MachO as well (e.g. compiler-rt/lib/orc/sysv_reenter.arm64.S).

Right, that is what I was thinking. For static linking, that might also enable DCE, which can be a benefit.

This is an orthogonal change to mine though. Would you be fine with merging this PR as is, and you/someone else preparing a separate patch for that? Alternatively that change could be done first, and I'd be happy to do a rebase on this PR accommodating those changes.

@compnerd
Copy link
Member

Part of the change does impact a place where there was no use of the macro and we placed text into .section __TEXT,__text which is the proper spelling.

Is there a meaningful difference between .text and .section __TEXT,__text? From what I found, and my local testing, the former is an alias of the latter. There are instances in compiler-rt, where .text is used on MachO as well (e.g. compiler-rt/lib/orc/sysv_reenter.arm64.S).

Oh, if .text is treated as an alias, I think that should be fine.

Right, that is what I was thinking. For static linking, that might also enable DCE, which can be a benefit.

This is an orthogonal change to mine though. Would you be fine with merging this PR as is, and you/someone else preparing a separate patch for that? Alternatively that change could be done first, and I'd be happy to do a rebase on this PR accommodating those changes.

Well, it is only coming up due to the changes you are making. I am thinking about how to simplify and make the code easier to maintain.

@Il-Capitano
Copy link
Contributor Author

@ldionne commented on my RFC about using a single CMake option for all runtime libraries.

If there aren't any opposing views, I'm fine with making that change, so if you have any thoughts (either in support of the change or opposing it), please comment on the RFC. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants