[compiler-rt] [compiler-rt] Add CMake option to enable execute-only code generation on AArch64 (PR #140555)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 19 07:59:08 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-xray
@llvm/pr-subscribers-compiler-rt-sanitizer
Author: Csanád Hajdú (Il-Capitano)
<details>
<summary>Changes</summary>
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
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", at 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", at 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", at 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)
``````````
</details>
https://github.com/llvm/llvm-project/pull/140555
More information about the llvm-commits
mailing list