- bad size for functions that have implementation defined behaviour
when the requested size is zero
+* Cachegrind:
+ - You can now profile part of a program's execution using the new
+ `CACHEGRIND_START_INSTRUMENTATION` and `CACHEGRIND_STOP_INSTRUMENTATION`
+ client requests, along with the new `--instr-at-start` option. The
+ behaviour is the same as Callgrind's equivalent functionality.
+
* ==================== FIXED BUGS ====================
The following bugs have been fixed or resolved. Note that "n-i-bz"
# Headers, etc
#----------------------------------------------------------------------------
+pkginclude_HEADERS = cachegrind.h
+
bin_SCRIPTS = cg_annotate cg_diff cg_merge
noinst_HEADERS = \
--- /dev/null
+/*
+ ----------------------------------------------------------------
+
+ Notice that the following BSD-style license applies to this one
+ file (cachegrind.h) only. The rest of Valgrind is licensed under the
+ terms of the GNU General Public License, version 2, unless
+ otherwise indicated. See the COPYING file in the source
+ distribution for details.
+
+ ----------------------------------------------------------------
+
+ This file is part of Cachegrind, a high-precision tracing profiler
+ built with Valgrind.
+
+ Copyright (C) 2023-2023 Nicholas Nethercote. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ----------------------------------------------------------------
+
+ Notice that the above BSD-style license applies to this one file
+ (cachegrind.h) only. The entire rest of Valgrind is licensed under
+ the terms of the GNU General Public License, version 2. See the
+ COPYING file in the source distribution for details.
+
+ ----------------------------------------------------------------
+*/
+
+#ifndef __CACHEGRIND_H
+#define __CACHEGRIND_H
+
+#include "valgrind.h"
+
+/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
+ This enum comprises an ABI exported by Valgrind to programs
+ which use client requests. DO NOT CHANGE THE ORDER OF THESE
+ ENTRIES, NOR DELETE ANY -- add new ones at the end.
+ */
+
+typedef
+ enum {
+ /* The `CG_` is required to distinguish these from the Callgrind
+ * client requests of the same name. Otherwise compile errors occur if
+ * you include both `cachegrind.h` and `callgrind.h`.
+ */
+ VG_USERREQ__CG_START_INSTRUMENTATION = VG_USERREQ_TOOL_BASE('C','G'),
+ VG_USERREQ__CG_STOP_INSTRUMENTATION
+ } Vg_CachegrindClientRequest;
+
+/* Start Cachegrind instrumentation if not already enabled. Use this
+ * in combination with `CACHEGRIND_STOP_INSTRUMENTATION` and
+ * `--instr-at-start` to measure only part of a client program's
+ * execution.
+ */
+#define CACHEGRIND_START_INSTRUMENTATION \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CG_START_INSTRUMENTATION, \
+ 0, 0, 0, 0, 0)
+
+/* Stop Cachegrind instrumentation if not already disabled. Use this
+ * in combination with `CACHEGRIND_START_INSTRUMENTATION` and
+ * `--instr-at-start` to measure only part of a client program's
+ * execution.
+ */
+#define CACHEGRIND_STOP_INSTRUMENTATION \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CG_STOP_INSTRUMENTATION, \
+ 0, 0, 0, 0, 0)
+
+#endif /* __CACHEGRIND_H */
+
This file is part of Cachegrind, a high-precision tracing profiler
built with Valgrind.
- Copyright (C) 2002-2017 Nicholas Nethercote
+ Copyright (C) 2002-2023 Nicholas Nethercote
njn@valgrind.org
This program is free software; you can redistribute it and/or
#include "pub_tool_options.h"
#include "pub_tool_oset.h"
#include "pub_tool_tooliface.h"
+#include "pub_tool_transtab.h"
#include "pub_tool_xarray.h"
#include "pub_tool_clientstate.h"
#include "pub_tool_machine.h" // VG_(fnptr_to_fnentry)
+#include "cachegrind.h"
#include "cg_arch.h"
#include "cg_sim.c"
#include "cg_branchpred.c"
static Bool clo_cache_sim = False; /* do cache simulation? */
static Bool clo_branch_sim = False; /* do branch simulation? */
+static Bool clo_instr_at_start = True; /* instrument at startup? */
static const HChar* clo_cachegrind_out_file = "cachegrind.out.%p";
/*------------------------------------------------------------*/
static Int fn_debugs = 0;
static Int no_debugs = 0;
+//------------------------------------------------------------
+// Instrumentation control
+static Bool instr_enabled = True;
+
/*------------------------------------------------------------*/
/*--- String table operations ---*/
/*------------------------------------------------------------*/
VG_(tool_panic)("host/guest word size mismatch");
}
+ if (!instr_enabled) {
+ return sbIn;
+ }
+
// Set up new SB
cgs.sbOut = deepCopyIRSBExceptStmts(sbIn);
static
void cg_discard_superblock_info ( Addr orig_addr64, VexGuestExtents vge )
{
- SB_info* sbInfo;
- Addr orig_addr = vge.base[0];
+ Addr orig_addr = vge.base[0];
tl_assert(vge.n_used > 0);
(void*)orig_addr,
(void*)vge.base[0], (ULong)vge.len[0]);
- // Get BB info, remove from table, free BB info. Simple! Note that we
- // use orig_addr, not the first instruction address in vge.
- sbInfo = VG_(OSetGen_Remove)(instrInfoTable, &orig_addr);
- tl_assert(NULL != sbInfo);
- VG_(OSetGen_FreeNode)(instrInfoTable, sbInfo);
+ // Get SB info, remove from table, free SB info. Simple! Unless
+ // instrumentation is currently disabled, in which case we won't have an SB
+ // info. Note that we use orig_addr, not the first instruction address in
+ // `vge`.
+ SB_info* sbInfo = VG_(OSetGen_Remove)(instrInfoTable, &orig_addr);
+ if (sbInfo) {
+ tl_assert(instr_enabled);
+ VG_(OSetGen_FreeNode)(instrInfoTable, sbInfo);
+ } else {
+ tl_assert(!instr_enabled);
+ }
}
/*--------------------------------------------------------------------*/
else if VG_STR_CLO( arg, "--cachegrind-out-file", clo_cachegrind_out_file) {}
else if VG_BOOL_CLO(arg, "--cache-sim", clo_cache_sim) {}
else if VG_BOOL_CLO(arg, "--branch-sim", clo_branch_sim) {}
+ else if VG_BOOL_CLO(arg, "--instr-at-start", clo_instr_at_start) {}
else
return False;
" --cachegrind-out-file=<file> output file name [cachegrind.out.%%p]\n"
" --cache-sim=yes|no collect cache stats? [no]\n"
" --branch-sim=yes|no collect branch prediction stats? [no]\n"
+" --instr-at-start=yes|no instrument at start? [yes]\n"
);
VG_(print_cache_clo_opts)();
}
);
}
+/*--------------------------------------------------------------------*/
+/*--- Client requests ---*/
+/*--------------------------------------------------------------------*/
+
+static void set_instr_enabled(Bool enable)
+{
+ if (enable) {
+ // Enable instrumentation.
+ if (!instr_enabled) {
+ // Discard first, then update `instr_enabled`;
+ // `cg_discard_superblock_info` relies on that.
+ VG_(discard_translations_safely)((Addr)0x1000, ~(SizeT)0xfff, "cachegrind");
+ instr_enabled = True;
+ } else {
+ VG_(dmsg)("warning: CACHEGRIND_START_INSTRUMENTATION called,\n");
+ VG_(dmsg)(" but instrumentation is already enabled\n");
+ }
+ } else {
+ // Disable instrumentation.
+ if (instr_enabled) {
+ // Discard first, then update `instr_enabled`;
+ // `cg_discard_superblock_info` relies on that.
+ VG_(discard_translations_safely)((Addr)0x1000, ~(SizeT)0xfff, "cachegrind");
+ instr_enabled = False;
+ } else {
+ VG_(dmsg)("warning: CACHEGRIND_STOP_INSTRUMENTATION called,\n");
+ VG_(dmsg)(" but instrumentation is already disabled\n");
+ }
+ }
+}
+
+static Bool cg_handle_client_request(ThreadId tid, UWord *args, UWord *ret)
+{
+ if (!VG_IS_TOOL_USERREQ('C', 'G', args[0])
+ && VG_USERREQ__GDB_MONITOR_COMMAND != args[0])
+ return False;
+
+ switch(args[0]) {
+ case VG_USERREQ__CG_START_INSTRUMENTATION:
+ set_instr_enabled(True);
+ *ret = 0;
+ return True;
+
+ case VG_USERREQ__CG_STOP_INSTRUMENTATION:
+ set_instr_enabled(False);
+ *ret = 0;
+ return True;
+
+ default:
+ return False;
+ }
+}
+
/*--------------------------------------------------------------------*/
/*--- Setup ---*/
/*--------------------------------------------------------------------*/
VG_(needs_command_line_options)(cg_process_cmd_line_option,
cg_print_usage,
cg_print_debug_usage);
+ VG_(needs_client_requests)(cg_handle_client_request);
}
static void cg_post_clo_init(void)
cachesim_initcaches(I1c, D1c, LLc);
}
+
+ // When instrumentation client requests are enabled, we start with
+ // instrumentation off.
+ if (!clo_instr_at_start) {
+ instr_enabled = False;
+ }
}
VG_DETERMINE_INTERFACE_VERSION(cg_pre_clo_init)
</listitem>
</varlistentry>
+ <varlistentry id="opt.instr-at-start" xreflabel="--instr-at-start">
+ <term>
+ <option><![CDATA[--instr-at-start=no|yes [yes] ]]></option>
+ </term>
+ <listitem>
+ <para>
+ Enables or disables instrumentation at the start of execution.
+ Use this in combination with
+ <computeroutput>CACHEGRIND_START_INSTRUMENTATION</computeroutput> and
+ <computeroutput>CACHEGRIND_STOP_INSTRUMENTATION</computeroutput> to
+ measure only part of a client program's execution.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="cg.opt.I1" xreflabel="--I1">
<term>
<option><![CDATA[--I1=<size>,<associativity>,<line size> ]]></option>
</sect1>
+<sect1 id="cg-manual.clientrequests" xreflabel="Client requests">
+<title>Cachegrind Client Requests</title>
+
+<para>Cachegrind provides the following client requests in
+<filename>cachegrind.h</filename>.
+</para>
+
+<variablelist id="cg.clientrequests.list">
+
+ <varlistentry id="cg.cr.start-instr" xreflabel="CACHEGRIND_START_INSTRUMENTATION">
+ <term>
+ <computeroutput>CACHEGRIND_START_INSTRUMENTATION</computeroutput>
+ </term>
+ <listitem>
+ <para>Start Cachegrind instrumentation if not already enabled. Use this
+ in combination with
+ <computeroutput>CACHEGRIND_STOP_INSTRUMENTATION</computeroutput> and
+ <option><link linkend="opt.instr-at-start">--instr-at-start</link></option>
+ to measure only part of a client program's execution.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry id="cg.cr.stop-instr" xreflabel="CACHEGRIND_STOP_INSTRUMENTATION">
+ <term>
+ <computeroutput>CACHEGRIND_STOP_INSTRUMENTATION</computeroutput>
+ </term>
+ <listitem>
+ <para>Stop Cachegrind instrumentation if not already disabled. Use this
+ in combination with
+ <computeroutput>CACHEGRIND_START_INSTRUMENTATION</computeroutput> and
+ <option><link linkend="opt.instr-at-start">--instr-at-start</link></option>
+ to measure only part of a client program's execution.
+ </para>
+ </listitem>
+ </varlistentry>
+
+</variablelist>
+
+</sect1>
+
+
<sect1 id="cg-manual.sim-details"
xreflabel="Simulation Details">
<title>Simulation Details</title>
DIST_SUBDIRS = x86 .
-dist_noinst_SCRIPTS = filter_stderr filter_cachesim_discards
+dist_noinst_SCRIPTS = \
+ filter_stderr \
+ filter_cachesim_discards \
+ filter_clreq3
# Note that `test.c` and `a.c` are not compiled.
# They just serve as input for cg_annotate in `ann1a` and `ann1b`.
ann2-negatives.rs ann2-past-the-end.rs \
chdir.vgtest chdir.stderr.exp \
clreq.vgtest clreq.stderr.exp \
+ clreq2a.vgtest clreq2a.stderr.exp \
+ clreq2b.vgtest clreq2b.stderr.exp \
+ clreq3.vgtest clreq3.stderr.exp \
dlclose.vgtest dlclose.stderr.exp dlclose.stdout.exp \
notpower2.vgtest notpower2.stderr.exp \
test.c a.c \
wrap5.vgtest wrap5.stderr.exp wrap5.stdout.exp
check_PROGRAMS = \
- chdir clreq dlclose myprint.so
+ chdir clreq clreq2 dlclose myprint.so
AM_CFLAGS += $(AM_FLAG_M3264_PRI)
AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
--- /dev/null
+// This is not a thorough test, but at least it's something. It's hard to do
+// much better because the exact number of instructions executed is
+// unpredictable.
+
+#include "../cachegrind.h"
+
+int main(void) {
+ CACHEGRIND_START_INSTRUMENTATION; // warning with `--instr-at-start=yes`
+ CACHEGRIND_STOP_INSTRUMENTATION;
+ CACHEGRIND_START_INSTRUMENTATION;
+ CACHEGRIND_START_INSTRUMENTATION; // warning
+ CACHEGRIND_STOP_INSTRUMENTATION;
+ CACHEGRIND_STOP_INSTRUMENTATION; // warning
+}
--- /dev/null
+warning: CACHEGRIND_START_INSTRUMENTATION called,
+ but instrumentation is already enabled
+warning: CACHEGRIND_START_INSTRUMENTATION called,
+ but instrumentation is already enabled
+warning: CACHEGRIND_STOP_INSTRUMENTATION called,
+ but instrumentation is already disabled
--- /dev/null
+prog: clreq2
+vgopts: -q --instr-at-start=yes
+cleanup: rm cachegrind.out.*
--- /dev/null
+warning: CACHEGRIND_START_INSTRUMENTATION called,
+ but instrumentation is already enabled
+warning: CACHEGRIND_STOP_INSTRUMENTATION called,
+ but instrumentation is already disabled
--- /dev/null
+prog: clreq2
+vgopts: -q --instr-at-start=no
+cleanup: rm cachegrind.out.*
--- /dev/null
+
+
+I refs: 0
--- /dev/null
+# Test that `--instr-at-start=no` results in zero instruction counts.
+prog: ../../tests/true
+vgopts: --instr-at-start=no
+stderr_filter: filter_clreq3
+cleanup: rm cachegrind.out.*
--- /dev/null
+#! /bin/sh
+
+dir=`dirname $0`
+
+$dir/../../tests/filter_stderr_basic |
+
+# Remove "Cachegrind, ..." line and the following copyright line.
+sed "/^Cachegrind, a high-precision tracing profiler/ , /./ d"