On Wed, May 15, 2024 at 12:59 PM Alexander Monakov <amona...@ispras.ru> wrote:
>
>
> Hello,
>
> I'd like to ask if anyone has any new thoughts on this patch.
>
> Let me also point out that valgrind/memcheck.h is permissively
> licensed (BSD-style, rest of Valgrind is GPLv2), with the intention
> to allow importing into projects that are interested in using
> client requests without build-time dependency on installed headers.
> So maybe we have that as an option too.

Inlining the VALGRIND_DO_CLIENT_REQUEST_EXPR would be a lot
cheaper and would not add to the libgcc ABI.  I would guess the
valgrind "ABI" for these is practically fixed but of course architecture
dependent.

I do like the feature in general.

> Alexander
>
> On Fri, 22 Dec 2023, Alexander Monakov wrote:
>
> > From: Daniil Frolov <exactl...@ispras.ru>
> >
> > PR 66487 is asking to provide sanitizer-like detection for C++ object
> > lifetime violations that are worked around with -fno-lifetime-dse or
> > -flifetime-dse=1 in Firefox, LLVM (PR 106943), OpenJade (PR 69534).
> >
> > The discussion in the PR was centered around extending MSan, but MSan
> > was not ported to GCC (and requires rebuilding everything with
> > instrumentation).
> >
> > Instead, allow Valgrind to see lifetime boundaries by emitting client
> > requests along *this = { CLOBBER }.  The client request marks the
> > "clobbered" memory as undefined for Valgrind; clobbering assignments
> > mark the beginning of ctor and end of dtor execution for C++ objects.
> > Hence, attempts to read object storage after the destructor, or
> > "pre-initialize" its fields prior to the constructor will be caught.
> >
> > Valgrind client requests are offered as macros that emit inline asm.
> > For use in code generation, let's wrap them as libgcc builtins.
> >
> > gcc/ChangeLog:
> >
> >       * Makefile.in (OBJS): Add gimple-valgrind-interop.o.
> >       * builtins.def (BUILT_IN_VALGRIND_MAKE_UNDEFINED): New.
> >       * common.opt (-fvalgrind-annotations): New option.
> >       * doc/install.texi (--enable-valgrind-interop): Document.
> >       * doc/invoke.texi (-fvalgrind-annotations): Document.
> >       * passes.def (pass_instrument_valgrind): Add.
> >       * tree-pass.h (make_pass_instrument_valgrind): Declare.
> >       * gimple-valgrind-interop.cc: New file.
> >
> > libgcc/ChangeLog:
> >
> >       * Makefile.in (LIB2ADD_ST): Add valgrind-interop.c.
> >       * config.in: Regenerate.
> >       * configure: Regenerate.
> >       * configure.ac (--enable-valgrind-interop): New flag.
> >       * libgcc2.h (__gcc_vgmc_make_mem_undefined): Declare.
> >       * valgrind-interop.c: New file.
> >
> > gcc/testsuite/ChangeLog:
> >
> >       * g++.dg/valgrind-annotations-1.C: New test.
> >       * g++.dg/valgrind-annotations-2.C: New test.
> >
> > Co-authored-by: Alexander Monakov <amona...@ispras.ru>
> > ---
> > Changes in v2:
> >
> > * Take new clobber kinds into account.
> > * Do not link valgrind-interop.o into libgcc_s.so.
> >
> >  gcc/Makefile.in                               |   1 +
> >  gcc/builtins.def                              |   3 +
> >  gcc/common.opt                                |   4 +
> >  gcc/doc/install.texi                          |   5 +
> >  gcc/doc/invoke.texi                           |  27 ++++
> >  gcc/gimple-valgrind-interop.cc                | 125 ++++++++++++++++++
> >  gcc/passes.def                                |   1 +
> >  gcc/testsuite/g++.dg/valgrind-annotations-1.C |  22 +++
> >  gcc/testsuite/g++.dg/valgrind-annotations-2.C |  12 ++
> >  gcc/tree-pass.h                               |   1 +
> >  libgcc/Makefile.in                            |   3 +
> >  libgcc/config.in                              |   6 +
> >  libgcc/configure                              |  22 ++-
> >  libgcc/configure.ac                           |  15 ++-
> >  libgcc/libgcc2.h                              |   2 +
> >  libgcc/valgrind-interop.c                     |  40 ++++++
> >  16 files changed, 287 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/gimple-valgrind-interop.cc
> >  create mode 100644 gcc/testsuite/g++.dg/valgrind-annotations-1.C
> >  create mode 100644 gcc/testsuite/g++.dg/valgrind-annotations-2.C
> >  create mode 100644 libgcc/valgrind-interop.c
> >
> > diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> > index 9373800018..d027548203 100644
> > --- a/gcc/Makefile.in
> > +++ b/gcc/Makefile.in
> > @@ -1507,6 +1507,7 @@ OBJS = \
> >       gimple-ssa-warn-restrict.o \
> >       gimple-streamer-in.o \
> >       gimple-streamer-out.o \
> > +     gimple-valgrind-interop.o \
> >       gimple-walk.o \
> >       gimple-warn-recursion.o \
> >       gimplify.o \
> > diff --git a/gcc/builtins.def b/gcc/builtins.def
> > index f03df32f98..b05e20e062 100644
> > --- a/gcc/builtins.def
> > +++ b/gcc/builtins.def
> > @@ -1194,6 +1194,9 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, 
> > ATTR_NOTHROW_LEAF_LIST)
> >  /* Control Flow Redundancy hardening out-of-line checker.  */
> >  DEF_BUILTIN_STUB (BUILT_IN___HARDCFR_CHECK, "__builtin___hardcfr_check")
> >
> > +/* Wrappers for Valgrind client requests.  */
> > +DEF_EXT_LIB_BUILTIN (BUILT_IN_VALGRIND_MAKE_UNDEFINED, 
> > "__gcc_vgmc_make_mem_undefined", BT_FN_VOID_PTR_SIZE, 
> > ATTR_NOTHROW_LEAF_LIST)
> > +
> >  /* Synchronization Primitives.  */
> >  #include "sync-builtins.def"
> >
> > diff --git a/gcc/common.opt b/gcc/common.opt
> > index d263a959df..2be5b8d0a6 100644
> > --- a/gcc/common.opt
> > +++ b/gcc/common.opt
> > @@ -3377,6 +3377,10 @@ Enum(auto_init_type) String(pattern) 
> > Value(AUTO_INIT_PATTERN)
> >  EnumValue
> >  Enum(auto_init_type) String(zero) Value(AUTO_INIT_ZERO)
> >
> > +fvalgrind-annotations
> > +Common Var(flag_valgrind_annotations) Optimization
> > +Annotate lifetime boundaries with Valgrind client requests.
> > +
> >  ; -fverbose-asm causes extra commentary information to be produced in
> >  ; the generated assembly code (to make it more readable).  This option
> >  ; is generally only of use to those who actually need to read the
> > diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> > index d20b43a5b2..d6e5e5fdaf 100644
> > --- a/gcc/doc/install.texi
> > +++ b/gcc/doc/install.texi
> > @@ -1563,6 +1563,11 @@ Disable TM clone registry in libgcc. It is enabled 
> > in libgcc by default.
> >  This option helps to reduce code size for embedded targets which do
> >  not use transactional memory.
> >
> > +@item --enable-valgrind-interop
> > +Provide wrappers for Valgrind client requests in libgcc, which are used for
> > +@option{-fvalgrind-annotations}.  Requires Valgrind header files for the
> > +target (in the build-time sysroot if building a cross-compiler).
> > +
> >  @item --with-cpu=@var{cpu}
> >  @itemx --with-cpu-32=@var{cpu}
> >  @itemx --with-cpu-64=@var{cpu}
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index d272b9228d..bfbe6a8bd9 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -660,6 +660,7 @@ Objective-C and Objective-C++ Dialects}.
> >  -fno-stack-limit  -fsplit-stack
> >  -fstrub=disable  -fstrub=strict  -fstrub=relaxed
> >  -fstrub=all  -fstrub=at-calls  -fstrub=internal
> > +-fvalgrind-annotations
> >  -fvtable-verify=@r{[}std@r{|}preinit@r{|}none@r{]}
> >  -fvtv-counts  -fvtv-debug
> >  -finstrument-functions  -finstrument-functions-once
> > @@ -12975,6 +12976,9 @@ can use @option{-flifetime-dse=1}.  The default 
> > behavior can be
> >  explicitly selected with @option{-flifetime-dse=2}.
> >  @option{-flifetime-dse=0} is equivalent to @option{-fno-lifetime-dse}.
> >
> > +See @option{-fvalgrind-annotations} for instrumentation that allows to
> > +detect violations of standard lifetime semantics using Valgrind.
> > +
> >  @opindex flive-range-shrinkage
> >  @item -flive-range-shrinkage
> >  Attempt to decrease register pressure through register live range
> > @@ -18051,6 +18055,29 @@ function attributes that tell which mode was 
> > selected for each function.
> >  The primary use of this option is for testing, to exercise thoroughly
> >  the @code{strub} machinery.
> >
> > +@opindex fvalgrind-annotations
> > +@item -fvalgrind-annotations
> > +Emit Valgrind client requests annotating object lifetime boundaries.
> > +This allows to detect attempts to access fields of a C++ object after
> > +its destructor has completed (but storage was not deallocated yet), or
> > +to initialize it in advance from @code{operator new} rather than the
> > +constructor.
> > +
> > +This instrumentation relies on presence of 
> > @code{__gcc_vgmc_make_mem_undefined}
> > +function that wraps the corresponding Valgrind client request. It is 
> > provided
> > +by libgcc when it is configured with @samp{--enable-valgrind-interop}.
> > +Otherwise, you can implement it like this:
> > +
> > +@smallexample
> > +#include <valgrind/memcheck.h>
> > +
> > +void
> > +__gcc_vgmc_make_mem_undefined (void *addr, size_t size)
> > +@{
> > +  VALGRIND_MAKE_MEM_UNDEFINED (addr, size);
> > +@}
> > +@end smallexample
> > +
> >  @opindex fvtable-verify
> >  @item -fvtable-verify=@r{[}std@r{|}preinit@r{|}none@r{]}
> >  This option is only available when compiling C++ code.
> > diff --git a/gcc/gimple-valgrind-interop.cc b/gcc/gimple-valgrind-interop.cc
> > new file mode 100644
> > index 0000000000..05d9bdc660
> > --- /dev/null
> > +++ b/gcc/gimple-valgrind-interop.cc
> > @@ -0,0 +1,125 @@
> > +/* Annotate lifetime boundaries for Valgrind.
> > +   Copyright (C) 2023 Free Software Foundation, Inc.
> > +
> > +This file is part of GCC.
> > +
> > +GCC 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, or (at your option) any
> > +later version.
> > +
> > +GCC 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.
> > +
> > +You should have received a copy of the GNU General Public License
> > +along with GCC; see the file COPYING3.  If not see
> > +<http://www.gnu.org/licenses/>.  */
> > +
> > +#include "config.h"
> > +#include "system.h"
> > +#include "coretypes.h"
> > +#include "tree.h"
> > +#include "function.h"
> > +#include "cfg.h"
> > +#include "basic-block.h"
> > +#include "gimple.h"
> > +#include "gimple-iterator.h"
> > +#include "tree-pass.h"
> > +#include "gimplify-me.h"
> > +#include "fold-const.h"
> > +
> > +namespace {
> > +
> > +/* Emit VALGRIND_MAKE_MEM_UNDEFINED annotation for the object given by 
> > VAR.  */
> > +
> > +bool
> > +annotate_undef (gimple_stmt_iterator *gsi, tree var)
> > +{
> > +  tree size = arg_size_in_bytes (TREE_TYPE (var));
> > +  if (size == size_zero_node)
> > +    return false;
> > +
> > +  tree addr = build_fold_addr_expr (var);
> > +  tree decl = builtin_decl_explicit (BUILT_IN_VALGRIND_MAKE_UNDEFINED);
> > +  tree call = build_call_expr (decl, 2, addr, size);
> > +
> > +  force_gimple_operand_gsi (gsi, call, false, NULL_TREE, false, 
> > GSI_NEW_STMT);
> > +  return true;
> > +}
> > +
> > +const pass_data pass_data_instrument_valgrind = {
> > +  GIMPLE_PASS, /* type */
> > +  "valgrind",  /* name */
> > +  OPTGROUP_NONE, /* optinfo_flags */
> > +  TV_NONE, /* tv_id */
> > +  PROP_cfg, /* properties_required */
> > +  0, /* properties_provided */
> > +  0, /* properties_destroyed */
> > +  0, /* todo_flags_start */
> > +  0, /* todo_flags_finish */
> > +};
> > +
> > +}
> > +
> > +class pass_instrument_valgrind : public gimple_opt_pass
> > +{
> > +public:
> > +  pass_instrument_valgrind (gcc::context *ctxt)
> > +    : gimple_opt_pass (pass_data_instrument_valgrind, ctxt)
> > +  {
> > +  }
> > +
> > +  unsigned int execute (function *) final override;
> > +  bool gate (function *) final override;
> > +};
> > +
> > +bool
> > +pass_instrument_valgrind::gate (function *)
> > +{
> > +  return flag_valgrind_annotations;
> > +}
> > +
> > +/* Scan for GIMPLE clobbers that mark object lifetime boundaries and
> > +   make them known to Valgrind by emitting corresponding client requests.  
> > */
> > +
> > +unsigned int
> > +pass_instrument_valgrind::execute (function *fun)
> > +{
> > +  bool changed = false;
> > +  basic_block bb;
> > +  FOR_EACH_BB_FN (bb, fun)
> > +    {
> > +      for (gimple_stmt_iterator gsi = gsi_start_nondebug_bb (bb);
> > +        !gsi_end_p (gsi); gsi_next_nondebug (&gsi))
> > +     {
> > +       gimple *stmt = gsi_stmt (gsi);
> > +
> > +       if (gimple_clobber_p (stmt))
> > +         switch (CLOBBER_KIND (gimple_assign_rhs1 (stmt)))
> > +           {
> > +           case CLOBBER_UNDEF:
> > +           case CLOBBER_OBJECT_BEGIN:
> > +           case CLOBBER_OBJECT_END:
> > +             changed |= annotate_undef (&gsi, gimple_assign_lhs (stmt));
> > +             break;
> > +           case CLOBBER_STORAGE_BEGIN:
> > +           case CLOBBER_STORAGE_END:
> > +             /* Leave these for ASan.  */
> > +             break;
> > +           case CLOBBER_LAST:
> > +           default:
> > +             gcc_unreachable ();
> > +           }
> > +     }
> > +    }
> > +
> > +  return changed ? TODO_update_ssa : 0;
> > +}
> > +
> > +gimple_opt_pass *
> > +make_pass_instrument_valgrind (gcc::context *ctxt)
> > +{
> > +  return new pass_instrument_valgrind (ctxt);
> > +}
> > diff --git a/gcc/passes.def b/gcc/passes.def
> > index 43b416f98f..2274304321 100644
> > --- a/gcc/passes.def
> > +++ b/gcc/passes.def
> > @@ -57,6 +57,7 @@ along with GCC; see the file COPYING3.  If not see
> >    PUSH_INSERT_PASSES_WITHIN (pass_build_ssa_passes)
> >        NEXT_PASS (pass_fixup_cfg);
> >        NEXT_PASS (pass_build_ssa);
> > +      NEXT_PASS (pass_instrument_valgrind);
> >        NEXT_PASS (pass_walloca, /*strict_mode_p=*/true);
> >        NEXT_PASS (pass_warn_printf);
> >        NEXT_PASS (pass_warn_nonnull_compare);
> > diff --git a/gcc/testsuite/g++.dg/valgrind-annotations-1.C 
> > b/gcc/testsuite/g++.dg/valgrind-annotations-1.C
> > new file mode 100644
> > index 0000000000..49dc5a9cf1
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/valgrind-annotations-1.C
> > @@ -0,0 +1,22 @@
> > +/* { dg-do compile { target c++11 } } */
> > +/* { dg-options "-O2 -fvalgrind-annotations -fdump-tree-optimized" } */
> > +
> > +#include <new>
> > +
> > +struct Foo
> > +{
> > +  int val;
> > +};
> > +
> > +struct Bar : Foo
> > +{
> > +  Bar() {}
> > +};
> > +
> > +int main ()
> > +{
> > +  alignas(Bar) char buf [sizeof (Bar)];
> > +  Bar *obj = new(buf) Bar;
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times 
> > "__builtin___gcc_vgmc_make_mem_undefined" 1 "optimized" } } */
> > diff --git a/gcc/testsuite/g++.dg/valgrind-annotations-2.C 
> > b/gcc/testsuite/g++.dg/valgrind-annotations-2.C
> > new file mode 100644
> > index 0000000000..a8b646d076
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/valgrind-annotations-2.C
> > @@ -0,0 +1,12 @@
> > +/* { dg-do compile { target c++11 } } */
> > +/* { dg-options "-O2 -fvalgrind-annotations -fdump-tree-optimized" } */
> > +
> > +struct Foo
> > +{
> > +  char buf [1024];
> > +  Foo () {}
> > +};
> > +
> > +Foo Obj;
> > +
> > +/* { dg-final { scan-tree-dump-times 
> > "__builtin___gcc_vgmc_make_mem_undefined" 1 "optimized" } } */
> > diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
> > index 52fd57fd4c..49de431bd8 100644
> > --- a/gcc/tree-pass.h
> > +++ b/gcc/tree-pass.h
> > @@ -441,6 +441,7 @@ extern gimple_opt_pass *make_pass_omp_device_lower 
> > (gcc::context *ctxt);
> >  extern gimple_opt_pass *make_pass_object_sizes (gcc::context *ctxt);
> >  extern gimple_opt_pass *make_pass_early_object_sizes (gcc::context *ctxt);
> >  extern gimple_opt_pass *make_pass_warn_access (gcc::context *ctxt);
> > +extern gimple_opt_pass *make_pass_instrument_valgrind (gcc::context *ctxt);
> >  extern gimple_opt_pass *make_pass_warn_printf (gcc::context *ctxt);
> >  extern gimple_opt_pass *make_pass_warn_recursion (gcc::context *ctxt);
> >  extern gimple_opt_pass *make_pass_strlen (gcc::context *ctxt);
> > diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
> > index 3f77283490..ea3ba705e9 100644
> > --- a/libgcc/Makefile.in
> > +++ b/libgcc/Makefile.in
> > @@ -436,6 +436,9 @@ LIB2ADD += $(srcdir)/hardcfr.c
> >  # Stack scrubbing infrastructure.
> >  @HAVE_STRUB_SUPPORT@LIB2ADD += $(srcdir)/strub.c
> >
> > +# Wrappers for Valgrind client requests.
> > +LIB2ADD_ST += $(srcdir)/valgrind-interop.c
> > +
> >  # While emutls.c has nothing to do with EH, it is in LIB2ADDEH*
> >  # instead of LIB2ADD because that's the way to be sure on some targets
> >  # (e.g. *-*-darwin*) only one copy of it is linked.
> > diff --git a/libgcc/config.in b/libgcc/config.in
> > index 8f7dd437b0..a77e9411fc 100644
> > --- a/libgcc/config.in
> > +++ b/libgcc/config.in
> > @@ -3,6 +3,9 @@
> >  /* Define to the .hidden-like directive if it exists. */
> >  #undef AS_HIDDEN_DIRECTIVE
> >
> > +/* Build Valgrind request wrappers */
> > +#undef ENABLE_VALGRIND_INTEROP
> > +
> >  /* Define to 1 if the assembler supports AVX. */
> >  #undef HAVE_AS_AVX
> >
> > @@ -64,6 +67,9 @@
> >  /* Define to 1 if you have the <unistd.h> header file. */
> >  #undef HAVE_UNISTD_H
> >
> > +/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
> > +#undef HAVE_VALGRIND_MEMCHECK_H
> > +
> >  /* Define to 1 if __getauxval is available. */
> >  #undef HAVE___GETAUXVAL
> >
> > diff --git a/libgcc/configure b/libgcc/configure
> > index 3671d9b1a1..431c028af9 100755
> > --- a/libgcc/configure
> > +++ b/libgcc/configure
> > @@ -716,6 +716,7 @@ with_system_libunwind
> >  enable_cet
> >  enable_explicit_exception_frame_registration
> >  enable_tm_clone_registry
> > +enable_valgrind_interop
> >  with_glibc_version
> >  enable_tls
> >  with_gcc_major_version_only
> > @@ -1360,6 +1361,8 @@ Optional Features:
> >                            start, for use e.g. for compatibility with
> >                            installations without PT_GNU_EH_FRAME support
> >    --disable-tm-clone-registry    disable TM clone registry
> > +  --enable-valgrind-interop
> > +                          build wrappers for Valgrind client requests
> >    --enable-tls            Use thread-local storage [default=yes]
> >
> >  Optional Packages:
> > @@ -4467,7 +4470,8 @@ as_fn_arith $ac_cv_sizeof_long_double \* 8 && 
> > long_double_type_size=$as_val
> >
> >  for ac_header in inttypes.h stdint.h stdlib.h ftw.h \
> >       unistd.h sys/stat.h sys/types.h \
> > -     string.h strings.h memory.h sys/auxv.h sys/mman.h
> > +     string.h strings.h memory.h sys/auxv.h sys/mman.h \
> > +     valgrind/memcheck.h
> >  do :
> >    as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
> >  ac_fn_c_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header"
> > @@ -5025,6 +5029,22 @@ fi
> >
> >
> >
> > +# Check whether --enable-valgrind-interop was given.
> > +if test "${enable_valgrind_interop+set}" = set; then :
> > +  enableval=$enable_valgrind_interop;
> > +else
> > +  enable_valgrind_interop=no
> > +fi
> > +
> > +if test $enable_valgrind_interop != no; then
> > +  if test $ac_cv_header_valgrind_memcheck_h = no; then
> > +    as_fn_error $? "--enable-valgrind-interop: valgrind/memcheck.h not 
> > found" "$LINENO" 5
> > +  fi
> > +
> > +$as_echo "#define ENABLE_VALGRIND_INTEROP 1" >>confdefs.h
> > +
> > +fi
> > +
> >  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is 
> > GNU ld" >&5
> >  $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
> >  if ${acl_cv_prog_gnu_ld+:} false; then :
> > diff --git a/libgcc/configure.ac b/libgcc/configure.ac
> > index 467f5e63ef..d19f5e7e84 100644
> > --- a/libgcc/configure.ac
> > +++ b/libgcc/configure.ac
> > @@ -231,7 +231,8 @@ AC_SUBST(long_double_type_size)
> >
> >  AC_CHECK_HEADERS(inttypes.h stdint.h stdlib.h ftw.h \
> >       unistd.h sys/stat.h sys/types.h \
> > -     string.h strings.h memory.h sys/auxv.h sys/mman.h)
> > +     string.h strings.h memory.h sys/auxv.h sys/mman.h \
> > +     valgrind/memcheck.h)
> >  AC_HEADER_STDC
> >
> >  # Check for decimal float support.
> > @@ -303,6 +304,18 @@ esac
> >  ])
> >  AC_SUBST([use_tm_clone_registry])
> >
> > +AC_ARG_ENABLE([valgrind-interop],
> > +              [AC_HELP_STRING([--enable-valgrind-interop],
> > +                              [build wrappers for Valgrind client 
> > requests])],
> > +              [],
> > +              [enable_valgrind_interop=no])
> > +if test $enable_valgrind_interop != no; then
> > +  if test $ac_cv_header_valgrind_memcheck_h = no; then
> > +    AC_MSG_ERROR([--enable-valgrind-interop: valgrind/memcheck.h not 
> > found])
> > +  fi
> > +  AC_DEFINE(ENABLE_VALGRIND_INTEROP, 1, [Build Valgrind request wrappers])
> > +fi
> > +
> >  AC_LIB_PROG_LD_GNU
> >
> >  AC_MSG_CHECKING([for thread model used by GCC])
> > diff --git a/libgcc/libgcc2.h b/libgcc/libgcc2.h
> > index 750670e8ca..ee4500adc1 100644
> > --- a/libgcc/libgcc2.h
> > +++ b/libgcc/libgcc2.h
> > @@ -558,6 +558,8 @@ extern void __strub_enter (void **);
> >  extern void __strub_update (void**);
> >  extern void __strub_leave (void **);
> >
> > +extern void __gcc_vgmc_make_mem_undefined (void *, size_t);
> > +
> >  #ifndef HIDE_EXPORTS
> >  #pragma GCC visibility pop
> >  #endif
> > diff --git a/libgcc/valgrind-interop.c b/libgcc/valgrind-interop.c
> > new file mode 100644
> > index 0000000000..fdb8d41bc5
> > --- /dev/null
> > +++ b/libgcc/valgrind-interop.c
> > @@ -0,0 +1,40 @@
> > +/* Wrappers for Valgrind client requests.
> > +   Copyright (C) 2023 Free Software Foundation, Inc.
> > +
> > +This file is part of GCC.
> > +
> > +GCC 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, or (at your option) any later
> > +version.
> > +
> > +GCC 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 "tsystem.h"
> > +#include "auto-target.h"
> > +
> > +#ifdef ENABLE_VALGRIND_INTEROP
> > +
> > +#include <valgrind/memcheck.h>
> > +
> > +/* Externally callable wrapper for Valgrind Memcheck client request:
> > +   declare SIZE bytes of memory at address ADDR as uninitialized.  */
> > +
> > +void
> > +__gcc_vgmc_make_mem_undefined (void *addr, size_t size)
> > +{
> > +  VALGRIND_MAKE_MEM_UNDEFINED (addr, size);
> > +}
> > +#endif
> >

Reply via email to