[libcxx-commits] [libcxx] WIP [libc++][debugging] P2546R5: Debugging support (PR #81447)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Fri Feb 16 04:11:33 PST 2024


https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/81447

>From 9dd3ca5f46c628e0b150214c0f08420dd6e93851 Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Sat, 13 Jan 2024 12:41:46 +0200
Subject: [PATCH 01/29] [libc++][debugging] P2546R5: Debugging Support

Implements (partially): https://wg21.link/P0543R3
- https://eel.is/c++draft/debugging
---
 libcxx/docs/Status/Cxx2cPapers.csv            |   2 +-
 libcxx/include/CMakeLists.txt                 |   1 +
 libcxx/include/__config                       |   5 +
 libcxx/include/__std_clang_module             |   1 +
 libcxx/include/debugging                      |  44 +++
 libcxx/modules/CMakeLists.txt                 |   1 +
 libcxx/modules/std.cppm.in                    |   1 +
 libcxx/modules/std/debugging.inc              |  17 +
 libcxx/src/CMakeLists.txt                     |   1 +
 libcxx/src/debugging.cpp                      | 324 ++++++++++++++++++
 .../debugging.version.compile.pass.cpp        |  71 ++++
 .../utilities/debugging/breakpoint.pass.cpp   |  24 ++
 .../breakpoint_if_debugging.pass.cpp          |  24 ++
 .../debugging/is_debugger_present.pass.cpp    |  24 ++
 .../generate_feature_test_macro_components.py |   2 +-
 15 files changed, 540 insertions(+), 2 deletions(-)
 create mode 100644 libcxx/include/debugging
 create mode 100644 libcxx/modules/std/debugging.inc
 create mode 100644 libcxx/src/debugging.cpp
 create mode 100644 libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint.pass.cpp
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
 create mode 100644 libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp

diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index a62faee4f44e22..bc391e198be4e7 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -29,7 +29,7 @@
 "","","","","","",""
 "`P0543R3 <https://wg21.link/P0543R3>`__","LWG","Saturation arithmetic","Kona November 2023","|Complete|","18.0",""
 "`P2407R5 <https://wg21.link/P2407R5>`__","LWG","Freestanding Library: Partial Classes","Kona November 2023","","",""
-"`P2546R5 <https://wg21.link/P2546R5>`__","LWG","Debugging Support","Kona November 2023","","",""
+"`P2546R5 <https://wg21.link/P2546R5>`__","LWG","Debugging Support","Kona November 2023","|Partial|","19.0",""
 "`P2905R2 <https://wg21.link/P2905R2>`__","LWG","Runtime format strings","Kona November 2023","|Complete|","18.0","|format| |DR|"
 "`P2918R2 <https://wg21.link/P2918R2>`__","LWG","Runtime format strings II","Kona November 2023","|Complete|","18.0","|format|"
 "`P2909R4 <https://wg21.link/P2909R4>`__","LWG","Fix formatting of code units as integers (Dude, where’s my ``char``?)","Kona November 2023","|Complete|","18.0","|format| |DR|"
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index b44068357e7089..52f28da2a20af7 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -914,6 +914,7 @@ set(files
   cuchar
   cwchar
   cwctype
+  debugging
   deque
   errno.h
   exception
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 0797880cb2f5da..4d19f423dc71eb 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -516,6 +516,7 @@ _LIBCPP_HARDENING_MODE_DEBUG
 #    define _LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN
 #    define _LIBCPP_HAS_NO_INCOMPLETE_TZDB
 #    define _LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM
+#    define _LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING
 #  endif
 
 // Need to detect which libc we're using if we're on Linux.
@@ -1567,6 +1568,10 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c
 #    define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
 #  endif
 
+#  if defined(__APPLE__) || defined(__linux__) || defined (_WIN32)
+#    define _LIBCPP_HAS_DEBUGGING
+#  endif
+
 #endif // __cplusplus
 
 #endif // _LIBCPP___CONFIG
diff --git a/libcxx/include/__std_clang_module b/libcxx/include/__std_clang_module
index 18d6ce6b46c1f6..7dcee53c68b399 100644
--- a/libcxx/include/__std_clang_module
+++ b/libcxx/include/__std_clang_module
@@ -81,6 +81,7 @@
 #if !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
 #  include <cwctype>
 #endif
+#include <debugging>
 #include <deque>
 #include <errno.h>
 #include <exception>
diff --git a/libcxx/include/debugging b/libcxx/include/debugging
new file mode 100644
index 00000000000000..07d6b45db30175
--- /dev/null
+++ b/libcxx/include/debugging
@@ -0,0 +1,44 @@
+// -*- 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_DEBUGGING
+#define _LIBCPP_DEBUGGING
+
+/*
+// all freestanding
+namespace std {
+  // [debugging.utility], utility
+  void breakpoint() noexcept;
+  void breakpoint_if_debugging() noexcept;
+  bool is_debugger_present() noexcept;
+}
+*/
+
+#include <__config>
+#include <version>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+_LIBCPP_EXPORTED_FROM_ABI void breakpoint() noexcept;
+
+_LIBCPP_EXPORTED_FROM_ABI void breakpoint_if_debugging() noexcept;
+
+_LIBCPP_EXPORTED_FROM_ABI bool is_debugger_present() noexcept;
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_DEBUGGING
diff --git a/libcxx/modules/CMakeLists.txt b/libcxx/modules/CMakeLists.txt
index 0dea8cfca94ac3..bfafdc9f4fe242 100644
--- a/libcxx/modules/CMakeLists.txt
+++ b/libcxx/modules/CMakeLists.txt
@@ -37,6 +37,7 @@ set(LIBCXX_MODULE_STD_SOURCES
   std/cuchar.inc
   std/cwchar.inc
   std/cwctype.inc
+  std/debugging.inc
   std/deque.inc
   std/exception.inc
   std/execution.inc
diff --git a/libcxx/modules/std.cppm.in b/libcxx/modules/std.cppm.in
index b8d89130aae989..0fb465f49301d1 100644
--- a/libcxx/modules/std.cppm.in
+++ b/libcxx/modules/std.cppm.in
@@ -65,6 +65,7 @@ module;
 #if !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
 #  include <cwctype>
 #endif
+#include <debugging>
 #include <deque>
 #include <exception>
 #include <execution>
diff --git a/libcxx/modules/std/debugging.inc b/libcxx/modules/std/debugging.inc
new file mode 100644
index 00000000000000..a65890d8e8167a
--- /dev/null
+++ b/libcxx/modules/std/debugging.inc
@@ -0,0 +1,17 @@
+// -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+export namespace std {
+#if _LIBCPP_STD_VER >= 26
+  // [debugging.utility], utility
+  using stgd::breakpoint;
+  using stgd::breakpoint_if_debugging;
+  using stgd::is_debugger_present;
+#endif
+} // namespace std
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 44a088663463c9..a314e85a2e1083 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -10,6 +10,7 @@ set(LIBCXX_SOURCES
   chrono.cpp
   error_category.cpp
   exception.cpp
+  debugging.cpp
   filesystem/filesystem_clock.cpp
   filesystem/filesystem_error.cpp
   filesystem/path_parser.h
diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
new file mode 100644
index 00000000000000..738addc5e0c9bb
--- /dev/null
+++ b/libcxx/src/debugging.cpp
@@ -0,0 +1,324 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <debugging>
+
+#if defined(_LIBCPP_WIN32API)
+#  define WIN32_LEAN_AND_MEAN
+#  define NOMINMAX
+#  include <windows.h>
+#elif defined(__APPLE__)
+#  include <stdbool.h>
+#  include <sys/sysctl.h>
+#  include <sys/types.h>
+#  include <unistd.h>
+#elif defined(__linux__)
+#  include <csignal>
+#  include <fstream>
+#  include <regex>
+#  include <sstream>
+#  include <string>
+// Linux
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace __impl {
+
+// Linux
+//   https://docs.kernel.org/filesystems/proc.html
+//   https://stackoverflow.com/a/49079078
+//   https://linuxsecurity.com/features/anti-debugging-for-noobs-part-1
+//   https://linuxsecurity.com/features/hacker-s-corner-complete-guide-to-anti-debugging-in-linux-part-2
+//   https://linuxsecurity.com/features/hacker-s-corner-complete-guide-to-anti-debugging-in-linux-part-3
+
+// macOS
+//   https://developer.apple.com/library/archive/qa/qa1361/_index.html
+//   https://ladydebug.com/blog/2020/09/02/isdebuggerpresent-for-mac-osx/
+//   https://github.com/freebsd/freebsd-src/blob/7f3184ba797452703904d33377dada5f0f8eae96/sys/sys/proc.h#L822
+
+#if defined(_LIBCPP_WIN32API)
+
+void __breakpoint() noexcept { void DebugBreak(); }
+
+bool __is_debugger_present() noexcept { return IsDebuggerPresent(); }
+
+#elif defined(__APPLE__) || defined(__FreeBSD__)
+
+// TODO
+void __breakpoint() {
+#  ifdef _LIBCPP_HARDENING_MODE_DEBUG
+#    if __has_builtin(__builtin_debugtrap)
+  __builtin_debugtrap();
+#    else
+  raise(SIGTRAP);
+#    endif
+#  endif
+}
+
+bool __is_debugger_present() noexcept {
+  // Technical Q&A QA1361: Detecting the Debugger
+  // https://github.com/freebsd/freebsd-src/blob/7f3184ba797452703904d33377dada5f0f8eae96/sys/sys/proc.h#L822
+
+  int junk;
+  int mib[4];
+  struct kinfo_proc info;
+  size_t size;
+
+  // Initialize the flags so that, if sysctl fails for some bizarre
+  // reason, we get a predictable result.
+
+  info.kp_proc.p_flag = 0;
+
+  // Initialize mib, which tells sysctl the info we want, in this case
+  // we're looking for information about a specific process ID.
+
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_PROC;
+  mib[2] = KERN_PROC_PID;
+  mib[3] = getpid();
+
+  // Call sysctl.
+
+  size = sizeof(info);
+  junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
+  _LIBCPP_ASSERT_INTERNAL(junk == 0, "'sysctl' runtime error");
+
+  // We're being debugged if the P_TRACED flag is set.
+
+  return ((info.kp_proc.p_flag & P_TRACED) != 0);
+}
+
+#elif defined(__linux__)
+
+void __breakpoint() noexcept {
+#  if defined SIGTRAP
+  raise(SIGTRAP);
+#  else
+  raise(SIGABRT);
+#  endif
+}
+
+bool __is_debugger_present() noexcept {
+  // https://docs.kernel.org/filesystems/proc.html
+
+  try {
+    // Get the status information of a process by reading the file /proc/PID/status.
+    // The link 'self' points to the process reading the file system.
+    ifstream status_file{"/proc/self/status"};
+    if (!status_file.is_open())
+      return false;
+#  if 0
+    // string line;
+    // while (std::getline(status_file, line)) {
+    for (string line; std::getline(status_file, line);) {
+      istringstream ss{line};
+      string field;
+      string value;
+
+      ss >> field >> value;
+
+      // TracerPid - PID of process tracing this process (0 if not, or the tracer is outside of the current pid
+      // namespace).
+      if ((field == "TracerPid:") && (value != "0")) {
+        return true;
+      }
+    }
+#  elif 0
+    std::string line;
+    while (status_file >> line) {
+      if (line == "TracerPid:") {
+        int pid;
+        status_file >> pid;
+        return pid != 0;
+      }
+      std::getline(status_file, line);
+    }
+#  else
+    // This is too slow
+    const regex reg_ex{R"(^TracerPid:\s+(.+)$)"};
+    smatch match;
+    string line;
+    while (std::getline(status_file, line)) {
+      if (regex_match(line, match, reg_ex)) {
+        if (match[1] != "0") [[likely]]
+          return true;
+        return false;
+      }
+    }
+#  endif
+  } catch (...) {
+    return false;
+  }
+
+  return false;
+}
+
+#else
+#  define __LIBCPP_DEBUGGER_NOT_IMPLEMENTED 1
+#endif
+
+} // namespace __impl
+
+_LIBCPP_EXPORTED_FROM_ABI void breakpoint() noexcept {
+#ifdef __LIBCPP_DEBUGGER_NOT_IMPLEMENTED
+  _LIBCPP_ASSERT_INTERNAL(false, "'std::is_debugger_present' is not implemented on this platform.");
+#else
+  __impl::__breakpoint();
+#endif
+}
+
+_LIBCPP_EXPORTED_FROM_ABI void breakpoint_if_debugging() noexcept {
+#ifdef __LIBCPP_DEBUGGER_NOT_IMPLEMENTED
+  _LIBCPP_ASSERT_INTERNAL(false, "'std::breakpoint_if_debugging' is not implemented on this platform.");
+#else
+  if (__impl::__is_debugger_present())
+    __impl::__breakpoint();
+#endif
+}
+
+_LIBCPP_EXPORTED_FROM_ABI bool is_debugger_present() noexcept {
+#ifdef __LIBCPP_DEBUGGER_NOT_IMPLEMENTED
+  _LIBCPP_ASSERT_INTERNAL(false, "'std::is_debugger_present' is not implemented on this platform.");
+  return false;
+#else
+  return __impl::__is_debugger_present();
+#endif
+}
+
+#if 0
+#  include <regex>
+#  include <sstream>
+#  include <string>
+
+static std::string status_file_str = R"(
+Name:	file:// Content
+Umask:	0002
+State:	R (running)
+Tgid:	84655
+Ngid:	0
+Pid:	84655
+PPid:	3287
+TracerPid:	0
+Uid:	1000	1000	1000	1000
+Gid:	1000	1000	1000	1000
+FDSize:	512
+Groups:	4 24 27 30 46 122 134 135 1000 
+NStgid:	84655
+NSpid:	84655
+NSpgid:	1923
+NSsid:	1923
+Kthread:	0
+VmPeak:	 2387520 kB
+VmSize:	 2387520 kB
+VmLck:	       0 kB
+VmPin:	       0 kB
+VmHWM:	   71680 kB
+VmRSS:	   71680 kB
+RssAnon:	   11904 kB
+RssFile:	   58752 kB
+RssShmem:	    1024 kB
+VmData:	   30796 kB
+VmStk:	     148 kB
+VmExe:	     700 kB
+VmLib:	  115052 kB
+VmPTE:	     420 kB
+VmSwap:	       0 kB
+HugetlbPages:	       0 kB
+CoreDumping:	0
+THP_enabled:	1
+untag_mask:	0xffffffffffffffff
+Threads:	21
+SigQ:	0/30009
+SigPnd:	0000000000000000
+ShdPnd:	0000000000000000
+SigBlk:	0000000000000000
+SigIgn:	0000000000011002
+SigCgt:	0000000f408004f8
+CapInh:	0000000000000000
+CapPrm:	0000000000000000
+CapEff:	0000000000000000
+CapBnd:	000001ffffffffff
+CapAmb:	0000000000000000
+NoNewPrivs:	1
+Seccomp:	2
+Seccomp_filters:	3
+Speculation_Store_Bypass:	thread vulnerable
+SpeculationIndirectBranch:	conditional enabled
+Cpus_allowed:	ff
+Cpus_allowed_list:	0-7
+Mems_allowed:	00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
+Mems_allowed_list:	0
+voluntary_ctxt_switches:	31
+nonvoluntary_ctxt_switches:	18
+)";
+
+static void DebuggerPresent01(benchmark::State& state) {
+  // Code before the loop is not measured
+  std::istringstream status_file{status_file_str};
+  
+  for (auto _ : state) {
+    for (std::string line; std::getline(status_file, line);) {
+      std::istringstream ss{line};
+      std::string field;
+      std::string value;
+      ss >> field >> value;
+      if ((field == "TracerPid:") && (value != "0")) {
+        goto DP01;
+      }
+    }
+  }
+DP01:
+}
+BENCHMARK(DebuggerPresent01);
+
+static void DebuggerPresent02(benchmark::State& state) {
+  // Code before the loop is not measured
+  std::istringstream status_file{status_file_str};
+  
+  for (auto _ : state) {
+    std::string line;
+    while (status_file >> line) {
+      if (line == "TracerPid:") {
+        int pid;
+        status_file >> pid;
+        auto a = pid != 0;
+        benchmark::DoNotOptimize(a);
+        goto DP02;
+      }
+      std::getline(status_file, line);
+    }
+DP02:
+  }
+}
+BENCHMARK(DebuggerPresent02);
+
+static void DebuggerPresent03(benchmark::State& state) {
+  // Code before the loop is not measured
+  std::istringstream status_file{status_file_str};
+  
+  for (auto _ : state) {
+    std::smatch match;
+    std::string line;
+    const std::regex reg_ex{R"(^TracerPid:\s+(.+)$)"};
+    while (std::getline(status_file, line)) {
+      if (std::regex_match(line, match, reg_ex)) {
+        if (match[1] != "0") [[likely]]
+          goto DP03;
+        goto DP03;
+      }
+    }
+DP03:
+  }
+}
+BENCHMARK(DebuggerPresent03);
+
+#endif
+
+_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp
new file mode 100644
index 00000000000000..a22b404a634fd2
--- /dev/null
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+//
+// clang-format off
+
+// <debugging>
+
+// Test the feature test macros defined by <debugging>
+
+/*  Constant               Value
+    __cpp_lib_debugging    202311L [C++26]
+*/
+
+#include <debugging>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 14
+
+# ifdef __cpp_lib_debugging
+#   error "__cpp_lib_debugging should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_debugging
+#   error "__cpp_lib_debugging should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_debugging
+#   error "__cpp_lib_debugging should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# ifdef __cpp_lib_debugging
+#   error "__cpp_lib_debugging should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 23
+
+# ifdef __cpp_lib_debugging
+#   error "__cpp_lib_debugging should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER > 23
+
+# if !defined(_LIBCPP_VERSION)
+#   ifndef __cpp_lib_debugging
+#     error "__cpp_lib_debugging should be defined in c++26"
+#   endif
+#   if __cpp_lib_debugging != 202311L
+#     error "__cpp_lib_debugging should have the value 202311L in c++26"
+#   endif
+# else // _LIBCPP_VERSION
+#   ifdef __cpp_lib_debugging
+#     error "__cpp_lib_debugging should not be defined because it is unimplemented in libc++!"
+#   endif
+# endif
+
+#endif // TEST_STD_VER > 23
+
diff --git a/libcxx/test/std/utilities/debugging/breakpoint.pass.cpp b/libcxx/test/std/utilities/debugging/breakpoint.pass.cpp
new file mode 100644
index 00000000000000..7389600fa191ee
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <debugging>
+
+// void breakpoint() noexcept;
+
+#include <cassert>
+#include <debugging>
+
+void test() { static_assert(noexcept(breakpoint())); }
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
new file mode 100644
index 00000000000000..453ba9155b2236
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <debugging>
+
+// void breakpoint_if_debugging() noexcept;
+
+#include <cassert>
+#include <debugging>
+
+void test() { static_assert(noexcept(breakpoint_if_debugging())); }
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
new file mode 100644
index 00000000000000..88b271de9ce79d
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <debugging>
+
+// bool is_debugger_present() noexcept;
+
+#include <cassert>
+#include <debugging>
+
+void test() { static_assert(noexcept(is_debugger_present())); }
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 9e7ea86f2daa80..b2d1565055c516 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -401,7 +401,7 @@ def add_version_header(tc):
             "name": "__cpp_lib_debugging",
             "values": {"c++26": 202311},  # P2546R5 Debugging Support
             "headers": ["debugging"],
-            "unimplemented": True,
+            "unimplemented": True, # Implemented on Linux, macOS, Windows
         },
         {
             "name": "__cpp_lib_destroying_delete",

>From 73ad28c5ecef5d8d8663d77389c30e587943b035 Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Tue, 23 Jan 2024 10:19:32 +0200
Subject: [PATCH 02/29] Cleanup

---
 libcxx/src/debugging.cpp | 249 ++++++---------------------------------
 1 file changed, 38 insertions(+), 211 deletions(-)

diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index 738addc5e0c9bb..75fbb186e386fd 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -13,45 +13,30 @@
 #  define WIN32_LEAN_AND_MEAN
 #  define NOMINMAX
 #  include <windows.h>
-#elif defined(__APPLE__)
-#  include <stdbool.h>
+#elif defined(__APPLE__) || defined(__FreeBSD__)
+#  include <csignal>
 #  include <sys/sysctl.h>
 #  include <sys/types.h>
 #  include <unistd.h>
 #elif defined(__linux__)
 #  include <csignal>
 #  include <fstream>
-#  include <regex>
 #  include <sstream>
 #  include <string>
-// Linux
 #endif
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 namespace __impl {
 
-// Linux
-//   https://docs.kernel.org/filesystems/proc.html
-//   https://stackoverflow.com/a/49079078
-//   https://linuxsecurity.com/features/anti-debugging-for-noobs-part-1
-//   https://linuxsecurity.com/features/hacker-s-corner-complete-guide-to-anti-debugging-in-linux-part-2
-//   https://linuxsecurity.com/features/hacker-s-corner-complete-guide-to-anti-debugging-in-linux-part-3
-
-// macOS
-//   https://developer.apple.com/library/archive/qa/qa1361/_index.html
-//   https://ladydebug.com/blog/2020/09/02/isdebuggerpresent-for-mac-osx/
-//   https://github.com/freebsd/freebsd-src/blob/7f3184ba797452703904d33377dada5f0f8eae96/sys/sys/proc.h#L822
+// breakpoint()
 
 #if defined(_LIBCPP_WIN32API)
 
 void __breakpoint() noexcept { void DebugBreak(); }
 
-bool __is_debugger_present() noexcept { return IsDebuggerPresent(); }
+#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__)
 
-#elif defined(__APPLE__) || defined(__FreeBSD__)
-
-// TODO
 void __breakpoint() {
 #  ifdef _LIBCPP_HARDENING_MODE_DEBUG
 #    if __has_builtin(__builtin_debugtrap)
@@ -62,9 +47,28 @@ void __breakpoint() {
 #  endif
 }
 
+#else
+
+void __breakpoint() noexcept {
+  _LIBCPP_ASSERT_INTERNAL(false, "'std::breakpoint()' is not implemented on this platform.");
+  return false;
+}
+
+#endif
+
+// is_debugger_present()
+
+#if defined(_LIBC_WIN32API)
+
+bool __is_debugger_present() noexcept { return IsDebuggerPresent(); }
+
+#elif defined(__APPLE__) || defined(__FreeBSD__)
+
+// TODO
+
 bool __is_debugger_present() noexcept {
   // Technical Q&A QA1361: Detecting the Debugger
-  // https://github.com/freebsd/freebsd-src/blob/7f3184ba797452703904d33377dada5f0f8eae96/sys/sys/proc.h#L822
+  // https://developer.apple.com/library/archive/qa/qa1361/_index.html
 
   int junk;
   int mib[4];
@@ -91,20 +95,13 @@ bool __is_debugger_present() noexcept {
   _LIBCPP_ASSERT_INTERNAL(junk == 0, "'sysctl' runtime error");
 
   // We're being debugged if the P_TRACED flag is set.
+  // https://github.com/freebsd/freebsd-src/blob/7f3184ba797452703904d33377dada5f0f8eae96/sys/sys/proc.h#L822
 
   return ((info.kp_proc.p_flag & P_TRACED) != 0);
 }
 
 #elif defined(__linux__)
 
-void __breakpoint() noexcept {
-#  if defined SIGTRAP
-  raise(SIGTRAP);
-#  else
-  raise(SIGABRT);
-#  endif
-}
-
 bool __is_debugger_present() noexcept {
   // https://docs.kernel.org/filesystems/proc.html
 
@@ -114,45 +111,16 @@ bool __is_debugger_present() noexcept {
     ifstream status_file{"/proc/self/status"};
     if (!status_file.is_open())
       return false;
-#  if 0
-    // string line;
-    // while (std::getline(status_file, line)) {
-    for (string line; std::getline(status_file, line);) {
-      istringstream ss{line};
-      string field;
-      string value;
-
-      ss >> field >> value;
-
-      // TracerPid - PID of process tracing this process (0 if not, or the tracer is outside of the current pid
-      // namespace).
-      if ((field == "TracerPid:") && (value != "0")) {
-        return true;
-      }
-    }
-#  elif 0
-    std::string line;
-    while (status_file >> line) {
-      if (line == "TracerPid:") {
+
+    std::string token;
+    while (status_file >> token) {
+      if (token == "TracerPid:") {
         int pid;
         status_file >> pid;
         return pid != 0;
       }
-      std::getline(status_file, line);
-    }
-#  else
-    // This is too slow
-    const regex reg_ex{R"(^TracerPid:\s+(.+)$)"};
-    smatch match;
-    string line;
-    while (std::getline(status_file, line)) {
-      if (regex_match(line, match, reg_ex)) {
-        if (match[1] != "0") [[likely]]
-          return true;
-        return false;
-      }
+      std::getline(status_file, token);
     }
-#  endif
   } catch (...) {
     return false;
   }
@@ -161,164 +129,23 @@ bool __is_debugger_present() noexcept {
 }
 
 #else
-#  define __LIBCPP_DEBUGGER_NOT_IMPLEMENTED 1
+
+bool __is_debugger_present() noexcept {
+  _LIBCPP_ASSERT_INTERNAL(false, "'std::is_debugger_present()' is not implemented on this platform.");
+  return false;
+}
+
 #endif
 
 } // namespace __impl
 
-_LIBCPP_EXPORTED_FROM_ABI void breakpoint() noexcept {
-#ifdef __LIBCPP_DEBUGGER_NOT_IMPLEMENTED
-  _LIBCPP_ASSERT_INTERNAL(false, "'std::is_debugger_present' is not implemented on this platform.");
-#else
-  __impl::__breakpoint();
-#endif
-}
+_LIBCPP_EXPORTED_FROM_ABI void breakpoint() noexcept { __impl::__breakpoint(); }
 
 _LIBCPP_EXPORTED_FROM_ABI void breakpoint_if_debugging() noexcept {
-#ifdef __LIBCPP_DEBUGGER_NOT_IMPLEMENTED
-  _LIBCPP_ASSERT_INTERNAL(false, "'std::breakpoint_if_debugging' is not implemented on this platform.");
-#else
   if (__impl::__is_debugger_present())
     __impl::__breakpoint();
-#endif
 }
 
-_LIBCPP_EXPORTED_FROM_ABI bool is_debugger_present() noexcept {
-#ifdef __LIBCPP_DEBUGGER_NOT_IMPLEMENTED
-  _LIBCPP_ASSERT_INTERNAL(false, "'std::is_debugger_present' is not implemented on this platform.");
-  return false;
-#else
-  return __impl::__is_debugger_present();
-#endif
-}
-
-#if 0
-#  include <regex>
-#  include <sstream>
-#  include <string>
-
-static std::string status_file_str = R"(
-Name:	file:// Content
-Umask:	0002
-State:	R (running)
-Tgid:	84655
-Ngid:	0
-Pid:	84655
-PPid:	3287
-TracerPid:	0
-Uid:	1000	1000	1000	1000
-Gid:	1000	1000	1000	1000
-FDSize:	512
-Groups:	4 24 27 30 46 122 134 135 1000 
-NStgid:	84655
-NSpid:	84655
-NSpgid:	1923
-NSsid:	1923
-Kthread:	0
-VmPeak:	 2387520 kB
-VmSize:	 2387520 kB
-VmLck:	       0 kB
-VmPin:	       0 kB
-VmHWM:	   71680 kB
-VmRSS:	   71680 kB
-RssAnon:	   11904 kB
-RssFile:	   58752 kB
-RssShmem:	    1024 kB
-VmData:	   30796 kB
-VmStk:	     148 kB
-VmExe:	     700 kB
-VmLib:	  115052 kB
-VmPTE:	     420 kB
-VmSwap:	       0 kB
-HugetlbPages:	       0 kB
-CoreDumping:	0
-THP_enabled:	1
-untag_mask:	0xffffffffffffffff
-Threads:	21
-SigQ:	0/30009
-SigPnd:	0000000000000000
-ShdPnd:	0000000000000000
-SigBlk:	0000000000000000
-SigIgn:	0000000000011002
-SigCgt:	0000000f408004f8
-CapInh:	0000000000000000
-CapPrm:	0000000000000000
-CapEff:	0000000000000000
-CapBnd:	000001ffffffffff
-CapAmb:	0000000000000000
-NoNewPrivs:	1
-Seccomp:	2
-Seccomp_filters:	3
-Speculation_Store_Bypass:	thread vulnerable
-SpeculationIndirectBranch:	conditional enabled
-Cpus_allowed:	ff
-Cpus_allowed_list:	0-7
-Mems_allowed:	00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
-Mems_allowed_list:	0
-voluntary_ctxt_switches:	31
-nonvoluntary_ctxt_switches:	18
-)";
-
-static void DebuggerPresent01(benchmark::State& state) {
-  // Code before the loop is not measured
-  std::istringstream status_file{status_file_str};
-  
-  for (auto _ : state) {
-    for (std::string line; std::getline(status_file, line);) {
-      std::istringstream ss{line};
-      std::string field;
-      std::string value;
-      ss >> field >> value;
-      if ((field == "TracerPid:") && (value != "0")) {
-        goto DP01;
-      }
-    }
-  }
-DP01:
-}
-BENCHMARK(DebuggerPresent01);
-
-static void DebuggerPresent02(benchmark::State& state) {
-  // Code before the loop is not measured
-  std::istringstream status_file{status_file_str};
-  
-  for (auto _ : state) {
-    std::string line;
-    while (status_file >> line) {
-      if (line == "TracerPid:") {
-        int pid;
-        status_file >> pid;
-        auto a = pid != 0;
-        benchmark::DoNotOptimize(a);
-        goto DP02;
-      }
-      std::getline(status_file, line);
-    }
-DP02:
-  }
-}
-BENCHMARK(DebuggerPresent02);
-
-static void DebuggerPresent03(benchmark::State& state) {
-  // Code before the loop is not measured
-  std::istringstream status_file{status_file_str};
-  
-  for (auto _ : state) {
-    std::smatch match;
-    std::string line;
-    const std::regex reg_ex{R"(^TracerPid:\s+(.+)$)"};
-    while (std::getline(status_file, line)) {
-      if (std::regex_match(line, match, reg_ex)) {
-        if (match[1] != "0") [[likely]]
-          goto DP03;
-        goto DP03;
-      }
-    }
-DP03:
-  }
-}
-BENCHMARK(DebuggerPresent03);
-
-#endif
+_LIBCPP_EXPORTED_FROM_ABI bool is_debugger_present() noexcept { return __impl::__is_debugger_present(); }
 
 _LIBCPP_END_NAMESPACE_STD

>From fa6f1d746d4777cf5a5a5eeb8b89ea67a7294b07 Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Tue, 23 Jan 2024 11:25:28 +0200
Subject: [PATCH 03/29] Implementation: Apple, FreeBSD, Linux, Windows

---
 libcxx/src/debugging.cpp | 45 +++++++++++++++++-----------------------
 1 file changed, 19 insertions(+), 26 deletions(-)

diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index 75fbb186e386fd..eee0234a21c682 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -27,8 +27,6 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-namespace __impl {
-
 // breakpoint()
 
 #if defined(_LIBCPP_WIN32API)
@@ -38,23 +36,21 @@ void __breakpoint() noexcept { void DebugBreak(); }
 #elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__)
 
 void __breakpoint() {
-#  ifdef _LIBCPP_HARDENING_MODE_DEBUG
-#    if __has_builtin(__builtin_debugtrap)
+#  if __has_builtin(__builtin_debugtrap)
   __builtin_debugtrap();
-#    else
+#  else
   raise(SIGTRAP);
-#    endif
 #  endif
 }
 
 #else
 
 void __breakpoint() noexcept {
-  _LIBCPP_ASSERT_INTERNAL(false, "'std::breakpoint()' is not implemented on this platform.");
+  static_assert(false, "'std::breakpoint()' is not implemented on this platform.");
   return false;
 }
 
-#endif
+#endif // defined(_LIBCPP_WIN32API)
 
 // is_debugger_present()
 
@@ -64,8 +60,6 @@ bool __is_debugger_present() noexcept { return IsDebuggerPresent(); }
 
 #elif defined(__APPLE__) || defined(__FreeBSD__)
 
-// TODO
-
 bool __is_debugger_present() noexcept {
   // Technical Q&A QA1361: Detecting the Debugger
   // https://developer.apple.com/library/archive/qa/qa1361/_index.html
@@ -109,19 +103,20 @@ bool __is_debugger_present() noexcept {
     // Get the status information of a process by reading the file /proc/PID/status.
     // The link 'self' points to the process reading the file system.
     ifstream status_file{"/proc/self/status"};
-    if (!status_file.is_open())
+    if (!status_file.is_open()) {
+      _LIBCPP_ASSERT_INTERNAL(false, "Could not open '/proc/self/status' for reading.");
       return false;
+    }
 
-    std::string token;
-    while (status_file >> token) {
-      if (token == "TracerPid:") {
-        int pid;
-        status_file >> pid;
-        return pid != 0;
+    const string tracerPid{"TracerPid"};
+    for (string line; getline(status_file, line);) {
+      if (line.starts_with(tracerPid)) {
+        string value = line.substr(tracerPid.size() + 1);
+        return stoll(value) != 0;
       }
-      std::getline(status_file, token);
     }
   } catch (...) {
+    _LIBCPP_ASSERT_INTERNAL(false, "Failed to read '/proc/self/status'.");
     return false;
   }
 
@@ -131,21 +126,19 @@ bool __is_debugger_present() noexcept {
 #else
 
 bool __is_debugger_present() noexcept {
-  _LIBCPP_ASSERT_INTERNAL(false, "'std::is_debugger_present()' is not implemented on this platform.");
+  static_assert(false, "'std::is_debugger_present()' is not implemented on this platform.");
   return false;
 }
 
-#endif
-
-} // namespace __impl
+#endif // defined(_LIBCPP_WIN32API)
 
-_LIBCPP_EXPORTED_FROM_ABI void breakpoint() noexcept { __impl::__breakpoint(); }
+_LIBCPP_EXPORTED_FROM_ABI void breakpoint() noexcept { __breakpoint(); }
 
 _LIBCPP_EXPORTED_FROM_ABI void breakpoint_if_debugging() noexcept {
-  if (__impl::__is_debugger_present())
-    __impl::__breakpoint();
+  if (__is_debugger_present())
+    __breakpoint();
 }
 
-_LIBCPP_EXPORTED_FROM_ABI bool is_debugger_present() noexcept { return __impl::__is_debugger_present(); }
+_LIBCPP_EXPORTED_FROM_ABI bool is_debugger_present() noexcept { return __is_debugger_present(); }
 
 _LIBCPP_END_NAMESPACE_STD

>From b1c767619cb9eb3159cb4720a387b2d474ab8d1b Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Tue, 23 Jan 2024 14:40:31 +0200
Subject: [PATCH 04/29] Implementation: Linux

... the new implementation is 3-4x faster than the previous one.
---
 libcxx/src/debugging.cpp | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index eee0234a21c682..615139f51f154c 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -21,7 +21,6 @@
 #elif defined(__linux__)
 #  include <csignal>
 #  include <fstream>
-#  include <sstream>
 #  include <string>
 #endif
 
@@ -108,15 +107,17 @@ bool __is_debugger_present() noexcept {
       return false;
     }
 
-    const string tracerPid{"TracerPid"};
-    for (string line; getline(status_file, line);) {
-      if (line.starts_with(tracerPid)) {
-        string value = line.substr(tracerPid.size() + 1);
-        return stoll(value) != 0;
+    std::string token;
+    while (status_file >> token) {
+      if (token == "TracerPid:") {
+        int pid;
+        status_file >> pid;
+        return pid != 0;
       }
+      std::getline(status_file, token);
     }
   } catch (...) {
-    _LIBCPP_ASSERT_INTERNAL(false, "Failed to read '/proc/self/status'.");
+    _LIBCPP_ASSERT_INTERNAL(false, "Failed to parse '/proc/self/status'.");
     return false;
   }
 

>From 51dc4001dcbd581500f93dcf78e31db9f3c97880 Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Tue, 23 Jan 2024 15:00:26 +0200
Subject: [PATCH 05/29] Implementation: Apple

---
 libcxx/src/debugging.cpp | 36 +++++++++++++++++-------------------
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index 615139f51f154c..2b19761513fb6c 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -14,6 +14,7 @@
 #  define NOMINMAX
 #  include <windows.h>
 #elif defined(__APPLE__) || defined(__FreeBSD__)
+#  include <array>
 #  include <csignal>
 #  include <sys/sysctl.h>
 #  include <sys/types.h>
@@ -59,35 +60,31 @@ bool __is_debugger_present() noexcept { return IsDebuggerPresent(); }
 
 #elif defined(__APPLE__) || defined(__FreeBSD__)
 
+// Returns true if the current process is being debugged (either
+// running under the debugger or has a debugger attached post facto).
 bool __is_debugger_present() noexcept {
   // Technical Q&A QA1361: Detecting the Debugger
   // https://developer.apple.com/library/archive/qa/qa1361/_index.html
 
-  int junk;
-  int mib[4];
-  struct kinfo_proc info;
-  size_t size;
+  // Initialize mib, which tells 'sysctl' to fetch the information about the current process.
 
-  // Initialize the flags so that, if sysctl fails for some bizarre
-  // reason, we get a predictable result.
-
-  info.kp_proc.p_flag = 0;
+  array mib{CTL_KERN, KERN_PROC, KERN_PROC_PID, ::getpid()};
 
-  // Initialize mib, which tells sysctl the info we want, in this case
-  // we're looking for information about a specific process ID.
+  // Initialize the flags so that, if 'sysctl' fails for some bizarre
+  // reason, we get a predictable result.
 
-  mib[0] = CTL_KERN;
-  mib[1] = KERN_PROC;
-  mib[2] = KERN_PROC_PID;
-  mib[3] = getpid();
+  struct kinfo_proc info {};
 
   // Call sysctl.
+  // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sysctl.3.html
 
-  size = sizeof(info);
-  junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
-  _LIBCPP_ASSERT_INTERNAL(junk == 0, "'sysctl' runtime error");
+  size_t info_size = sizeof(info);
+  if (::sysctl(mib.data(), mib.size(), &info, &info_size, nullptr, 0) != 0) {
+    _LIBCPP_ASSERT_INTERNAL(false, "'sysctl' runtime error");
+    return false;
+  }
 
-  // We're being debugged if the P_TRACED flag is set.
+  // If the process is being debugged if the 'P_TRACED' flag is set.
   // https://github.com/freebsd/freebsd-src/blob/7f3184ba797452703904d33377dada5f0f8eae96/sys/sys/proc.h#L822
 
   return ((info.kp_proc.p_flag & P_TRACED) != 0);
@@ -109,12 +106,13 @@ bool __is_debugger_present() noexcept {
 
     std::string token;
     while (status_file >> token) {
+      // If the process is being debugged "TracerPid"'s value is non-zero.
       if (token == "TracerPid:") {
         int pid;
         status_file >> pid;
         return pid != 0;
       }
-      std::getline(status_file, token);
+      getline(status_file, token);
     }
   } catch (...) {
     _LIBCPP_ASSERT_INTERNAL(false, "Failed to parse '/proc/self/status'.");

>From aa6d18b5e854624e6323ecf01f51f99fb2ec1feb Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Wed, 24 Jan 2024 11:13:38 +0200
Subject: [PATCH 06/29] Updated Feature Test Macro (FTM)

---
 libcxx/docs/FeatureTestMacroTable.rst         |  2 +-
 libcxx/include/__config                       |  2 +-
 libcxx/include/debugging                      |  4 +--
 libcxx/include/version                        |  4 ++-
 libcxx/modules/std/debugging.inc              |  2 +-
 libcxx/src/debugging.cpp                      | 35 ++++++++-----------
 .../debugging.version.compile.pass.cpp        |  6 ++--
 .../version.version.compile.pass.cpp          |  6 ++--
 .../generate_feature_test_macro_components.py |  3 +-
 9 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 468226c0c2dddf..6b86aed145218c 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -400,7 +400,7 @@ Status
     --------------------------------------------------- -----------------
     ``__cpp_lib_copyable_function``                     *unimplemented*
     --------------------------------------------------- -----------------
-    ``__cpp_lib_debugging``                             *unimplemented*
+    ``__cpp_lib_debugging``                             ``202311L``
     --------------------------------------------------- -----------------
     ``__cpp_lib_freestanding_algorithm``                *unimplemented*
     --------------------------------------------------- -----------------
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 4d19f423dc71eb..986bf23205df51 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1568,7 +1568,7 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c
 #    define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
 #  endif
 
-#  if defined(__APPLE__) || defined(__linux__) || defined (_WIN32)
+#  if (defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) || defined (_WIN32)) && !defined(__PICOLIBC__)
 #    define _LIBCPP_HAS_DEBUGGING
 #  endif
 
diff --git a/libcxx/include/debugging b/libcxx/include/debugging
index 07d6b45db30175..8bf608b0ddf00e 100644
--- a/libcxx/include/debugging
+++ b/libcxx/include/debugging
@@ -29,7 +29,7 @@ namespace std {
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-#if _LIBCPP_STD_VER >= 26
+#if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
 
 _LIBCPP_EXPORTED_FROM_ABI void breakpoint() noexcept;
 
@@ -37,7 +37,7 @@ _LIBCPP_EXPORTED_FROM_ABI void breakpoint_if_debugging() noexcept;
 
 _LIBCPP_EXPORTED_FROM_ABI bool is_debugger_present() noexcept;
 
-#endif // _LIBCPP_STD_VER >= 26
+#endif
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/include/version b/libcxx/include/version
index b18927a2bc38c2..13ee7ab37d33f3 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -491,7 +491,9 @@ __cpp_lib_within_lifetime                               202306L <type_traits>
 # define __cpp_lib_bind_front                           202306L
 # define __cpp_lib_bitset                               202306L
 // # define __cpp_lib_copyable_function                    202306L
-// # define __cpp_lib_debugging                            202311L
+# if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
+#   define __cpp_lib_debugging                          202311L
+# endif
 // # define __cpp_lib_freestanding_algorithm               202311L
 // # define __cpp_lib_freestanding_array                   202311L
 // # define __cpp_lib_freestanding_cstring                 202306L
diff --git a/libcxx/modules/std/debugging.inc b/libcxx/modules/std/debugging.inc
index a65890d8e8167a..000b2ae7fe633a 100644
--- a/libcxx/modules/std/debugging.inc
+++ b/libcxx/modules/std/debugging.inc
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 export namespace std {
-#if _LIBCPP_STD_VER >= 26
+#if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
   // [debugging.utility], utility
   using stgd::breakpoint;
   using stgd::breakpoint_if_debugging;
diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index 2b19761513fb6c..fccd6f8c397502 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -95,28 +95,23 @@ bool __is_debugger_present() noexcept {
 bool __is_debugger_present() noexcept {
   // https://docs.kernel.org/filesystems/proc.html
 
-  try {
-    // Get the status information of a process by reading the file /proc/PID/status.
-    // The link 'self' points to the process reading the file system.
-    ifstream status_file{"/proc/self/status"};
-    if (!status_file.is_open()) {
-      _LIBCPP_ASSERT_INTERNAL(false, "Could not open '/proc/self/status' for reading.");
-      return false;
-    }
+  // Get the status information of a process by reading the file /proc/PID/status.
+  // The link 'self' points to the process reading the file system.
+  ifstream status_file{"/proc/self/status"};
+  if (!status_file.is_open()) {
+    _LIBCPP_ASSERT_INTERNAL(false, "Could not open '/proc/self/status' for reading.");
+    return false;
+  }
 
-    std::string token;
-    while (status_file >> token) {
-      // If the process is being debugged "TracerPid"'s value is non-zero.
-      if (token == "TracerPid:") {
-        int pid;
-        status_file >> pid;
-        return pid != 0;
-      }
-      getline(status_file, token);
+  std::string token;
+  while (status_file >> token) {
+    // If the process is being debugged "TracerPid"'s value is non-zero.
+    if (token == "TracerPid:") {
+      int pid;
+      status_file >> pid;
+      return pid != 0;
     }
-  } catch (...) {
-    _LIBCPP_ASSERT_INTERNAL(false, "Failed to parse '/proc/self/status'.");
-    return false;
+    getline(status_file, token);
   }
 
   return false;
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp
index a22b404a634fd2..9eb39a26a87116 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp
@@ -54,16 +54,16 @@
 
 #elif TEST_STD_VER > 23
 
-# if !defined(_LIBCPP_VERSION)
+# if TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
 #   ifndef __cpp_lib_debugging
 #     error "__cpp_lib_debugging should be defined in c++26"
 #   endif
 #   if __cpp_lib_debugging != 202311L
 #     error "__cpp_lib_debugging should have the value 202311L in c++26"
 #   endif
-# else // _LIBCPP_VERSION
+# else
 #   ifdef __cpp_lib_debugging
-#     error "__cpp_lib_debugging should not be defined because it is unimplemented in libc++!"
+#     error "__cpp_lib_debugging should not be defined when the requirement 'TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)' is not met!"
 #   endif
 # endif
 
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 14271308624e65..9aed97c0968fbd 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -6315,16 +6315,16 @@
 #   error "__cpp_lib_coroutine should have the value 201902L in c++26"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
+# if TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
 #   ifndef __cpp_lib_debugging
 #     error "__cpp_lib_debugging should be defined in c++26"
 #   endif
 #   if __cpp_lib_debugging != 202311L
 #     error "__cpp_lib_debugging should have the value 202311L in c++26"
 #   endif
-# else // _LIBCPP_VERSION
+# else
 #   ifdef __cpp_lib_debugging
-#     error "__cpp_lib_debugging should not be defined because it is unimplemented in libc++!"
+#     error "__cpp_lib_debugging should not be defined when the requirement 'TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)' is not met!"
 #   endif
 # endif
 
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index b2d1565055c516..3e8849a58904b6 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -401,7 +401,8 @@ def add_version_header(tc):
             "name": "__cpp_lib_debugging",
             "values": {"c++26": 202311},  # P2546R5 Debugging Support
             "headers": ["debugging"],
-            "unimplemented": True, # Implemented on Linux, macOS, Windows
+            "test_suite_guard": "TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)",
+            "libcxx_guard": "_LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)",
         },
         {
             "name": "__cpp_lib_destroying_delete",

>From 3595c0e4f751655a6b80db93640e692ab9e6d440 Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Wed, 24 Jan 2024 11:17:47 +0200
Subject: [PATCH 07/29] Simplified guards and fixed tests

---
 libcxx/include/__config                       |  3 +-
 libcxx/include/debugging                      |  2 +-
 libcxx/include/version                        |  2 +-
 libcxx/modules/std/debugging.inc              |  2 +-
 .../debugging.version.compile.pass.cpp        |  4 +-
 .../version.version.compile.pass.cpp          |  4 +-
 .../utilities/debugging/breakpoint.pass.cpp   | 45 ++++++++++++++++++-
 .../breakpoint_if_debugging.pass.cpp          | 12 ++++-
 .../debugging/is_debugger_present.pass.cpp    |  9 +++-
 ...debugger_present.with_debugger_lldb.sh.cpp | 40 +++++++++++++++++
 .../generate_feature_test_macro_components.py |  4 +-
 libcxx/utils/libcxx/test/features.py          | 42 +++++++++++++++++
 12 files changed, 156 insertions(+), 13 deletions(-)
 create mode 100644 libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp

diff --git a/libcxx/include/__config b/libcxx/include/__config
index 986bf23205df51..197400d85859b1 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1568,7 +1568,8 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c
 #    define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER
 #  endif
 
-#  if (defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) || defined (_WIN32)) && !defined(__PICOLIBC__)
+#  if (defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__) || defined(_WIN32)) &&                         \
+      !defined(__PICOLIBC__) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
 #    define _LIBCPP_HAS_DEBUGGING
 #  endif
 
diff --git a/libcxx/include/debugging b/libcxx/include/debugging
index 8bf608b0ddf00e..686ce7c861fa7e 100644
--- a/libcxx/include/debugging
+++ b/libcxx/include/debugging
@@ -29,7 +29,7 @@ namespace std {
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-#if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
+#if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)
 
 _LIBCPP_EXPORTED_FROM_ABI void breakpoint() noexcept;
 
diff --git a/libcxx/include/version b/libcxx/include/version
index 13ee7ab37d33f3..5f9203ae36091f 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -491,7 +491,7 @@ __cpp_lib_within_lifetime                               202306L <type_traits>
 # define __cpp_lib_bind_front                           202306L
 # define __cpp_lib_bitset                               202306L
 // # define __cpp_lib_copyable_function                    202306L
-# if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
+# if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)
 #   define __cpp_lib_debugging                          202311L
 # endif
 // # define __cpp_lib_freestanding_algorithm               202311L
diff --git a/libcxx/modules/std/debugging.inc b/libcxx/modules/std/debugging.inc
index 000b2ae7fe633a..e8f8dd13f88ba6 100644
--- a/libcxx/modules/std/debugging.inc
+++ b/libcxx/modules/std/debugging.inc
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 export namespace std {
-#if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
+#if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)
   // [debugging.utility], utility
   using stgd::breakpoint;
   using stgd::breakpoint_if_debugging;
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp
index 9eb39a26a87116..b18646321094cb 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/debugging.version.compile.pass.cpp
@@ -54,7 +54,7 @@
 
 #elif TEST_STD_VER > 23
 
-# if TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
+# if TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)
 #   ifndef __cpp_lib_debugging
 #     error "__cpp_lib_debugging should be defined in c++26"
 #   endif
@@ -63,7 +63,7 @@
 #   endif
 # else
 #   ifdef __cpp_lib_debugging
-#     error "__cpp_lib_debugging should not be defined when the requirement 'TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)' is not met!"
+#     error "__cpp_lib_debugging should not be defined when the requirement 'TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)' is not met!"
 #   endif
 # endif
 
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 9aed97c0968fbd..117c41700674e4 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -6315,7 +6315,7 @@
 #   error "__cpp_lib_coroutine should have the value 201902L in c++26"
 # endif
 
-# if TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)
+# if TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)
 #   ifndef __cpp_lib_debugging
 #     error "__cpp_lib_debugging should be defined in c++26"
 #   endif
@@ -6324,7 +6324,7 @@
 #   endif
 # else
 #   ifdef __cpp_lib_debugging
-#     error "__cpp_lib_debugging should not be defined when the requirement 'TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)' is not met!"
+#     error "__cpp_lib_debugging should not be defined when the requirement 'TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)' is not met!"
 #   endif
 # endif
 
diff --git a/libcxx/test/std/utilities/debugging/breakpoint.pass.cpp b/libcxx/test/std/utilities/debugging/breakpoint.pass.cpp
index 7389600fa191ee..f27a01dab5a25e 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint.pass.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // <debugging>
 
@@ -15,7 +16,49 @@
 #include <cassert>
 #include <debugging>
 
-void test() { static_assert(noexcept(breakpoint())); }
+// Test with debugger attached:
+
+// LLDB command: `lldb "breakpoint.pass" -o run -o detach -o quit`
+// GDB command:  `gdb breakpoint.pass -ex run -ex detach -ex quit --silent`
+
+//
+// Sample LLDB output:
+//
+// Process 43162 launched: '/home/llvm-dev/Projects/llvm-project/build/breakpoint.pass' (x86_64)
+// Process 43162 stopped
+// * thread #1, name = 'breakpoint.pass', stop reason = signal SIGTRAP
+//     frame #0: 0x00007ffff7eb27e5 libc++.so.1`std::__1::__breakpoint() at debugging.cpp:44:1
+//    41  	#  else
+//    42  	  raise(SIGTRAP);
+//    43  	#  endif
+// -> 44  	}
+//    45
+//    46  	#else
+//    47
+// (lldb) detach
+// Process 43162 detached
+// (lldb) quit
+
+//
+// Sample GDB ouput:
+//
+// Reading symbols from breakpoint.pass..
+// Starting program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass
+// [Thread debugging using libthread_db enabled]
+// Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
+
+// Program received signal SIGTRAP, Trace/breakpoint trap.
+// std::__1::__breakpoint () at /home/llvm-dev/Projects/llvm-project/libcxx/src/debugging.cpp:44
+// warning: Source file is more recent than executable.
+// 44	}
+// Detaching from program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass, process 53887
+// [Inferior 1 (process 53887) detached]
+
+void test() {
+  static_assert(noexcept(std::breakpoint()));
+
+  std::breakpoint();
+}
 
 int main(int, char**) {
   test();
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
index 453ba9155b2236..6bd6a479235bd9 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // <debugging>
 
@@ -15,7 +16,16 @@
 #include <cassert>
 #include <debugging>
 
-void test() { static_assert(noexcept(breakpoint_if_debugging())); }
+// Test with debugger attached:
+
+// LLDB command: `lldb "breakpoint_if_debugging.pass" -o run -o detach -o quit`
+// GDB command:  `gdb breakpoint_if_debugging.pass -ex run -ex detach -ex quit --silent`
+
+void test() {
+  static_assert(noexcept(std::breakpoint_if_debugging()));
+
+  std::breakpoint_if_debugging();
+}
 
 int main(int, char**) {
   test();
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
index 88b271de9ce79d..79c541922572ba 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // <debugging>
 
@@ -15,7 +16,13 @@
 #include <cassert>
 #include <debugging>
 
-void test() { static_assert(noexcept(is_debugger_present())); }
+// Test without debugger.
+
+void test() {
+  static_assert(noexcept(std::is_debugger_present()));
+
+  assert(!std::is_debugger_present());
+}
 
 int main(int, char**) {
   test();
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
new file mode 100644
index 00000000000000..2da2246fe6fac9
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
+// UNSUPPORTED: gcc
+
+// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
+// RUN: %{lldb} %t.exe -o run -o detach -o quit
+// RUN: %{gdb} %t.exe -ex run -ex detach -ex quit --silent
+
+// <debugging>
+
+// bool is_debugger_present() noexcept;
+
+#include <cassert>
+#include <debugging>
+#include <cstdlib>
+
+// Test with debugger attached:
+
+// LLDB command: `lldb "is_debugger_present.pass" -o run -o detach -o quit`
+// GDB command:  `gdb is_debugger_present.pass -ex run -ex detach -ex quit --silent`
+
+void test() {
+  static_assert(noexcept(std::is_debugger_present()));
+
+  assert(std::is_debugger_present());
+}
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 3e8849a58904b6..6eef95bb88d11e 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -401,8 +401,8 @@ def add_version_header(tc):
             "name": "__cpp_lib_debugging",
             "values": {"c++26": 202311},  # P2546R5 Debugging Support
             "headers": ["debugging"],
-            "test_suite_guard": "TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)",
-            "libcxx_guard": "_LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_DEBUGGING)",
+            "test_suite_guard": "TEST_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)",
+            "libcxx_guard": "_LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)",
         },
         {
             "name": "__cpp_lib_destroying_delete",
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index 6ef40755c59d97..aaf22a42959ae9 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -474,6 +474,48 @@ def _getAndroidDeviceApi(cfg):
     ),
 ]
 
+# Detect whether LLDB is on the system, has Python scripting and supports
+# adding breakpoint commands. If so add a substitution to access it.
+def check_lldb(cfg):
+    lldb_path = shutil.which("lldb")
+    if lldb_path is None:
+        return False
+
+#     # Check that we can set breakpoint commands.
+#     test_src = """
+# try:
+#   debugger = lldb.SBDebugger.Create()
+#   # Block until target process exits.
+#   debugger.SetAsync(False)
+#   # target = debugger.CreateTarget()
+# except AttributeError:
+#   sys.exit(1)
+# #sys.exit()
+# """
+
+#     try:
+#         stdout = subprocess.check_output(
+#             [lldb_path, "-o", f"script {test_src}", "--batch"],
+#             stderr=subprocess.DEVNULL,
+#             universal_newlines=True,
+#         )
+#     except subprocess.CalledProcessError:
+#         # We can't set breakpoint commands
+#         return False
+
+#     # Check we actually ran the Python
+#     return not "Python scripting is not supported" in stdout
+    return True # TODO: Remove this line
+
+
+DEFAULT_FEATURES += [
+    Feature(
+        name="host-has-lldb-with-python",
+        when=check_lldb,
+        actions=[AddSubstitution("%{lldb}", lambda cfg: shutil.which("lldb"))],
+    )
+]
+
 # Detect whether GDB is on the system, has Python scripting and supports
 # adding breakpoint commands. If so add a substitution to access it.
 def check_gdb(cfg):

>From 43928e8a7ed29fae00400b5e36828b55a1f89779 Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Wed, 24 Jan 2024 22:35:48 +0200
Subject: [PATCH 08/29] WIP: LLDB python script

---
 .../breakpoint.with_debugger_lldb.py          | 14 +++++++
 ...p => breakpoint.with_debugger_lldb.sh.cpp} |  8 ++++
 .../breakpoint_if_debugging.pass.cpp          |  5 +--
 ...int_if_debugging.with_debugger_lldb.sh.cpp | 40 +++++++++++++++++++
 .../is_debugger_present.with_debugger_lldb.py | 10 +++++
 ...debugger_present.with_debugger_lldb.sh.cpp |  1 +
 6 files changed, 74 insertions(+), 4 deletions(-)
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.py
 rename libcxx/test/std/utilities/debugging/{breakpoint.pass.cpp => breakpoint.with_debugger_lldb.sh.cpp} (86%)
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging.with_debugger_lldb.sh.cpp
 create mode 100644 libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py

diff --git a/libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.py
new file mode 100644
index 00000000000000..41af51bc13a19b
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.py
@@ -0,0 +1,14 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import lldb
+
+# https://lldb.llvm.org/use/python-reference.html#running-a-python-script-when-a-breakpoint-gets-hit
+
+def breakpoint_function_wrapper(frame, bp_loc, internal_dict):
+   # Your code goes here
diff --git a/libcxx/test/std/utilities/debugging/breakpoint.pass.cpp b/libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.sh.cpp
similarity index 86%
rename from libcxx/test/std/utilities/debugging/breakpoint.pass.cpp
rename to libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.sh.cpp
index f27a01dab5a25e..2c753b05592e37 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint.pass.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.sh.cpp
@@ -8,6 +8,12 @@
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
+// UNSUPPORTED: gcc
+// UNSUPPORTED: android
+
+// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
+// RUN: %{lldb} %t.exe -o run -o detach -o quit
+// RUN: %{gdb} %t.exe -ex run -ex detach -ex quit --silent
 
 // <debugging>
 
@@ -54,6 +60,8 @@
 // Detaching from program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass, process 53887
 // [Inferior 1 (process 53887) detached]
 
+// https://lldb.llvm.org/use/python-reference.html#running-a-python-script-when-a-breakpoint-gets-hit
+
 void test() {
   static_assert(noexcept(std::breakpoint()));
 
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
index 6bd6a479235bd9..6f3a85498efbf6 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
@@ -16,10 +16,7 @@
 #include <cassert>
 #include <debugging>
 
-// Test with debugger attached:
-
-// LLDB command: `lldb "breakpoint_if_debugging.pass" -o run -o detach -o quit`
-// GDB command:  `gdb breakpoint_if_debugging.pass -ex run -ex detach -ex quit --silent`
+// Test without debugger.
 
 void test() {
   static_assert(noexcept(std::breakpoint_if_debugging()));
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.with_debugger_lldb.sh.cpp
new file mode 100644
index 00000000000000..2fe76aa8e1b3e2
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.with_debugger_lldb.sh.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
+// UNSUPPORTED: gcc
+// UNSUPPORTED: android
+
+// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
+// RUN: %{lldb} %t.exe -o run -o detach -o quit
+// RUN: %{gdb} %t.exe -ex run -ex detach -ex quit --silent
+
+// <debugging>
+
+// void breakpoint_if_debugging() noexcept;
+
+#include <cassert>
+#include <debugging>
+
+// Test with debugger attached:
+
+// LLDB command: `lldb "breakpoint_if_debugging.pass" -o run -o detach -o quit`
+// GDB command:  `gdb breakpoint_if_debugging.pass -ex run -ex detach -ex quit --silent`
+
+void test() {
+  static_assert(noexcept(std::breakpoint_if_debugging()));
+
+  std::breakpoint_if_debugging();
+}
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py
new file mode 100644
index 00000000000000..61979b9a6e53d9
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py
@@ -0,0 +1,10 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import lldb
+
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
index 2da2246fe6fac9..49dff7574e14ce 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
@@ -9,6 +9,7 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 // UNSUPPORTED: gcc
+// UNSUPPORTED: android
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
 // RUN: %{lldb} %t.exe -o run -o detach -o quit

>From ba6ee1e5bbc179e6d9ccae0c74aef598e802ba30 Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Fri, 26 Jan 2024 08:13:05 +0200
Subject: [PATCH 09/29] WIP: GDB python script

---
 .../debugging/is_debugger_present.pass.cpp    |   4 +-
 .../is_debugger_present.with_debugger_gdb.py  | 122 ++++++++++++++++++
 ..._debugger_present.with_debugger_gdb.sh.cpp |  57 ++++++++
 ...debugger_present.with_debugger_lldb.sh.cpp |  36 ++++--
 4 files changed, 208 insertions(+), 11 deletions(-)
 create mode 100644 libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py
 create mode 100644 libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp

diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
index 79c541922572ba..106890e77fa7e0 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
@@ -14,6 +14,7 @@
 // bool is_debugger_present() noexcept;
 
 #include <cassert>
+#include <concepts>
 #include <debugging>
 
 // Test without debugger.
@@ -21,7 +22,8 @@
 void test() {
   static_assert(noexcept(std::is_debugger_present()));
 
-  assert(!std::is_debugger_present());
+  std::same_as<bool> decltype(auto) isDebuggerPresent = is_debugger_present();
+  assert(isDebuggerPresent == false);
 }
 
 int main(int, char**) {
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py
new file mode 100644
index 00000000000000..c10d95ddd3d22e
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py
@@ -0,0 +1,122 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+from __future__ import print_function
+import re
+import gdb
+import sys
+
+# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
+
+test_failures = 0
+# Sometimes the inital run command can fail to trace the process.
+# (e.g. you don't have ptrace permissions)
+# In these cases gdb still sends us an exited event so we cannot
+# see what "run" printed to check for a warning message, since
+# we get taken to our exit handler before we can look.
+# Instead check that at least one test has been run by the time
+# we exit.
+has_run_tests = False
+
+
+class CheckResult(gdb.Command):
+    def __init__(self):
+        super(CheckResult, self).__init__("print_and_compare", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        global has_run_tests
+
+        try:
+            has_run_tests = True
+
+            # Stack frame is:
+            # 0. StopForDebugger
+            # 1. ComparePrettyPrintToChars or ComparePrettyPrintToRegex
+            # 2. TestCase
+            compare_frame = gdb.newest_frame().older()
+            testcase_frame = compare_frame.older()
+            test_loc = testcase_frame.find_sal()
+            # Use interactive commands in the correct context to get the pretty
+            # printed version
+
+            value_str = self._get_value_string(compare_frame, testcase_frame)
+
+            # Ignore the convenience variable name and newline
+            value = value_str[value_str.find("= ") + 2 : -1]
+            gdb.newest_frame().select()
+            expectation_val = compare_frame.read_var("expectation")
+            check_literal = expectation_val.string(encoding="utf-8")
+            if "PrettyPrintToRegex" in compare_frame.name():
+                test_fails = not re.search(check_literal, value)
+            else:
+                test_fails = value != check_literal
+
+            if test_fails:
+                global test_failures
+                print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+                print("GDB printed:")
+                print("   " + repr(value))
+                print("Value should match:")
+                print("   " + repr(check_literal))
+                test_failures += 1
+            else:
+                print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+
+        except RuntimeError as e:
+            # At this point, lots of different things could be wrong, so don't try to
+            # recover or figure it out. Don't exit either, because then it's
+            # impossible to debug the framework itself.
+            print("FAIL: Something is wrong in the test framework.")
+            print(str(e))
+            test_failures += 1
+
+    def _get_value_string(self, compare_frame, testcase_frame):
+        compare_frame.select()
+        if "ComparePrettyPrint" in compare_frame.name():
+            s = gdb.execute("p value", to_string=True)
+        else:
+            value_str = str(compare_frame.read_var("value"))
+            clean_expression_str = value_str.strip("'\"")
+            testcase_frame.select()
+            s = gdb.execute("p " + clean_expression_str, to_string=True)
+        if sys.version_info.major == 2:
+            return s.decode("utf-8")
+        return s
+
+
+def exit_handler(event=None):
+    global test_failures
+    global has_run_tests
+
+    if not has_run_tests:
+        print("FAILED test program did not run correctly, check gdb warnings")
+        test_failures = -1
+    elif test_failures:
+        print("FAILED %d cases" % test_failures)
+    exit(test_failures)
+
+
+# Start code executed at load time
+
+# Disable terminal paging
+gdb.execute("set height 0")
+gdb.execute("set python print-stack full")
+test_failures = 0
+CheckResult()
+test_bp = gdb.Breakpoint("StopForDebugger")
+test_bp.enabled = True
+test_bp.silent = True
+test_bp.commands = "print_and_compare\ncontinue"
+# "run" won't return if the program exits; ensure the script regains control.
+gdb.events.exited.connect(exit_handler)
+gdb.execute("run")
+# If the program didn't exit, something went wrong, but we don't
+# know what. Fail on exit.
+test_failures += 1
+exit_handler(None)
+
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
new file mode 100644
index 00000000000000..bec613abfd764e
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// REQUIRES: host-has-gdb-with-python
+// UNSUPPORTED: android
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
+
+// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
+// RUN: %{gdb} %t.exe -ex "source %S/is_debugger_present.with_debugger_gdb.py" -ex run -ex detach -ex quit --silent
+
+// <debugging>
+
+// bool is_debugger_present() noexcept;
+
+#include <cassert>
+#include <concepts>
+#include <debugging>
+
+#include "test_macros.h"
+
+#ifdef TEST_COMPILER_GCC
+#  define OPT_NONE __attribute__((noinline))
+#else
+#  define OPT_NONE __attribute__((optnone))
+#endif
+
+// Prevents the compiler optimizing away the parameter in the caller function.
+template <typename Type>
+void MarkAsLive(Type&&) OPT_NONE;
+template <typename Type>
+void MarkAsLive(Type&&) {}
+
+void StopForDebugger(void*, void*) OPT_NONE;
+void StopForDebugger(void*, void*) {}
+
+// Test with debugger attached:
+//   GDB command: `gdb is_debugger_present.pass -ex run -ex detach -ex quit --silent`
+
+void test() {
+  static_assert(noexcept(std::is_debugger_present()));
+
+  std::same_as<bool> decltype(auto) isDebuggerPresent = std::is_debugger_present();
+  MarkAsLive(isDebuggerPresent);
+  StopForDebuger(&isDebuggerPresent);
+}
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
index 49dff7574e14ce..ba0db48d479a61 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
@@ -7,35 +7,51 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
-// UNSUPPORTED: gcc
+// REQUIRES: host-has-lldb-with-python
 // UNSUPPORTED: android
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{lldb} %t.exe -o run -o detach -o quit
-// RUN: %{gdb} %t.exe -ex run -ex detach -ex quit --silent
+// RUN: %{lldb} %t.exe -ex "command source %S/is_debugger_present.with_debugger_lldb.py" -o run -o detach -o quit
 
 // <debugging>
 
 // bool is_debugger_present() noexcept;
 
 #include <cassert>
+#include <concepts>
 #include <debugging>
-#include <cstdlib>
 
-// Test with debugger attached:
+#include "test_macros.h"
+
+#ifdef TEST_COMPILER_GCC
+#  define OPT_NONE __attribute__((noinline))
+#else
+#  define OPT_NONE __attribute__((optnone))
+#endif
 
-// LLDB command: `lldb "is_debugger_present.pass" -o run -o detach -o quit`
-// GDB command:  `gdb is_debugger_present.pass -ex run -ex detach -ex quit --silent`
+// Prevents the compiler optimizing away the parameter in the caller function.
+template <typename Type>
+void MarkAsLive(Type&&) OPT_NONE;
+template <typename Type>
+void MarkAsLive(Type&&) {}
+
+void StopForDebugger(void*, void*) OPT_NONE;
+void StopForDebugger(void*, void*) {}
+
+// Test with debugger attached:
+//   LLDB command: `lldb "is_debugger_present.pass" -o run -o detach -o quit`
 
 void test() {
   static_assert(noexcept(std::is_debugger_present()));
 
-  assert(std::is_debugger_present());
+  std::same_as<bool> decltype(auto) isDebuggerPresent = std::is_debugger_present();
+  MarkAsLive(isDebuggerPresent);
+  StopForDebuger(&isDebuggerPresent);
 }
 
 int main(int, char**) {
   test();
 
   return 0;
-}
+}
\ No newline at end of file

>From 523ec6ad6580f0afc98f0ad6cf17eea50bdb8cc1 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 5 Feb 2024 12:52:42 +0200
Subject: [PATCH 10/29] WIP: GDB python script

---
 ..._debugger_present.with_debugger_gdb.sh.cpp |  10 +-
 ...debugger_present.with_debugger_gdb_test.py | 171 ++++++++++++++++++
 ...debugger_present.with_debugger_lldb.sh.cpp |   2 +-
 3 files changed, 179 insertions(+), 4 deletions(-)
 create mode 100644 libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb_test.py

diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
index bec613abfd764e..0e91cc533e6f8c 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
@@ -36,8 +36,8 @@ void MarkAsLive(Type&&) OPT_NONE;
 template <typename Type>
 void MarkAsLive(Type&&) {}
 
-void StopForDebugger(void*, void*) OPT_NONE;
-void StopForDebugger(void*, void*) {}
+void StopForDebugger(void*) OPT_NONE;
+void StopForDebugger(void*) {}
 
 // Test with debugger attached:
 //   GDB command: `gdb is_debugger_present.pass -ex run -ex detach -ex quit --silent`
@@ -46,8 +46,12 @@ void test() {
   static_assert(noexcept(std::is_debugger_present()));
 
   std::same_as<bool> decltype(auto) isDebuggerPresent = std::is_debugger_present();
+  auto isDebuggerPresent1 = false;
+  auto helpMeStr = "Yeah it is working!";
   MarkAsLive(isDebuggerPresent);
-  StopForDebuger(&isDebuggerPresent);
+  MarkAsLive(isDebuggerPresent1);
+  MarkAsLive(helpMeStr);
+  StopForDebugger(&isDebuggerPresent);
 }
 
 int main(int, char**) {
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb_test.py b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb_test.py
new file mode 100644
index 00000000000000..2946ea471cb4fe
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb_test.py
@@ -0,0 +1,171 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+from __future__ import print_function
+import re
+import gdb
+import sys
+
+# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
+
+test_failures = 0
+
+# Sometimes the inital run command can fail to trace the process.
+# (e.g. you don't have ptrace permissions)
+# In these cases gdb still sends us an exited event so we cannot
+# see what "run" printed to check for a warning message, since
+# we get taken to our exit handler before we can look.
+# Instead check that at least one test has been run by the time
+# we exit.
+has_run_tests = False
+
+
+class CheckResult(gdb.Command):
+    """GDB Tester"""
+
+    def __init__(self):
+        super(CheckResult, self).__init__("check_is_debugger_present", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        global has_run_tests
+
+        try:
+            print("GDB Custom Test is starting!")
+
+            has_run_tests = True
+
+            # Stack frame is:
+            # 0. StopForDebugger
+            # 1. ComparePrettyPrintToChars or ComparePrettyPrintToRegex
+            # 2. TestCase
+            compare_frame = gdb.newest_frame().older()
+            testcase_frame = compare_frame.older()
+            test_loc = testcase_frame.find_sal()
+
+            # Use interactive commands in the correct context to get the pretty
+            # printed version
+
+            value_str = self._get_value_string(compare_frame, testcase_frame)
+            print(f"====> GDB output: {compare_frame}")
+            print(f"====> GDB output: {testcase_frame}")
+            print(f"====> GDB output: {test_loc}")
+            print(f"====> GDB output: {value_str}")
+
+            # Ignore the convenience variable name and newline
+            value = value_str[value_str.find("= ") + 2 : -1]
+            gdb.newest_frame().select()
+            expectation_val = compare_frame.read_var("isDebuggerPresent")
+            print(f"====> GDB: expectation_val isDebuggerPresent = {expectation_val}")
+            if not expectation_val:
+                global test_failures
+                print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+                print("`isDebuggerPresent` value is `false`, value should be `true`")
+                test_failures += 1
+            else:
+                print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+            
+            expectation_val = compare_frame.read_var("isDebuggerPresent1")
+            if expectation_val:
+                print(f"====> GDB: expectation_val isDebuggerPresent1 = {expectation_val}")
+            expectation_val = compare_frame.read_var("helpMeStr")
+            if expectation_val == "Yeah it is working!":
+                print(f"====> GDB: expectation_val helpMeStr = {expectation_val}")
+            else:
+                print(f"====> GDB error: helpMeStr  {expectation_val}")
+
+            # check_literal = expectation_val.string(encoding="utf-8")
+            # if "PrettyPrintToRegex" in compare_frame.name():
+            #     test_fails = not re.search(check_literal, value)
+            # else:
+            #     test_fails = value != check_literal
+
+            # if test_fails:
+            #     global test_failures
+            #     print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+            #     print("GDB printed:")
+            #     print("   " + repr(value))
+            #     print("Value should match:")
+            #     print("   " + repr(check_literal))
+            #     test_failures += 1
+            # else:
+            #     print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+
+        except RuntimeError as e:
+            # At this point, lots of different things could be wrong, so don't try to
+            # recover or figure it out. Don't exit either, because then it's
+            # impossible to debug the framework itself.
+            print("FAIL: Something is wrong in the test framework.")
+            print(str(e))
+
+            test_failures += 1
+
+    # def _get_value_string(self, compare_frame, testcase_frame):
+    #     compare_frame.select()
+    #     if "ComparePrettyPrint" in compare_frame.name():
+    #         s = gdb.execute("p value", to_string=True)
+    #     else:
+    #         value_str = str(compare_frame.read_var("value"))
+    #         clean_expression_str = value_str.strip("'\"")
+    #         testcase_frame.select()
+    #         s = gdb.execute("p " + clean_expression_str, to_string=True)
+    #     if sys.version_info.major == 2:
+    #         return s.decode("utf-8")
+    #     return s
+    def _get_value_string(self, compare_frame, testcase_frame):
+        compare_frame.select()
+        # if "ComparePrettyPrint" in compare_frame.name():
+        #     s = gdb.execute("p value", to_string=True)
+        # else:
+        #     value_str = str(compare_frame.read_var("value"))
+        #     clean_expression_str = value_str.strip("'\"")
+        #     testcase_frame.select()
+        #     s = gdb.execute("p " + clean_expression_str, to_string=True)
+        # if sys.version_info.major == 2:
+        #     return s.decode("utf-8")
+        s = compare_frame.name()
+        return s
+
+
+def exit_handler(event=None):
+    global test_failures
+    global has_run_tests
+
+    if not has_run_tests:
+        print("FAILED test program did not run correctly, check gdb warnings")
+        test_failures = -1
+    elif test_failures:
+        print("FAILED %d cases" % test_failures)
+    exit(test_failures)
+
+def main():
+    # Start code executed at load time
+
+    # Disable terminal paging
+    gdb.execute("set height 0")
+    gdb.execute("set python print-stack full")
+
+    test = CheckResult()
+    test_bp = gdb.Breakpoint("StopForDebugger")
+    test_bp.enabled = True
+    test_bp.silent = True
+    # test_bp.commands = "check_is_debugger_present\ncontinue"
+    test_bp.commands = """check_is_debugger_present
+    continue"""
+
+    # "run" won't return if the program exits; ensure the script regains control.
+    gdb.events.exited.connect(exit_handler)
+    gdb.execute("run")
+    # If the program didn't exit, something went wrong, but we don't
+    # know what. Fail on exit.
+    test.test_failures += 1
+    exit_handler(None)
+
+    print(f"Test failures count: {test.test_failures}")
+
+if __name__ == "__main__":
+    main()
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
index ba0db48d479a61..1d954137b8e693 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
@@ -54,4 +54,4 @@ int main(int, char**) {
   test();
 
   return 0;
-}
\ No newline at end of file
+}

>From 15fb1ccaf5381e2b83d9493bcfb4f15b52bfef8e Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 5 Feb 2024 13:15:41 +0200
Subject: [PATCH 11/29] GDB python script

---
 .../is_debugger_present.with_debugger_gdb.py  |  97 +++++-----
 ..._debugger_present.with_debugger_gdb.sh.cpp |   4 -
 ...debugger_present.with_debugger_gdb_test.py | 171 ------------------
 3 files changed, 45 insertions(+), 227 deletions(-)
 delete mode 100644 libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb_test.py

diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py
index c10d95ddd3d22e..1446df2bd0ed13 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py
@@ -7,13 +7,12 @@
 # ===----------------------------------------------------------------------===##
 
 from __future__ import print_function
-import re
 import gdb
-import sys
 
 # https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
 
 test_failures = 0
+
 # Sometimes the inital run command can fail to trace the process.
 # (e.g. you don't have ptrace permissions)
 # In these cases gdb still sends us an exited event so we cannot
@@ -25,8 +24,10 @@
 
 
 class CheckResult(gdb.Command):
+    """GDB Tester"""
+
     def __init__(self):
-        super(CheckResult, self).__init__("print_and_compare", gdb.COMMAND_DATA)
+        super(CheckResult, self).__init__("check_is_debugger_present", gdb.COMMAND_DATA)
 
     def invoke(self, arg, from_tty):
         global has_run_tests
@@ -36,33 +37,24 @@ def invoke(self, arg, from_tty):
 
             # Stack frame is:
             # 0. StopForDebugger
-            # 1. ComparePrettyPrintToChars or ComparePrettyPrintToRegex
-            # 2. TestCase
+            # 1. Check `isDebuggerPresent`
+
             compare_frame = gdb.newest_frame().older()
             testcase_frame = compare_frame.older()
             test_loc = testcase_frame.find_sal()
-            # Use interactive commands in the correct context to get the pretty
-            # printed version
-
-            value_str = self._get_value_string(compare_frame, testcase_frame)
 
             # Ignore the convenience variable name and newline
-            value = value_str[value_str.find("= ") + 2 : -1]
+
+            # value = value_str[value_str.find("= ") + 2 : -1]
             gdb.newest_frame().select()
-            expectation_val = compare_frame.read_var("expectation")
-            check_literal = expectation_val.string(encoding="utf-8")
-            if "PrettyPrintToRegex" in compare_frame.name():
-                test_fails = not re.search(check_literal, value)
-            else:
-                test_fails = value != check_literal
+            expectation_val = compare_frame.read_var("isDebuggerPresent")
 
-            if test_fails:
+            if not expectation_val:
                 global test_failures
+
                 print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-                print("GDB printed:")
-                print("   " + repr(value))
-                print("Value should match:")
-                print("   " + repr(check_literal))
+                print("`isDebuggerPresent` value is `false`, value should be `true`")
+
                 test_failures += 1
             else:
                 print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
@@ -71,25 +63,16 @@ def invoke(self, arg, from_tty):
             # At this point, lots of different things could be wrong, so don't try to
             # recover or figure it out. Don't exit either, because then it's
             # impossible to debug the framework itself.
+
             print("FAIL: Something is wrong in the test framework.")
             print(str(e))
-            test_failures += 1
 
-    def _get_value_string(self, compare_frame, testcase_frame):
-        compare_frame.select()
-        if "ComparePrettyPrint" in compare_frame.name():
-            s = gdb.execute("p value", to_string=True)
-        else:
-            value_str = str(compare_frame.read_var("value"))
-            clean_expression_str = value_str.strip("'\"")
-            testcase_frame.select()
-            s = gdb.execute("p " + clean_expression_str, to_string=True)
-        if sys.version_info.major == 2:
-            return s.decode("utf-8")
-        return s
+            test_failures += 1
 
 
 def exit_handler(event=None):
+    """Exit handler"""
+
     global test_failures
     global has_run_tests
 
@@ -97,26 +80,36 @@ def exit_handler(event=None):
         print("FAILED test program did not run correctly, check gdb warnings")
         test_failures = -1
     elif test_failures:
-        print("FAILED %d cases" % test_failures)
+        print(f"FAILED {test_failures} cases")
     exit(test_failures)
 
+def main():
+    # Start code executed at load time
 
-# Start code executed at load time
+    # Disable terminal paging
 
-# Disable terminal paging
-gdb.execute("set height 0")
-gdb.execute("set python print-stack full")
-test_failures = 0
-CheckResult()
-test_bp = gdb.Breakpoint("StopForDebugger")
-test_bp.enabled = True
-test_bp.silent = True
-test_bp.commands = "print_and_compare\ncontinue"
-# "run" won't return if the program exits; ensure the script regains control.
-gdb.events.exited.connect(exit_handler)
-gdb.execute("run")
-# If the program didn't exit, something went wrong, but we don't
-# know what. Fail on exit.
-test_failures += 1
-exit_handler(None)
+    gdb.execute("set height 0")
+    gdb.execute("set python print-stack full")
+
+    test = CheckResult()
+    test_bp = gdb.Breakpoint("StopForDebugger")
+    test_bp.enabled = True
+    test_bp.silent = True
+    test_bp.commands = """check_is_debugger_present
+    continue"""
+
+    # "run" won't return if the program exits; ensure the script regains control.
+
+    gdb.events.exited.connect(exit_handler)
+    gdb.execute("run")
+
+    # If the program didn't exit, something went wrong, but we don't
+    # know what. Fail on exit.
+
+    test_failures += 1
+    exit_handler(None)
+
+    print(f"Test failures count: {test_failures}")
 
+if __name__ == "__main__":
+    main()
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
index 0e91cc533e6f8c..f35bec75a98553 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
@@ -46,11 +46,7 @@ void test() {
   static_assert(noexcept(std::is_debugger_present()));
 
   std::same_as<bool> decltype(auto) isDebuggerPresent = std::is_debugger_present();
-  auto isDebuggerPresent1 = false;
-  auto helpMeStr = "Yeah it is working!";
   MarkAsLive(isDebuggerPresent);
-  MarkAsLive(isDebuggerPresent1);
-  MarkAsLive(helpMeStr);
   StopForDebugger(&isDebuggerPresent);
 }
 
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb_test.py b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb_test.py
deleted file mode 100644
index 2946ea471cb4fe..00000000000000
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb_test.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# ===----------------------------------------------------------------------===##
-#
-# 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
-#
-# ===----------------------------------------------------------------------===##
-
-from __future__ import print_function
-import re
-import gdb
-import sys
-
-# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
-
-test_failures = 0
-
-# Sometimes the inital run command can fail to trace the process.
-# (e.g. you don't have ptrace permissions)
-# In these cases gdb still sends us an exited event so we cannot
-# see what "run" printed to check for a warning message, since
-# we get taken to our exit handler before we can look.
-# Instead check that at least one test has been run by the time
-# we exit.
-has_run_tests = False
-
-
-class CheckResult(gdb.Command):
-    """GDB Tester"""
-
-    def __init__(self):
-        super(CheckResult, self).__init__("check_is_debugger_present", gdb.COMMAND_DATA)
-
-    def invoke(self, arg, from_tty):
-        global has_run_tests
-
-        try:
-            print("GDB Custom Test is starting!")
-
-            has_run_tests = True
-
-            # Stack frame is:
-            # 0. StopForDebugger
-            # 1. ComparePrettyPrintToChars or ComparePrettyPrintToRegex
-            # 2. TestCase
-            compare_frame = gdb.newest_frame().older()
-            testcase_frame = compare_frame.older()
-            test_loc = testcase_frame.find_sal()
-
-            # Use interactive commands in the correct context to get the pretty
-            # printed version
-
-            value_str = self._get_value_string(compare_frame, testcase_frame)
-            print(f"====> GDB output: {compare_frame}")
-            print(f"====> GDB output: {testcase_frame}")
-            print(f"====> GDB output: {test_loc}")
-            print(f"====> GDB output: {value_str}")
-
-            # Ignore the convenience variable name and newline
-            value = value_str[value_str.find("= ") + 2 : -1]
-            gdb.newest_frame().select()
-            expectation_val = compare_frame.read_var("isDebuggerPresent")
-            print(f"====> GDB: expectation_val isDebuggerPresent = {expectation_val}")
-            if not expectation_val:
-                global test_failures
-                print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-                print("`isDebuggerPresent` value is `false`, value should be `true`")
-                test_failures += 1
-            else:
-                print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-            
-            expectation_val = compare_frame.read_var("isDebuggerPresent1")
-            if expectation_val:
-                print(f"====> GDB: expectation_val isDebuggerPresent1 = {expectation_val}")
-            expectation_val = compare_frame.read_var("helpMeStr")
-            if expectation_val == "Yeah it is working!":
-                print(f"====> GDB: expectation_val helpMeStr = {expectation_val}")
-            else:
-                print(f"====> GDB error: helpMeStr  {expectation_val}")
-
-            # check_literal = expectation_val.string(encoding="utf-8")
-            # if "PrettyPrintToRegex" in compare_frame.name():
-            #     test_fails = not re.search(check_literal, value)
-            # else:
-            #     test_fails = value != check_literal
-
-            # if test_fails:
-            #     global test_failures
-            #     print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-            #     print("GDB printed:")
-            #     print("   " + repr(value))
-            #     print("Value should match:")
-            #     print("   " + repr(check_literal))
-            #     test_failures += 1
-            # else:
-            #     print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-
-        except RuntimeError as e:
-            # At this point, lots of different things could be wrong, so don't try to
-            # recover or figure it out. Don't exit either, because then it's
-            # impossible to debug the framework itself.
-            print("FAIL: Something is wrong in the test framework.")
-            print(str(e))
-
-            test_failures += 1
-
-    # def _get_value_string(self, compare_frame, testcase_frame):
-    #     compare_frame.select()
-    #     if "ComparePrettyPrint" in compare_frame.name():
-    #         s = gdb.execute("p value", to_string=True)
-    #     else:
-    #         value_str = str(compare_frame.read_var("value"))
-    #         clean_expression_str = value_str.strip("'\"")
-    #         testcase_frame.select()
-    #         s = gdb.execute("p " + clean_expression_str, to_string=True)
-    #     if sys.version_info.major == 2:
-    #         return s.decode("utf-8")
-    #     return s
-    def _get_value_string(self, compare_frame, testcase_frame):
-        compare_frame.select()
-        # if "ComparePrettyPrint" in compare_frame.name():
-        #     s = gdb.execute("p value", to_string=True)
-        # else:
-        #     value_str = str(compare_frame.read_var("value"))
-        #     clean_expression_str = value_str.strip("'\"")
-        #     testcase_frame.select()
-        #     s = gdb.execute("p " + clean_expression_str, to_string=True)
-        # if sys.version_info.major == 2:
-        #     return s.decode("utf-8")
-        s = compare_frame.name()
-        return s
-
-
-def exit_handler(event=None):
-    global test_failures
-    global has_run_tests
-
-    if not has_run_tests:
-        print("FAILED test program did not run correctly, check gdb warnings")
-        test_failures = -1
-    elif test_failures:
-        print("FAILED %d cases" % test_failures)
-    exit(test_failures)
-
-def main():
-    # Start code executed at load time
-
-    # Disable terminal paging
-    gdb.execute("set height 0")
-    gdb.execute("set python print-stack full")
-
-    test = CheckResult()
-    test_bp = gdb.Breakpoint("StopForDebugger")
-    test_bp.enabled = True
-    test_bp.silent = True
-    # test_bp.commands = "check_is_debugger_present\ncontinue"
-    test_bp.commands = """check_is_debugger_present
-    continue"""
-
-    # "run" won't return if the program exits; ensure the script regains control.
-    gdb.events.exited.connect(exit_handler)
-    gdb.execute("run")
-    # If the program didn't exit, something went wrong, but we don't
-    # know what. Fail on exit.
-    test.test_failures += 1
-    exit_handler(None)
-
-    print(f"Test failures count: {test.test_failures}")
-
-if __name__ == "__main__":
-    main()

>From 7ac16912e9856d2003c9e93472e51b0e0e846925 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 6 Feb 2024 13:37:07 +0200
Subject: [PATCH 12/29] Refactoring

---
 ...nt_if_debugging_with_debugger_lldb.sh.cpp} |   0
 .../debugging/breakpoint_with_debugger_gdb.py | 120 +++++++++++++++++
 .../breakpoint_with_debugger_gdb.sh.cpp       |  69 ++++++++++
 .../breakpoint_with_debugger_gdb_test.py      | 123 ++++++++++++++++++
 ...db.py => breakpoint_with_debugger_lldb.py} |   2 +
 ...p => breakpoint_with_debugger_lldb.sh.cpp} |   0
 .../is_debugger_present.with_debugger_lldb.py |  10 --
 ... is_debugger_present_with_debugger_gdb.py} |   6 +-
 ...debugger_present_with_debugger_gdb.sh.cpp} |   4 +-
 .../is_debugger_present_with_debugger_lldb.py |  99 ++++++++++++++
 ...ebugger_present_with_debugger_lldb.sh.cpp} |  10 +-
 11 files changed, 422 insertions(+), 21 deletions(-)
 rename libcxx/test/std/utilities/debugging/{breakpoint_if_debugging.with_debugger_lldb.sh.cpp => breakpoint_if_debugging_with_debugger_lldb.sh.cpp} (100%)
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb_test.py
 rename libcxx/test/std/utilities/debugging/{breakpoint.with_debugger_lldb.py => breakpoint_with_debugger_lldb.py} (79%)
 rename libcxx/test/std/utilities/debugging/{breakpoint.with_debugger_lldb.sh.cpp => breakpoint_with_debugger_lldb.sh.cpp} (100%)
 delete mode 100644 libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py
 rename libcxx/test/std/utilities/debugging/{is_debugger_present.with_debugger_gdb.py => is_debugger_present_with_debugger_gdb.py} (96%)
 rename libcxx/test/std/utilities/debugging/{is_debugger_present.with_debugger_gdb.sh.cpp => is_debugger_present_with_debugger_gdb.sh.cpp} (90%)
 create mode 100644 libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
 rename libcxx/test/std/utilities/debugging/{is_debugger_present.with_debugger_lldb.sh.cpp => is_debugger_present_with_debugger_lldb.sh.cpp} (80%)

diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp
similarity index 100%
rename from libcxx/test/std/utilities/debugging/breakpoint_if_debugging.with_debugger_lldb.sh.cpp
rename to libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
new file mode 100644
index 00000000000000..851d11e00786fe
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
@@ -0,0 +1,120 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+from __future__ import print_function
+import gdb
+
+# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
+
+test_failures = 0
+
+# Sometimes the inital run command can fail to trace the process.
+# (e.g. you don't have ptrace permissions)
+# In these cases gdb still sends us an exited event so we cannot
+# see what "run" printed to check for a warning message, since
+# we get taken to our exit handler before we can look.
+# Instead check that at least one test has been run by the time
+# we exit.
+has_run_tests = False
+
+
+class CheckResult(gdb.Command):
+    """GDB Tester"""
+
+    def __init__(self):
+        super(CheckResult, self).__init__("check_breakpoint", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        global has_run_tests
+
+        try:
+            has_run_tests = True
+
+            # Stack frame is:
+            # 0. StopForDebugger
+            # 1. Check `isDebuggerPresent`
+
+            compare_frame = gdb.newest_frame().older()
+            testcase_frame = compare_frame.older()
+            test_loc = testcase_frame.find_sal()
+
+            # Ignore the convenience variable name and newline
+
+            frame_name = compare_frame.name()
+
+            if "std::__1::__breakpoint" in compare_frame.name():
+                print(f"===> GDB frame name:{frame_name}")
+                # s = gdb.execute("p value", to_string=True)
+
+            gdb.newest_frame().select()
+            expectation_val = compare_frame.read_var("isDebuggerPresent")
+
+            if not expectation_val:
+                global test_failures
+
+                print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+                print("`isDebuggerPresent` value is `false`, value should be `true`")
+
+                test_failures += 1
+            else:
+                print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+
+        except RuntimeError as e:
+            # At this point, lots of different things could be wrong, so don't try to
+            # recover or figure it out. Don't exit either, because then it's
+            # impossible to debug the framework itself.
+
+            print("FAIL: Something is wrong in the test framework.")
+            print(str(e))
+
+            test_failures += 1
+
+
+def exit_handler(event=None):
+    """Exit handler"""
+
+    global test_failures
+    global has_run_tests
+
+    if not has_run_tests:
+        print("FAILED test program did not run correctly, check gdb warnings")
+        test_failures = -1
+    elif test_failures:
+        print(f"FAILED {test_failures} cases")
+    exit(test_failures)
+
+def main():
+    # Start code executed at load time
+
+    # Disable terminal paging
+
+    gdb.execute("set height 0")
+    gdb.execute("set python print-stack full")
+
+    test = CheckResult()
+    test_bp = gdb.Breakpoint("StopForDebugger")
+    test_bp.enabled = True
+    test_bp.silent = True
+    test_bp.commands = """check_breakpoint
+    continue"""
+
+    # "run" won't return if the program exits; ensure the script regains control.
+
+    gdb.events.exited.connect(exit_handler)
+    gdb.execute("run")
+
+    # If the program didn't exit, something went wrong, but we don't
+    # know what. Fail on exit.
+
+    test_failures += 1
+    exit_handler(None)
+
+    print(f"Test failures count: {test_failures}")
+
+if __name__ == "__main__":
+    main()
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
new file mode 100644
index 00000000000000..0315869489949d
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// REQUIRES: host-has-gdb-with-python
+// UNSUPPORTED: android
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
+
+// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
+// RUN: %{gdb} %t.exe -ex "source %S/breakpoint.with_debugger_gdb.py" -ex run// lldb ./build/default.debug.libcxx.testing/LLVM-Testing -o "command script -l python import /home/hristo/Projects/llvm-project/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py" -o run -o detach -o quit
+ -ex detach -ex quit --silent
+
+// <debugging>
+
+// void breakpoint() noexcept;
+
+#include <cassert>
+#include <debugging>
+
+#include "test_macros.h"
+
+#ifdef TEST_COMPILER_GCC
+#  define OPT_NONE __attribute__((noinline))
+#else
+#  define OPT_NONE __attribute__((optnone))
+#endif
+
+void StopForDebugger() OPT_NONE;
+void StopForDebugger() {}
+
+// Test with debugger attached:
+
+// GDB command:  `gdb breakpoint.pass -ex run -ex detach -ex quit --silent`
+
+gdb breakpoint.pass -ex run -ex "signal SIGTRAP" -ex detach -ex quit --silent
+
+//
+// Sample GDB ouput:
+//
+// Reading symbols from breakpoint.pass..
+// Starting program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass
+// [Thread debugging using libthread_db enabled]
+// Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
+
+// Program received signal SIGTRAP, Trace/breakpoint trap.
+// std::__1::__breakpoint () at /home/llvm-dev/Projects/llvm-project/libcxx/src/debugging.cpp:44
+// warning: Source file is more recent than executable.
+// 44	}
+// Detaching from program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass, process 53887
+// [Inferior 1 (process 53887) detached]
+
+void test() {
+  static_assert(noexcept(std::breakpoint()));
+
+  StopForDebugger();
+  std::breakpoint();
+  StopForDebugger();
+}
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb_test.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb_test.py
new file mode 100644
index 00000000000000..8e8ac0eaf17a12
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb_test.py
@@ -0,0 +1,123 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+from __future__ import print_function
+import gdb
+
+# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
+
+test_failures = 0
+
+# Sometimes the inital run command can fail to trace the process.
+# (e.g. you don't have ptrace permissions)
+# In these cases gdb still sends us an exited event so we cannot
+# see what "run" printed to check for a warning message, since
+# we get taken to our exit handler before we can look.
+# Instead check that at least one test has been run by the time
+# we exit.
+has_run_tests = False
+
+
+class CheckResult(gdb.Command):
+    """GDB Tester"""
+
+    def __init__(self):
+        super(CheckResult, self).__init__("check_breakpoint", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        global has_run_tests
+
+        try:
+            has_run_tests = True
+
+            # Stack frame is:
+            # 0. StopForDebugger
+            # 1. Check `isDebuggerPresent`
+
+            compare_frame = gdb.newest_frame().older()
+            testcase_frame = compare_frame.older()
+            test_loc = testcase_frame.find_sal()
+
+            # Ignore the convenience variable name and newline
+
+            frame_name = compare_frame.name()
+
+            if "std::__1::__breakpoint" in compare_frame.name():
+                print(f"===> GDB frame name:{frame_name}")
+                # s = gdb.execute("p value", to_string=True)
+            print(f"===> GDB frame name:{frame_name}")
+
+            gdb.newest_frame().select()
+            expectation_val = compare_frame.read_var("isDebuggerPresent")
+
+            if not expectation_val:
+                global test_failures
+
+                print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+                print("`isDebuggerPresent` value is `false`, value should be `true`")
+
+                test_failures += 1
+            else:
+                print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+
+        except RuntimeError as e:
+            # At this point, lots of different things could be wrong, so don't try to
+            # recover or figure it out. Don't exit either, because then it's
+            # impossible to debug the framework itself.
+
+            print("FAIL: Something is wrong in the test framework.")
+            print(str(e))
+
+            test_failures += 1
+
+
+def exit_handler(event=None):
+    """Exit handler"""
+
+    global test_failures
+    global has_run_tests
+
+    if not has_run_tests:
+        print("FAILED test program did not run correctly, check gdb warnings")
+        test_failures = -1
+    elif test_failures:
+        print(f"FAILED {test_failures} cases")
+    exit(test_failures)
+
+def main():
+    # Start code executed at load time
+
+    # Disable terminal paging
+
+    gdb.execute("set height 0")
+    gdb.execute("set python print-stack full")
+
+    test = CheckResult()
+    test_bp = gdb.Breakpoint("StopForDebugger")
+    test_bp.enabled = True
+    test_bp.silent = True
+    test_bp.commands = """continue
+    signal SIGTRAP
+    check_breakpoint
+    continue"""
+
+    # "run" won't return if the program exits; ensure the script regains control.
+
+    gdb.events.exited.connect(exit_handler)
+    gdb.execute("run")
+
+    # If the program didn't exit, something went wrong, but we don't
+    # know what. Fail on exit.
+
+   #  test_failures += 1
+    exit_handler(None)
+
+    print(f"Test failures count: {test_failures}")
+
+if __name__ == "__main__":
+    main()
diff --git a/libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
similarity index 79%
rename from libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.py
rename to libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
index 41af51bc13a19b..4d0f19d1203a50 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.py
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
@@ -9,6 +9,8 @@
 import lldb
 
 # https://lldb.llvm.org/use/python-reference.html#running-a-python-script-when-a-breakpoint-gets-hit
+# Recognize __builtin_debugtrap on arm64, advance pc past it so users can continue easily
+# https://reviews.llvm.org/D91238#change-LKCsq6kcwyVV
 
 def breakpoint_function_wrapper(frame, bp_loc, internal_dict):
    # Your code goes here
diff --git a/libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp
similarity index 100%
rename from libcxx/test/std/utilities/debugging/breakpoint.with_debugger_lldb.sh.cpp
rename to libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py
deleted file mode 100644
index 61979b9a6e53d9..00000000000000
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# ===----------------------------------------------------------------------===##
-#
-# 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
-#
-# ===----------------------------------------------------------------------===##
-
-import lldb
-
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
similarity index 96%
rename from libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py
rename to libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
index 1446df2bd0ed13..ce6b19c59ade81 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
@@ -45,7 +45,6 @@ def invoke(self, arg, from_tty):
 
             # Ignore the convenience variable name and newline
 
-            # value = value_str[value_str.find("= ") + 2 : -1]
             gdb.newest_frame().select()
             expectation_val = compare_frame.read_var("isDebuggerPresent")
 
@@ -84,14 +83,13 @@ def exit_handler(event=None):
     exit(test_failures)
 
 def main():
-    # Start code executed at load time
-
+    """Main entry point"""
     # Disable terminal paging
 
     gdb.execute("set height 0")
     gdb.execute("set python print-stack full")
 
-    test = CheckResult()
+    CheckResult()
     test_bp = gdb.Breakpoint("StopForDebugger")
     test_bp.enabled = True
     test_bp.silent = True
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.sh.cpp
similarity index 90%
rename from libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
rename to libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.sh.cpp
index f35bec75a98553..9a1e7fdcf1b787 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_gdb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.sh.cpp
@@ -12,7 +12,7 @@
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{gdb} %t.exe -ex "source %S/is_debugger_present.with_debugger_gdb.py" -ex run -ex detach -ex quit --silent
+// RUN: %{gdb} %t.exe -ex "source %S/is_debugger_present_with_debugger_gdb.py" -ex run -ex detach -ex quit --silent
 
 // <debugging>
 
@@ -40,7 +40,7 @@ void StopForDebugger(void*) OPT_NONE;
 void StopForDebugger(void*) {}
 
 // Test with debugger attached:
-//   GDB command: `gdb is_debugger_present.pass -ex run -ex detach -ex quit --silent`
+//   GDB command: `gdb is_debugger_present_with_debugger_gdb.sh -ex run -ex detach -ex quit --silent`
 
 void test() {
   static_assert(noexcept(std::is_debugger_present()));
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
new file mode 100644
index 00000000000000..d0349db626d099
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
@@ -0,0 +1,99 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import lldb
+
+def breakpoint_handler(frame, bp_loc, internal_dict):
+    name = frame.GetFunctionName()
+    print(f"======> LLDB: func: {name}")
+    module = frame.GetModule()
+    filename = module.file.GetFilename()
+    print(f"======> LLDB: file: {filename}")
+    line = frame.GetLineEntry().GetLine()
+    print(f"======> LLDB: file: {line}")
+    parent = frame.get_parent_frame()
+
+    expectation_val = parent.FindVariable("isDebuggerPresent")
+    print(f"------ var: {expectation_val}")
+    expectation_val = parent.FindVariable("isDebuggerPresent")
+    print(f"------ var val: {expectation_val.value}")
+
+    # expectation_val = frame.FindVariable("isDebuggerPresent")
+    # print(f"------ var: {frame.variables}")
+
+    # for var in frame.variables:
+    #     print(f"     far: {var.name}")
+
+    # print(f"typeof: {type(expectation_val.value)}")
+    # print(f"typeof: {type(expectation_val.type)}")
+    # print(f"typeof: {type(expectation_val.value_type)}")
+    # print(f"expectation_val.value: {expectation_val.value}")
+    # print(f"expectation_val.value 2: {expectation_val}")
+    # value_value = expectation_val.value
+
+    # if value_value is None:
+    #     print(" ---- None")
+    # else:
+    #     print(f"---- Yes {value_value}")
+
+
+    if expectation_val.value == "true":
+        print(" ---- yes")
+    else:
+        print("---- no")
+
+    if expectation_val is None or expectation_val.value == "false":
+        # global test_failures
+
+        print("FAIL: " + filename + ":" + str(line))
+        print("`isDebuggerPresent` value is `false`, value should be `true`")
+
+        # test_failures += 1
+    else:
+        print("PASS: " + filename + ":" + str(line))
+
+
+def __lldb_init_module(debugger, internal_dict):
+    print("-------- START")
+    target = debugger.GetSelectedTarget()
+    test_bp = target.BreakpointCreateByName("StopForDebugger")
+    test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
+    test_bp.enabled = True
+    print("------- END")
+
+
+# def main():
+#     """Main entry point"""
+#     print("==============> Hello LLDB Python")
+#     # Disable terminal paging
+
+#     # gdb.execute("set height 0")
+#     # gdb.execute("set python print-stack full")
+
+#     # CheckResult()
+#     # test_bp = gdb.Breakpoint("StopForDebugger")
+#     # test_bp.enabled = True
+#     # test_bp.silent = True
+#     # test_bp.commands = """check_is_debugger_present
+#     # continue"""
+
+#     # # "run" won't return if the program exits; ensure the script regains control.
+
+#     # gdb.events.exited.connect(exit_handler)
+#     # gdb.execute("run")
+
+#     # # If the program didn't exit, something went wrong, but we don't
+#     # # know what. Fail on exit.
+
+#     # test_failures += 1
+#     # exit_handler(None)
+
+#     # print(f"Test failures count: {test_failures}")
+
+# if __name__ == "__main__":
+#     main()
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp
similarity index 80%
rename from libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
rename to libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp
index 1d954137b8e693..0411b42bd31e00 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp
@@ -12,7 +12,7 @@
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{lldb} %t.exe -ex "command source %S/is_debugger_present.with_debugger_lldb.py" -o run -o detach -o quit
+// RUN: %{lldb} %t.exe -ex "command script import %S/is_debugger_present_with_debugger_lldb.py" -o run -o detach -o quit
 
 // <debugging>
 
@@ -36,18 +36,18 @@ void MarkAsLive(Type&&) OPT_NONE;
 template <typename Type>
 void MarkAsLive(Type&&) {}
 
-void StopForDebugger(void*, void*) OPT_NONE;
-void StopForDebugger(void*, void*) {}
+void StopForDebugger(void*) OPT_NONE;
+void StopForDebugger(void*) {}
 
 // Test with debugger attached:
-//   LLDB command: `lldb "is_debugger_present.pass" -o run -o detach -o quit`
+//   LLDB command: `lldb "is_debugger_present_with_debugger_lldb.sh" -o run -o detach -o quit`
 
 void test() {
   static_assert(noexcept(std::is_debugger_present()));
 
   std::same_as<bool> decltype(auto) isDebuggerPresent = std::is_debugger_present();
   MarkAsLive(isDebuggerPresent);
-  StopForDebuger(&isDebuggerPresent);
+  StopForDebugger(&isDebuggerPresent);
 }
 
 int main(int, char**) {

>From cba70493d8f1d704cd6194dac56c6364301a34e8 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 6 Feb 2024 14:51:34 +0200
Subject: [PATCH 13/29] WIP: LLDB `is_debugger_present` script

---
 .../is_debugger_present_with_debugger_lldb.py | 119 ++++++++----------
 ...debugger_present_with_debugger_lldb.sh.cpp |   2 +-
 libcxx/utils/libcxx/test/features.py          |  29 +----
 3 files changed, 52 insertions(+), 98 deletions(-)

diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
index d0349db626d099..960ceae8dd8b4b 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
@@ -8,92 +8,71 @@
 
 import lldb
 
+test_failures = 0
+
+# Sometimes the inital run command can fail to trace the process.
+# (e.g. you don't have ptrace permissions)
+# In these cases gdb still sends us an exited event so we cannot
+# see what "run" printed to check for a warning message, since
+# we get taken to our exit handler before we can look.
+# Instead check that at least one test has been run by the time
+# we exit.
+has_run_tests = False
+
 def breakpoint_handler(frame, bp_loc, internal_dict):
-    name = frame.GetFunctionName()
-    print(f"======> LLDB: func: {name}")
-    module = frame.GetModule()
-    filename = module.file.GetFilename()
-    print(f"======> LLDB: file: {filename}")
-    line = frame.GetLineEntry().GetLine()
-    print(f"======> LLDB: file: {line}")
-    parent = frame.get_parent_frame()
+    print("===> breakpoint_handler")
+    global has_run_tests
+
+    try:
+        has_run_tests = True
+
+        module = frame.GetModule()
+        filename = module.compile_units[0].file
+        line = frame.GetLineEntry().GetLine()
+        parent = frame.get_parent_frame()
+        expectation_val = parent.FindVariable("isDebuggerPresent")
 
-    expectation_val = parent.FindVariable("isDebuggerPresent")
-    print(f"------ var: {expectation_val}")
-    expectation_val = parent.FindVariable("isDebuggerPresent")
-    print(f"------ var val: {expectation_val.value}")
+        if expectation_val is None or expectation_val.value == "false":
+            global test_failures
 
-    # expectation_val = frame.FindVariable("isDebuggerPresent")
-    # print(f"------ var: {frame.variables}")
+            print(f"FAIL: {filename}:{line}")
+            print("`isDebuggerPresent` value is `false`, value should be `true`")
 
-    # for var in frame.variables:
-    #     print(f"     far: {var.name}")
+            test_failures += 1
+            exit(-1)
+        else:
+            print(f"PASS: {filename}:{line}")
 
-    # print(f"typeof: {type(expectation_val.value)}")
-    # print(f"typeof: {type(expectation_val.type)}")
-    # print(f"typeof: {type(expectation_val.value_type)}")
-    # print(f"expectation_val.value: {expectation_val.value}")
-    # print(f"expectation_val.value 2: {expectation_val}")
-    # value_value = expectation_val.value
+    except RuntimeError as e:
+        # At this point, lots of different things could be wrong, so don't try to
+        # recover or figure it out. Don't exit either, because then it's
+        # impossible to debug the framework itself.
 
-    # if value_value is None:
-    #     print(" ---- None")
-    # else:
-    #     print(f"---- Yes {value_value}")
+        print("FAIL: Something is wrong in the test framework.")
+        print(str(e))
 
+        test_failures += 1
 
-    if expectation_val.value == "true":
-        print(" ---- yes")
-    else:
-        print("---- no")
+def exit_handler(event=None):
+    """Exit handler"""
 
-    if expectation_val is None or expectation_val.value == "false":
-        # global test_failures
+    global test_failures
+    global has_run_tests
 
-        print("FAIL: " + filename + ":" + str(line))
-        print("`isDebuggerPresent` value is `false`, value should be `true`")
+    if not has_run_tests:
+        print("FAILED test program did not run correctly, check lldb warnings")
+        test_failures = -1
+    elif test_failures:
+        print(f"FAILED {test_failures} cases")
 
-        # test_failures += 1
-    else:
-        print("PASS: " + filename + ":" + str(line))
+    exit(test_failures)
 
 
 def __lldb_init_module(debugger, internal_dict):
-    print("-------- START")
     target = debugger.GetSelectedTarget()
     test_bp = target.BreakpointCreateByName("StopForDebugger")
     test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
     test_bp.enabled = True
-    print("------- END")
-
-
-# def main():
-#     """Main entry point"""
-#     print("==============> Hello LLDB Python")
-#     # Disable terminal paging
-
-#     # gdb.execute("set height 0")
-#     # gdb.execute("set python print-stack full")
-
-#     # CheckResult()
-#     # test_bp = gdb.Breakpoint("StopForDebugger")
-#     # test_bp.enabled = True
-#     # test_bp.silent = True
-#     # test_bp.commands = """check_is_debugger_present
-#     # continue"""
-
-#     # # "run" won't return if the program exits; ensure the script regains control.
-
-#     # gdb.events.exited.connect(exit_handler)
-#     # gdb.execute("run")
-
-#     # # If the program didn't exit, something went wrong, but we don't
-#     # # know what. Fail on exit.
-
-#     # test_failures += 1
-#     # exit_handler(None)
-
-#     # print(f"Test failures count: {test_failures}")
 
-# if __name__ == "__main__":
-#     main()
+    # test_failures += 1
+    # exit_handler(None)
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp
index 0411b42bd31e00..d51eb03e1e9dc1 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp
@@ -12,7 +12,7 @@
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{lldb} %t.exe -ex "command script import %S/is_debugger_present_with_debugger_lldb.py" -o run -o detach -o quit
+// RUN: %{lldb} %t.exe -o "command script import %S/is_debugger_present_with_debugger_lldb.py" -o run -o detach -o quit
 
 // <debugging>
 
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index aaf22a42959ae9..e8685a74cc3323 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -474,38 +474,13 @@ def _getAndroidDeviceApi(cfg):
     ),
 ]
 
-# Detect whether LLDB is on the system, has Python scripting and supports
-# adding breakpoint commands. If so add a substitution to access it.
+# Detect whether LLDB is on the system.
 def check_lldb(cfg):
     lldb_path = shutil.which("lldb")
     if lldb_path is None:
         return False
 
-#     # Check that we can set breakpoint commands.
-#     test_src = """
-# try:
-#   debugger = lldb.SBDebugger.Create()
-#   # Block until target process exits.
-#   debugger.SetAsync(False)
-#   # target = debugger.CreateTarget()
-# except AttributeError:
-#   sys.exit(1)
-# #sys.exit()
-# """
-
-#     try:
-#         stdout = subprocess.check_output(
-#             [lldb_path, "-o", f"script {test_src}", "--batch"],
-#             stderr=subprocess.DEVNULL,
-#             universal_newlines=True,
-#         )
-#     except subprocess.CalledProcessError:
-#         # We can't set breakpoint commands
-#         return False
-
-#     # Check we actually ran the Python
-#     return not "Python scripting is not supported" in stdout
-    return True # TODO: Remove this line
+    return True
 
 
 DEFAULT_FEATURES += [

>From 673e90b6414638bfab7e4d10f446022bc526e866 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 6 Feb 2024 15:12:09 +0200
Subject: [PATCH 14/29] Added test skelettons

---
 ...eakpoint_if_debugging_with_debugger_gdb.py | 120 ++++++++++++++++++
 ...oint_if_debugging_with_debugger_gdb.sh.cpp |  49 +++++++
 ...akpoint_if_debugging_with_debugger_lldb.py |  67 ++++++++++
 ...int_if_debugging_with_debugger_lldb.sh.cpp |  19 ++-
 .../breakpoint_with_debugger_gdb.sh.cpp       |   5 +-
 .../breakpoint_with_debugger_lldb.py          |  61 ++++++++-
 .../breakpoint_with_debugger_lldb.sh.cpp      |  36 ++----
 7 files changed, 322 insertions(+), 35 deletions(-)
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp
 create mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py

diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py
new file mode 100644
index 00000000000000..be96eccfe26f89
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py
@@ -0,0 +1,120 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+from __future__ import print_function
+import gdb
+
+# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
+
+test_failures = 0
+
+# Sometimes the inital run command can fail to trace the process.
+# (e.g. you don't have ptrace permissions)
+# In these cases gdb still sends us an exited event so we cannot
+# see what "run" printed to check for a warning message, since
+# we get taken to our exit handler before we can look.
+# Instead check that at least one test has been run by the time
+# we exit.
+has_run_tests = False
+
+
+class CheckResult(gdb.Command):
+    """GDB Tester"""
+
+    def __init__(self):
+        super(CheckResult, self).__init__("check_breakpoint_if_debugging", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        global has_run_tests
+
+        try:
+            has_run_tests = True
+
+            # Stack frame is:
+            # 0. StopForDebugger
+            # 1. Check `isDebuggerPresent`
+
+            compare_frame = gdb.newest_frame().older()
+            testcase_frame = compare_frame.older()
+            test_loc = testcase_frame.find_sal()
+
+            # Ignore the convenience variable name and newline
+
+            frame_name = compare_frame.name()
+
+            if "std::__1::__breakpoint" in compare_frame.name():
+                print(f"===> GDB frame name:{frame_name}")
+                # s = gdb.execute("p value", to_string=True)
+
+            gdb.newest_frame().select()
+            expectation_val = compare_frame.read_var("isDebuggerPresent")
+
+            if not expectation_val:
+                global test_failures
+
+                print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+                print("`isDebuggerPresent` value is `false`, value should be `true`")
+
+                test_failures += 1
+            else:
+                print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
+
+        except RuntimeError as e:
+            # At this point, lots of different things could be wrong, so don't try to
+            # recover or figure it out. Don't exit either, because then it's
+            # impossible to debug the framework itself.
+
+            print("FAIL: Something is wrong in the test framework.")
+            print(str(e))
+
+            test_failures += 1
+
+
+def exit_handler(event=None):
+    """Exit handler"""
+
+    global test_failures
+    global has_run_tests
+
+    if not has_run_tests:
+        print("FAILED test program did not run correctly, check gdb warnings")
+        test_failures = -1
+    elif test_failures:
+        print(f"FAILED {test_failures} cases")
+    exit(test_failures)
+
+def main():
+    # Start code executed at load time
+
+    # Disable terminal paging
+
+    gdb.execute("set height 0")
+    gdb.execute("set python print-stack full")
+
+    test = CheckResult()
+    test_bp = gdb.Breakpoint("StopForDebugger")
+    test_bp.enabled = True
+    test_bp.silent = True
+    test_bp.commands = """check_breakpoint_if_debugging
+    continue"""
+
+    # "run" won't return if the program exits; ensure the script regains control.
+
+    gdb.events.exited.connect(exit_handler)
+    gdb.execute("run")
+
+    # If the program didn't exit, something went wrong, but we don't
+    # know what. Fail on exit.
+
+    test_failures += 1
+    exit_handler(None)
+
+    print(f"Test failures count: {test_failures}")
+
+if __name__ == "__main__":
+    main()
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp
new file mode 100644
index 00000000000000..f618e5240f52cb
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// REQUIRES: host-has-gdb-with-python
+// UNSUPPORTED: android
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
+
+// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
+// RUN: %{gdb} %t.exe -ex "source %S/breakpoint_if_debugging_with_debugger_gdb.py" -ex run -ex detach -ex quit --silent
+
+// <debugging>
+
+// void breakpoint_if_debugging() noexcept;
+
+#include <cassert>
+#include <debugging>
+
+#include "test_macros.h"
+
+#ifdef TEST_COMPILER_GCC
+#  define OPT_NONE __attribute__((noinline))
+#else
+#  define OPT_NONE __attribute__((optnone))
+#endif
+
+void StopForDebugger() OPT_NONE;
+void StopForDebugger() {}
+
+// Test with debugger attached:
+
+// GDB command:  `gdb breakpoint_if_debugging.pass -ex run -ex detach -ex quit --silent`
+
+void test() {
+  static_assert(noexcept(std::breakpoint_if_debugging()));
+
+  std::breakpoint_if_debugging();
+}
+
+int main(int, char**) {
+  test();
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py
new file mode 100644
index 00000000000000..e72802479bc15f
--- /dev/null
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py
@@ -0,0 +1,67 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import lldb
+
+test_failures = 0
+
+# Sometimes the inital run command can fail to trace the process.
+# (e.g. you don't have ptrace permissions)
+# In these cases gdb still sends us an exited event so we cannot
+# see what "run" printed to check for a warning message, since
+# we get taken to our exit handler before we can look.
+# Instead check that at least one test has been run by the time
+# we exit.
+has_run_tests = False
+
+def breakpoint_handler(frame, bp_loc, internal_dict):
+    global has_run_tests
+
+    try:
+        has_run_tests = True
+
+        module = frame.GetModule()
+        filename = module.compile_units[0].file
+        line = frame.GetLineEntry().GetLine()
+        parent = frame.get_parent_frame()
+
+      #   TODO: test
+
+    except RuntimeError as e:
+        # At this point, lots of different things could be wrong, so don't try to
+        # recover or figure it out. Don't exit either, because then it's
+        # impossible to debug the framework itself.
+
+        print("FAIL: Something is wrong in the test framework.")
+        print(str(e))
+
+        test_failures += 1
+
+def exit_handler(event=None):
+    """Exit handler"""
+
+    global test_failures
+    global has_run_tests
+
+    if not has_run_tests:
+        print("FAILED test program did not run correctly, check lldb warnings")
+        test_failures = -1
+    elif test_failures:
+        print(f"FAILED {test_failures} cases")
+
+    exit(test_failures)
+
+
+def __lldb_init_module(debugger, internal_dict):
+    target = debugger.GetSelectedTarget()
+    test_bp = target.BreakpointCreateByName("StopForDebugger")
+    test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
+    test_bp.enabled = True
+
+    # test_failures += 1
+    # exit_handler(None)
\ No newline at end of file
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp
index 2fe76aa8e1b3e2..2b31456f00b275 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp
@@ -7,13 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
-// UNSUPPORTED: gcc
+// REQUIRES: host-has-lldb-with-python
 // UNSUPPORTED: android
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{lldb} %t.exe -o run -o detach -o quit
-// RUN: %{gdb} %t.exe -ex run -ex detach -ex quit --silent
+// RUN: %{lldb} %t.exe -o "command script import %S/breakpoint_if_debugging_with_debugger_lldb.py" -o run -o detach -o quit
 
 // <debugging>
 
@@ -22,10 +21,20 @@
 #include <cassert>
 #include <debugging>
 
+#include "test_macros.h"
+
+#ifdef TEST_COMPILER_GCC
+#  define OPT_NONE __attribute__((noinline))
+#else
+#  define OPT_NONE __attribute__((optnone))
+#endif
+
+void StopForDebugger() OPT_NONE;
+void StopForDebugger() {}
+
 // Test with debugger attached:
 
 // LLDB command: `lldb "breakpoint_if_debugging.pass" -o run -o detach -o quit`
-// GDB command:  `gdb breakpoint_if_debugging.pass -ex run -ex detach -ex quit --silent`
 
 void test() {
   static_assert(noexcept(std::breakpoint_if_debugging()));
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
index 0315869489949d..efdc0daff1f98f 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
@@ -12,8 +12,7 @@
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{gdb} %t.exe -ex "source %S/breakpoint.with_debugger_gdb.py" -ex run// lldb ./build/default.debug.libcxx.testing/LLVM-Testing -o "command script -l python import /home/hristo/Projects/llvm-project/libcxx/test/std/utilities/debugging/is_debugger_present.with_debugger_lldb.py" -o run -o detach -o quit
- -ex detach -ex quit --silent
+// RUN: %{gdb} %t.exe -ex "source %S/breakpoint_with_debugger_gdb.py" -ex run -ex detach -ex quit --silent
 
 // <debugging>
 
@@ -37,7 +36,7 @@ void StopForDebugger() {}
 
 // GDB command:  `gdb breakpoint.pass -ex run -ex detach -ex quit --silent`
 
-gdb breakpoint.pass -ex run -ex "signal SIGTRAP" -ex detach -ex quit --silent
+// gdb breakpoint.pass -ex run -ex "signal SIGTRAP" -ex detach -ex quit --silent
 
 //
 // Sample GDB ouput:
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
index 4d0f19d1203a50..e72802479bc15f 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
@@ -8,9 +8,60 @@
 
 import lldb
 
-# https://lldb.llvm.org/use/python-reference.html#running-a-python-script-when-a-breakpoint-gets-hit
-# Recognize __builtin_debugtrap on arm64, advance pc past it so users can continue easily
-# https://reviews.llvm.org/D91238#change-LKCsq6kcwyVV
+test_failures = 0
 
-def breakpoint_function_wrapper(frame, bp_loc, internal_dict):
-   # Your code goes here
+# Sometimes the inital run command can fail to trace the process.
+# (e.g. you don't have ptrace permissions)
+# In these cases gdb still sends us an exited event so we cannot
+# see what "run" printed to check for a warning message, since
+# we get taken to our exit handler before we can look.
+# Instead check that at least one test has been run by the time
+# we exit.
+has_run_tests = False
+
+def breakpoint_handler(frame, bp_loc, internal_dict):
+    global has_run_tests
+
+    try:
+        has_run_tests = True
+
+        module = frame.GetModule()
+        filename = module.compile_units[0].file
+        line = frame.GetLineEntry().GetLine()
+        parent = frame.get_parent_frame()
+
+      #   TODO: test
+
+    except RuntimeError as e:
+        # At this point, lots of different things could be wrong, so don't try to
+        # recover or figure it out. Don't exit either, because then it's
+        # impossible to debug the framework itself.
+
+        print("FAIL: Something is wrong in the test framework.")
+        print(str(e))
+
+        test_failures += 1
+
+def exit_handler(event=None):
+    """Exit handler"""
+
+    global test_failures
+    global has_run_tests
+
+    if not has_run_tests:
+        print("FAILED test program did not run correctly, check lldb warnings")
+        test_failures = -1
+    elif test_failures:
+        print(f"FAILED {test_failures} cases")
+
+    exit(test_failures)
+
+
+def __lldb_init_module(debugger, internal_dict):
+    target = debugger.GetSelectedTarget()
+    test_bp = target.BreakpointCreateByName("StopForDebugger")
+    test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
+    test_bp.enabled = True
+
+    # test_failures += 1
+    # exit_handler(None)
\ No newline at end of file
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp
index 2c753b05592e37..9a3ef6c4e5cd60 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp
@@ -7,13 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
-// UNSUPPORTED: gcc
+// REQUIRES: host-has-lldb-with-python
 // UNSUPPORTED: android
+// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{lldb} %t.exe -o run -o detach -o quit
-// RUN: %{gdb} %t.exe -ex run -ex detach -ex quit --silent
+// RUN: %{lldb} %t.exe -o "command script import %S/breakpoint_with_debugger_lldb.py" -o run -o detach -o quit
 
 // <debugging>
 
@@ -22,10 +21,20 @@
 #include <cassert>
 #include <debugging>
 
+#include "test_macros.h"
+
+#ifdef TEST_COMPILER_GCC
+#  define OPT_NONE __attribute__((noinline))
+#else
+#  define OPT_NONE __attribute__((optnone))
+#endif
+
+void StopForDebugger() OPT_NONE;
+void StopForDebugger() {}
+
 // Test with debugger attached:
 
 // LLDB command: `lldb "breakpoint.pass" -o run -o detach -o quit`
-// GDB command:  `gdb breakpoint.pass -ex run -ex detach -ex quit --silent`
 
 //
 // Sample LLDB output:
@@ -45,23 +54,6 @@
 // Process 43162 detached
 // (lldb) quit
 
-//
-// Sample GDB ouput:
-//
-// Reading symbols from breakpoint.pass..
-// Starting program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass
-// [Thread debugging using libthread_db enabled]
-// Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
-
-// Program received signal SIGTRAP, Trace/breakpoint trap.
-// std::__1::__breakpoint () at /home/llvm-dev/Projects/llvm-project/libcxx/src/debugging.cpp:44
-// warning: Source file is more recent than executable.
-// 44	}
-// Detaching from program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass, process 53887
-// [Inferior 1 (process 53887) detached]
-
-// https://lldb.llvm.org/use/python-reference.html#running-a-python-script-when-a-breakpoint-gets-hit
-
 void test() {
   static_assert(noexcept(std::breakpoint()));
 

>From 22694d0b39471ddb5b9318fb0442d9768d37bc40 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 6 Feb 2024 15:50:28 +0200
Subject: [PATCH 15/29] Tweaks

What was implemented so far:

- Implemented functions
  - [ ] `breakpoint()`
  - [ ] `breakpoint_if_debugging()`
  - [ ] `is_debugger_present()`
- Supported platforms
  - [ ] AIX
  - [x] Apple
  - [x] FreeBSD (not tested)
  - [x] Linux
  - [ ] Picolib
  - [x] Windows
- Supported debuggers (implemented tests)
  - GDB
    - [ ] `breakpoint()`
    - [ ] `breakpoint_if_debugging()`
    - [x] `is_debugger_present()`
  - LLDB
    - [ ] `breakpoint()`
    - [ ] `breakpoint_if_debugging()`
    - [ ] `is_debugger_present()`
---
 .../debugging/is_debugger_present_with_debugger_gdb.py          | 1 +
 .../debugging/is_debugger_present_with_debugger_lldb.py         | 2 --
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
index ce6b19c59ade81..e4669c83c4426c 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
@@ -98,6 +98,7 @@ def main():
 
     # "run" won't return if the program exits; ensure the script regains control.
 
+    # https://sourceware.org/gdb/current/onlinedocs/gdb.html/Events-In-Python.html
     gdb.events.exited.connect(exit_handler)
     gdb.execute("run")
 
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
index 960ceae8dd8b4b..e8351149082eb8 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
@@ -20,7 +20,6 @@
 has_run_tests = False
 
 def breakpoint_handler(frame, bp_loc, internal_dict):
-    print("===> breakpoint_handler")
     global has_run_tests
 
     try:
@@ -39,7 +38,6 @@ def breakpoint_handler(frame, bp_loc, internal_dict):
             print("`isDebuggerPresent` value is `false`, value should be `true`")
 
             test_failures += 1
-            exit(-1)
         else:
             print(f"PASS: {filename}:{line}")
 

>From 92a7691c82d54ef29a2c502e98916316945f931b Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 7 Feb 2024 14:02:08 +0200
Subject: [PATCH 16/29] DONE: `is_debugger_present` test works for GDB and LLDB

---
 ...reakpoint_if_debugging_with_debugger_gdb.sh.cpp |  2 +-
 .../debugging/breakpoint_with_debugger_gdb.sh.cpp  |  2 +-
 .../is_debugger_present_with_debugger_gdb.sh.cpp   |  2 +-
 .../is_debugger_present_with_debugger_lldb.py      | 14 ++++++++++----
 .../is_debugger_present_with_debugger_lldb.sh.cpp  |  2 +-
 5 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp
index f618e5240f52cb..ef6e7778369c5c 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp
@@ -12,7 +12,7 @@
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{gdb} %t.exe -ex "source %S/breakpoint_if_debugging_with_debugger_gdb.py" -ex run -ex detach -ex quit --silent
+// RUN: %{gdb} %t.exe -ex "source %S/breakpoint_if_debugging_with_debugger_gdb.py" --silent
 
 // <debugging>
 
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
index efdc0daff1f98f..d1906460a0dfaf 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
@@ -12,7 +12,7 @@
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{gdb} %t.exe -ex "source %S/breakpoint_with_debugger_gdb.py" -ex run -ex detach -ex quit --silent
+// RUN: %{gdb} %t.exe -ex "source %S/breakpoint_with_debugger_gdb.py" --silent
 
 // <debugging>
 
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.sh.cpp
index 9a1e7fdcf1b787..21f2bbc0fc6c98 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.sh.cpp
@@ -12,7 +12,7 @@
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{gdb} %t.exe -ex "source %S/is_debugger_present_with_debugger_gdb.py" -ex run -ex detach -ex quit --silent
+// RUN: %{gdb} %t.exe -ex "source %S/is_debugger_present_with_debugger_gdb.py" --silent
 
 // <debugging>
 
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
index e8351149082eb8..2b7523c74ff29e 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
@@ -20,6 +20,7 @@
 has_run_tests = False
 
 def breakpoint_handler(frame, bp_loc, internal_dict):
+    print("===============> breakpoint_handler")
     global has_run_tests
 
     try:
@@ -51,7 +52,7 @@ def breakpoint_handler(frame, bp_loc, internal_dict):
 
         test_failures += 1
 
-def exit_handler(event=None):
+def exit_handler(debugger):
     """Exit handler"""
 
     global test_failures
@@ -61,9 +62,10 @@ def exit_handler(event=None):
         print("FAILED test program did not run correctly, check lldb warnings")
         test_failures = -1
     elif test_failures:
+        test_failures -= 1
         print(f"FAILED {test_failures} cases")
 
-    exit(test_failures)
+    debugger.HandleCommand(f"exit {test_failures}")
 
 
 def __lldb_init_module(debugger, internal_dict):
@@ -72,5 +74,9 @@ def __lldb_init_module(debugger, internal_dict):
     test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
     test_bp.enabled = True
 
-    # test_failures += 1
-    # exit_handler(None)
+    debugger.HandleCommand("run")
+
+    global test_failures
+    test_failures += 1
+
+    exit_handler(debugger)
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp
index d51eb03e1e9dc1..2365203d66dcff 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.sh.cpp
@@ -12,7 +12,7 @@
 // XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
 
 // RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{lldb} %t.exe -o "command script import %S/is_debugger_present_with_debugger_lldb.py" -o run -o detach -o quit
+// RUN: %{lldb} %t.exe -o "command script import %S/is_debugger_present_with_debugger_lldb.py"
 
 // <debugging>
 

>From 894f4214392d1790dc5ea60793aee27aa0e5fc6d Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 7 Feb 2024 14:31:21 +0200
Subject: [PATCH 17/29] Tweaks and cleanups

---
 .../breakpoint_if_debugging_with_debugger_gdb.py  |  5 ++++-
 .../breakpoint_if_debugging_with_debugger_lldb.py | 15 +++++++++++----
 .../debugging/breakpoint_with_debugger_gdb.py     |  5 ++++-
 .../debugging/breakpoint_with_debugger_gdb.sh.cpp |  4 ++--
 .../debugging/breakpoint_with_debugger_lldb.py    | 14 ++++++++++----
 .../debugging/is_debugger_present.pass.cpp        |  2 +-
 .../is_debugger_present_with_debugger_gdb.py      |  4 ++++
 .../is_debugger_present_with_debugger_lldb.py     |  3 ++-
 8 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py
index be96eccfe26f89..7e4b2f56c17d2f 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py
@@ -89,14 +89,17 @@ def exit_handler(event=None):
     exit(test_failures)
 
 def main():
+    """Main entry point"""
     # Start code executed at load time
 
+    global test_failures
+
     # Disable terminal paging
 
     gdb.execute("set height 0")
     gdb.execute("set python print-stack full")
 
-    test = CheckResult()
+    CheckResult()
     test_bp = gdb.Breakpoint("StopForDebugger")
     test_bp.enabled = True
     test_bp.silent = True
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py
index e72802479bc15f..29077c6ca99b95 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py
+++ b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py
@@ -42,7 +42,7 @@ def breakpoint_handler(frame, bp_loc, internal_dict):
 
         test_failures += 1
 
-def exit_handler(event=None):
+def exit_handler(debugger):
     """Exit handler"""
 
     global test_failures
@@ -52,16 +52,23 @@ def exit_handler(event=None):
         print("FAILED test program did not run correctly, check lldb warnings")
         test_failures = -1
     elif test_failures:
+        test_failures -= 1
         print(f"FAILED {test_failures} cases")
 
-    exit(test_failures)
+    debugger.HandleCommand(f"exit {test_failures}")
 
 
 def __lldb_init_module(debugger, internal_dict):
+    global test_failures
+
     target = debugger.GetSelectedTarget()
     test_bp = target.BreakpointCreateByName("StopForDebugger")
     test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
     test_bp.enabled = True
 
-    # test_failures += 1
-    # exit_handler(None)
\ No newline at end of file
+
+    debugger.HandleCommand("run")
+
+    test_failures += 1
+
+    exit_handler(debugger)
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
index 851d11e00786fe..648f4ceca6f9e2 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
@@ -89,14 +89,17 @@ def exit_handler(event=None):
     exit(test_failures)
 
 def main():
+    """Main entry point"""
     # Start code executed at load time
 
+    global test_failures
+
     # Disable terminal paging
 
     gdb.execute("set height 0")
     gdb.execute("set python print-stack full")
 
-    test = CheckResult()
+    CheckResult()
     test_bp = gdb.Breakpoint("StopForDebugger")
     test_bp.enabled = True
     test_bp.silent = True
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
index d1906460a0dfaf..0aa80f562f777f 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
@@ -56,9 +56,9 @@ void StopForDebugger() {}
 void test() {
   static_assert(noexcept(std::breakpoint()));
 
-  StopForDebugger();
+  // StopForDebugger();
   std::breakpoint();
-  StopForDebugger();
+  // StopForDebugger();
 }
 
 int main(int, char**) {
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
index e72802479bc15f..558bbd6d89ca08 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
@@ -42,7 +42,7 @@ def breakpoint_handler(frame, bp_loc, internal_dict):
 
         test_failures += 1
 
-def exit_handler(event=None):
+def exit_handler(debugger):
     """Exit handler"""
 
     global test_failures
@@ -52,16 +52,22 @@ def exit_handler(event=None):
         print("FAILED test program did not run correctly, check lldb warnings")
         test_failures = -1
     elif test_failures:
+        test_failures -= 1
         print(f"FAILED {test_failures} cases")
 
-    exit(test_failures)
+    debugger.HandleCommand(f"exit {test_failures}")
 
 
 def __lldb_init_module(debugger, internal_dict):
+    global test_failures
+
     target = debugger.GetSelectedTarget()
     test_bp = target.BreakpointCreateByName("StopForDebugger")
     test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
     test_bp.enabled = True
 
-    # test_failures += 1
-    # exit_handler(None)
\ No newline at end of file
+    debugger.HandleCommand("run")
+
+    test_failures += 1
+
+    exit_handler(debugger)
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp b/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
index 106890e77fa7e0..0b1e2aa109a870 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present.pass.cpp
@@ -22,7 +22,7 @@
 void test() {
   static_assert(noexcept(std::is_debugger_present()));
 
-  std::same_as<bool> decltype(auto) isDebuggerPresent = is_debugger_present();
+  std::same_as<bool> decltype(auto) isDebuggerPresent = std::is_debugger_present();
   assert(isDebuggerPresent == false);
 }
 
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
index e4669c83c4426c..43c5b60662218e 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
@@ -84,6 +84,10 @@ def exit_handler(event=None):
 
 def main():
     """Main entry point"""
+    # Start code executed at load time
+
+    global test_failures
+
     # Disable terminal paging
 
     gdb.execute("set height 0")
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
index 2b7523c74ff29e..3374a866f31f61 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
@@ -69,6 +69,8 @@ def exit_handler(debugger):
 
 
 def __lldb_init_module(debugger, internal_dict):
+    global test_failures
+
     target = debugger.GetSelectedTarget()
     test_bp = target.BreakpointCreateByName("StopForDebugger")
     test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
@@ -76,7 +78,6 @@ def __lldb_init_module(debugger, internal_dict):
 
     debugger.HandleCommand("run")
 
-    global test_failures
     test_failures += 1
 
     exit_handler(debugger)

>From 50763fef5b4b3a340aeebdd430c14487e795eb59 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 8 Feb 2024 12:45:12 +0200
Subject: [PATCH 18/29] Fixed Windows

---
 libcxx/src/debugging.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index fccd6f8c397502..81527079b17f10 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -31,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if defined(_LIBCPP_WIN32API)
 
-void __breakpoint() noexcept { void DebugBreak(); }
+void __breakpoint() noexcept { DebugBreak(); }
 
 #elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__)
 
@@ -54,7 +54,7 @@ void __breakpoint() noexcept {
 
 // is_debugger_present()
 
-#if defined(_LIBC_WIN32API)
+#if defined(_LIBCPP_WIN32API)
 
 bool __is_debugger_present() noexcept { return IsDebuggerPresent(); }
 

>From e3d816a14cff437e94b901814cde4c351ce7e409 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 8 Feb 2024 19:34:04 +0200
Subject: [PATCH 19/29] Use `#error` instead of `static_assert`

---
 libcxx/src/debugging.cpp | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index 81527079b17f10..2efcd120a2f4e9 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -45,10 +45,7 @@ void __breakpoint() {
 
 #else
 
-void __breakpoint() noexcept {
-  static_assert(false, "'std::breakpoint()' is not implemented on this platform.");
-  return false;
-}
+#  error "'std::breakpoint()' is not implemented on this platform."
 
 #endif // defined(_LIBCPP_WIN32API)
 
@@ -119,10 +116,7 @@ bool __is_debugger_present() noexcept {
 
 #else
 
-bool __is_debugger_present() noexcept {
-  static_assert(false, "'std::is_debugger_present()' is not implemented on this platform.");
-  return false;
-}
+#  error "'std::is_debugger_present()' is not implemented on this platform."
 
 #endif // defined(_LIBCPP_WIN32API)
 

>From 310aa7ad3e1c68421d8a0254b802cccefbfd1800 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 12 Feb 2024 09:50:45 +0200
Subject: [PATCH 20/29] WIP

---
 .../debugging/breakpoint_with_debugger_gdb.py | 20 ++++++++++++++-----
 .../breakpoint_with_debugger_gdb.sh.cpp       |  6 +++++-
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
index 648f4ceca6f9e2..58f0fa0b6775ad 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
@@ -30,6 +30,7 @@ def __init__(self):
         super(CheckResult, self).__init__("check_breakpoint", gdb.COMMAND_DATA)
 
     def invoke(self, arg, from_tty):
+        print("--------2")
         global has_run_tests
 
         try:
@@ -39,13 +40,17 @@ def invoke(self, arg, from_tty):
             # 0. StopForDebugger
             # 1. Check `isDebuggerPresent`
 
-            compare_frame = gdb.newest_frame().older()
+            compare_frame = gdb.newest_frame()
             testcase_frame = compare_frame.older()
             test_loc = testcase_frame.find_sal()
 
             # Ignore the convenience variable name and newline
 
             frame_name = compare_frame.name()
+            print(f"===> GDB frame name:{frame_name}")
+
+            frame_name = testcase_frame.name()
+            print(f"===> GDB frame name:{frame_name}")
 
             if "std::__1::__breakpoint" in compare_frame.name():
                 print(f"===> GDB frame name:{frame_name}")
@@ -77,7 +82,7 @@ def invoke(self, arg, from_tty):
 
 def exit_handler(event=None):
     """Exit handler"""
-
+    print("-----1")
     global test_failures
     global has_run_tests
 
@@ -93,7 +98,7 @@ def main():
     # Start code executed at load time
 
     global test_failures
-
+    print("-----9")
     # Disable terminal paging
 
     gdb.execute("set height 0")
@@ -108,14 +113,19 @@ def main():
 
     # "run" won't return if the program exits; ensure the script regains control.
 
-    gdb.events.exited.connect(exit_handler)
+    # gdb.events.exited.connect(exit_handler)
+    # gdb.execute("handle SIGTRAP ignore")
+    # gdb.execute("handle SIGTRAP nostop noprint noignore")
     gdb.execute("run")
+    gdb.execute("signal 0")
+    # gdb.execute("detach")
+    gdb.execute("quit")
 
     # If the program didn't exit, something went wrong, but we don't
     # know what. Fail on exit.
 
     test_failures += 1
-    exit_handler(None)
+    # exit_handler(None)
 
     print(f"Test failures count: {test_failures}")
 
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
index 0aa80f562f777f..624638d9115eae 100644
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
+++ b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
@@ -53,12 +53,16 @@ void StopForDebugger() {}
 // Detaching from program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass, process 53887
 // [Inferior 1 (process 53887) detached]
 
+#include <print>
+
 void test() {
   static_assert(noexcept(std::breakpoint()));
 
+  std::println("1111111");
   // StopForDebugger();
   std::breakpoint();
-  // StopForDebugger();
+  StopForDebugger();
+  std::println("222222");
 }
 
 int main(int, char**) {

>From 17dcbd6b3eb60778eeef0ec09a06105ea04ee671 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 12 Feb 2024 09:52:43 +0200
Subject: [PATCH 21/29] Removed `breakpoint` test skelettons

---
 .../breakpoint_if_debugging.pass.cpp          |  31 ----
 ...eakpoint_if_debugging_with_debugger_gdb.py | 123 ----------------
 ...oint_if_debugging_with_debugger_gdb.sh.cpp |  49 -------
 ...akpoint_if_debugging_with_debugger_lldb.py |  74 ----------
 ...int_if_debugging_with_debugger_lldb.sh.cpp |  49 -------
 .../debugging/breakpoint_with_debugger_gdb.py | 133 ------------------
 .../breakpoint_with_debugger_gdb.sh.cpp       |  72 ----------
 .../breakpoint_with_debugger_gdb_test.py      | 123 ----------------
 .../breakpoint_with_debugger_lldb.py          |  73 ----------
 .../breakpoint_with_debugger_lldb.sh.cpp      |  67 ---------
 10 files changed, 794 deletions(-)
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb_test.py
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
 delete mode 100644 libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp

diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
deleted file mode 100644
index 6f3a85498efbf6..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging.pass.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
-
-// <debugging>
-
-// void breakpoint_if_debugging() noexcept;
-
-#include <cassert>
-#include <debugging>
-
-// Test without debugger.
-
-void test() {
-  static_assert(noexcept(std::breakpoint_if_debugging()));
-
-  std::breakpoint_if_debugging();
-}
-
-int main(int, char**) {
-  test();
-
-  return 0;
-}
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py
deleted file mode 100644
index 7e4b2f56c17d2f..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# ===----------------------------------------------------------------------===##
-#
-# 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
-#
-# ===----------------------------------------------------------------------===##
-
-from __future__ import print_function
-import gdb
-
-# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
-
-test_failures = 0
-
-# Sometimes the inital run command can fail to trace the process.
-# (e.g. you don't have ptrace permissions)
-# In these cases gdb still sends us an exited event so we cannot
-# see what "run" printed to check for a warning message, since
-# we get taken to our exit handler before we can look.
-# Instead check that at least one test has been run by the time
-# we exit.
-has_run_tests = False
-
-
-class CheckResult(gdb.Command):
-    """GDB Tester"""
-
-    def __init__(self):
-        super(CheckResult, self).__init__("check_breakpoint_if_debugging", gdb.COMMAND_DATA)
-
-    def invoke(self, arg, from_tty):
-        global has_run_tests
-
-        try:
-            has_run_tests = True
-
-            # Stack frame is:
-            # 0. StopForDebugger
-            # 1. Check `isDebuggerPresent`
-
-            compare_frame = gdb.newest_frame().older()
-            testcase_frame = compare_frame.older()
-            test_loc = testcase_frame.find_sal()
-
-            # Ignore the convenience variable name and newline
-
-            frame_name = compare_frame.name()
-
-            if "std::__1::__breakpoint" in compare_frame.name():
-                print(f"===> GDB frame name:{frame_name}")
-                # s = gdb.execute("p value", to_string=True)
-
-            gdb.newest_frame().select()
-            expectation_val = compare_frame.read_var("isDebuggerPresent")
-
-            if not expectation_val:
-                global test_failures
-
-                print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-                print("`isDebuggerPresent` value is `false`, value should be `true`")
-
-                test_failures += 1
-            else:
-                print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-
-        except RuntimeError as e:
-            # At this point, lots of different things could be wrong, so don't try to
-            # recover or figure it out. Don't exit either, because then it's
-            # impossible to debug the framework itself.
-
-            print("FAIL: Something is wrong in the test framework.")
-            print(str(e))
-
-            test_failures += 1
-
-
-def exit_handler(event=None):
-    """Exit handler"""
-
-    global test_failures
-    global has_run_tests
-
-    if not has_run_tests:
-        print("FAILED test program did not run correctly, check gdb warnings")
-        test_failures = -1
-    elif test_failures:
-        print(f"FAILED {test_failures} cases")
-    exit(test_failures)
-
-def main():
-    """Main entry point"""
-    # Start code executed at load time
-
-    global test_failures
-
-    # Disable terminal paging
-
-    gdb.execute("set height 0")
-    gdb.execute("set python print-stack full")
-
-    CheckResult()
-    test_bp = gdb.Breakpoint("StopForDebugger")
-    test_bp.enabled = True
-    test_bp.silent = True
-    test_bp.commands = """check_breakpoint_if_debugging
-    continue"""
-
-    # "run" won't return if the program exits; ensure the script regains control.
-
-    gdb.events.exited.connect(exit_handler)
-    gdb.execute("run")
-
-    # If the program didn't exit, something went wrong, but we don't
-    # know what. Fail on exit.
-
-    test_failures += 1
-    exit_handler(None)
-
-    print(f"Test failures count: {test_failures}")
-
-if __name__ == "__main__":
-    main()
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp
deleted file mode 100644
index ef6e7778369c5c..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_gdb.sh.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// REQUIRES: host-has-gdb-with-python
-// UNSUPPORTED: android
-// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
-
-// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{gdb} %t.exe -ex "source %S/breakpoint_if_debugging_with_debugger_gdb.py" --silent
-
-// <debugging>
-
-// void breakpoint_if_debugging() noexcept;
-
-#include <cassert>
-#include <debugging>
-
-#include "test_macros.h"
-
-#ifdef TEST_COMPILER_GCC
-#  define OPT_NONE __attribute__((noinline))
-#else
-#  define OPT_NONE __attribute__((optnone))
-#endif
-
-void StopForDebugger() OPT_NONE;
-void StopForDebugger() {}
-
-// Test with debugger attached:
-
-// GDB command:  `gdb breakpoint_if_debugging.pass -ex run -ex detach -ex quit --silent`
-
-void test() {
-  static_assert(noexcept(std::breakpoint_if_debugging()));
-
-  std::breakpoint_if_debugging();
-}
-
-int main(int, char**) {
-  test();
-
-  return 0;
-}
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py
deleted file mode 100644
index 29077c6ca99b95..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# ===----------------------------------------------------------------------===##
-#
-# 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
-#
-# ===----------------------------------------------------------------------===##
-
-import lldb
-
-test_failures = 0
-
-# Sometimes the inital run command can fail to trace the process.
-# (e.g. you don't have ptrace permissions)
-# In these cases gdb still sends us an exited event so we cannot
-# see what "run" printed to check for a warning message, since
-# we get taken to our exit handler before we can look.
-# Instead check that at least one test has been run by the time
-# we exit.
-has_run_tests = False
-
-def breakpoint_handler(frame, bp_loc, internal_dict):
-    global has_run_tests
-
-    try:
-        has_run_tests = True
-
-        module = frame.GetModule()
-        filename = module.compile_units[0].file
-        line = frame.GetLineEntry().GetLine()
-        parent = frame.get_parent_frame()
-
-      #   TODO: test
-
-    except RuntimeError as e:
-        # At this point, lots of different things could be wrong, so don't try to
-        # recover or figure it out. Don't exit either, because then it's
-        # impossible to debug the framework itself.
-
-        print("FAIL: Something is wrong in the test framework.")
-        print(str(e))
-
-        test_failures += 1
-
-def exit_handler(debugger):
-    """Exit handler"""
-
-    global test_failures
-    global has_run_tests
-
-    if not has_run_tests:
-        print("FAILED test program did not run correctly, check lldb warnings")
-        test_failures = -1
-    elif test_failures:
-        test_failures -= 1
-        print(f"FAILED {test_failures} cases")
-
-    debugger.HandleCommand(f"exit {test_failures}")
-
-
-def __lldb_init_module(debugger, internal_dict):
-    global test_failures
-
-    target = debugger.GetSelectedTarget()
-    test_bp = target.BreakpointCreateByName("StopForDebugger")
-    test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
-    test_bp.enabled = True
-
-
-    debugger.HandleCommand("run")
-
-    test_failures += 1
-
-    exit_handler(debugger)
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp
deleted file mode 100644
index 2b31456f00b275..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_if_debugging_with_debugger_lldb.sh.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// REQUIRES: host-has-lldb-with-python
-// UNSUPPORTED: android
-// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
-
-// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{lldb} %t.exe -o "command script import %S/breakpoint_if_debugging_with_debugger_lldb.py" -o run -o detach -o quit
-
-// <debugging>
-
-// void breakpoint_if_debugging() noexcept;
-
-#include <cassert>
-#include <debugging>
-
-#include "test_macros.h"
-
-#ifdef TEST_COMPILER_GCC
-#  define OPT_NONE __attribute__((noinline))
-#else
-#  define OPT_NONE __attribute__((optnone))
-#endif
-
-void StopForDebugger() OPT_NONE;
-void StopForDebugger() {}
-
-// Test with debugger attached:
-
-// LLDB command: `lldb "breakpoint_if_debugging.pass" -o run -o detach -o quit`
-
-void test() {
-  static_assert(noexcept(std::breakpoint_if_debugging()));
-
-  std::breakpoint_if_debugging();
-}
-
-int main(int, char**) {
-  test();
-
-  return 0;
-}
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
deleted file mode 100644
index 58f0fa0b6775ad..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# ===----------------------------------------------------------------------===##
-#
-# 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
-#
-# ===----------------------------------------------------------------------===##
-
-from __future__ import print_function
-import gdb
-
-# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
-
-test_failures = 0
-
-# Sometimes the inital run command can fail to trace the process.
-# (e.g. you don't have ptrace permissions)
-# In these cases gdb still sends us an exited event so we cannot
-# see what "run" printed to check for a warning message, since
-# we get taken to our exit handler before we can look.
-# Instead check that at least one test has been run by the time
-# we exit.
-has_run_tests = False
-
-
-class CheckResult(gdb.Command):
-    """GDB Tester"""
-
-    def __init__(self):
-        super(CheckResult, self).__init__("check_breakpoint", gdb.COMMAND_DATA)
-
-    def invoke(self, arg, from_tty):
-        print("--------2")
-        global has_run_tests
-
-        try:
-            has_run_tests = True
-
-            # Stack frame is:
-            # 0. StopForDebugger
-            # 1. Check `isDebuggerPresent`
-
-            compare_frame = gdb.newest_frame()
-            testcase_frame = compare_frame.older()
-            test_loc = testcase_frame.find_sal()
-
-            # Ignore the convenience variable name and newline
-
-            frame_name = compare_frame.name()
-            print(f"===> GDB frame name:{frame_name}")
-
-            frame_name = testcase_frame.name()
-            print(f"===> GDB frame name:{frame_name}")
-
-            if "std::__1::__breakpoint" in compare_frame.name():
-                print(f"===> GDB frame name:{frame_name}")
-                # s = gdb.execute("p value", to_string=True)
-
-            gdb.newest_frame().select()
-            expectation_val = compare_frame.read_var("isDebuggerPresent")
-
-            if not expectation_val:
-                global test_failures
-
-                print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-                print("`isDebuggerPresent` value is `false`, value should be `true`")
-
-                test_failures += 1
-            else:
-                print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-
-        except RuntimeError as e:
-            # At this point, lots of different things could be wrong, so don't try to
-            # recover or figure it out. Don't exit either, because then it's
-            # impossible to debug the framework itself.
-
-            print("FAIL: Something is wrong in the test framework.")
-            print(str(e))
-
-            test_failures += 1
-
-
-def exit_handler(event=None):
-    """Exit handler"""
-    print("-----1")
-    global test_failures
-    global has_run_tests
-
-    if not has_run_tests:
-        print("FAILED test program did not run correctly, check gdb warnings")
-        test_failures = -1
-    elif test_failures:
-        print(f"FAILED {test_failures} cases")
-    exit(test_failures)
-
-def main():
-    """Main entry point"""
-    # Start code executed at load time
-
-    global test_failures
-    print("-----9")
-    # Disable terminal paging
-
-    gdb.execute("set height 0")
-    gdb.execute("set python print-stack full")
-
-    CheckResult()
-    test_bp = gdb.Breakpoint("StopForDebugger")
-    test_bp.enabled = True
-    test_bp.silent = True
-    test_bp.commands = """check_breakpoint
-    continue"""
-
-    # "run" won't return if the program exits; ensure the script regains control.
-
-    # gdb.events.exited.connect(exit_handler)
-    # gdb.execute("handle SIGTRAP ignore")
-    # gdb.execute("handle SIGTRAP nostop noprint noignore")
-    gdb.execute("run")
-    gdb.execute("signal 0")
-    # gdb.execute("detach")
-    gdb.execute("quit")
-
-    # If the program didn't exit, something went wrong, but we don't
-    # know what. Fail on exit.
-
-    test_failures += 1
-    # exit_handler(None)
-
-    print(f"Test failures count: {test_failures}")
-
-if __name__ == "__main__":
-    main()
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
deleted file mode 100644
index 624638d9115eae..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb.sh.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// REQUIRES: host-has-gdb-with-python
-// UNSUPPORTED: android
-// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
-
-// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{gdb} %t.exe -ex "source %S/breakpoint_with_debugger_gdb.py" --silent
-
-// <debugging>
-
-// void breakpoint() noexcept;
-
-#include <cassert>
-#include <debugging>
-
-#include "test_macros.h"
-
-#ifdef TEST_COMPILER_GCC
-#  define OPT_NONE __attribute__((noinline))
-#else
-#  define OPT_NONE __attribute__((optnone))
-#endif
-
-void StopForDebugger() OPT_NONE;
-void StopForDebugger() {}
-
-// Test with debugger attached:
-
-// GDB command:  `gdb breakpoint.pass -ex run -ex detach -ex quit --silent`
-
-// gdb breakpoint.pass -ex run -ex "signal SIGTRAP" -ex detach -ex quit --silent
-
-//
-// Sample GDB ouput:
-//
-// Reading symbols from breakpoint.pass..
-// Starting program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass
-// [Thread debugging using libthread_db enabled]
-// Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
-
-// Program received signal SIGTRAP, Trace/breakpoint trap.
-// std::__1::__breakpoint () at /home/llvm-dev/Projects/llvm-project/libcxx/src/debugging.cpp:44
-// warning: Source file is more recent than executable.
-// 44	}
-// Detaching from program: /home/llvm-dev/Projects/llvm-project/build/breakpoint.pass, process 53887
-// [Inferior 1 (process 53887) detached]
-
-#include <print>
-
-void test() {
-  static_assert(noexcept(std::breakpoint()));
-
-  std::println("1111111");
-  // StopForDebugger();
-  std::breakpoint();
-  StopForDebugger();
-  std::println("222222");
-}
-
-int main(int, char**) {
-  test();
-
-  return 0;
-}
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb_test.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb_test.py
deleted file mode 100644
index 8e8ac0eaf17a12..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_gdb_test.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# ===----------------------------------------------------------------------===##
-#
-# 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
-#
-# ===----------------------------------------------------------------------===##
-
-from __future__ import print_function
-import gdb
-
-# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
-
-test_failures = 0
-
-# Sometimes the inital run command can fail to trace the process.
-# (e.g. you don't have ptrace permissions)
-# In these cases gdb still sends us an exited event so we cannot
-# see what "run" printed to check for a warning message, since
-# we get taken to our exit handler before we can look.
-# Instead check that at least one test has been run by the time
-# we exit.
-has_run_tests = False
-
-
-class CheckResult(gdb.Command):
-    """GDB Tester"""
-
-    def __init__(self):
-        super(CheckResult, self).__init__("check_breakpoint", gdb.COMMAND_DATA)
-
-    def invoke(self, arg, from_tty):
-        global has_run_tests
-
-        try:
-            has_run_tests = True
-
-            # Stack frame is:
-            # 0. StopForDebugger
-            # 1. Check `isDebuggerPresent`
-
-            compare_frame = gdb.newest_frame().older()
-            testcase_frame = compare_frame.older()
-            test_loc = testcase_frame.find_sal()
-
-            # Ignore the convenience variable name and newline
-
-            frame_name = compare_frame.name()
-
-            if "std::__1::__breakpoint" in compare_frame.name():
-                print(f"===> GDB frame name:{frame_name}")
-                # s = gdb.execute("p value", to_string=True)
-            print(f"===> GDB frame name:{frame_name}")
-
-            gdb.newest_frame().select()
-            expectation_val = compare_frame.read_var("isDebuggerPresent")
-
-            if not expectation_val:
-                global test_failures
-
-                print("FAIL: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-                print("`isDebuggerPresent` value is `false`, value should be `true`")
-
-                test_failures += 1
-            else:
-                print("PASS: " + test_loc.symtab.filename + ":" + str(test_loc.line))
-
-        except RuntimeError as e:
-            # At this point, lots of different things could be wrong, so don't try to
-            # recover or figure it out. Don't exit either, because then it's
-            # impossible to debug the framework itself.
-
-            print("FAIL: Something is wrong in the test framework.")
-            print(str(e))
-
-            test_failures += 1
-
-
-def exit_handler(event=None):
-    """Exit handler"""
-
-    global test_failures
-    global has_run_tests
-
-    if not has_run_tests:
-        print("FAILED test program did not run correctly, check gdb warnings")
-        test_failures = -1
-    elif test_failures:
-        print(f"FAILED {test_failures} cases")
-    exit(test_failures)
-
-def main():
-    # Start code executed at load time
-
-    # Disable terminal paging
-
-    gdb.execute("set height 0")
-    gdb.execute("set python print-stack full")
-
-    test = CheckResult()
-    test_bp = gdb.Breakpoint("StopForDebugger")
-    test_bp.enabled = True
-    test_bp.silent = True
-    test_bp.commands = """continue
-    signal SIGTRAP
-    check_breakpoint
-    continue"""
-
-    # "run" won't return if the program exits; ensure the script regains control.
-
-    gdb.events.exited.connect(exit_handler)
-    gdb.execute("run")
-
-    # If the program didn't exit, something went wrong, but we don't
-    # know what. Fail on exit.
-
-   #  test_failures += 1
-    exit_handler(None)
-
-    print(f"Test failures count: {test_failures}")
-
-if __name__ == "__main__":
-    main()
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
deleted file mode 100644
index 558bbd6d89ca08..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# ===----------------------------------------------------------------------===##
-#
-# 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
-#
-# ===----------------------------------------------------------------------===##
-
-import lldb
-
-test_failures = 0
-
-# Sometimes the inital run command can fail to trace the process.
-# (e.g. you don't have ptrace permissions)
-# In these cases gdb still sends us an exited event so we cannot
-# see what "run" printed to check for a warning message, since
-# we get taken to our exit handler before we can look.
-# Instead check that at least one test has been run by the time
-# we exit.
-has_run_tests = False
-
-def breakpoint_handler(frame, bp_loc, internal_dict):
-    global has_run_tests
-
-    try:
-        has_run_tests = True
-
-        module = frame.GetModule()
-        filename = module.compile_units[0].file
-        line = frame.GetLineEntry().GetLine()
-        parent = frame.get_parent_frame()
-
-      #   TODO: test
-
-    except RuntimeError as e:
-        # At this point, lots of different things could be wrong, so don't try to
-        # recover or figure it out. Don't exit either, because then it's
-        # impossible to debug the framework itself.
-
-        print("FAIL: Something is wrong in the test framework.")
-        print(str(e))
-
-        test_failures += 1
-
-def exit_handler(debugger):
-    """Exit handler"""
-
-    global test_failures
-    global has_run_tests
-
-    if not has_run_tests:
-        print("FAILED test program did not run correctly, check lldb warnings")
-        test_failures = -1
-    elif test_failures:
-        test_failures -= 1
-        print(f"FAILED {test_failures} cases")
-
-    debugger.HandleCommand(f"exit {test_failures}")
-
-
-def __lldb_init_module(debugger, internal_dict):
-    global test_failures
-
-    target = debugger.GetSelectedTarget()
-    test_bp = target.BreakpointCreateByName("StopForDebugger")
-    test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
-    test_bp.enabled = True
-
-    debugger.HandleCommand("run")
-
-    test_failures += 1
-
-    exit_handler(debugger)
diff --git a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp b/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp
deleted file mode 100644
index 9a3ef6c4e5cd60..00000000000000
--- a/libcxx/test/std/utilities/debugging/breakpoint_with_debugger_lldb.sh.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
-// REQUIRES: host-has-lldb-with-python
-// UNSUPPORTED: android
-// XFAIL: LIBCXX-AIX-FIXME, LIBCXX-PICOLIBC-FIXME
-
-// RUN: %{cxx} %{flags} %s -o %t.exe %{compile_flags} -g %{link_flags}
-// RUN: %{lldb} %t.exe -o "command script import %S/breakpoint_with_debugger_lldb.py" -o run -o detach -o quit
-
-// <debugging>
-
-// void breakpoint() noexcept;
-
-#include <cassert>
-#include <debugging>
-
-#include "test_macros.h"
-
-#ifdef TEST_COMPILER_GCC
-#  define OPT_NONE __attribute__((noinline))
-#else
-#  define OPT_NONE __attribute__((optnone))
-#endif
-
-void StopForDebugger() OPT_NONE;
-void StopForDebugger() {}
-
-// Test with debugger attached:
-
-// LLDB command: `lldb "breakpoint.pass" -o run -o detach -o quit`
-
-//
-// Sample LLDB output:
-//
-// Process 43162 launched: '/home/llvm-dev/Projects/llvm-project/build/breakpoint.pass' (x86_64)
-// Process 43162 stopped
-// * thread #1, name = 'breakpoint.pass', stop reason = signal SIGTRAP
-//     frame #0: 0x00007ffff7eb27e5 libc++.so.1`std::__1::__breakpoint() at debugging.cpp:44:1
-//    41  	#  else
-//    42  	  raise(SIGTRAP);
-//    43  	#  endif
-// -> 44  	}
-//    45
-//    46  	#else
-//    47
-// (lldb) detach
-// Process 43162 detached
-// (lldb) quit
-
-void test() {
-  static_assert(noexcept(std::breakpoint()));
-
-  std::breakpoint();
-}
-
-int main(int, char**) {
-  test();
-
-  return 0;
-}

>From 7dec98b5fcf94cfb07d0d224d3391398bb07f2ff Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 12 Feb 2024 14:33:23 +0200
Subject: [PATCH 22/29] Fix CI

---
 libcxx/modules/std/debugging.inc                           | 6 +++---
 libcxx/test/libcxx/transitive_includes/cxx03.csv           | 5 +++++
 libcxx/test/libcxx/transitive_includes/cxx11.csv           | 1 +
 libcxx/test/libcxx/transitive_includes/cxx14.csv           | 1 +
 libcxx/test/libcxx/transitive_includes/cxx17.csv           | 1 +
 libcxx/test/libcxx/transitive_includes/cxx20.csv           | 1 +
 libcxx/test/libcxx/transitive_includes/cxx23.csv           | 1 +
 libcxx/test/libcxx/transitive_includes/cxx26.csv           | 1 +
 .../debugging/is_debugger_present_with_debugger_gdb.py     | 2 ++
 .../debugging/is_debugger_present_with_debugger_lldb.py    | 7 +++++--
 libcxx/utils/libcxx/test/features.py                       | 2 ++
 11 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/libcxx/modules/std/debugging.inc b/libcxx/modules/std/debugging.inc
index e8f8dd13f88ba6..86ad5d25a059f0 100644
--- a/libcxx/modules/std/debugging.inc
+++ b/libcxx/modules/std/debugging.inc
@@ -10,8 +10,8 @@
 export namespace std {
 #if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_DEBUGGING)
   // [debugging.utility], utility
-  using stgd::breakpoint;
-  using stgd::breakpoint_if_debugging;
-  using stgd::is_debugger_present;
+  using std::breakpoint;
+  using std::breakpoint_if_debugging;
+  using std::is_debugger_present;
 #endif
 } // namespace std
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index c65c65449f4e07..d26de05b26f187 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -199,6 +199,7 @@ ctgmath cmath
 cwchar cstddef
 cwchar cwctype
 cwctype cctype
+debugging version
 deque algorithm
 deque atomic
 deque compare
@@ -834,13 +835,17 @@ system_error type_traits
 system_error version
 thread array
 thread atomic
+thread cctype
 thread cerrno
 thread chrono
+thread clocale
 thread compare
 thread cstddef
 thread cstdint
+thread cstdlib
 thread cstring
 thread ctime
+thread cwchar
 thread functional
 thread iosfwd
 thread limits
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index e9eae06807e6b8..983cb39baf5176 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -200,6 +200,7 @@ ctgmath cmath
 cwchar cstddef
 cwchar cwctype
 cwctype cctype
+debugging version
 deque algorithm
 deque atomic
 deque compare
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 08db2a0ea6b1a0..2d14cf978a89d3 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -200,6 +200,7 @@ ctgmath cmath
 cwchar cstddef
 cwchar cwctype
 cwctype cctype
+debugging version
 deque algorithm
 deque atomic
 deque compare
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 08db2a0ea6b1a0..2d14cf978a89d3 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -200,6 +200,7 @@ ctgmath cmath
 cwchar cstddef
 cwchar cwctype
 cwctype cctype
+debugging version
 deque algorithm
 deque atomic
 deque compare
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 69805d6af3e94e..586b588544094b 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -206,6 +206,7 @@ ctgmath cmath
 cwchar cstddef
 cwchar cwctype
 cwctype cctype
+debugging version
 deque algorithm
 deque atomic
 deque compare
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index f9957897c743ac..8b8f5ed745bed4 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -139,6 +139,7 @@ ctgmath cmath
 cwchar cstddef
 cwchar cwctype
 cwctype cctype
+debugging version
 deque compare
 deque cstddef
 deque cstdint
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index f9957897c743ac..8b8f5ed745bed4 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -139,6 +139,7 @@ ctgmath cmath
 cwchar cstddef
 cwchar cwctype
 cwctype cctype
+debugging version
 deque compare
 deque cstddef
 deque cstdint
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
index 43c5b60662218e..ea7ecaeadf024c 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_gdb.py
@@ -82,6 +82,7 @@ def exit_handler(event=None):
         print(f"FAILED {test_failures} cases")
     exit(test_failures)
 
+
 def main():
     """Main entry point"""
     # Start code executed at load time
@@ -114,5 +115,6 @@ def main():
 
     print(f"Test failures count: {test_failures}")
 
+
 if __name__ == "__main__":
     main()
diff --git a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
index 3374a866f31f61..62907670367da2 100644
--- a/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
+++ b/libcxx/test/std/utilities/debugging/is_debugger_present_with_debugger_lldb.py
@@ -19,8 +19,8 @@
 # we exit.
 has_run_tests = False
 
+
 def breakpoint_handler(frame, bp_loc, internal_dict):
-    print("===============> breakpoint_handler")
     global has_run_tests
 
     try:
@@ -52,6 +52,7 @@ def breakpoint_handler(frame, bp_loc, internal_dict):
 
         test_failures += 1
 
+
 def exit_handler(debugger):
     """Exit handler"""
 
@@ -73,7 +74,9 @@ def __lldb_init_module(debugger, internal_dict):
 
     target = debugger.GetSelectedTarget()
     test_bp = target.BreakpointCreateByName("StopForDebugger")
-    test_bp.SetScriptCallbackFunction("is_debugger_present_with_debugger_lldb.breakpoint_handler")
+    test_bp.SetScriptCallbackFunction(
+        "is_debugger_present_with_debugger_lldb.breakpoint_handler"
+    )
     test_bp.enabled = True
 
     debugger.HandleCommand("run")
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index e8685a74cc3323..f8da76e9ab0f9e 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -474,6 +474,7 @@ def _getAndroidDeviceApi(cfg):
     ),
 ]
 
+
 # Detect whether LLDB is on the system.
 def check_lldb(cfg):
     lldb_path = shutil.which("lldb")
@@ -491,6 +492,7 @@ def check_lldb(cfg):
     )
 ]
 
+
 # Detect whether GDB is on the system, has Python scripting and supports
 # adding breakpoint commands. If so add a substitution to access it.
 def check_gdb(cfg):

>From e60b08cbbdb6186413dd896b329c4b531833275f Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 12 Feb 2024 15:48:34 +0200
Subject: [PATCH 23/29] Try to fix CI

---
 libcxx/utils/libcxx/header_information.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/utils/libcxx/header_information.py b/libcxx/utils/libcxx/header_information.py
index b2aa3739ea697d..fc84b371a033e9 100644
--- a/libcxx/utils/libcxx/header_information.py
+++ b/libcxx/utils/libcxx/header_information.py
@@ -55,6 +55,7 @@
     "coroutine": "// UNSUPPORTED: c++03, c++11, c++14, c++17",
     "cwchar": "// UNSUPPORTED: no-wide-characters",
     "cwctype": "// UNSUPPORTED: no-wide-characters",
+    "debugging": "// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23",
     "experimental/iterator": "// UNSUPPORTED: c++03",
     "experimental/propagate_const": "// UNSUPPORTED: c++03",
     "experimental/simd": "// UNSUPPORTED: c++03",
@@ -138,7 +139,6 @@
 # implemented yet. They are used in the generated module input. The C++23 standard
 # modules will fail to build if a header is added but this list is not updated.
 headers_not_available = [
-    "debugging",
     "flat_map",
     "flat_set",
     "generator",

>From 833d1306bffb96711ed29ed3c830a805cddffd7e Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 12 Feb 2024 15:54:34 +0200
Subject: [PATCH 24/29] Try to fix CI

---
 libcxx/modules/std.compat.cppm.in | 3 ---
 libcxx/modules/std.cppm.in        | 3 ---
 2 files changed, 6 deletions(-)

diff --git a/libcxx/modules/std.compat.cppm.in b/libcxx/modules/std.compat.cppm.in
index b44dbab25c74b4..c9ca9e18a77a6f 100644
--- a/libcxx/modules/std.compat.cppm.in
+++ b/libcxx/modules/std.compat.cppm.in
@@ -54,9 +54,6 @@ module;
 // into thinking that libc++ provides the header.
 //
 #ifndef _WIN32
-#  if __has_include(<debugging>)
-#    error "please update the header information for <debugging> in headers_not_available in utils/libcxx/header_information.py"
-#  endif // __has_include(<debugging>)
 #  if __has_include(<flat_map>)
 #    error "please update the header information for <flat_map> in headers_not_available in utils/libcxx/header_information.py"
 #  endif // __has_include(<flat_map>)
diff --git a/libcxx/modules/std.cppm.in b/libcxx/modules/std.cppm.in
index 0fb465f49301d1..f07b48df7d89b6 100644
--- a/libcxx/modules/std.cppm.in
+++ b/libcxx/modules/std.cppm.in
@@ -177,9 +177,6 @@ module;
 // into thinking that libc++ provides the header.
 //
 #ifndef _WIN32
-#  if __has_include(<debugging>)
-#    error "please update the header information for <debugging> in headers_not_available in utils/libcxx/header_information.py"
-#  endif // __has_include(<debugging>)
 #  if __has_include(<flat_map>)
 #    error "please update the header information for <flat_map> in headers_not_available in utils/libcxx/header_information.py"
 #  endif // __has_include(<flat_map>)

>From f3c49f4c5a40a9b1ae83d5838d67ebb67a5ccafb Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 12 Feb 2024 16:35:25 +0200
Subject: [PATCH 25/29] Try to fix CI

---
 libcxx/include/module.modulemap.in | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 63af3a90d88b9b..11dca60a92b5db 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -59,6 +59,10 @@ module std_coroutine [system] {
   header "coroutine"
   export *
 }
+module std_debugging [system] {
+  header "debugging"
+  export *
+}
 module std_deque [system] {
   header "deque"
   export *

>From ccc4c2b72421eb7187e5c09fc2197ab02744de95 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 12 Feb 2024 16:52:33 +0200
Subject: [PATCH 26/29] Try to fix CI

---
 libcxx/src/debugging.cpp | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index 2efcd120a2f4e9..3d92eecf62ea4b 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -27,35 +27,37 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+#if defined(_LIBCPP_HAS_DEBUGGING)
+
 // breakpoint()
 
-#if defined(_LIBCPP_WIN32API)
+#  if defined(_LIBCPP_WIN32API)
 
 void __breakpoint() noexcept { DebugBreak(); }
 
-#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__)
+#  elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__linux__)
 
 void __breakpoint() {
-#  if __has_builtin(__builtin_debugtrap)
+#    if __has_builtin(__builtin_debugtrap)
   __builtin_debugtrap();
-#  else
+#    else
   raise(SIGTRAP);
-#  endif
+#    endif
 }
 
-#else
+#  else
 
-#  error "'std::breakpoint()' is not implemented on this platform."
+#    error "'std::breakpoint()' is not implemented on this platform."
 
-#endif // defined(_LIBCPP_WIN32API)
+#  endif // defined(_LIBCPP_WIN32API)
 
 // is_debugger_present()
 
-#if defined(_LIBCPP_WIN32API)
+#  if defined(_LIBCPP_WIN32API)
 
 bool __is_debugger_present() noexcept { return IsDebuggerPresent(); }
 
-#elif defined(__APPLE__) || defined(__FreeBSD__)
+#  elif defined(__APPLE__) || defined(__FreeBSD__)
 
 // Returns true if the current process is being debugged (either
 // running under the debugger or has a debugger attached post facto).
@@ -87,7 +89,7 @@ bool __is_debugger_present() noexcept {
   return ((info.kp_proc.p_flag & P_TRACED) != 0);
 }
 
-#elif defined(__linux__)
+#  elif defined(__linux__)
 
 bool __is_debugger_present() noexcept {
   // https://docs.kernel.org/filesystems/proc.html
@@ -114,11 +116,11 @@ bool __is_debugger_present() noexcept {
   return false;
 }
 
-#else
+#  else
 
-#  error "'std::is_debugger_present()' is not implemented on this platform."
+#    error "'std::is_debugger_present()' is not implemented on this platform."
 
-#endif // defined(_LIBCPP_WIN32API)
+#  endif // defined(_LIBCPP_WIN32API)
 
 _LIBCPP_EXPORTED_FROM_ABI void breakpoint() noexcept { __breakpoint(); }
 
@@ -129,4 +131,6 @@ _LIBCPP_EXPORTED_FROM_ABI void breakpoint_if_debugging() noexcept {
 
 _LIBCPP_EXPORTED_FROM_ABI bool is_debugger_present() noexcept { return __is_debugger_present(); }
 
+#endif // defined(_LIBCPP_HAS_DEBUGGING)
+
 _LIBCPP_END_NAMESPACE_STD

>From ac30f43c8759d6908bbf20d5fc5001a8a9af63b1 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 12 Feb 2024 17:05:44 +0200
Subject: [PATCH 27/29] Try to fix CI

---
 ...n-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index 6432ad3be35859..b47eddaa1bfad0 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -36,6 +36,7 @@
 {'is_defined': False, 'name': '_ZTVSt13runtime_error', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': False, 'name': '_ZTVSt14overflow_error', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': False, 'name': '_ZTVSt16invalid_argument', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': False, 'name': '_ZTVSt9exception', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': False, 'name': '_ZdaPv', 'type': 'FUNC'}
 {'is_defined': False, 'name': '_ZdaPvSt11align_val_t', 'type': 'FUNC'}
 {'is_defined': False, 'name': '_ZdlPv', 'type': 'FUNC'}
@@ -555,6 +556,7 @@
 {'is_defined': True, 'name': '_ZNSt3__110__time_putC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__110__time_putD1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__110__time_putD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__110breakpointEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__110ctype_base5alnumE', 'size': 2, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt3__110ctype_base5alphaE', 'size': 2, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt3__110ctype_base5blankE', 'size': 2, 'type': 'OBJECT'}
@@ -1209,6 +1211,7 @@
 {'is_defined': True, 'name': '_ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__119declare_no_pointersEPcm', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__119is_debugger_presentEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__120__get_collation_nameEPKc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__120__libcpp_atomic_waitEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEEi', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__120__libcpp_atomic_waitEPVKvi', 'type': 'FUNC'}
@@ -1230,6 +1233,7 @@
 {'is_defined': True, 'name': '_ZNSt3__123__cxx_atomic_notify_oneEPVKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__123breakpoint_if_debuggingEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
@@ -1968,6 +1972,8 @@
 {'is_defined': True, 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IDiEE', 'size': 96, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IDsEE', 'size': 96, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IwEE', 'size': 96, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVNSt3__120__time_get_c_storageIcEE', 'size': 72, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVNSt3__120__time_get_c_storageIwEE', 'size': 72, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__13pmr15memory_resourceE', 'size': 56, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__13pmr25monotonic_buffer_resourceE', 'size': 56, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__13pmr26__null_memory_resource_impE', 'size': 56, 'type': 'OBJECT'}

>From bb9c7571932a99ba225b0bad4f4d73fe1457d075 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 15 Feb 2024 09:11:08 +0200
Subject: [PATCH 28/29] Added ABIs

---
 ...4-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 3 +++
 ...inux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist | 3 +++
 ...4-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist | 3 +++
 ...inux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist | 3 +++
 ...nknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist | 3 +++
 ...wn-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist | 3 +++
 libcxx/src/debugging.cpp                                       | 3 +++
 7 files changed, 21 insertions(+)

diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 2064f45bf8c084..7612a3ec25ff53 100644
--- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -862,6 +862,7 @@
 {'is_defined': True, 'name': '__ZNSt3__110__time_putC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__110__time_putD1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__110__time_putD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__110breakpointEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__110ctype_base5alnumE', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZNSt3__110ctype_base5alphaE', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZNSt3__110ctype_base5blankE', 'size': 0, 'type': 'OBJECT'}
@@ -1516,6 +1517,7 @@
 {'is_defined': True, 'name': '__ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__119declare_no_pointersEPcm', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__119is_debugger_presentEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__120__get_collation_nameEPKc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__120__libcpp_atomic_waitEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEEx', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__120__libcpp_atomic_waitEPVKvx', 'type': 'FUNC'}
@@ -1537,6 +1539,7 @@
 {'is_defined': True, 'name': '__ZNSt3__123__cxx_atomic_notify_oneEPVKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__123breakpoint_if_debuggingEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
index fec3a4505a0c6d..b57785484f8ae8 100644
--- a/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/i686-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -543,6 +543,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk110__time_putC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110__time_putD1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110__time_putD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk110breakpointEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110ctype_base5alnumE', 'size': 4, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110ctype_base5alphaE', 'size': 4, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110ctype_base5blankE', 'size': 4, 'type': 'OBJECT'}
@@ -1197,6 +1198,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk119declare_no_pointersEPcj', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk119is_debugger_presentEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk120__get_collation_nameEPKc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk120__libcpp_atomic_waitEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEEi', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk120__libcpp_atomic_waitEPVKvi', 'type': 'FUNC'}
@@ -1218,6 +1220,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk123__cxx_atomic_notify_oneEPVKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk123breakpoint_if_debuggingEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index bced6b2ea81ba5..c6c24b148ea80a 100644
--- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -862,6 +862,7 @@
 {'is_defined': True, 'name': '__ZNSt3__110__time_putC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__110__time_putD1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__110__time_putD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__110breakpointEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__110ctype_base5alnumE', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZNSt3__110ctype_base5alphaE', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZNSt3__110ctype_base5blankE', 'size': 0, 'type': 'OBJECT'}
@@ -1516,6 +1517,7 @@
 {'is_defined': True, 'name': '__ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__119declare_no_pointersEPcm', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__119is_debugger_presentEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__120__get_collation_nameEPKc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__120__libcpp_atomic_waitEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEEx', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__120__libcpp_atomic_waitEPVKvx', 'type': 'FUNC'}
@@ -1537,6 +1539,7 @@
 {'is_defined': True, 'name': '__ZNSt3__123__cxx_atomic_notify_oneEPVKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIxNS_22__cxx_atomic_base_implIxEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__123breakpoint_if_debuggingEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
index efa2189e9c9287..2297a0067b6a1c 100644
--- a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -543,6 +543,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk110__time_putC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110__time_putD1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110__time_putD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk110breakpointEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110ctype_base5alnumE', 'size': 8, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110ctype_base5alphaE', 'size': 8, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt6__ndk110ctype_base5blankE', 'size': 8, 'type': 'OBJECT'}
@@ -1197,6 +1198,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk119declare_no_pointersEPcm', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk119is_debugger_presentEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk120__get_collation_nameEPKc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk120__libcpp_atomic_waitEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEEi', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk120__libcpp_atomic_waitEPVKvi', 'type': 'FUNC'}
@@ -1218,6 +1220,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk123__cxx_atomic_notify_oneEPVKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__123breakpoint_if_debuggingEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
index ebda5b0dfba57d..467284019aab7c 100644
--- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -557,6 +557,7 @@
 {'is_defined': True, 'name': '_ZNSt3__110__time_putC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__110__time_putD1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__110__time_putD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__110breakpointEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__110ctype_base5alnumE', 'size': 8, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt3__110ctype_base5alphaE', 'size': 8, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt3__110ctype_base5blankE', 'size': 8, 'type': 'OBJECT'}
@@ -1211,6 +1212,7 @@
 {'is_defined': True, 'name': '_ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__119declare_no_pointersEPcm', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__119is_debugger_presentEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__120__get_collation_nameEPKc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__120__libcpp_atomic_waitEPVKNS_17__cxx_atomic_implIlNS_22__cxx_atomic_base_implIlEEEEl', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__120__libcpp_atomic_waitEPVKvl', 'type': 'FUNC'}
@@ -1232,6 +1234,7 @@
 {'is_defined': True, 'name': '_ZNSt3__123__cxx_atomic_notify_oneEPVKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIlNS_22__cxx_atomic_base_implIlEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__123breakpoint_if_debuggingEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
index 1fe84e17b3f7f0..df9ebe53bbd8a3 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
@@ -526,6 +526,7 @@
 {'is_defined': True, 'name': '_ZNSt3__110__time_putC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__110__time_putD1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__110__time_putD2Ev', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__110breakpointEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__110ctype_base5alnumE', 'size': 2, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt3__110ctype_base5alphaE', 'size': 2, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZNSt3__110ctype_base5blankE', 'size': 2, 'type': 'OBJECT'}
@@ -1180,6 +1181,7 @@
 {'is_defined': True, 'name': '_ZNSt3__119basic_istringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__119basic_ostringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEOS5_', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__119declare_no_pointersEPcm', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__119is_debugger_presentEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__120__get_collation_nameEPKc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__120__libcpp_atomic_waitEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEEi', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__120__libcpp_atomic_waitEPVKvi', 'type': 'FUNC'}
@@ -1201,6 +1203,7 @@
 {'is_defined': True, 'name': '_ZNSt3__123__cxx_atomic_notify_oneEPVKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__123breakpoint_if_debuggingEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index 3d92eecf62ea4b..648df15cabef07 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -16,8 +16,11 @@
 #elif defined(__APPLE__) || defined(__FreeBSD__)
 #  include <array>
 #  include <csignal>
+#  include <libutil.h>
+#  include <sys/proc.h>
 #  include <sys/sysctl.h>
 #  include <sys/types.h>
+#  include <sys/user.h>
 #  include <unistd.h>
 #elif defined(__linux__)
 #  include <csignal>

>From 96b5e74be1641293ad5da63beb24ca1a77ae632a Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 16 Feb 2024 14:10:21 +0200
Subject: [PATCH 29/29] Various fixes: macOS, Android ABI

---
 ...android21.libcxxabi.v1.stable.exceptions.nonew.abilist | 2 +-
 ...linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist | 3 ---
 libcxx/src/debugging.cpp                                  | 8 +++++++-
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
index 2297a0067b6a1c..0187b958bed61c 100644
--- a/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-linux-android21.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1220,7 +1220,7 @@
 {'is_defined': True, 'name': '_ZNSt6__ndk123__cxx_atomic_notify_oneEPVKv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKNS_17__cxx_atomic_implIiNS_22__cxx_atomic_base_implIiEEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk123__libcpp_atomic_monitorEPVKv', 'type': 'FUNC'}
-{'is_defined': True, 'name': '_ZNSt6__123breakpoint_if_debuggingEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt6__ndk123breakpoint_if_debuggingEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk125notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk131__arrive_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseEh', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt6__ndk132__destroy_barrier_algorithm_baseEPNS_24__barrier_algorithm_baseE', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index b47eddaa1bfad0..2c4045dc798ebf 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -36,7 +36,6 @@
 {'is_defined': False, 'name': '_ZTVSt13runtime_error', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': False, 'name': '_ZTVSt14overflow_error', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': False, 'name': '_ZTVSt16invalid_argument', 'size': 0, 'type': 'OBJECT'}
-{'is_defined': False, 'name': '_ZTVSt9exception', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': False, 'name': '_ZdaPv', 'type': 'FUNC'}
 {'is_defined': False, 'name': '_ZdaPvSt11align_val_t', 'type': 'FUNC'}
 {'is_defined': False, 'name': '_ZdlPv', 'type': 'FUNC'}
@@ -1972,8 +1971,6 @@
 {'is_defined': True, 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IDiEE', 'size': 96, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IDsEE', 'size': 96, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__120__codecvt_utf8_utf16IwEE', 'size': 96, 'type': 'OBJECT'}
-{'is_defined': True, 'name': '_ZTVNSt3__120__time_get_c_storageIcEE', 'size': 72, 'type': 'OBJECT'}
-{'is_defined': True, 'name': '_ZTVNSt3__120__time_get_c_storageIwEE', 'size': 72, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__13pmr15memory_resourceE', 'size': 56, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__13pmr25monotonic_buffer_resourceE', 'size': 56, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVNSt3__13pmr26__null_memory_resource_impE', 'size': 56, 'type': 'OBJECT'}
diff --git a/libcxx/src/debugging.cpp b/libcxx/src/debugging.cpp
index 648df15cabef07..afaf0b4a92bbc5 100644
--- a/libcxx/src/debugging.cpp
+++ b/libcxx/src/debugging.cpp
@@ -13,7 +13,13 @@
 #  define WIN32_LEAN_AND_MEAN
 #  define NOMINMAX
 #  include <windows.h>
-#elif defined(__APPLE__) || defined(__FreeBSD__)
+#elif defined(__APPLE__)
+#  include <array>
+#  include <csignal>
+#  include <sys/sysctl.h>
+#  include <sys/types.h>
+#  include <unistd.h>
+#elif defined(__FreeBSD__)
 #  include <array>
 #  include <csignal>
 #  include <libutil.h>



More information about the libcxx-commits mailing list