[libcxx-commits] [libcxx] [libc++][hardening] Introduce a dylib function to log hardening errors. (PR #148266)
Konstantin Varlamov via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Jul 12 01:58:59 PDT 2025
https://github.com/var-const updated https://github.com/llvm/llvm-project/pull/148266
>From 1fcfec368e34964811270b9a10ad969814e3a691 Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Fri, 11 Jul 2025 10:29:10 -0700
Subject: [PATCH 1/2] [libc++][hardening] Introduce a dylib function to log
hardening errors.
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.
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__configuration/availability.h | 5 ++
libcxx/include/__log_hardening_failure | 45 +++++++++++++++++
libcxx/src/CMakeLists.txt | 1 +
libcxx/src/log_hardening_failure.cpp | 49 +++++++++++++++++++
5 files changed, 101 insertions(+)
create mode 100644 libcxx/include/__log_hardening_failure
create mode 100644 libcxx/src/log_hardening_failure.cpp
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index c8e6d28584623..2f8be540e73e2 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/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index ae58e36b508b4..cb72e927caa9c 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -304,6 +304,11 @@
#define _LIBCPP_AVAILABILITY_HAS_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15
#define _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15_ATTRIBUTE
+// This controls whether the library provides a function to log hardening failures without terminating the program (for
+// the `observe` assertion semantic).
+#define _LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21
+#define _LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE
+
// This controls the availability of the C++17 std::pmr library,
// which is implemented in large part in the built library.
//
diff --git a/libcxx/include/__log_hardening_failure b/libcxx/include/__log_hardening_failure
new file mode 100644
index 0000000000000..73cff0ac64155
--- /dev/null
+++ b/libcxx/include/__log_hardening_failure
@@ -0,0 +1,45 @@
+// -*- 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
+
+_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.
+_LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_OVERRIDABLE_FUNC_VIS void
+__libcpp_log_hardening_failure(const char* message) _NOEXCEPT;
+
+// _LIBCPP_LOG_HARDENING_FAILURE(message)
+//
+// This macro is used to log a hardening failure without terminating the program (as is the case if the `observe`
+// assertion semantic is used). Where possible, it logs in a way that indicates a fatal error (which might include
+// capturing the stack trace).
+#if !defined(_LIBCPP_LOG_HARDENING_FAILURE)
+
+# if !_LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE
+// The decltype is there to suppress -Wunused warnings in this configuration.
+void __use(const char*);
+# define _LIBCPP_LOG_HARDENING_FAILURE(message) (decltype(::std::__use(message))())
+# else
+# define _LIBCPP_LOG_HARDENING_FAILURE(message) ::std::__libcpp_log_hardening_failure(message)
+# endif
+
+#endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE)
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___LOG_HARDENING_FAILURE
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 97fe57a5f24f8..926deb3a1c732 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -30,6 +30,7 @@ set(LIBCXX_SOURCES
include/ryu/ryu.h
include/to_chars_floating_point.h
include/from_chars_floating_point.h
+ log_hardening_failure.cpp
memory.cpp
memory_resource.cpp
new_handler.cpp
diff --git a/libcxx/src/log_hardening_failure.cpp b/libcxx/src/log_hardening_failure.cpp
new file mode 100644
index 0000000000000..7e408a6f010b4
--- /dev/null
+++ b/libcxx/src/log_hardening_failure.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+extern "C" void android_set_abort_message(const char* msg);
+#endif // __BIONIC__
+
+#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
+# include <os/reason_private.h>
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+_LIBCPP_WEAK void __libcpp_log_hardening_failure(const char* message) noexcept {
+ // On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
+#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
+ os_fault_with_payload(
+ /*reason_namespace=*/OS_REASON_SECURITY,
+ /*reason_code=*/0,
+ /*payload=*/nullptr,
+ /*payload_size=*/0,
+ /*reason_string=*/message,
+ /*reason_flags=*/0);
+
+#elif defined(__BIONIC__)
+ // Show error in tombstone.
+ android_set_abort_message(message);
+
+ // Show error in logcat.
+ openlog("libc++", 0, 0);
+ syslog(LOG_CRIT, "%s", message);
+ closelog();
+
+#else
+ fprintf(stderr, "%s", message);
+#endif
+}
+
+_LIBCPP_END_NAMESPACE_STD
>From ef34aded6cfa935fe9d904bb8d4f79bfb705137a Mon Sep 17 00:00:00 2001
From: Konstantin Varlamov <varconst at apple.com>
Date: Sat, 12 Jul 2025 01:58:15 -0700
Subject: [PATCH 2/2] Address feedback
---
libcxx/include/CMakeLists.txt | 2 +-
libcxx/include/__configuration/availability.h | 8 +--
libcxx/include/__log_error | 50 +++++++++++++++++++
libcxx/include/__log_hardening_failure | 45 -----------------
libcxx/include/module.modulemap.in | 3 ++
libcxx/src/CMakeLists.txt | 2 +-
...og_hardening_failure.cpp => log_error.cpp} | 16 +++++-
7 files changed, 73 insertions(+), 53 deletions(-)
create mode 100644 libcxx/include/__log_error
delete mode 100644 libcxx/include/__log_hardening_failure
rename libcxx/src/{log_hardening_failure.cpp => log_error.cpp} (81%)
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 2f8be540e73e2..ceaf45e9e8ae6 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -535,7 +535,7 @@ set(files
__locale_dir/time.h
__locale_dir/wbuffer_convert.h
__locale_dir/wstring_convert.h
- __log_hardening_failure
+ __log_error
__math/abs.h
__math/copysign.h
__math/error_functions.h
diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index cb72e927caa9c..5de0b98ba22a9 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -304,10 +304,10 @@
#define _LIBCPP_AVAILABILITY_HAS_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15
#define _LIBCPP_AVAILABILITY_VERBOSE_ABORT _LIBCPP_INTRODUCED_IN_LLVM_15_ATTRIBUTE
-// This controls whether the library provides a function to log hardening failures without terminating the program (for
-// the `observe` assertion semantic).
-#define _LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21
-#define _LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE
+// This controls whether the library provides a function to log errors without terminating the program (used in
+// particular by the `observe` assertion semantic).
+#define _LIBCPP_AVAILABILITY_HAS_LOG_ERROR _LIBCPP_INTRODUCED_IN_LLVM_21
+#define _LIBCPP_AVAILABILITY_LOG_ERROR _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE
// This controls the availability of the C++17 std::pmr library,
// which is implemented in large part in the built library.
diff --git a/libcxx/include/__log_error b/libcxx/include/__log_error
new file mode 100644
index 0000000000000..9f308898247c4
--- /dev/null
+++ b/libcxx/include/__log_error
@@ -0,0 +1,50 @@
+// -*- 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_ERROR
+#define _LIBCPP___LOG_ERROR
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+enum class _LogErrorReason {
+ // Where possible, it logs in a way that indicates a fatal error (which might include capturing the stack trace).
+ _HardeningFailure
+};
+
+// This function should never be called directly from the code -- it should only be called through the
+// `_LIBCPP_LOG_ERROR` macro.
+_LIBCPP_AVAILABILITY_LOG_ERROR _LIBCPP_EXPORTED_FROM_ABI void
+__log_error(_LogErrorReason __reason, const char* __message) _NOEXCEPT;
+
+// _LIBCPP_LOG_ERROR(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, for example).
+
+#if !defined(_LIBCPP_LOG_ERROR)
+
+# if !_LIBCPP_AVAILABILITY_HAS_LOG_ERROR
+// The decltype is there to suppress -Wunused warnings in this configuration.
+void __use(const char*);
+# define _LIBCPP_LOG_ERROR(__message) (decltype(::std::__use(__message))())
+# else
+# define _LIBCPP_LOG_ERROR(__reason, __message) ::std::__log_error(__reason, __message)
+# endif
+
+#endif // !defined(_LIBCPP_LOG_ERROR)
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___LOG_ERROR
diff --git a/libcxx/include/__log_hardening_failure b/libcxx/include/__log_hardening_failure
deleted file mode 100644
index 73cff0ac64155..0000000000000
--- a/libcxx/include/__log_hardening_failure
+++ /dev/null
@@ -1,45 +0,0 @@
-// -*- 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
-
-_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.
-_LIBCPP_AVAILABILITY_LOG_HARDENING_FAILURE _LIBCPP_OVERRIDABLE_FUNC_VIS void
-__libcpp_log_hardening_failure(const char* message) _NOEXCEPT;
-
-// _LIBCPP_LOG_HARDENING_FAILURE(message)
-//
-// This macro is used to log a hardening failure without terminating the program (as is the case if the `observe`
-// assertion semantic is used). Where possible, it logs in a way that indicates a fatal error (which might include
-// capturing the stack trace).
-#if !defined(_LIBCPP_LOG_HARDENING_FAILURE)
-
-# if !_LIBCPP_AVAILABILITY_HAS_LOG_HARDENING_FAILURE
-// The decltype is there to suppress -Wunused warnings in this configuration.
-void __use(const char*);
-# define _LIBCPP_LOG_HARDENING_FAILURE(message) (decltype(::std::__use(message))())
-# else
-# define _LIBCPP_LOG_HARDENING_FAILURE(message) ::std::__libcpp_log_hardening_failure(message)
-# endif
-
-#endif // !defined(_LIBCPP_LOG_HARDENING_FAILURE)
-
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP___LOG_HARDENING_FAILURE
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 45b9c72a05b82..763d32296a03d 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_error {
+ header "__log_error"
+ }
module verbose_abort {
header "__verbose_abort"
}
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 926deb3a1c732..0e83b2728aa5a 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -30,7 +30,7 @@ set(LIBCXX_SOURCES
include/ryu/ryu.h
include/to_chars_floating_point.h
include/from_chars_floating_point.h
- log_hardening_failure.cpp
+ log_error.cpp
memory.cpp
memory_resource.cpp
new_handler.cpp
diff --git a/libcxx/src/log_hardening_failure.cpp b/libcxx/src/log_error.cpp
similarity index 81%
rename from libcxx/src/log_hardening_failure.cpp
rename to libcxx/src/log_error.cpp
index 7e408a6f010b4..01ddaf65bf618 100644
--- a/libcxx/src/log_hardening_failure.cpp
+++ b/libcxx/src/log_error.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include <__config>
-#include <__log_hardening_failure>
+#include <__log_error>
#include <cstdio>
#ifdef __BIONIC__
@@ -21,7 +21,9 @@ extern "C" void android_set_abort_message(const char* msg);
_LIBCPP_BEGIN_NAMESPACE_STD
-_LIBCPP_WEAK void __libcpp_log_hardening_failure(const char* message) noexcept {
+namespace {
+
+void log_fatal_error(const char* message) noexcept {
// On Apple platforms, use the `os_fault_with_payload` OS function that simulates a crash.
#if defined(__APPLE__) && __has_include(<os/reason_private.h>)
os_fault_with_payload(
@@ -46,4 +48,14 @@ _LIBCPP_WEAK void __libcpp_log_hardening_failure(const char* message) noexcept {
#endif
}
+} // namespace
+
+void __log_error(_LogErrorReason reason, const char* message) noexcept {
+ switch (reason) {
+ case _LogErrorReason::_HardeningFailure:
+ default:
+ log_fatal_error(message);
+ }
+}
+
_LIBCPP_END_NAMESPACE_STD
More information about the libcxx-commits
mailing list