[libcxx-commits] [libcxx] [libc++] Add Android assertion handler (PR #198831)

George Burgess IV via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jun 29 09:56:23 PDT 2026


https://github.com/gburgessiv updated https://github.com/llvm/llvm-project/pull/198831

>From 1909910e60b38c6a865ff2f7ed320e60aecae724 Mon Sep 17 00:00:00 2001
From: George Burgess IV <gbiv at google.com>
Date: Fri, 15 May 2026 11:41:11 -0600
Subject: [PATCH 1/5] [libcxx] add Android assertion handler

We're in the process of increasing the use of libcxx hardening in
Android. The handlers we're using deviate from the defaults in two ways:

- All handlers are `nomerge` for better postmortem crash attribution
- `_LIBCPP_VERBOSE_ABORT` is wrapped by a `NOINLINE` function to reduce
  binary size overhead slightly (on x86_64, the diff is ~9B per call
  to _LIBCPP_VERBOSE_ABORT).
---
 .../android/android_assertion_handler.in      | 58 +++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 libcxx/vendor/android/android_assertion_handler.in

diff --git a/libcxx/vendor/android/android_assertion_handler.in b/libcxx/vendor/android/android_assertion_handler.in
new file mode 100644
index 0000000000000..f1d08ff2303c7
--- /dev/null
+++ b/libcxx/vendor/android/android_assertion_handler.in
@@ -0,0 +1,58 @@
+// -*- 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_ANDROID_ASSERTION_HANDLER
+#define __LIBCPP_ANDROID_ASSERTION_HANDLER
+
+#include <__config>
+#include <__log_hardening_failure>
+#include <__verbose_abort>
+#include <__verbose_trap>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+#if _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
+#  define _LIBCPP_ASSERTION_HANDLER(message) ((void)0)
+
+#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_OBSERVE
+#  define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_LOG_HARDENING_FAILURE(message)
+
+#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
+
+// Require `nomerge` for better crash attribution.
+#  define _LIBCPP_ASSERTION_HANDLER(message) \
+  ({ [[clang::nomerge]] _LIBCPP_VERBOSE_TRAP(message); })
+
+#elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// Calling a `void(const char *)` takes fewer bytes than calling a
+// `void(const char *, ...)`.
+[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_NOINLINE
+inline void __libcpp_android_verbose_abort(const char *__message) {
+  _LIBCPP_VERBOSE_ABORT("%s", __message);
+}
+_LIBCPP_END_NAMESPACE_STD
+
+#  define _LIBCPP_ASSERTION_HANDLER(message) \
+  ({ [[clang::nomerge]] ::std::__libcpp_android_verbose_abort(message); })
+
+#else
+
+#  error _LIBCPP_ASSERTION_SEMANTIC must be set to one of the following values: \
+_LIBCPP_ASSERTION_SEMANTIC_IGNORE, \
+_LIBCPP_ASSERTION_SEMANTIC_OBSERVE, \
+_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE, \
+_LIBCPP_ASSERTION_SEMANTIC_ENFORCE
+
+#endif // _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_IGNORE
+
+#endif // __LIBCPP_ANDROID_ASSERTION_HANDLER

>From 959f57290abbc30a2a25ee70862073592bf6d3d6 Mon Sep 17 00:00:00 2001
From: George Burgess IV <gbiv at google.com>
Date: Wed, 20 May 2026 16:51:42 -0600
Subject: [PATCH 2/5] clarify comment

---
 libcxx/vendor/android/android_assertion_handler.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/vendor/android/android_assertion_handler.in b/libcxx/vendor/android/android_assertion_handler.in
index f1d08ff2303c7..76e619d08e25b 100644
--- a/libcxx/vendor/android/android_assertion_handler.in
+++ b/libcxx/vendor/android/android_assertion_handler.in
@@ -34,8 +34,8 @@
 #elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-// Calling a `void(const char *)` takes fewer bytes than calling a
-// `void(const char *, ...)`.
+// Calling this saves code size compared to
+// `__libcpp_verbose_abort("%s", "error message")`.
 [[__noreturn__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_NOINLINE
 inline void __libcpp_android_verbose_abort(const char *__message) {
   _LIBCPP_VERBOSE_ABORT("%s", __message);

>From e5a2f37660aa3831b38041c5a59bc97b6e662cfc Mon Sep 17 00:00:00 2001
From: George Burgess IV <gbiv at google.com>
Date: Wed, 27 May 2026 16:56:39 -0600
Subject: [PATCH 3/5] address feedback

---
 libcxx/vendor/android/android_assertion_handler.in | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/libcxx/vendor/android/android_assertion_handler.in b/libcxx/vendor/android/android_assertion_handler.in
index 76e619d08e25b..1551958ad5646 100644
--- a/libcxx/vendor/android/android_assertion_handler.in
+++ b/libcxx/vendor/android/android_assertion_handler.in
@@ -29,21 +29,23 @@
 
 // Require `nomerge` for better crash attribution.
 #  define _LIBCPP_ASSERTION_HANDLER(message) \
-  ({ [[clang::nomerge]] _LIBCPP_VERBOSE_TRAP(message); })
+  ({ [[clang::__nomerge__]] _LIBCPP_VERBOSE_TRAP(message); })
 
 #elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 // Calling this saves code size compared to
 // `__libcpp_verbose_abort("%s", "error message")`.
-[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_NOINLINE
+// Force it to be `hidden` so we also don't have to pay for runtime
+// relocations.
+[[clang::__nomerge__]] [[__noreturn__]] _LIBCPP_HIDDEN
 inline void __libcpp_android_verbose_abort(const char *__message) {
   _LIBCPP_VERBOSE_ABORT("%s", __message);
 }
 _LIBCPP_END_NAMESPACE_STD
 
 #  define _LIBCPP_ASSERTION_HANDLER(message) \
-  ({ [[clang::nomerge]] ::std::__libcpp_android_verbose_abort(message); })
+  ::std::__libcpp_android_verbose_abort(message)
 
 #else
 

>From 8bd5e03f9f346e08e10b9d8c19d0e018cd15a0d5 Mon Sep 17 00:00:00 2001
From: George Burgess IV <gbiv at google.com>
Date: Fri, 29 May 2026 12:50:05 -0600
Subject: [PATCH 4/5] no hidden, use _Clang

---
 libcxx/vendor/android/android_assertion_handler.in | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/libcxx/vendor/android/android_assertion_handler.in b/libcxx/vendor/android/android_assertion_handler.in
index 1551958ad5646..d48036bd84ad6 100644
--- a/libcxx/vendor/android/android_assertion_handler.in
+++ b/libcxx/vendor/android/android_assertion_handler.in
@@ -29,16 +29,14 @@
 
 // Require `nomerge` for better crash attribution.
 #  define _LIBCPP_ASSERTION_HANDLER(message) \
-  ({ [[clang::__nomerge__]] _LIBCPP_VERBOSE_TRAP(message); })
+  ({ [[_Clang::__nomerge__]] _LIBCPP_VERBOSE_TRAP(message); })
 
 #elif _LIBCPP_ASSERTION_SEMANTIC == _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 // Calling this saves code size compared to
 // `__libcpp_verbose_abort("%s", "error message")`.
-// Force it to be `hidden` so we also don't have to pay for runtime
-// relocations.
-[[clang::__nomerge__]] [[__noreturn__]] _LIBCPP_HIDDEN
+[[_Clang::__nomerge__]] [[__noreturn__]]
 inline void __libcpp_android_verbose_abort(const char *__message) {
   _LIBCPP_VERBOSE_ABORT("%s", __message);
 }

>From 770ec196515b44cc14ffef87f2aef75e3c20ef93 Mon Sep 17 00:00:00 2001
From: George Burgess IV <gbiv at google.com>
Date: Fri, 26 Jun 2026 10:43:03 -0600
Subject: [PATCH 5/5] update cmake cache

---
 libcxx/cmake/caches/AndroidNDK.cmake | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/cmake/caches/AndroidNDK.cmake b/libcxx/cmake/caches/AndroidNDK.cmake
index 1a04b7fbb217d..515078c8396df 100644
--- a/libcxx/cmake/caches/AndroidNDK.cmake
+++ b/libcxx/cmake/caches/AndroidNDK.cmake
@@ -35,3 +35,4 @@ set(CMAKE_CXX_COMPILER_WORKS ON CACHE BOOL "")
 # them.
 set(LIBCXX_TEST_CONFIG "llvm-libc++-android.cfg.in" CACHE STRING "")
 set(LIBCXXABI_TEST_CONFIG "llvm-libc++abi-android.cfg.in" CACHE STRING "")
+set(LIBCXX_ASSERTION_HANDLER_FILE "vendor/android/android_assertion_handler.in" CACHE STRING "")



More information about the libcxx-commits mailing list