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__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..7f3af0141ae12 100644 --- a/compiler-rt/lib/builtins/assembly.h +++ b/compiler-rt/lib/builtins/assembly.h @@ -71,9 +71,24 @@ #endif +#if defined(__aarch64__) && defined(__ELF__) && \ + defined(COMPILER_RT_EXECUTE_ONLY_CODE) +// The assembler always creates an implicit '.text' section with default flags +// (SHF_ALLOC | SHF_EXECINSTR), which is incompatible with the execute-only +// '.text' section we want to create here because of the missing +// SHF_AARCH64_PURECODE section flag. To solve this, we use 'unique,0' to +// 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 +#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 +245,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 +255,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 +265,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 +275,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 +284,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..25d97e6593dc0 100644 --- a/compiler-rt/lib/orc/elfnix_tls.aarch64.S +++ b/compiler-rt/lib/orc/elfnix_tls.aarch64.S @@ -13,9 +13,11 @@ // The content of this file is aarch64-only #if defined(__arm64__) || defined(__aarch64__) +#include "builtins/assembly.h" + #define REGISTER_SAVE_SPACE_SIZE 32 * 24 - .text + TEXT_SECTION // 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..61e58e50c97c7 100644 --- a/compiler-rt/lib/orc/sysv_reenter.arm64.S +++ b/compiler-rt/lib/orc/sysv_reenter.arm64.S @@ -13,7 +13,9 @@ // The content of this file is arm64-only #if defined(__arm64__) || defined(__aarch64__) - .text +#include "builtins/assembly.h" + + TEXT_SECTION // 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)