]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add inner requests in VEX
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Thu, 27 Jul 2017 19:10:30 +0000 (19:10 +0000)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Thu, 27 Jul 2017 19:10:30 +0000 (19:10 +0000)
When running Valgrind under Valgrind, the VEX memory allocation
(temporary or permanent) was not checked, as there was no
inner request.
This patch changes VEX to mark the temporary and permanent
allocations with redzone, and memory is marked unaddressable
when the VEX temporary pool is cleared.

The changes are:
* add a file libvex_inner.h which mostly takes over what
  was in pub_core_inner.h (which now just includes libvex_inner.h)

* modify main_util.h and main_util.c to mark the temporary
  and permanent pool with memcheck pool requests to indicate
  when a block is allocated or freed.

* Impact is (should be) none, unless Valgrind is configured
  as an inner.

* Outer memcheck/inner regression tests run on gcc20 (amd64).
  Nothing (more worrying than the 3.13 self hosting) detected

git-svn-id: svn://svn.valgrind.org/vex/trunk@3399

VEX/priv/main_util.c
VEX/priv/main_util.h
VEX/pub/libvex_inner.h [new file with mode: 0644]

index 4e0494b62f6be5669f25c3744f502f1a00766481..865fe0c7a79027c8e492b4fc4d17e976c9b2470d 100644 (file)
    into memory, the rate falls by about a factor of 3. 
 */
 
+#if defined(ENABLE_INNER)
+/* 5 times more memory to be on the safe side:  consider each allocation is
+   8 bytes, and we need 16 bytes redzone before and after. */
+#define N_TEMPORARY_BYTES (5*5000000)
+static Bool mempools_created = False;
+#else
 #define N_TEMPORARY_BYTES 5000000
+#endif
 
 static HChar  temporary[N_TEMPORARY_BYTES] __attribute__((aligned(REQ_ALIGN)));
 static HChar* temporary_first = &temporary[0];
@@ -61,7 +68,12 @@ static HChar* temporary_last  = &temporary[N_TEMPORARY_BYTES-1];
 
 static ULong  temporary_bytes_allocd_TOT = 0;
 
+#if defined(ENABLE_INNER)
+/* See N_TEMPORARY_BYTES */
+#define N_PERMANENT_BYTES (5*10000)
+#else
 #define N_PERMANENT_BYTES 10000
+#endif
 
 static HChar  permanent[N_PERMANENT_BYTES] __attribute__((aligned(REQ_ALIGN)));
 static HChar* permanent_first = &permanent[0];
@@ -178,6 +190,18 @@ void vexSetAllocModeTEMP_and_clear ( void )
    temporary_bytes_allocd_TOT 
       += (ULong)(private_LibVEX_alloc_curr - private_LibVEX_alloc_first);
 
+#if defined(ENABLE_INNER)
+   if (mempools_created) {
+      VALGRIND_MEMPOOL_TRIM(&temporary[0], &temporary[0], 0);
+   } else {
+      VALGRIND_CREATE_MEMPOOL(&temporary[0], VEX_REDZONE_SIZEB, 0);
+      VALGRIND_CREATE_MEMPOOL(&permanent[0], VEX_REDZONE_SIZEB, 0);
+      VALGRIND_MAKE_MEM_NOACCESS(&permanent[0], N_PERMANENT_BYTES);
+      mempools_created = True;
+   }
+   VALGRIND_MAKE_MEM_NOACCESS(&temporary[0], N_TEMPORARY_BYTES);
+#endif
+
    mode = VexAllocModeTEMP;
    temporary_curr            = &temporary[0];
    private_LibVEX_alloc_curr = &temporary[0];
index 8627d1f8e0354f938c3bed172b5b9735f4561d88..82b9a5f1e6d54ba9cd4240345e8ae8ea548dbd8c 100644 (file)
 
 #include "libvex_basictypes.h"
 
+#include "libvex_inner.h"
+#if defined(ENABLE_INNER_CLIENT_REQUEST)
+/* Including here memcheck include file is kind of a hack, but this is needed
+   to have self-hosting checking VEX. Note however that this is included only
+   when Valgrind and VEX are configured using --enable-inner. */
+#include "memcheck/memcheck.h"
+#endif
 
 /* Misc. */
 
@@ -129,6 +136,10 @@ extern void   private_LibVEX_alloc_OOM(void) __attribute__((noreturn));
    boundary. */
 #define REQ_ALIGN 8
 
+#if defined(ENABLE_INNER)
+#define VEX_REDZONE_SIZEB (2*REQ_ALIGN)
+#endif
+
 static inline void* LibVEX_Alloc_inline ( SizeT nbytes )
 {
    struct align {
@@ -160,12 +171,15 @@ static inline void* LibVEX_Alloc_inline ( SizeT nbytes )
    HChar* next;
    SizeT  ALIGN;
    ALIGN  = offsetof(struct align,x) - 1;
-   nbytes = (nbytes + ALIGN) & ~ALIGN;
    curr   = private_LibVEX_alloc_curr;
-   next   = curr + nbytes;
+   next   = curr + ((nbytes + ALIGN) & ~ALIGN);
+   INNER_REQUEST(next += 2 * VEX_REDZONE_SIZEB);
    if (next >= private_LibVEX_alloc_last)
       private_LibVEX_alloc_OOM();
    private_LibVEX_alloc_curr = next;
+   INNER_REQUEST(curr += VEX_REDZONE_SIZEB);
+   INNER_REQUEST(VALGRIND_MEMPOOL_ALLOC(private_LibVEX_alloc_first,
+                                        curr, nbytes));
    return curr;
 #endif
 }
diff --git a/VEX/pub/libvex_inner.h b/VEX/pub/libvex_inner.h
new file mode 100644 (file)
index 0000000..9fb563e
--- /dev/null
@@ -0,0 +1,73 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Utilities for inner Valgrind                  libvex_inner.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2017-2017 Philippe Waroquiers
+      philippe.waroquiers@skynet.be
+
+   This program 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 2 of the
+   License, or (at your option) any later version.
+
+   This program 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 this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __LIBVEX_INNER_H
+#define __LIBVEX_INNER_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This header should be imported by every  file in Valgrind
+// which needs specific behaviour when running as an "inner" Valgrind.
+// Valgrind can self-host itself (i.e. Valgrind can run Valgrind) :
+// The outer Valgrind executes the inner Valgrind.
+// For more details, see README_DEVELOPPERS.
+//--------------------------------------------------------------------
+
+#include "config.h" 
+
+// The code of the inner Valgrind (core or tool code) contains client
+// requests (e.g. from helgrind.h, memcheck.h, ...) to help the
+// outer Valgrind finding (relevant) errors in the inner Valgrind.
+// Such client requests should only be compiled in for an inner Valgrind.
+// Use the macro INNER_REQUEST to allow a central enabling/disabling
+// of these client requests.
+#if defined(ENABLE_INNER)
+
+// By default, the inner Valgrind annotates various actions to help
+// the outer tool (memcheck or helgrind).
+// Undefine the below to have an inner Valgrind without any annotation.
+#define ENABLE_INNER_CLIENT_REQUEST 1
+
+#if defined(ENABLE_INNER_CLIENT_REQUEST)
+#define INNER_REQUEST(__zza)  __zza
+#else
+#define INNER_REQUEST(__zza)  do {} while (0)
+#endif
+
+#else
+
+#define INNER_REQUEST(__zza)  do {} while (0)
+
+#endif
+
+#endif   // __LIBVEX_INNER_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/