From patchwork Tue Oct 24 14:11:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniil Frolov X-Patchwork-Id: 78468 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 A8C883858020 for ; Tue, 24 Oct 2023 14:12: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 348453858D37 for ; Tue, 24 Oct 2023 14:11:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 348453858D37 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 348453858D37 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=1698156711; cv=none; b=gBoZVuIqdsPASJj5ta4bqZDpHvW0Vel69Fv16u7GoR07OBNPMNh3yXzZC2Dgljm5/eZbyrUiwJFZTVu9DASSwAIW+zumYjRAUauai8LheCI6acadMVl/Y9fBchLRygksPFqkN9lJe/1eddd+xikhxfZqgANYRtYg6/VGgER40N0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698156711; c=relaxed/simple; bh=wamyNZUJcuwA8J/rRUhiJCoHsOAQEYp9gTlU/ZhuGPk=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=WPIqGKcWZdjgZQ6E3zPaOu+Aklz/yv1bztl9VCbBxSVN68ZzI9gkI3j29YvCs65TlSAGBWRdQXiSnQ9ZTUlqI/kZyLW64Q5Hw8NwMXGNVG7D+ppBtDxJ1uc3MRcgPIzMS3RBaEHNO48Kqyi2n05fJtwZCWKRSmq0jrSE3oaLD74= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from exactlywb-BOD-WXX9.ispras.ru (unknown [83.149.199.86]) by mail.ispras.ru (Postfix) with ESMTP id D5F3440762E4; Tue, 24 Oct 2023 14:11:46 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 mail.ispras.ru D5F3440762E4 From: exactlywb@ispras.ru To: gcc-patches@gcc.gnu.org Cc: amonakov@ispras.ru, Daniil Frolov Subject: [RFC PATCH] Detecting lifetime-dse issues via Valgrind Date: Tue, 24 Oct 2023 17:11:24 +0300 Message-Id: <20231024141124.210708-1-exactlywb@ispras.ru> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP 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 in Firefox, LLVM, OpenJade. 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, we need to wrap it in a built-in. We know that implementing such a built-in in libgcc is undesirable, ideally contents of libgcc should not depend on availability of external headers. Suggestion for cleaner solutions would be welcome. gcc/ChangeLog: * Makefile.in: Add gimple-valgrind.o. * builtins.def (BUILT_IN_VALGRIND_MEM_UNDEF): Add new built-in. * common.opt: Add new option. * passes.def: Add new pass. * tree-pass.h (make_pass_emit_valgrind): New function. * gimple-valgrind.cc: New file. libgcc/ChangeLog: * Makefile.in: Add valgrind.o. * config.in: Regenerate. * configure: Regenerate. * configure.ac: Add option --enable-valgrind-annotations into libgcc config. * libgcc2.h (__valgrind_make_mem_undefined): New function. * valgrind.c: New file. --- gcc/Makefile.in | 1 + gcc/builtins.def | 1 + gcc/common.opt | 4 ++ gcc/gimple-valgrind.cc | 124 +++++++++++++++++++++++++++++++++++++++++ gcc/passes.def | 1 + gcc/tree-pass.h | 1 + libgcc/Makefile.in | 2 +- libgcc/config.in | 9 +++ libgcc/configure | 79 ++++++++++++++++++++++++++ libgcc/configure.ac | 48 ++++++++++++++++ libgcc/libgcc2.h | 1 + libgcc/valgrind.c | 50 +++++++++++++++++ 12 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 gcc/gimple-valgrind.cc create mode 100644 libgcc/valgrind.c diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 9cc16268abf..ded6bdf1673 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1487,6 +1487,7 @@ OBJS = \ gimple-ssa-warn-access.o \ gimple-ssa-warn-alloca.o \ gimple-ssa-warn-restrict.o \ + gimple-valgrind.o \ gimple-streamer-in.o \ gimple-streamer-out.o \ gimple-walk.o \ diff --git a/gcc/builtins.def b/gcc/builtins.def index 5953266acba..42d34189f1e 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -1064,6 +1064,7 @@ DEF_GCC_BUILTIN (BUILT_IN_VA_END, "va_end", BT_FN_VOID_VALIST_REF, ATTR_N DEF_GCC_BUILTIN (BUILT_IN_VA_START, "va_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_VA_ARG_PACK, "va_arg_pack", BT_FN_INT, ATTR_PURE_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_VA_ARG_PACK_LEN, "va_arg_pack_len", BT_FN_INT, ATTR_PURE_NOTHROW_LEAF_LIST) +DEF_EXT_LIB_BUILTIN (BUILT_IN_VALGRIND_MEM_UNDEF, "__valgrind_make_mem_undefined", BT_FN_VOID_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN__EXIT, "_exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN__EXIT2, "_Exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LEAF_LIST) diff --git a/gcc/common.opt b/gcc/common.opt index f137a1f81ac..c9040386956 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2515,6 +2515,10 @@ starts and when the destructor finishes. flifetime-dse= Common Joined RejectNegative UInteger Var(flag_lifetime_dse) Optimization IntegerRange(0, 2) +fvalgrind-emit-annotations +Common Var(flag_valgrind_annotations,1) +Emit Valgrind annotations with respect to object's lifetime. + flive-patching Common RejectNegative Alias(flive-patching=,inline-clone) Optimization diff --git a/gcc/gimple-valgrind.cc b/gcc/gimple-valgrind.cc new file mode 100644 index 00000000000..8075e6404d4 --- /dev/null +++ b/gcc/gimple-valgrind.cc @@ -0,0 +1,124 @@ +/* Emit 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. + +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 "backend.h" +#include "tree.h" +#include "gimple.h" +#include "gimple-iterator.h" +#include "tree-pass.h" +#include "gimplify-me.h" +#include "fold-const.h" + +namespace { + +/* Interface for emitting a call for __valgrind_make_mem_undefined. This + function returns true if the call was successfully emitted and false + otherwise. */ + +bool +emit_builtin_memory_undefined (gimple_stmt_iterator *gsi, gimple *stmt) +{ + tree var_ptr, call; + tree lhs = gimple_assign_lhs (stmt); + tree sizet = arg_size_in_bytes (TREE_TYPE (lhs)); + if (sizet == size_zero_node) + return false; + + var_ptr = build_fold_addr_expr (lhs); + call = build_call_expr (builtin_decl_explicit (BUILT_IN_VALGRIND_MEM_UNDEF), + 2, var_ptr, sizet); + force_gimple_operand_gsi (gsi, call, false, NULL_TREE, false, GSI_NEW_STMT); + + return true; +} + +const pass_data pass_data_emit_valgrind = { + GIMPLE_PASS, /* type */ + "emit_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_emit_valgrind : public gimple_opt_pass +{ +public: + pass_emit_valgrind (gcc::context *ctxt) + : gimple_opt_pass (pass_data_emit_valgrind, ctxt) + { + } + + unsigned int execute (function *) final override; + bool gate (function *) final override; +}; + +bool +pass_emit_valgrind::gate (function *) +{ + return flag_valgrind_annotations; +} + +/* Valgrind does not know about lifetime violations because of it is working in + machine code level. There are special Valgrind client requests like + VALGRIND_MAKE_MEM_UNDEFINED, VALGRIND_MAKE_MEM_NOACCESS etc. to mark memory + especially. + + This pass emits such annotations automatically. */ + +unsigned int +pass_emit_valgrind::execute (function *fun) +{ + bool todo = 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); + /* GCC emits special clobber gimple instructions with respect to + lifetime of memory like: + + x ={v} {CLOBBER}; + + Insert __builtin_valgrind_make_mem_undefined after such statement + to trigger lifetime violations in Valgrind. */ + if (gimple_clobber_p (stmt)) + todo |= emit_builtin_memory_undefined (&gsi, stmt); + } + } + + return todo ? TODO_update_ssa : 0; +} + +gimple_opt_pass * +make_pass_emit_valgrind (gcc::context *ctxt) +{ + return new pass_emit_valgrind (ctxt); +} + diff --git a/gcc/passes.def b/gcc/passes.def index 4110a472914..c7fb47db864 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -56,6 +56,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_emit_valgrind); NEXT_PASS (pass_walloca, /*strict_mode_p=*/true); NEXT_PASS (pass_warn_printf); NEXT_PASS (pass_warn_nonnull_compare); diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index eba2d54ac76..b8797b465e3 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -440,6 +440,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_emit_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 7ee8b5f9bcb..56cb8a9d903 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -428,7 +428,7 @@ ifneq ($(enable_shared),yes) iterator = $(patsubst %,$(srcdir)/static-object.mk,$(iter-items)) endif -LIB2ADD += enable-execute-stack.c +LIB2ADD += enable-execute-stack.c $(srcdir)/valgrind.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 diff --git a/libgcc/config.in b/libgcc/config.in index f93c64a00c3..278d6e94817 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 +/* Define to get calls to the valgrind runtime enabled. */ +#undef ENABLE_VALGRIND_ANNOTATIONS + /* Define to 1 if the assembler supports AVX. */ #undef HAVE_AS_AVX @@ -28,6 +31,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define if valgrind's memcheck.h header is installed. */ +#undef HAVE_MEMCHECK_H + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H @@ -61,6 +67,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Define if valgrind's valgrind/memcheck.h header is installed. */ +#undef HAVE_VALGRIND_MEMCHECK_H + /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT diff --git a/libgcc/configure b/libgcc/configure index cf149209652..98f5bffb293 100755 --- a/libgcc/configure +++ b/libgcc/configure @@ -713,6 +713,7 @@ enable_largefile enable_decimal_float with_system_libunwind enable_cet +enable_valgrind_annotations enable_explicit_exception_frame_registration enable_tm_clone_registry with_glibc_version @@ -1354,6 +1355,8 @@ Optional Features: or 'dpd' choses which decimal floating point format to use --enable-cet enable Intel CET in target libraries [default=auto] + --enable-valgrind-annotations + enable valgrind runtime interaction --enable-explicit-exception-frame-registration register exception tables explicitly at module start, for use e.g. for compatibility with @@ -4987,6 +4990,82 @@ fi +ac_fn_c_check_header_preproc "$LINENO" "valgrind.h" "ac_cv_header_valgrind_h" +if test "x$ac_cv_header_valgrind_h" = xyes; then : + have_valgrind_h=yes +else + have_valgrind_h=no +fi + + +# It is certainly possible that there's valgrind but no valgrind.h. +# GCC relies on making annotations so we must have both. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in " >&5 +$as_echo_n "checking for VALGRIND_DISCARD in ... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#ifndef VALGRIND_DISCARD +#error VALGRIND_DISCARD not defined +#endif +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + gcc_cv_header_valgrind_memcheck_h=yes +else + gcc_cv_header_valgrind_memcheck_h=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_valgrind_memcheck_h" >&5 +$as_echo "$gcc_cv_header_valgrind_memcheck_h" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in " >&5 +$as_echo_n "checking for VALGRIND_DISCARD in ... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#ifndef VALGRIND_DISCARD +#error VALGRIND_DISCARD not defined +#endif +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + gcc_cv_header_memcheck_h=yes +else + gcc_cv_header_memcheck_h=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_memcheck_h" >&5 +$as_echo "$gcc_cv_header_memcheck_h" >&6; } +if test $gcc_cv_header_valgrind_memcheck_h = yes; then + +$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h + +fi +if test $gcc_cv_header_memcheck_h = yes; then + +$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h + +fi + +# Check whether --enable-valgrind-annotations was given. +if test "${enable_valgrind_annotations+set}" = set; then : + enableval=$enable_valgrind_annotations; +else + enable_valgrind_annotations=no +fi + +if test x$enable_valgrind_annotations != xno \ + || test x$ac_valgrind_checking != x; then + if (test $have_valgrind_h = no \ + && test $gcc_cv_header_memcheck_h = no \ + && test $gcc_cv_header_valgrind_memcheck_h = no); then + as_fn_error $? "*** valgrind annotations requested, but" "$LINENO" 5 + as_fn_error $? "*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5 + fi + +$as_echo "#define ENABLE_VALGRIND_ANNOTATIONS 1" >>confdefs.h + +fi + + # Check whether --enable-explicit-exception-frame-registration was given. if test "${enable_explicit_exception_frame_registration+set}" = set; then : enableval=$enable_explicit_exception_frame_registration; diff --git a/libgcc/configure.ac b/libgcc/configure.ac index 2fc9d5d7c93..6054581f41f 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -269,6 +269,54 @@ GCC_CHECK_SJLJ_EXCEPTIONS GCC_CET_FLAGS(CET_FLAGS) AC_SUBST(CET_FLAGS) +AC_CHECK_HEADER(valgrind.h, have_valgrind_h=yes, have_valgrind_h=no) + +# It is certainly possible that there's valgrind but no valgrind.h. +# GCC relies on making annotations so we must have both. +AC_MSG_CHECKING(for VALGRIND_DISCARD in ) +AC_PREPROC_IFELSE([AC_LANG_SOURCE( + [[#include +#ifndef VALGRIND_DISCARD +#error VALGRIND_DISCARD not defined +#endif]])], + [gcc_cv_header_valgrind_memcheck_h=yes], + [gcc_cv_header_valgrind_memcheck_h=no]) +AC_MSG_RESULT($gcc_cv_header_valgrind_memcheck_h) +AC_MSG_CHECKING(for VALGRIND_DISCARD in ) +AC_PREPROC_IFELSE([AC_LANG_SOURCE( + [[#include +#ifndef VALGRIND_DISCARD +#error VALGRIND_DISCARD not defined +#endif]])], + [gcc_cv_header_memcheck_h=yes], + [gcc_cv_header_memcheck_h=no]) +AC_MSG_RESULT($gcc_cv_header_memcheck_h) +if test $gcc_cv_header_valgrind_memcheck_h = yes; then + AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1, + [Define if valgrind's valgrind/memcheck.h header is installed.]) +fi +if test $gcc_cv_header_memcheck_h = yes; then + AC_DEFINE(HAVE_MEMCHECK_H, 1, + [Define if valgrind's memcheck.h header is installed.]) +fi + +AC_ARG_ENABLE(valgrind-annotations, +[AS_HELP_STRING([--enable-valgrind-annotations], + [enable valgrind runtime interaction])], [], +[enable_valgrind_annotations=no]) +if test x$enable_valgrind_annotations != xno \ + || test x$ac_valgrind_checking != x; then + if (test $have_valgrind_h = no \ + && test $gcc_cv_header_memcheck_h = no \ + && test $gcc_cv_header_valgrind_memcheck_h = no); then + AC_MSG_ERROR([*** valgrind annotations requested, but]) + AC_MSG_ERROR([*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h]) + fi + AC_DEFINE(ENABLE_VALGRIND_ANNOTATIONS, 1, +[Define to get calls to the valgrind runtime enabled.]) +fi + + AC_ARG_ENABLE([explicit-exception-frame-registration], [AC_HELP_STRING([--enable-explicit-exception-frame-registration], [register exception tables explicitly at module start, for use diff --git a/libgcc/libgcc2.h b/libgcc/libgcc2.h index 06e26cad884..af37ae7d816 100644 --- a/libgcc/libgcc2.h +++ b/libgcc/libgcc2.h @@ -31,6 +31,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see extern int __gcc_bcmp (const unsigned char *, const unsigned char *, size_t); extern void __clear_cache (void *, void *); +extern void __valgrind_make_mem_undefined (void *ptr, unsigned long sz); extern void __eprintf (const char *, const char *, unsigned int, const char *) __attribute__ ((__noreturn__)); diff --git a/libgcc/valgrind.c b/libgcc/valgrind.c new file mode 100644 index 00000000000..a64e22d0cb3 --- /dev/null +++ b/libgcc/valgrind.c @@ -0,0 +1,50 @@ +/* Implement interface 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 "tconfig.h" +#include "tsystem.h" +#include "auto-target.h" + +#ifdef ENABLE_VALGRIND_ANNOTATIONS +# ifdef HAVE_VALGRIND_MEMCHECK_H +# include +# elif defined HAVE_MEMCHECK_H +# include +# else +# include +# endif +/* Compatibility macros to let valgrind 3.1 work. */ +# ifndef VALGRIND_MAKE_MEM_UNDEFINED +# define VALGRIND_MAKE_MEM_UNDEFINED VALGRIND_MAKE_WRITABLE +# endif +/* Abort if ENABLE_VALGRIND_ANNOTATIONS is not defined. */ +#else +# define VALGRIND_MAKE_MEM_UNDEFINED(ptr, sz) __builtin_trap () +#endif + +void __valgrind_make_mem_undefined (void *ptr, unsigned long sz) +{ + VALGRIND_MAKE_MEM_UNDEFINED (ptr, sz); +} +