From patchwork Fri Dec 22 14:10:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Monakov X-Patchwork-Id: 82762 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6909A3858C36 for ; Fri, 22 Dec 2023 14:11:07 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail.ispras.ru (mail.ispras.ru [83.149.199.84]) by sourceware.org (Postfix) with ESMTPS id AEC323858C60 for ; Fri, 22 Dec 2023 14:10:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AEC323858C60 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=ispras.ru Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=ispras.ru ARC-Filter: OpenARC Filter v1.0.0 sourceware.org AEC323858C60 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=83.149.199.84 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703254252; cv=none; b=wrAOFcUwIIMrIUxKrv3ucMJa9dGP5NF9sfK3P20FVO8SKYTeGqF0mchW9+Y/epfxsV2tNZl/5MbWjaInE5iJsB345neS/lAm3npL65wwh5fHhexcLTMnpW6pAhHnqDalKchfY2ao037up2QuxWw7tfy5hGMZGGvXLIu2uwdf0wg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1703254252; c=relaxed/simple; bh=U+C7KKj8xqOyZ9zD1BkUjUHnowUr6RaJnma0jFlc4UI=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=PMa2CvlMnxbwE4MNVfuwd2mUHtv/S/3YRFhiWEtXlSwjTRc8bOu0sI9UEqLRDAC9d2vbfdrIhDQi9KxTLZBDXZi1AhtlzE/jpg7G8yxWcQmZszW9gv+q57LJjkMmwz+hkLew7AR+gNhe3qv/s7VwoRou4+0c8sNVgvryClx9SNg= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from localhost.intra.ispras.ru (unknown [10.10.3.121]) by mail.ispras.ru (Postfix) with ESMTP id 1ABA140F1DCA; Fri, 22 Dec 2023 14:10:47 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.ispras.ru 1ABA140F1DCA From: Alexander Monakov To: gcc-patches@gcc.gnu.org Cc: =?utf-8?q?Arsen_Arsenovi=C4=87?= , Sam James , Daniil Frolov , Alexander Monakov Subject: [PATCH v2] object lifetime instrumentation for Valgrind [PR66487] Date: Fri, 22 Dec 2023 17:10:38 +0300 Message-Id: <20231222141038.6657-1-amonakov@ispras.ru> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20231208134950.14883-1-amonakov@ispras.ru> References: <20231208134950.14883-1-amonakov@ispras.ru> MIME-Version: 1.0 X-Spam-Status: No, score=-9.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org From: Daniil Frolov 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 --- 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 + +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 +. */ + +#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 + +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 header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the 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 +. */ + +#include "tsystem.h" +#include "auto-target.h" + +#ifdef ENABLE_VALGRIND_INTEROP + +#include + +/* 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