On Fri, 11 Apr 2025 at 10:31, Tomasz Kaminski <tkami...@redhat.com> wrote:
>
>
>
> On Fri, Apr 11, 2025 at 10:13 AM Jonathan Wakely <jwak...@redhat.com> wrote:
>>
>> On Fri, 11 Apr 2025 at 08:00, Tomasz Kaminski <tkami...@redhat.com> wrote:
>> >
>> >
>> >
>> > On Thu, Apr 10, 2025 at 6:53 PM Jonathan Wakely <jwak...@redhat.com> wrote:
>> >>
>> >> It would be good to provide a macOS definition of is_debugger_present as
>> >> per https://developer.apple.com/library/archive/qa/qa1361/_index.html
>> >> but that isn't included in this change.
>> >>
>> >> libstdc++-v3/ChangeLog:
>> >>
>> >>         * config.h.in: Regenerate.
>> >>         * configure: Regenerate.
>> >>         * configure.ac: Check for facilities needed by <debugging>.
>> >>         * include/Makefile.am: Add new header.
>> >>         * include/Makefile.in: Regenerate.
>> >>         * include/bits/version.def (debugging): Add.
>> >>         * include/bits/version.h: Regenerate.
>> >>         * src/c++26/Makefile.am: Add new file.
>> >>         * src/c++26/Makefile.in: Regenerate.
>> >>         * include/std/debugging: New file.
>> >>         * src/c++26/debugging.cc: New file.
>> >>         * testsuite/19_diagnostics/debugging/breakpoint.cc: New test.
>> >>         * testsuite/19_diagnostics/debugging/breakpoint_if_debugging.cc:
>> >>         New test.
>> >>         * testsuite/19_diagnostics/debugging/is_debugger_present.cc: New
>> >>         test.
>> >> ---
>> >>
>> >> I sent v1 of this patch in June last year:
>> >> https://gcc.gnu.org/pipermail/gcc-patches/2024-June/653293.html
>> >> My comments about testing with GDB still apply.
>> >>
>> >> Compared to v1, this adds a void __gnu_cxx::attach_debugger(bool)
>> >> function that could be called by debuggers to announce that they are
>> >> attaching and detaching. It also adds a systemtap probe point to
>> >> std::breakpoint().
>> >>
>> >> Tested x86_64-linux.
>> >>
>> >> N.B. this only adds new symbols to the libstdc++exp.a archive, not to
>> >> libstdc++.so so it's not a risky change at this stage.
>> >>
>> >>  libstdc++-v3/config.h.in                      |   9 +
>> >>  libstdc++-v3/configure                        |  22 +++
>> >>  libstdc++-v3/configure.ac                     |   9 +
>> >>  libstdc++-v3/include/Makefile.am              |   1 +
>> >>  libstdc++-v3/include/Makefile.in              |   1 +
>> >>  libstdc++-v3/include/bits/version.def         |   8 +
>> >>  libstdc++-v3/include/bits/version.h           |  10 ++
>> >>  libstdc++-v3/include/std/debugging            |  77 ++++++++
>> >>  libstdc++-v3/src/c++26/Makefile.am            |   4 +-
>> >>  libstdc++-v3/src/c++26/Makefile.in            |   7 +-
>> >>  libstdc++-v3/src/c++26/debugging.cc           | 165 ++++++++++++++++++
>> >>  .../19_diagnostics/debugging/breakpoint.cc    |  13 ++
>> >>  .../debugging/breakpoint_if_debugging.cc      |  13 ++
>> >>  .../debugging/is_debugger_present.cc          |  14 ++
>> >>  14 files changed, 350 insertions(+), 3 deletions(-)
>> >>  create mode 100644 libstdc++-v3/include/std/debugging
>> >>  create mode 100644 libstdc++-v3/src/c++26/debugging.cc
>> >>  create mode 100644 
>> >> libstdc++-v3/testsuite/19_diagnostics/debugging/breakpoint.cc
>> >>  create mode 100644 
>> >> libstdc++-v3/testsuite/19_diagnostics/debugging/breakpoint_if_debugging.cc
>> >>  create mode 100644 
>> >> libstdc++-v3/testsuite/19_diagnostics/debugging/is_debugger_present.cc
>> >>
>> >> diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
>> >> index 77bbaf1beaa..3f1331ff36f 100644
>> >> --- a/libstdc++-v3/config.h.in
>> >> +++ b/libstdc++-v3/config.h.in
>> >> @@ -70,6 +70,9 @@
>> >>  /* Define to 1 if you have the `cosl' function. */
>> >>  #undef HAVE_COSL
>> >>
>> >> +/* Define to 1 if you have the <debugapi.h> header file. */
>> >> +#undef HAVE_DEBUGAPI_H
>> >> +
>> >>  /* Define to 1 if you have the declaration of `strnlen', and to 0 if you
>> >>     don't. */
>> >>  #undef HAVE_DECL_STRNLEN
>> >> @@ -439,6 +442,9 @@
>> >>  /* Define to 1 if you have the <sys/param.h> header file. */
>> >>  #undef HAVE_SYS_PARAM_H
>> >>
>> >> +/* Define to 1 if you have the <sys/ptrace.h> header file. */
>> >> +#undef HAVE_SYS_PTRACE_H
>> >> +
>> >>  /* Define to 1 if you have the <sys/resource.h> header file. */
>> >>  #undef HAVE_SYS_RESOURCE_H
>> >>
>> >> @@ -850,6 +856,9 @@
>> >>  /* Define if nl_langinfo_l should be used for std::text_encoding. */
>> >>  #undef _GLIBCXX_USE_NL_LANGINFO_L
>> >>
>> >> +/* Define if /proc/self/status should be used for <debugging>. */
>> >> +#undef _GLIBCXX_USE_PROC_SELF_STATUS
>> >> +
>> >>  /* Define if pthreads_num_processors_np is available in <pthread.h>. */
>> >>  #undef _GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP
>> >>
>> >> diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
>> >> index 819a1d82876..8143df91c38 100755
>> >> --- a/libstdc++-v3/configure
>> >> +++ b/libstdc++-v3/configure
>> >> @@ -54700,6 +54700,28 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
>> >>
>> >>
>> >>
>> >> +# For std::is_debugger_present
>> >> +case "$target_os" in
>> >> +  linux*)
>> >> +
>> >> +$as_echo "#define _GLIBCXX_USE_PROC_SELF_STATUS 1" >>confdefs.h
>> >> +
>> >> +    ;;
>> >> +esac
>> >> +for ac_header in sys/ptrace.h debugapi.h
>> >> +do :
>> >> +  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
>> >> +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" 
>> >> "$ac_includes_default"
>> >> +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
>> >> +  cat >>confdefs.h <<_ACEOF
>> >> +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
>> >> +_ACEOF
>> >> +
>> >> +fi
>> >> +
>> >> +done
>> >> +
>> >> +
>> >>  # Define documentation rules conditionally.
>> >>
>> >>  # See if makeinfo has been installed and is modern enough
>> >> diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
>> >> index a6c01b29e94..83adb46454e 100644
>> >> --- a/libstdc++-v3/configure.ac
>> >> +++ b/libstdc++-v3/configure.ac
>> >> @@ -587,6 +587,15 @@ GLIBCXX_CHECK_FILEBUF_NATIVE_HANDLES
>> >>  # For std::text_encoding
>> >>  GLIBCXX_CHECK_TEXT_ENCODING
>> >>
>> >> +# For std::is_debugger_present
>> >> +case "$target_os" in
>> >> +  linux*)
>> >> +    AC_DEFINE([_GLIBCXX_USE_PROC_SELF_STATUS],1,
>> >> +             [Define if /proc/self/status should be used for 
>> >> <debugging>.])
>> >> +    ;;
>> >> +esac
>> >> +AC_CHECK_HEADERS([sys/ptrace.h debugapi.h])
>> >> +
>> >>  # Define documentation rules conditionally.
>> >>
>> >>  # See if makeinfo has been installed and is modern enough
>> >> diff --git a/libstdc++-v3/include/Makefile.am 
>> >> b/libstdc++-v3/include/Makefile.am
>> >> index 537774c2668..6bb3f3dc3d6 100644
>> >> --- a/libstdc++-v3/include/Makefile.am
>> >> +++ b/libstdc++-v3/include/Makefile.am
>> >> @@ -67,6 +67,7 @@ std_headers = \
>> >>         ${std_srcdir}/codecvt \
>> >>         ${std_srcdir}/complex \
>> >>         ${std_srcdir}/condition_variable \
>> >> +       ${std_srcdir}/debugging \
>> >>         ${std_srcdir}/deque \
>> >>         ${std_srcdir}/execution \
>> >>         ${std_srcdir}/filesystem \
>> >> diff --git a/libstdc++-v3/include/Makefile.in 
>> >> b/libstdc++-v3/include/Makefile.in
>> >> index 7b96b2207f8..81c3cfce4c4 100644
>> >> --- a/libstdc++-v3/include/Makefile.in
>> >> +++ b/libstdc++-v3/include/Makefile.in
>> >> @@ -423,6 +423,7 @@ std_freestanding = \
>> >>  @GLIBCXX_HOSTED_TRUE@  ${std_srcdir}/codecvt \
>> >>  @GLIBCXX_HOSTED_TRUE@  ${std_srcdir}/complex \
>> >>  @GLIBCXX_HOSTED_TRUE@  ${std_srcdir}/condition_variable \
>> >> +@GLIBCXX_HOSTED_TRUE@  ${std_srcdir}/debugging \
>> >>  @GLIBCXX_HOSTED_TRUE@  ${std_srcdir}/deque \
>> >>  @GLIBCXX_HOSTED_TRUE@  ${std_srcdir}/execution \
>> >>  @GLIBCXX_HOSTED_TRUE@  ${std_srcdir}/filesystem \
>> >> diff --git a/libstdc++-v3/include/bits/version.def 
>> >> b/libstdc++-v3/include/bits/version.def
>> >> index 2ec1b40bd38..092d0427e4a 100644
>> >> --- a/libstdc++-v3/include/bits/version.def
>> >> +++ b/libstdc++-v3/include/bits/version.def
>> >> @@ -1841,6 +1841,14 @@ ftms = {
>> >>    };
>> >>  };
>> >>
>> >> +ftms = {
>> >> +  name = debugging;
>> >> +  values = {
>> >> +    v = 202403;
>> >> +    cxxmin = 26;
>> >> +  };
>> >>
>> >> +};
>> >> +
>> >>  ftms = {
>> >>    name = fstream_native_handle;
>> >>    values = {
>> >> diff --git a/libstdc++-v3/include/bits/version.h 
>> >> b/libstdc++-v3/include/bits/version.h
>> >> index 04c1349c84b..12892fc135d 100644
>> >> --- a/libstdc++-v3/include/bits/version.h
>> >> +++ b/libstdc++-v3/include/bits/version.h
>> >> @@ -2044,6 +2044,16 @@
>> >>  #endif /* !defined(__cpp_lib_constexpr_new) && 
>> >> defined(__glibcxx_want_constexpr_new) */
>> >>  #undef __glibcxx_want_constexpr_new
>> >>
>> >> +#if !defined(__cpp_lib_debugging)
>> >> +# if (__cplusplus >  202302L)
>> >> +#  define __glibcxx_debugging 202403L
>> >> +#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_debugging)
>> >> +#   define __cpp_lib_debugging 202403L
>> >> +#  endif
>> >> +# endif
>> >> +#endif /* !defined(__cpp_lib_debugging) && 
>> >> defined(__glibcxx_want_debugging) */
>> >> +#undef __glibcxx_want_debugging
>> >> +
>> >>  #if !defined(__cpp_lib_fstream_native_handle)
>> >>  # if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
>> >>  #  define __glibcxx_fstream_native_handle 202306L
>> >> diff --git a/libstdc++-v3/include/std/debugging 
>> >> b/libstdc++-v3/include/std/debugging
>> >> new file mode 100644
>> >> index 00000000000..4cf7e4acbc4
>> >> --- /dev/null
>> >> +++ b/libstdc++-v3/include/std/debugging
>> >> @@ -0,0 +1,77 @@
>> >> +// Debugging support -*- C++ -*-
>> >> +
>> >> +// Copyright The GNU Toolchain Authors.
>> >> +//
>> >> +// This file is part of the GNU ISO C++ Library.  This library is free
>> >> +// software; you can redistribute it and/or modify it under the
>> >> +// terms of the GNU General Public License as published by the
>> >> +// Free Software Foundation; either version 3.
>> >> +
>> >> +// This library is distributed in the hope that it will be useful,
>> >> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
>> >> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> >> +// GNU General Public License for more details.
>> >> +
>> >> +// Under Section 7 of GPL version 3, you are granted additional
>> >> +// permissions described in the GCC Runtime Library Exception, version
>> >> +// 3.1, as published by the Free Software Foundation.
>> >> +
>> >> +// You should have received a copy of the GNU General Public License and
>> >> +// a copy of the GCC Runtime Library Exception along with this program;
>> >> +// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>> >> +// <http://www.gnu.org/licenses/>.
>> >> +
>> >> +/** @file include/debugging
>> >> + *  This is a Standard C++ Library header.
>> >> + */
>> >> +
>> >> +#ifndef _GLIBCXX_DEBUGGING
>> >> +#define _GLIBCXX_DEBUGGING 1
>> >> +
>> >> +#define __glibcxx_want_debugging
>> >> +#include <bits/version.h>
>> >> +
>> >> +#if __cpp_lib_debugging // C++ >= 26
>> >> +namespace std _GLIBCXX_VISIBILITY(default)
>> >> +{
>> >> +// N.B. _GLIBCXX_BEGIN_NAMESPACE_VERSION is not used here.
>> >> +
>> >> +/** Try to determine if the program is running under control of a 
>> >> debugger.
>> >> + *
>> >> + * On GNU/Linux systems this function will only return true if the 
>> >> program
>> >> + * is being traced by another program which is known to be a debugger.
>> >> + * This is determined by checking the command name of the tracing program
>> >> + * against a list of known debuggers, such as "gdb".
>> >> + *
>> >> + * On other POSIX-based systems, this function will return true if the
>> >> + * program is being traced by any other process, which means it can 
>> >> return
>> >> + * true for non-debugger utilities that use the ptrace system call.
>> >> + *
>> >> + * @since C++26
>> >> + */
>> >> +bool
>> >> +is_debugger_present() noexcept;
>> >> +
>> >> +/** Stop the program with a breakpoint or debug trap.
>> >> + *
>> >> + * The details of how a breakpoint is implemented are platform-specific.
>> >> + * Some systems provide a special instruction, such as `int3` in x86.
>> >> + * When no more appropriate mechanism is available, this will stop the
>> >> + * program using `__builtin_trap()`. It might not be possible for the
>> >> + * program to continue after such a breakpoint.
>> >> + *
>> >> + * @since C++26
>> >> + */
>> >> +void
>> >> +breakpoint() noexcept;
>> >> +
>> >> +/** Stop the program if it is running under control of a debugger.
>> >> + *
>> >> + * @since C++26
>> >> + */
>> >> +void
>> >> +breakpoint_if_debugging() noexcept;
>> >> +
>> >> +} // namespace std
>> >> +#endif
>> >> +#endif // _GLIBCXX_DEBUGGING
>> >> diff --git a/libstdc++-v3/src/c++26/Makefile.am 
>> >> b/libstdc++-v3/src/c++26/Makefile.am
>> >> index 5defa4ac481..4123b7dd369 100644
>> >> --- a/libstdc++-v3/src/c++26/Makefile.am
>> >> +++ b/libstdc++-v3/src/c++26/Makefile.am
>> >> @@ -35,7 +35,9 @@ else
>> >>  inst_sources =
>> >>  endif
>> >>
>> >> -sources = text_encoding.cc
>> >> +sources = \
>> >> +         debugging.cc \
>> >> +         text_encoding.cc
>> >>
>> >>  vpath % $(top_srcdir)/src/c++26
>> >>
>> >> diff --git a/libstdc++-v3/src/c++26/Makefile.in 
>> >> b/libstdc++-v3/src/c++26/Makefile.in
>> >> index 77e73b2b265..1c317d6ac7c 100644
>> >> --- a/libstdc++-v3/src/c++26/Makefile.in
>> >> +++ b/libstdc++-v3/src/c++26/Makefile.in
>> >> @@ -121,7 +121,7 @@ CONFIG_CLEAN_FILES =
>> >>  CONFIG_CLEAN_VPATH_FILES =
>> >>  LTLIBRARIES = $(noinst_LTLIBRARIES)
>> >>  libc__26convenience_la_LIBADD =
>> >> -am__objects_1 = text_encoding.lo
>> >> +am__objects_1 = debugging.lo text_encoding.lo
>> >>  am__objects_2 =
>> >>  @GLIBCXX_HOSTED_TRUE@am_libc__26convenience_la_OBJECTS =  \
>> >>  @GLIBCXX_HOSTED_TRUE@  $(am__objects_1) $(am__objects_2)
>> >> @@ -430,7 +430,10 @@ headers =
>> >>
>> >>  # XTEMPLATE_FLAGS = -fno-implicit-templates
>> >>  @ENABLE_EXTERN_TEMPLATE_TRUE@inst_sources =
>> >> -sources = text_encoding.cc
>> >> +sources = \
>> >> +         debugging.cc \
>> >> +         text_encoding.cc
>> >> +
>> >>  @GLIBCXX_HOSTED_FALSE@libc__26convenience_la_SOURCES =
>> >>  @GLIBCXX_HOSTED_TRUE@libc__26convenience_la_SOURCES = $(sources)  
>> >> $(inst_sources)
>> >>
>> >> diff --git a/libstdc++-v3/src/c++26/debugging.cc 
>> >> b/libstdc++-v3/src/c++26/debugging.cc
>> >> new file mode 100644
>> >> index 00000000000..5ad85309ba1
>> >> --- /dev/null
>> >> +++ b/libstdc++-v3/src/c++26/debugging.cc
>> >> @@ -0,0 +1,165 @@
>> >> +// Implementation of <debugging> -*- C++ -*-
>> >> +
>> >> +// Copyright The GNU Toolchain Authors.
>> >> +//
>> >> +// This file is part of the GNU ISO C++ Library.  This library is free
>> >> +// software; you can redistribute it and/or modify it under the
>> >> +// terms of the GNU General Public License as published by the
>> >> +// Free Software Foundation; either version 3.
>> >> +
>> >> +// This library is distributed in the hope that it will be useful,
>> >> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
>> >> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> >> +// GNU General Public License for more details.
>> >> +
>> >> +// Under Section 7 of GPL version 3, you are granted additional
>> >> +// permissions described in the GCC Runtime Library Exception, version
>> >> +// 3.1, as published by the Free Software Foundation.
>> >> +
>> >> +// You should have received a copy of the GNU General Public License and
>> >> +// a copy of the GCC Runtime Library Exception along with this program;
>> >> +// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>> >> +// <http://www.gnu.org/licenses/>.
>> >> +
>> >> +#include <debugging>
>> >> +
>> >> +#if __cpp_lib_debugging
>> >> +
>> >> +#if _GLIBCXX_USE_PROC_SELF_STATUS
>> >> +# include <fstream>
>> >> +# include <string>
>> >> +#endif
>> >> +
>> >> +#if _GLIBCXX_HAVE_SYS_PTRACE_H
>> >> +# include <sys/ptrace.h>
>> >> +# include <errno.h>
>> >> +#endif
>> >> +
>> >> +#if _GLIBCXX_HAVE_DEBUGAPI_H
>> >> +# include <debugapi.h>
>> >> +#endif
>> >> +
>> >> +#ifdef _GLIBCXX_HAVE_SYS_SDT_H
>> >> +# include <sys/sdt.h>
>> >> +/* We only want to use stap probes starting with v3.  Earlier versions
>> >> +   added too much startup cost.  */
>> >> +# if defined (STAP_PROBE) && _SDT_NOTE_TYPE >= 3
>> >> +#  define PROBE(name) STAP_PROBE(libstdcxx, name)
>> >> +# endif
>> >> +#endif
>> >> +
>> >> +#ifndef PROBE
>> >> +# define PROBE(name)
>> >> +#endif
>> >> +
>> >> +namespace
>> >> +{
>> >> +  volatile bool debugger_attached = false;
>> >> +}
>> >> +
>> >> +namespace __gnu_cxx
>> >> +{
>> >> +  // This should be called by debuggers when they attach and detach.
>> >> +  void attach_debugger(bool attached) { debugger_attached = attached; }
>> >> +}
>> >> +
>> >> +_GLIBCXX_WEAK_DEFINITION
>> >> +bool
>> >> +std::is_debugger_present() noexcept
>> >> +{
>> >> +  if (debugger_attached)
>> >> +    return true;
>> >> +
>> >> +#if _GLIBCXX_HOSTED
>> >> +# if _GLIBCXX_USE_PROC_SELF_STATUS
>> >> +  const string_view prefix = "TracerPid:\t";
>> >> +  ifstream in("/proc/self/status");
>> >> +  string line;
>> >> +  while (std::getline(in, line))
>> >> +    {
>> >> +      if (!line.starts_with(prefix))
>> >> +       continue;
>> >> +
>> >> +      string_view tracer = line;
>> >> +      tracer.remove_prefix(prefix.size());
>> >> +      if (tracer.size() == 1 && tracer[0] == '0') [[likely]]
>> >> +       return false; // Not being traced.
>> >> +
>> >> +      in.close();
>> >> +      string_view cmd;
>> >> +      string proc_dir = "/proc/" + string(tracer) + '/';
>> >> +      in.open(proc_dir + "comm"); // since Linux 2.6.33
>> >> +      if (std::getline(in, line)) [[likely]]
>> >> +       cmd = line;
>> >> +      else
>> >> +       {
>> >> +         in.close();
>> >> +         in.open(proc_dir + "cmdline");
>> >> +         if (std::getline(in, line))
>> >> +           cmd = line.c_str(); // Only up to first '\0'
>> >> +         else
>> >> +           return false;
>> >> +       }
>> >> +
>> >> +      for (auto i : {"gdb", "lldb"}) // known debuggers
>> >> +       if (cmd.ends_with(i))
>> >> +         return true;
>> >> +
>> >> +      // We found the TracerPid line, no need to do any more work.
>> >> +      return false;
>> >> +    }
>> >> +# endif
>> >> +# if _GLIBCXX_HAVE_SYS_PTRACE_H
>> >
>> > Are _GLIBCXX_USE_PROC_SELF_STATUS and  _GLIBCXX_HAVE_SYS_PTRACE_H 
>> > exclusive, i.e. both cannot be true at same time?
>>
>> They're not exclusive, e.g. Linux has both /proc/self and ptrace. Most
>> UNIX systems only have ptrace.
>>
>> > If not, using `ptrace` seems to be preferablable, given that it does not 
>> > involve fstreams.
>>
>> But it can give false positives. There are other uses of ptrace that
>> are not debuggers, e.g. running the program under strace. The
>> /proc/self version checks for the tracer name, so should only detect
>> real debuggers.
>
> We will still use the ptrace result, if `proc/self` exists but does not 
> contain the TracerPid line.

Yes, that was my intention.

According to Documentation/filesystems/proc.rst the TracerPid line was
added for Linux 2.4, although it wasn't actually set until later
(maybe 2.6?): https://lkml.org/lkml/2002/9/6/96
But that means we'll find a TracerPid line even for ancient kernels.
If its PID is zero (e.g. because it's in a different pid namespace, or
it's kernel 2.4) or the cmdline of the tracer is not readable by the
process (e.g. because the debugger is running as a different user),
then we'll still find a TracerPid and return early.

> I am not sure if this is a possible case, but if not I would prefer the use 
> of `elif` here.

I had intended it to be used as a fallback, but based on what I wrote
above, it looks like that fallback will never happen.

>>
>>
>> >>
>> >> +  if (::ptrace(PTRACE_TRACEME, 0, 1, 0) == -1)
>> >> +    return errno == EPERM;
>> >> +# endif
>> >> +# if _GLIBCXX_HAVE_DEBUGAPI_H && defined(_WIN32) && !defined(__CYGWIN__)
>> >> +  return IsDebuggerPresent();
>> >> +# endif
>> >> +#endif // HOSTED
>> >> +  return false;
>> >> +}
>> >> +
>> >> +void
>> >> +std::breakpoint() noexcept
>> >> +{
>> >> +  PROBE(std::breakpoint);
>> >> +
>> >> +#if _GLIBCXX_HAVE_DEBUGAPI_H && defined(_WIN32) && !defined(__CYGWIN__)
>> >> +  DebugBreak();
>> >> +#elif __has_builtin(__builtin_debugtrap)
>> >> +  __builtin_debugtrap(); // Clang
>> >> +#elif defined(__i386__) || defined(__x86_64__)
>> >> +  __asm__ volatile ("int3; nop");
>> >> +#elifdef __thumb__
>> >> +  __asm__ volatile (".inst 0xde01");
>> >> +#elifdef __aarch64__
>> >> +  __asm__ volatile (".inst 0xd4200000");
>> >> +#elifdef __arm__
>> >> +  __asm__ volatile (".inst 0xe7f001f0");
>> >> +#elifdef __riscv
>> >> +  /* section 2.8 in the RISC-V unprivileged ISA manual says for 
>> >> semi-hosted
>> >> +   * environments we want the sequence:
>> >> +   * slli x0, x0, 0x1f     # Entry NOP
>> >> +   * ebreak         # Break to debugger
>> >> +   * srai x0, x0, 7    # NOP encoding the semihosting call number 7
>> >> +   */
>> >> +  __asm__ volatile (".4byte 0x00100073");
>> >> +#elifdef __powerpc__
>> >> +  __asm__ volatile(".4byte 0x7d821008");
>> >> +#else
>> >> +  __builtin_trap();
>> >> +#endif
>> >> +} // If the debugger stops here, std::breakpoint() was called.
>> >> +
>> >> +// This is intentionally not defined inline. A non-inline definition 
>> >> allows
>> >> +// debuggers to insert a breakpoint on calls to the function, avoiding 
>> >> the
>> >> +// overhead of calling `is_debugger_present()`.
>> >> +void
>> >> +std::breakpoint_if_debugging() noexcept
>> >> +{
>> >> +  if (std::is_debugger_present()) [[unlikely]]
>> >> +    std::breakpoint();
>> >> +}
>> >> +
>> >> +#endif // __cpp_lib_debugging
>> >> diff --git 
>> >> a/libstdc++-v3/testsuite/19_diagnostics/debugging/breakpoint.cc 
>> >> b/libstdc++-v3/testsuite/19_diagnostics/debugging/breakpoint.cc
>> >> new file mode 100644
>> >> index 00000000000..ad24177f644
>> >> --- /dev/null
>> >> +++ b/libstdc++-v3/testsuite/19_diagnostics/debugging/breakpoint.cc
>> >> @@ -0,0 +1,13 @@
>> >> +// { dg-do run { target c++26 xfail c++26 } }
>> >> +// { dg-options "-lstdc++exp" }
>> >> +// { dg-require-cpp-feature-test __cpp_lib_debugging }
>> >> +#include <debugging>
>> >> +#include <type_traits>
>> >> +
>> >> +static_assert( noexcept(std::breakpoint()) );
>> >> +static_assert( std::is_void_v<decltype(std::breakpoint())> );
>> >> +
>> >> +int main()
>> >> +{
>> >> +  std::breakpoint();
>> >> +}
>> >> diff --git 
>> >> a/libstdc++-v3/testsuite/19_diagnostics/debugging/breakpoint_if_debugging.cc
>> >>  
>> >> b/libstdc++-v3/testsuite/19_diagnostics/debugging/breakpoint_if_debugging.cc
>> >> new file mode 100644
>> >> index 00000000000..26461836ef7
>> >> --- /dev/null
>> >> +++ 
>> >> b/libstdc++-v3/testsuite/19_diagnostics/debugging/breakpoint_if_debugging.cc
>> >> @@ -0,0 +1,13 @@
>> >> +// { dg-do run { target c++26 } }
>> >> +// { dg-options "-lstdc++exp" }
>> >> +// { dg-require-cpp-feature-test __cpp_lib_debugging }
>> >> +#include <debugging>
>> >> +#include <type_traits>
>> >> +
>> >> +static_assert( noexcept(std::breakpoint_if_debugging()) );
>> >> +static_assert( std::is_void_v<decltype(std::breakpoint_if_debugging())> 
>> >> );
>> >> +
>> >> +int main()
>> >> +{
>> >> +  std::breakpoint_if_debugging();
>> >> +}
>> >> diff --git 
>> >> a/libstdc++-v3/testsuite/19_diagnostics/debugging/is_debugger_present.cc 
>> >> b/libstdc++-v3/testsuite/19_diagnostics/debugging/is_debugger_present.cc
>> >> new file mode 100644
>> >> index 00000000000..8dbfa694243
>> >> --- /dev/null
>> >> +++ 
>> >> b/libstdc++-v3/testsuite/19_diagnostics/debugging/is_debugger_present.cc
>> >> @@ -0,0 +1,14 @@
>> >> +// { dg-do run { target c++26 } }
>> >> +// { dg-options "-lstdc++exp" }
>> >> +// { dg-require-cpp-feature-test __cpp_lib_debugging }
>> >> +#include <debugging>
>> >> +#include <type_traits>
>> >> +#include <testsuite_hooks.h>
>> >> +
>> >> +static_assert( noexcept(std::is_debugger_present()) );
>> >> +static_assert( std::is_same_v<decltype(std::is_debugger_present()), 
>> >> bool> );
>> >> +
>> >> +int main()
>> >> +{
>> >> +  VERIFY( ! std::is_debugger_present() );
>> >> +}
>> >> --
>> >> 2.49.0
>> >>
>>

Reply via email to