https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/150481
Backport d750c6de8a75cbe2bc16c136764195471be8f0b7 Requested by: @ldionne >From ef25cd0673f918cb5ca422e58cf4e9af0c2325f6 Mon Sep 17 00:00:00 2001 From: Konstantin Varlamov <varcons...@gmail.com> Date: Thu, 24 Jul 2025 10:39:48 -0700 Subject: [PATCH] [libc++][hardening] Add an experimental function to log hardening errors (#149452) Unlike `verbose_abort`, this function merely logs the error but does not terminate execution. It is intended to make it possible to implement the `observe` semantic for Hardening. (cherry picked from commit d750c6de8a75cbe2bc16c136764195471be8f0b7) --- libcxx/include/CMakeLists.txt | 1 + libcxx/include/__config | 1 + libcxx/include/__log_hardening_failure | 42 +++++++++++++++++++ libcxx/include/module.modulemap.in | 3 ++ libcxx/src/CMakeLists.txt | 1 + .../experimental/log_hardening_failure.cpp | 31 ++++++++++++++ .../assertions/log_hardening_failure.pass.cpp | 26 ++++++++++++ .../fexperimental-library.compile.pass.cpp | 4 ++ libcxx/utils/libcxx/test/params.py | 1 + 9 files changed, 110 insertions(+) create mode 100644 libcxx/include/__log_hardening_failure create mode 100644 libcxx/src/experimental/log_hardening_failure.cpp create mode 100644 libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 4f2a8dddad92c..85758c671e1e0 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -535,6 +535,7 @@ set(files __locale_dir/time.h __locale_dir/wbuffer_convert.h __locale_dir/wstring_convert.h + __log_hardening_failure __math/abs.h __math/copysign.h __math/error_functions.h diff --git a/libcxx/include/__config b/libcxx/include/__config index 8f215bbe47928..7bb5d9ac77ea4 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -207,6 +207,7 @@ _LIBCPP_HARDENING_MODE_DEBUG # define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY # define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY # define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY +# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY # if defined(__MVS__) # include <features.h> // for __NATIVE_ASCII_F diff --git a/libcxx/include/__log_hardening_failure b/libcxx/include/__log_hardening_failure new file mode 100644 index 0000000000000..d1805306f6b6e --- /dev/null +++ b/libcxx/include/__log_hardening_failure @@ -0,0 +1,42 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOG_HARDENING_FAILURE +#define _LIBCPP___LOG_HARDENING_FAILURE + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// Hardening logging is not available in the C++03 mode; moreover, it is currently only available in the experimental +// library. +#if _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG) + +_LIBCPP_BEGIN_NAMESPACE_STD + +// This function should never be called directly from the code -- it should only be called through the +// `_LIBCPP_LOG_HARDENING_FAILURE` macro. +[[__gnu__::__cold__]] _LIBCPP_EXPORTED_FROM_ABI void __log_hardening_failure(const char* __message) noexcept; + +// _LIBCPP_LOG_HARDENING_FAILURE(message) +// +// This macro is used to log an error without terminating the program (as is the case for hardening failures if the +// `observe` assertion semantic is used). + +# if !defined(_LIBCPP_LOG_HARDENING_FAILURE) +# define _LIBCPP_LOG_HARDENING_FAILURE(__message) ::std::__log_hardening_failure(__message) +# endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC && !defined(_LIBCPP_CXX03_LANG) + +#endif // _LIBCPP___LOG_HARDENING_FAILURE diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 61ba1c381b2b3..53f10ab8a92a5 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -2353,6 +2353,9 @@ module std [system] { header "__std_mbstate_t.h" export * } + module log_hardening_failure { + header "__log_hardening_failure" + } module verbose_abort { header "__verbose_abort" } diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 97fe57a5f24f8..f59fe0e08fccb 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -309,6 +309,7 @@ add_custom_target(cxx DEPENDS ${LIBCXX_BUILD_TARGETS}) # Build the experimental static library set(LIBCXX_EXPERIMENTAL_SOURCES experimental/keep.cpp + experimental/log_hardening_failure.cpp ) if (LIBCXX_PSTL_BACKEND STREQUAL "libdispatch") diff --git a/libcxx/src/experimental/log_hardening_failure.cpp b/libcxx/src/experimental/log_hardening_failure.cpp new file mode 100644 index 0000000000000..f836c15452249 --- /dev/null +++ b/libcxx/src/experimental/log_hardening_failure.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <__config> +#include <__log_hardening_failure> +#include <cstdio> + +#ifdef __BIONIC__ +# include <syslog.h> +#endif // __BIONIC__ + +_LIBCPP_BEGIN_NAMESPACE_STD + +void __log_hardening_failure(const char* message) noexcept { + // Always log the message to `stderr` in case the platform-specific system calls fail. + std::fputs(message, stderr); + +#if defined(__BIONIC__) + // Show error in logcat. The latter two arguments are ignored on Android. + openlog("libc++", 0, 0); + syslog(LOG_CRIT, "%s", message); + closelog(); +#endif +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp b/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp new file mode 100644 index 0000000000000..dda071b8d0296 --- /dev/null +++ b/libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Basic smoke test for `__log_hardening_failure`. +// +// UNSUPPORTED: c++03 +// UNSUPPORTED: libcpp-has-no-experimental-hardening-observe-semantic + +#include <__log_hardening_failure> + +#include "test_macros.h" + +ASSERT_NOEXCEPT(std::__log_hardening_failure("")); + +int main(int, char**) { + std::__log_hardening_failure("Some message"); + // It's difficult to properly test platform-specific logging behavior of the function; just make sure it exists and + // can be called at runtime. + + return 0; +} diff --git a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp index 3cf497da233fb..3d97446ffe826 100644 --- a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp +++ b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp @@ -29,3 +29,7 @@ #if !_LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM # error "-fexperimental-library should enable the syncstream header" #endif + +#if !_LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC +# error "-fexperimental-library should allow using the Hardening observe semantic" +#endif diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py index adfb2a9f69508..93cf29bcdff0d 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -361,6 +361,7 @@ def getSuitableClangTidy(cfg): AddFeature("libcpp-has-no-incomplete-pstl"), AddFeature("libcpp-has-no-experimental-tzdb"), AddFeature("libcpp-has-no-experimental-syncstream"), + AddFeature("libcpp-has-no-experimental-hardening-observe-semantic"), ], ), # TODO: This can be improved once we use a version of GoogleBenchmark that supports the dry-run mode. _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits