Skip to content

[libc++] Add build and CI support for pointer field protection #152414

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 2 commits into
base: users/pcc/spr/main.libc-add-build-and-ci-support-for-pointer-field-protection
Choose a base branch
from

Conversation

pcc
Copy link
Contributor

@pcc pcc commented Aug 7, 2025

Add support for building the libc++ runtime with pointer field
protection with a new CMake variable, LIBCXX_PFP. Add a new case to
libcxx/utils/ci/run-buildbot named bootstrapping-build-pfp that runs
the libc++ and libc++abi tests.

This implements the LLVM side of the CI support proposed in:
https://discourse.llvm.org/t/rfc-libc-and-pointer-field-protection/87713

Created using spr 1.3.6-beta.1
@pcc pcc requested review from a team as code owners August 7, 2025 00:12
@llvmbot llvmbot added libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. libc++abi libc++abi C++ Runtime Library. Not libc++. labels Aug 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 7, 2025

@llvm/pr-subscribers-libcxxabi

@llvm/pr-subscribers-libcxx

Author: Peter Collingbourne (pcc)

Changes

Add support for building the libc++ runtime with pointer field
protection with a new CMake variable, LIBCXX_PFP. Add a new case to
libcxx/utils/ci/run-buildbot named bootstrapping-build-pfp that runs
the libc++ and libc++abi tests.

This implements the LLVM side of the CI support proposed in:
https://discourse.llvm.org/t/rfc-libc-and-pointer-field-protection/87713


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

5 Files Affected:

  • (modified) libcxx/CMakeLists.txt (+15)
  • (modified) libcxx/test/CMakeLists.txt (+1)
  • (modified) libcxx/utils/ci/run-buildbot (+36)
  • (modified) libcxx/utils/libcxx/test/params.py (+16)
  • (modified) libcxxabi/test/CMakeLists.txt (+2)
diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index 85514cc7547a9..05f342d7002b3 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -66,6 +66,14 @@ if (NOT "${LIBCXX_HARDENING_MODE}" IN_LIST LIBCXX_SUPPORTED_HARDENING_MODES)
   message(FATAL_ERROR
     "Unsupported hardening mode: '${LIBCXX_HARDENING_MODE}'. Supported values are ${LIBCXX_SUPPORTED_HARDENING_MODES}.")
 endif()
+set(LIBCXX_SUPPORTED_PFP none untagged tagged)
+set(LIBCXX_PFP none CACHE STRING
+  "Specify whether to build with pointer field protection.
+   Supported values are ${LIBCXX_SUPPORTED_PFP}.")
+if (NOT "${LIBCXX_PFP}" IN_LIST LIBCXX_SUPPORTED_PFP)
+  message(FATAL_ERROR
+    "Unsupported PFP mode: '${LIBCXX_PFP}'. Supported values are ${LIBCXX_SUPPORTED_PFP}.")
+endif()
 set(LIBCXX_ASSERTION_HANDLER_FILE
   "vendor/llvm/default_assertion_handler.in"
   CACHE STRING
@@ -564,6 +572,12 @@ function(cxx_add_rtti_flags target)
   endif()
 endfunction()
 
+function(cxx_add_pfp_flags target)
+  if (NOT LIBCXX_PFP STREQUAL none)
+    target_add_compile_flags_if_supported(${target} PUBLIC -fexperimental-pointer-field-protection=${LIBCXX_PFP})
+  endif()
+endfunction()
+
 # Modules flags ===============================================================
 # FIXME The libc++ sources are fundamentally non-modular. They need special
 # versions of the headers in order to provide C++03 and legacy ABI definitions.
@@ -820,6 +834,7 @@ function(cxx_add_common_build_flags target)
   cxx_add_windows_flags(${target})
   cxx_add_exception_flags(${target})
   cxx_add_rtti_flags(${target})
+  cxx_add_pfp_flags(${target})
   cxx_add_module_flags(${target})
   cxx_link_system_libraries(${target})
   target_link_libraries(${target} PRIVATE cxx-sanitizer-flags)
diff --git a/libcxx/test/CMakeLists.txt b/libcxx/test/CMakeLists.txt
index f4e577aed57de..340f3d3c44101 100644
--- a/libcxx/test/CMakeLists.txt
+++ b/libcxx/test/CMakeLists.txt
@@ -79,6 +79,7 @@ if (NOT LIBCXX_ENABLE_RTTI)
 endif()
 
 serialize_lit_string_param(SERIALIZED_LIT_PARAMS hardening_mode "${LIBCXX_HARDENING_MODE}")
+serialize_lit_string_param(SERIALIZED_LIT_PARAMS pfp "${LIBCXX_PFP}")
 
 if (CMAKE_CXX_COMPILER_TARGET)
   serialize_lit_string_param(SERIALIZED_LIT_PARAMS target_triple "${CMAKE_CXX_COMPILER_TARGET}")
diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index 57ecf1e49dbf2..9965ebe78b497 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -411,6 +411,42 @@ bootstrapping-build)
 
     ccache -s
 ;;
+bootstrapping-build-pfp)
+    clean
+
+    triple="$(${CXX} --print-target-triple)"
+
+    step "Generating CMake"
+    ${CMAKE} \
+          -S "${MONOREPO_ROOT}/llvm" \
+          -B "${BUILD_DIR}" \
+          -GNinja -DCMAKE_MAKE_PROGRAM="${NINJA}" \
+          -DCMAKE_BUILD_TYPE=Release \
+          -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
+          -DLLVM_ENABLE_PROJECTS="clang;lld" \
+          -DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi;libunwind" \
+          -DLLVM_RUNTIME_TARGETS="$triple" \
+          -DLLVM_HOST_TRIPLE="$triple" \
+          -DLLVM_TARGETS_TO_BUILD="host" \
+          -DRUNTIMES_BUILD_ALLOW_DARWIN=ON \
+          -DLLVM_ENABLE_ASSERTIONS=ON \
+          "-DRUNTIMES_${triple}_LIBCXXABI_ENABLE_SHARED=OFF" \
+          "-DRUNTIMES_${triple}_LIBCXX_USE_COMPILER_RT=ON" \
+          "-DRUNTIMES_${triple}_LIBCXX_PFP=tagged" \
+          "-DRUNTIMES_${triple}_LIBCXX_ENABLE_SHARED=OFF" \
+          "-DRUNTIMES_${triple}_LIBCXX_TEST_CONFIG=llvm-libc++-static.cfg.in" \
+          "-DRUNTIMES_${triple}_LIBUNWIND_ENABLE_SHARED=OFF" \
+          -DLLVM_LIT_ARGS="-sv --xunit-xml-output test-results.xml --timeout=1500 --time-tests"
+
+    # FIXME: Currently this also runs the sanitizer tests due to compiler-rt
+    # being in LLVM_ENABLE_RUNTIMES for the emulated PAC runtime. Ideally this
+    # would only run the libc++ and libc++abi tests.
+    step "Running the libc++ and libc++abi tests"
+    ${NINJA} -vC "${BUILD_DIR}" check-runtimes
+
+    # FIXME: Debugging support for PFP is incomplete so don't run the LLDB tests
+    # as above for now.
+;;
 generic-static)
     clean
     generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-static.cmake"
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index 81c613421a465..67201c719d1ab 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -340,6 +340,22 @@ def getSuitableClangTidy(cfg):
             ]
         )
     ),
+    Parameter(
+        name="pfp",
+        choices=["none", "untagged", "tagged"],
+        type=str,
+        default="none",
+        help="Whether to build with pointer field protection.",
+        actions=lambda pfp: [] if pfp == "none" else [
+            AddCompileFlag(f"-fexperimental-pointer-field-protection={pfp}"),
+            # Requires support for new relocations which are only implemented in lld for now.
+            AddLinkFlag("-fuse-ld=lld"),
+            # Requires emulated PAC support in compiler-rt.
+            AddCompileFlag("--rtlib=compiler-rt"),
+            AddLinkFlag("--rtlib=compiler-rt"),
+            AddLinkFlag("--unwindlib=libunwind"),
+        ],
+    ),
     Parameter(
         name="enable_experimental",
         choices=[True, False],
diff --git a/libcxxabi/test/CMakeLists.txt b/libcxxabi/test/CMakeLists.txt
index 9eabfb08240b6..447b0fc43b813 100644
--- a/libcxxabi/test/CMakeLists.txt
+++ b/libcxxabi/test/CMakeLists.txt
@@ -80,6 +80,8 @@ if (LLVM_USE_SANITIZER)
   serialize_lit_string_param(SERIALIZED_LIT_PARAMS use_sanitizer "${LLVM_USE_SANITIZER}")
 endif()
 
+serialize_lit_string_param(SERIALIZED_LIT_PARAMS pfp "${LIBCXX_PFP}")
+
 if (CMAKE_CXX_COMPILER_TARGET)
   serialize_lit_string_param(SERIALIZED_LIT_PARAMS target_triple "${CMAKE_CXX_COMPILER_TARGET}")
 else()

Created using spr 1.3.6-beta.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++abi libc++abi C++ Runtime Library. Not libc++. libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

2 participants