diff options
author | Konstantin Varlamov <varconsteq@gmail.com> | 2025-07-24 10:39:48 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-24 13:39:48 -0400 |
commit | d750c6de8a75cbe2bc16c136764195471be8f0b7 (patch) | |
tree | 73d3f58bf11020314b42b3db14684a11ed5cfbf5 | |
parent | 78faf99c4f1d5eb991325e4e7a02fe56ce070d17 (diff) | |
download | llvm-d750c6de8a75cbe2bc16c136764195471be8f0b7.zip llvm-d750c6de8a75cbe2bc16c136764195471be8f0b7.tar.gz llvm-d750c6de8a75cbe2bc16c136764195471be8f0b7.tar.bz2 |
[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.
-rw-r--r-- | libcxx/include/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libcxx/include/__config | 1 | ||||
-rw-r--r-- | libcxx/include/__log_hardening_failure | 42 | ||||
-rw-r--r-- | libcxx/include/module.modulemap.in | 3 | ||||
-rw-r--r-- | libcxx/src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libcxx/src/experimental/log_hardening_failure.cpp | 31 | ||||
-rw-r--r-- | libcxx/test/libcxx/assertions/log_hardening_failure.pass.cpp | 26 | ||||
-rw-r--r-- | libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp | 4 | ||||
-rw-r--r-- | libcxx/utils/libcxx/test/params.py | 1 |
9 files changed, 110 insertions, 0 deletions
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index cd6583c..ed54751 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 19398dd..3fe377a 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 0000000..d180530 --- /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 ac49720..117556e 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -2355,6 +2355,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 97fe57a..f59fe0e 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 0000000..f836c15 --- /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 0000000..dda071b --- /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 3cf497d..3d97446 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 adfb2a9..93cf29b 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -361,6 +361,7 @@ DEFAULT_PARAMETERS = [ 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. |