1734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--------------------------------------------------------------------*/ 2734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Massif: a heap profiling tool. ms_main.c ---*/ 3734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--------------------------------------------------------------------*/ 4c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 5c9f3692175ba544ecef6f905f5dcd755c3b153benethercote/* 6996901a830e8e7c3fd8be8f0c675c71f2b108957nethercote This file is part of Massif, a Valgrind tool for profiling memory 7c9f3692175ba544ecef6f905f5dcd755c3b153benethercote usage of programs. 8c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 90f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj Copyright (C) 2003-2013 Nicholas Nethercote 102bc10126a94b421a490b2759dc50ab67ec4ee116njn njn@valgrind.org 11c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 12c9f3692175ba544ecef6f905f5dcd755c3b153benethercote This program is free software; you can redistribute it and/or 13c9f3692175ba544ecef6f905f5dcd755c3b153benethercote modify it under the terms of the GNU General Public License as 14c9f3692175ba544ecef6f905f5dcd755c3b153benethercote published by the Free Software Foundation; either version 2 of the 15c9f3692175ba544ecef6f905f5dcd755c3b153benethercote License, or (at your option) any later version. 16c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 17c9f3692175ba544ecef6f905f5dcd755c3b153benethercote This program is distributed in the hope that it will be useful, but 18c9f3692175ba544ecef6f905f5dcd755c3b153benethercote WITHOUT ANY WARRANTY; without even the implied warranty of 19c9f3692175ba544ecef6f905f5dcd755c3b153benethercote MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20c9f3692175ba544ecef6f905f5dcd755c3b153benethercote General Public License for more details. 21c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 22c9f3692175ba544ecef6f905f5dcd755c3b153benethercote You should have received a copy of the GNU General Public License 23c9f3692175ba544ecef6f905f5dcd755c3b153benethercote along with this program; if not, write to the Free Software 24c9f3692175ba544ecef6f905f5dcd755c3b153benethercote Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 25c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 02111-1307, USA. 26c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 27c9f3692175ba544ecef6f905f5dcd755c3b153benethercote The GNU General Public License is contained in the file COPYING. 28c9f3692175ba544ecef6f905f5dcd755c3b153benethercote*/ 29c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 30734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--------------------------------------------------------------------------- 31734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// XXX: 32734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--------------------------------------------------------------------------- 33734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Todo -- nice, but less critical: 34ab23b615fc56c1bf47fb04d62188932291c3a871njn// - do a graph-drawing test 35734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - make file format more generic. Obstacles: 36734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - unit prefixes are not generic 37734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - preset column widths for stats are not generic 38734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - preset column headers are not generic 39734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - "Massif arguments:" line is not generic 40868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe// - do snapshots on some specific client requests 41734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - "show me the extra allocations since the last snapshot" 42734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - "start/stop logging" (eg. quickly skip boring bits) 43734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - Add ability to draw multiple graphs, eg. heap-only, stack-only, total. 44734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Give each graph a title. (try to do it generically!) 45734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - make --show-below-main=no work 46a15b6661220b7ae6d4e417030eb5bd348f08ea20njn// - Options like --alloc-fn='operator new(unsigned, std::nothrow_t const&)' 471a2741aad64315cd5da0cc877f474d53af16b5a3njn// don't work in a .valgrindrc file or in $VALGRIND_OPTS. 481a2741aad64315cd5da0cc877f474d53af16b5a3njn// m_commandline.c:add_args_from_string() needs to respect single quotes. 493b677e56014e94554456bb24853849cec228d617njn// - With --stack=yes, want to add a stack trace for detailed snapshots so 503b677e56014e94554456bb24853849cec228d617njn// it's clear where/why the peak is occurring. (Mattieu Castet) Also, 513b677e56014e94554456bb24853849cec228d617njn// possibly useful even with --stack=no? (Andi Yin) 52734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 53734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Performance: 54734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - To run the benchmarks: 55734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 56734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// perl perf/vg_perf --tools=massif --reps=3 perf/{heap,tinycc} massif 57734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// time valgrind --tool=massif --depth=100 konqueror 58734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 59734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// The other benchmarks don't do much allocation, and so give similar speeds 60734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// to Nulgrind. 61734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 62734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Timing results on 'nevermore' (njn's machine) as of r7013: 63734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 64734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// heap 0.53s ma:12.4s (23.5x, -----) 65734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// tinycc 0.46s ma: 4.9s (10.7x, -----) 66734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// many-xpts 0.08s ma: 2.0s (25.0x, -----) 67734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// konqueror 29.6s real 0:21.0s user 68734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 69ab23b615fc56c1bf47fb04d62188932291c3a871njn// [Introduction of --time-unit=i as the default slowed things down by 70ab23b615fc56c1bf47fb04d62188932291c3a871njn// roughly 0--20%.] 71ab23b615fc56c1bf47fb04d62188932291c3a871njn// 72734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - get_XCon accounts for about 9% of konqueror startup time. Try 73734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// keeping XPt children sorted by 'ip' and use binary search in get_XCon. 74734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Requires factoring out binary search code from various places into a 75734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// VG_(bsearch) function. 76734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 77734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Todo -- low priority: 78734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - In each XPt, record both bytes and the number of allocations, and 79734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// possibly the global number of allocations. 800f85e029aec63c86bfe51360acee949b71e08600njn// - (Andy Lin) Give a stack trace on detailed snapshots? 81734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - (Artur Wisz) add a feature to Massif to ignore any heap blocks larger 82734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// than a certain size! Because: "linux's malloc allows to set a 83734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// MMAP_THRESHOLD value, so we set it to 4096 - all blocks above that will 84734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// be handled directly by the kernel, and are guaranteed to be returned to 85734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// the system when freed. So we needed to profile only blocks below this 86734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// limit." 87734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 88734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// File format working notes: 89734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 90734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#if 0 91734b805cb3af82ddd7d3ba22a0e22aba29b78305njndesc: --heap-admin=foo 92734b805cb3af82ddd7d3ba22a0e22aba29b78305njncmd: date 93734b805cb3af82ddd7d3ba22a0e22aba29b78305njntime_unit: ms 94734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#----------- 95734b805cb3af82ddd7d3ba22a0e22aba29b78305njnsnapshot=0 96734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#----------- 97734b805cb3af82ddd7d3ba22a0e22aba29b78305njntime=0 98734b805cb3af82ddd7d3ba22a0e22aba29b78305njnmem_heap_B=0 99734b805cb3af82ddd7d3ba22a0e22aba29b78305njnmem_heap_admin_B=0 100734b805cb3af82ddd7d3ba22a0e22aba29b78305njnmem_stacks_B=0 101734b805cb3af82ddd7d3ba22a0e22aba29b78305njnheap_tree=empty 102734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#----------- 103734b805cb3af82ddd7d3ba22a0e22aba29b78305njnsnapshot=1 104734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#----------- 105734b805cb3af82ddd7d3ba22a0e22aba29b78305njntime=353 106734b805cb3af82ddd7d3ba22a0e22aba29b78305njnmem_heap_B=5 107734b805cb3af82ddd7d3ba22a0e22aba29b78305njnmem_heap_admin_B=0 108734b805cb3af82ddd7d3ba22a0e22aba29b78305njnmem_stacks_B=0 109734b805cb3af82ddd7d3ba22a0e22aba29b78305njnheap_tree=detailed 110734b805cb3af82ddd7d3ba22a0e22aba29b78305njnn1: 5 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. 111734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n1: 5 0x27F6E0: _nl_normalize_codeset (in /lib/libc-2.3.5.so) 112734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n1: 5 0x279DE6: _nl_load_locale_from_archive (in /lib/libc-2.3.5.so) 113734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n1: 5 0x278E97: _nl_find_locale (in /lib/libc-2.3.5.so) 114734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n1: 5 0x278871: setlocale (in /lib/libc-2.3.5.so) 115734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n1: 5 0x8049821: (within /bin/date) 116734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n0: 5 0x26ED5E: (below main) (in /lib/libc-2.3.5.so) 117734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 118734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 119734b805cb3af82ddd7d3ba22a0e22aba29b78305njnn_events: n time(ms) total(B) useful-heap(B) admin-heap(B) stacks(B) 120734b805cb3af82ddd7d3ba22a0e22aba29b78305njnt_events: B 121734b805cb3af82ddd7d3ba22a0e22aba29b78305njnn 0 0 0 0 0 122734b805cb3af82ddd7d3ba22a0e22aba29b78305njnn 0 0 0 0 0 123734b805cb3af82ddd7d3ba22a0e22aba29b78305njnt1: 5 <string...> 124734b805cb3af82ddd7d3ba22a0e22aba29b78305njn t1: 6 <string...> 125734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 126734b805cb3af82ddd7d3ba22a0e22aba29b78305njnIdeas: 127734b805cb3af82ddd7d3ba22a0e22aba29b78305njn- each snapshot specifies an x-axis value and one or more y-axis values. 128734b805cb3af82ddd7d3ba22a0e22aba29b78305njn- can display the y-axis values separately if you like 129734b805cb3af82ddd7d3ba22a0e22aba29b78305njn- can completely separate connection between snapshots and trees. 130734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 131734b805cb3af82ddd7d3ba22a0e22aba29b78305njnChallenges: 132734b805cb3af82ddd7d3ba22a0e22aba29b78305njn- how to specify and scale/abbreviate units on axes? 133734b805cb3af82ddd7d3ba22a0e22aba29b78305njn- how to combine multiple values into the y-axis? 134734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 135734b805cb3af82ddd7d3ba22a0e22aba29b78305njn--------------------------------------------------------------------------------Command: date 136734b805cb3af82ddd7d3ba22a0e22aba29b78305njnMassif arguments: --heap-admin=foo 137734b805cb3af82ddd7d3ba22a0e22aba29b78305njnms_print arguments: massif.out 138734b805cb3af82ddd7d3ba22a0e22aba29b78305njn-------------------------------------------------------------------------------- 139734b805cb3af82ddd7d3ba22a0e22aba29b78305njn KB 140734b805cb3af82ddd7d3ba22a0e22aba29b78305njn6.472^ :# 141734b805cb3af82ddd7d3ba22a0e22aba29b78305njn | :# :: . . 142734b805cb3af82ddd7d3ba22a0e22aba29b78305njn ... 143734b805cb3af82ddd7d3ba22a0e22aba29b78305njn | ::@ :@ :@ :@:::# :: : :::: 144734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 0 +-----------------------------------@---@---@-----@--@---#-------------->ms 0 713 145734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 146734b805cb3af82ddd7d3ba22a0e22aba29b78305njnNumber of snapshots: 50 147734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Detailed snapshots: [2, 11, 13, 19, 25, 32 (peak)] 148734b805cb3af82ddd7d3ba22a0e22aba29b78305njn-------------------------------------------------------------------------------- n time(ms) total(B) useful-heap(B) admin-heap(B) stacks(B) 149734b805cb3af82ddd7d3ba22a0e22aba29b78305njn-------------------------------------------------------------------------------- 0 0 0 0 0 0 150734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1 345 5 5 0 0 151734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2 353 5 5 0 0 152734b805cb3af82ddd7d3ba22a0e22aba29b78305njn100.00% (5B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. 153734b805cb3af82ddd7d3ba22a0e22aba29b78305njn->100.00% (5B) 0x27F6E0: _nl_normalize_codeset (in /lib/libc-2.3.5.so) 154734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#endif 155734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 156734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--------------------------------------------------------------------------- 157c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 158c7561b931e249acf3768ead77638545b0ccaa8f1njn#include "pub_tool_basics.h" 1594cfea4f9480393ed6799db463b2e0fb8865a1a2fsewardj#include "pub_tool_vki.h" 16045f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_tool_aspacemgr.h" 161ea27e4627518665dd6c81213c0ba1f7ff0218e1anjn#include "pub_tool_debuginfo.h" 16281c00df9ac724e898179dd90e52b2e15deb11fd8njn#include "pub_tool_hashtable.h" 16397405b2d134b52880d6dbec3eb2929e2002c2542njn#include "pub_tool_libcbase.h" 164132bfccd21960e462352175f8553a5bdce8a210cnjn#include "pub_tool_libcassert.h" 165eb8896b58301a0a7a34281384d705072994369f0njn#include "pub_tool_libcfile.h" 16636a20fa5f779a0a6fb7b4a90dcaa6376481f1faanjn#include "pub_tool_libcprint.h" 167f39e9a36dca9642668a66c6b054f81c88650bcb9njn#include "pub_tool_libcproc.h" 168b506bd863e6cab5aea7cc4bea2ac3bc19a781b56njn#include "pub_tool_machine.h" 169717cde5bda18d17792d1994c61b6a27408b4b4a7njn#include "pub_tool_mallocfree.h" 1702024234c590f408994b373abfb00bc2cd2a90c48njn#include "pub_tool_options.h" 171717cde5bda18d17792d1994c61b6a27408b4b4a7njn#include "pub_tool_replacemalloc.h" 172d01fef7de693582a6ce32bdbef7c9040ad6b356bnjn#include "pub_tool_stacktrace.h" 173e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn#include "pub_tool_threadstate.h" 17443b9a8abb139b86a24457fa3c19b9cb60ca17c3anjn#include "pub_tool_tooliface.h" 17514c7cc5a5fbe9526329f058116f921988efe679esewardj#include "pub_tool_xarray.h" 17645f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include "pub_tool_clientstate.h" 1773b290486cd4cd601b20e04340e593c9ed9717e5fsewardj#include "pub_tool_gdbserver.h" 178c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1791a046d5a3c34f924b648cc22c01f0a8e02ca221eflorian#include "pub_tool_clreq.h" // For {MALLOC,FREE}LIKE_BLOCK 180c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 181734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------*/ 182734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Overview of operation ---*/ 183734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------*/ 184c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 185734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// The size of the stacks and heap is tracked. The heap is tracked in a lot 186734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// of detail, enough to tell how many bytes each line of code is responsible 187734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// for, more or less. The main data structure is a tree representing the 188734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// call tree beneath all the allocation functions like malloc(). 189e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// (Alternatively, if --pages-as-heap=yes is specified, memory is tracked at 190e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// the page level, and each page is treated much like a heap block. We use 191e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// "heap" throughout below to cover this case because the concepts are all the 192e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// same.) 193c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// 194734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// "Snapshots" are recordings of the memory usage. There are two basic 195734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// kinds: 196734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - Normal: these record the current time, total memory size, total heap 197734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// size, heap admin size and stack size. 198734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - Detailed: these record those things in a normal snapshot, plus a very 199734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// detailed XTree (see below) indicating how the heap is structured. 200c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// 201734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Snapshots are taken every so often. There are two storage classes of 202734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// snapshots: 203734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - Temporary: Massif does a temporary snapshot every so often. The idea 204734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// is to always have a certain number of temporary snapshots around. So 205734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// we take them frequently to begin with, but decreasingly often as the 206734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// program continues to run. Also, we remove some old ones after a while. 207734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Overall it's a kind of exponential decay thing. Most of these are 208734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// normal snapshots, a small fraction are detailed snapshots. 209734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - Permanent: Massif takes a permanent (detailed) snapshot in some 210734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// circumstances. They are: 211734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - Peak snapshot: When the memory usage peak is reached, it takes a 212734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// snapshot. It keeps this, unless the peak is subsequently exceeded, 213734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// in which case it will overwrite the peak snapshot. 214734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - User-requested snapshots: These are done in response to client 215734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// requests. They are always kept. 216734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 217734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Used for printing things when clo_verbosity > 1. 218734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#define VERB(verb, format, args...) \ 219734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (VG_(clo_verbosity) > verb) { \ 2205ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VG_(dmsg)("Massif: " format, ##args); \ 221c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 222c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 223734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 224734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Statistics ---// 225734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 226c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 227c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// Konqueror startup, to give an idea of the numbers involved with a biggish 228c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// program, with default depth: 229c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// 230c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// depth=3 depth=40 231c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// - 310,000 allocations 232c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// - 300,000 frees 233c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// - 15,000 XPts 800,000 XPts 234c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// - 1,800 top-XPts 235c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 236f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_heap_allocs = 0; 237f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_heap_reallocs = 0; 238f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_heap_frees = 0; 239f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_ignored_heap_allocs = 0; 240f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_ignored_heap_frees = 0; 241f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_ignored_heap_reallocs = 0; 242f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_stack_allocs = 0; 243f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_stack_frees = 0; 244f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_xpts = 0; 245f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_xpt_init_expansions = 0; 246f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_xpt_later_expansions = 0; 247f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_sxpt_allocs = 0; 248f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_sxpt_frees = 0; 249f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_skipped_snapshots = 0; 250f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_real_snapshots = 0; 251f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_detailed_snapshots = 0; 252f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_peak_snapshots = 0; 253f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_cullings = 0; 254f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic UInt n_XCon_redos = 0; 255734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 256734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 257734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Globals ---// 258734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 259734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2601a2741aad64315cd5da0cc877f474d53af16b5a3njn// Number of guest instructions executed so far. Only used with 2611a2741aad64315cd5da0cc877f474d53af16b5a3njn// --time-unit=i. 2621a2741aad64315cd5da0cc877f474d53af16b5a3njnstatic Long guest_instrs_executed = 0; 2631a2741aad64315cd5da0cc877f474d53af16b5a3njn 26432397c0c26fd49181e87a409ad986b9e1b5b0dfdnjnstatic SizeT heap_szB = 0; // Live heap size 26532397c0c26fd49181e87a409ad986b9e1b5b0dfdnjnstatic SizeT heap_extra_szB = 0; // Live heap extra size -- slop + admin bytes 26632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjnstatic SizeT stacks_szB = 0; // Live stacks size 267734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 268734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// This is the total size from the current peak snapshot, or 0 if no peak 269734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// snapshot has been taken yet. 270734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic SizeT peak_snapshot_total_szB = 0; 271734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 272734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Incremented every time memory is allocated/deallocated, by the 273734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// allocated/deallocated amount; includes heap, heap-admin and stack 274734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// memory. An alternative to milliseconds as a unit of program "time". 275734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic ULong total_allocs_deallocs_szB = 0; 276c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 277e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// When running with --heap=yes --pages-as-heap=no, we don't start taking 278e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// snapshots until the first basic block is executed, rather than doing it in 279e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// ms_post_clo_init (which is the obvious spot), for two reasons. 280734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - It lets us ignore stack events prior to that, because they're not 281734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// really proper ones and just would screw things up. 282734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - Because there's still some core initialisation to do, and so there 283734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// would be an artificial time gap between the first and second snapshots. 284734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 285e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// When running with --heap=yes --pages-as-heap=yes, snapshots start much 286e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// earlier due to new_mem_startup so this isn't relevant. 287e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn// 288734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic Bool have_started_executing_code = False; 289c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 290734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 291734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Alloc fns ---// 292734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 293c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 294734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic XArray* alloc_fns; 295f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic XArray* ignore_fns; 296c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 297734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void init_alloc_fns(void) 298734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 299734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Create the list, and add the default elements. 3009c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj alloc_fns = VG_(newXA)(VG_(malloc), "ms.main.iaf.1", 30119f91bbaedb4caef8a60ce94b0f507193cc0bc10florian VG_(free), sizeof(HChar*)); 3026bd9dc18c043927c1196caba20a327238a179c42florian #define DO(x) { const HChar* s = x; VG_(addToXA)(alloc_fns, &s); } 303734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 30413118f8b1ae7c0161df02d527cd802287e731a62njn // Ordered roughly according to (presumed) frequency. 305734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Nb: The C++ "operator new*" ones are overloadable. We include them 306734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // always anyway, because even if they're overloaded, it would be a 307734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // prodigiously stupid overloading that caused them to not allocate 308734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // memory. 309343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // 310343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // XXX: because we don't look at the first stack entry (unless it's a 311343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // custom allocation) there's not much point to having all these alloc 312343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // functions here -- they should never appear anywhere (I think?) other 313343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // than the top stack entry. The only exceptions are those that in 314343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // vg_replace_malloc.c are partly or fully implemented in terms of another 315343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // alloc function: realloc (which uses malloc); valloc, 316343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // malloc_zone_valloc, posix_memalign and memalign_common (which use 317343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // memalign). 318343a504d2c37a4dabd0241fd0e46d79a677f52a0njn // 319734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("malloc" ); 320734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("__builtin_new" ); 321734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("operator new(unsigned)" ); 322734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("operator new(unsigned long)" ); 323734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("__builtin_vec_new" ); 324734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("operator new[](unsigned)" ); 325734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("operator new[](unsigned long)" ); 326734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("calloc" ); 327734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("realloc" ); 328734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("memalign" ); 32913118f8b1ae7c0161df02d527cd802287e731a62njn DO("posix_memalign" ); 33013118f8b1ae7c0161df02d527cd802287e731a62njn DO("valloc" ); 331734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("operator new(unsigned, std::nothrow_t const&)" ); 332734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("operator new[](unsigned, std::nothrow_t const&)" ); 333734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("operator new(unsigned long, std::nothrow_t const&)" ); 334734b805cb3af82ddd7d3ba22a0e22aba29b78305njn DO("operator new[](unsigned long, std::nothrow_t const&)"); 3356e9de463ef677f093e9f24f126e1b11c28cf59fdsewardj#if defined(VGO_darwin) 33613118f8b1ae7c0161df02d527cd802287e731a62njn DO("malloc_zone_malloc" ); 33713118f8b1ae7c0161df02d527cd802287e731a62njn DO("malloc_zone_calloc" ); 33813118f8b1ae7c0161df02d527cd802287e731a62njn DO("malloc_zone_realloc" ); 33913118f8b1ae7c0161df02d527cd802287e731a62njn DO("malloc_zone_memalign" ); 34013118f8b1ae7c0161df02d527cd802287e731a62njn DO("malloc_zone_valloc" ); 34113118f8b1ae7c0161df02d527cd802287e731a62njn#endif 342734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 343c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 344f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic void init_ignore_fns(void) 345734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 346f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Create the (empty) list. 347f6b0076ba64f5c22f9e09be70c351a9d4b095883njn ignore_fns = VG_(newXA)(VG_(malloc), "ms.main.iif.1", 34819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian VG_(free), sizeof(HChar*)); 349f6b0076ba64f5c22f9e09be70c351a9d4b095883njn} 350f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 351f6b0076ba64f5c22f9e09be70c351a9d4b095883njn// Determines if the named function is a member of the XArray. 35246cc04521acf2827eb33310fadc119bf2dc039e4florianstatic Bool is_member_fn(const XArray* fns, const HChar* fnname) 353f6b0076ba64f5c22f9e09be70c351a9d4b095883njn{ 35419f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar** fn_ptr; 355734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int i; 356734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 357734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Nb: It's a linear search through the list, because we're comparing 358734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // strings rather than pointers to strings. 359734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Nb: This gets called a lot. It was an OSet, but they're quite slow to 360734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // iterate through so it wasn't a good choice. 361f6b0076ba64f5c22f9e09be70c351a9d4b095883njn for (i = 0; i < VG_(sizeXA)(fns); i++) { 362f6b0076ba64f5c22f9e09be70c351a9d4b095883njn fn_ptr = VG_(indexXA)(fns, i); 363f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (VG_STREQ(fnname, *fn_ptr)) 364734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return True; 365734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 366734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return False; 367734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 368c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 369c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 370734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 371734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Command line args ---// 372734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 373c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 374734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#define MAX_DEPTH 200 375c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 3761a2741aad64315cd5da0cc877f474d53af16b5a3njntypedef enum { TimeI, TimeMS, TimeB } TimeUnit; 377c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 378e58e8a7a82f81c9237e7cae9a1b70a31dec67d36florianstatic const HChar* TimeUnit_to_string(TimeUnit time_unit) 379734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 380734b805cb3af82ddd7d3ba22a0e22aba29b78305njn switch (time_unit) { 3811a2741aad64315cd5da0cc877f474d53af16b5a3njn case TimeI: return "i"; 382734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case TimeMS: return "ms"; 383734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case TimeB: return "B"; 384734b805cb3af82ddd7d3ba22a0e22aba29b78305njn default: tl_assert2(0, "TimeUnit_to_string: unrecognised TimeUnit"); 385c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 386734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 387c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 388e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic Bool clo_heap = True; 389429afb4dd4ef1fc17845f82132772b7a18c98e5bnjn // clo_heap_admin is deliberately a word-sized type. At one point it was 390429afb4dd4ef1fc17845f82132772b7a18c98e5bnjn // a UInt, but this caused problems on 64-bit machines when it was 391429afb4dd4ef1fc17845f82132772b7a18c98e5bnjn // multiplied by a small negative number and then promoted to a 392429afb4dd4ef1fc17845f82132772b7a18c98e5bnjn // word-sized type -- it ended up with a value of 4.2 billion. Sigh. 393efc13c21199dbb35ad07a5e00d538aa884863c01njnstatic SSizeT clo_heap_admin = 8; 394e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic Bool clo_pages_as_heap = False; 39562721e90cec685b202424719f7237620e2c5780dnjnstatic Bool clo_stacks = False; 39683df0b67a14425c484d8dda42b53f3ff0b598894njnstatic Int clo_depth = 30; 39762721e90cec685b202424719f7237620e2c5780dnjnstatic double clo_threshold = 1.0; // percentage 39862721e90cec685b202424719f7237620e2c5780dnjnstatic double clo_peak_inaccuracy = 1.0; // percentage 39983df0b67a14425c484d8dda42b53f3ff0b598894njnstatic Int clo_time_unit = TimeI; 40083df0b67a14425c484d8dda42b53f3ff0b598894njnstatic Int clo_detailed_freq = 10; 40183df0b67a14425c484d8dda42b53f3ff0b598894njnstatic Int clo_max_snapshots = 100; 40219f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic const HChar* clo_massif_out_file = "massif.out.%p"; 403734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 404734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic XArray* args_for_massif; 405c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 40619f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic Bool ms_process_cmd_line_option(const HChar* arg) 407c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 40819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian const HChar* tmp_str; 40983df0b67a14425c484d8dda42b53f3ff0b598894njn 410734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Remember the arg for later use. 411734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(addToXA)(args_for_massif, &arg); 412734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 413e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if VG_BOOL_CLO(arg, "--heap", clo_heap) {} 414e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_BINT_CLO(arg, "--heap-admin", clo_heap_admin, 0, 1024) {} 415734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 416e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_BOOL_CLO(arg, "--stacks", clo_stacks) {} 417734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 418e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_BOOL_CLO(arg, "--pages-as-heap", clo_pages_as_heap) {} 419734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 420e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_BINT_CLO(arg, "--depth", clo_depth, 1, MAX_DEPTH) {} 421c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 422e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_STR_CLO(arg, "--alloc-fn", tmp_str) { 42383df0b67a14425c484d8dda42b53f3ff0b598894njn VG_(addToXA)(alloc_fns, &tmp_str); 424c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 425e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_STR_CLO(arg, "--ignore-fn", tmp_str) { 426f6b0076ba64f5c22f9e09be70c351a9d4b095883njn VG_(addToXA)(ignore_fns, &tmp_str); 427f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } 428e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 429b1cc5d666cc8f8065419e4a8c819ed0b8256a764njn else if VG_DBL_CLO(arg, "--threshold", clo_threshold) { 430b1cc5d666cc8f8065419e4a8c819ed0b8256a764njn if (clo_threshold < 0 || clo_threshold > 100) { 431b1cc5d666cc8f8065419e4a8c819ed0b8256a764njn VG_(fmsg_bad_option)(arg, 432b1cc5d666cc8f8065419e4a8c819ed0b8256a764njn "--threshold must be between 0.0 and 100.0\n"); 433b1cc5d666cc8f8065419e4a8c819ed0b8256a764njn } 434b1cc5d666cc8f8065419e4a8c819ed0b8256a764njn } 435e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 436e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_DBL_CLO(arg, "--peak-inaccuracy", clo_peak_inaccuracy) {} 437e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 438e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_XACT_CLO(arg, "--time-unit=i", clo_time_unit, TimeI) {} 439e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_XACT_CLO(arg, "--time-unit=ms", clo_time_unit, TimeMS) {} 440e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_XACT_CLO(arg, "--time-unit=B", clo_time_unit, TimeB) {} 441e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 442e006e6f3046b3a53137489f89d6045cf709f6786njn else if VG_BINT_CLO(arg, "--detailed-freq", clo_detailed_freq, 1, 1000000) {} 443e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 444e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn else if VG_BINT_CLO(arg, "--max-snapshots", clo_max_snapshots, 10, 1000) {} 445e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 44683df0b67a14425c484d8dda42b53f3ff0b598894njn else if VG_STR_CLO(arg, "--massif-out-file", clo_massif_out_file) {} 447f4c665fc4cbfb05ed0b31364270b00334cbd1f18njn 448c9f3692175ba544ecef6f905f5dcd755c3b153benethercote else 449c9f3692175ba544ecef6f905f5dcd755c3b153benethercote return VG_(replacement_malloc_process_cmd_line_option)(arg); 45027fec9071fd5365fa4a517fb77b844b6f8712268nethercote 451c9f3692175ba544ecef6f905f5dcd755c3b153benethercote return True; 452c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 453c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 45451d827bcd88ce045a383ea1ca81768757df2d1fanjnstatic void ms_print_usage(void) 455c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 456734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(printf)( 457c9f3692175ba544ecef6f905f5dcd755c3b153benethercote" --heap=no|yes profile heap blocks [yes]\n" 458a15b6661220b7ae6d4e417030eb5bd348f08ea20njn" --heap-admin=<size> average admin bytes per heap block;\n" 459734b805cb3af82ddd7d3ba22a0e22aba29b78305njn" ignored if --heap=no [8]\n" 460734b805cb3af82ddd7d3ba22a0e22aba29b78305njn" --stacks=no|yes profile stack(s) [no]\n" 461e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn" --pages-as-heap=no|yes profile memory at the page level [no]\n" 462734b805cb3af82ddd7d3ba22a0e22aba29b78305njn" --depth=<number> depth of contexts [30]\n" 463f6b0076ba64f5c22f9e09be70c351a9d4b095883njn" --alloc-fn=<name> specify <name> as an alloc function [empty]\n" 464f6b0076ba64f5c22f9e09be70c351a9d4b095883njn" --ignore-fn=<name> ignore heap allocations within <name> [empty]\n" 46562721e90cec685b202424719f7237620e2c5780dnjn" --threshold=<m.n> significance threshold, as a percentage [1.0]\n" 46662721e90cec685b202424719f7237620e2c5780dnjn" --peak-inaccuracy=<m.n> maximum peak inaccuracy, as a percentage [1.0]\n" 4671a2741aad64315cd5da0cc877f474d53af16b5a3njn" --time-unit=i|ms|B time unit: instructions executed, milliseconds\n" 4681a2741aad64315cd5da0cc877f474d53af16b5a3njn" or heap bytes alloc'd/dealloc'd [i]\n" 469734b805cb3af82ddd7d3ba22a0e22aba29b78305njn" --detailed-freq=<N> every Nth snapshot should be detailed [10]\n" 470734b805cb3af82ddd7d3ba22a0e22aba29b78305njn" --max-snapshots=<N> maximum number of snapshots recorded [100]\n" 471374a36dbfb6d08ed8d77c31a88e198a861ffadf0njn" --massif-out-file=<file> output file name [massif.out.%%p]\n" 472c9f3692175ba544ecef6f905f5dcd755c3b153benethercote ); 473c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 474c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 47551d827bcd88ce045a383ea1ca81768757df2d1fanjnstatic void ms_print_debug_usage(void) 476c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 47797db761d2a94fc7a349aee9359ef85828d9618b6njn VG_(printf)( 47897db761d2a94fc7a349aee9359ef85828d9618b6njn" (none)\n" 47997db761d2a94fc7a349aee9359ef85828d9618b6njn ); 480c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 481c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 482734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 483734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 484734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- XPts, XTrees and XCons ---// 485734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 486734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 487734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// An XPt represents an "execution point", ie. a code address. Each XPt is 488734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// part of a tree of XPts (an "execution tree", or "XTree"). The details of 489734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// the heap are represented by a single XTree. 490734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 491734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// The root of the tree is 'alloc_xpt', which represents all allocation 492734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// functions, eg: 493734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - malloc/calloc/realloc/memalign/new/new[]; 494734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - user-specified allocation functions (using --alloc-fn); 495734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// - custom allocation (MALLOCLIKE) points 496734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// It's a bit of a fake XPt (ie. its 'ip' is zero), and is only used because 497734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// it makes the code simpler. 498734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 499734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Any child of 'alloc_xpt' is called a "top-XPt". The XPts at the bottom 500734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// of an XTree (leaf nodes) are "bottom-XPTs". 501734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 502734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Each path from a top-XPt to a bottom-XPt through an XTree gives an 503734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// execution context ("XCon"), ie. a stack trace. (And sub-paths represent 504734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// stack sub-traces.) The number of XCons in an XTree is equal to the 505734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// number of bottom-XPTs in that XTree. 506734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 507734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// alloc_xpt XTrees are bi-directional. 508734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// | ^ 509734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// v | 510734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// > parent < Example: if child1() calls parent() and child2() 511734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// / | \ also calls parent(), and parent() calls malloc(), 512734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// | / \ | the XTree will look like this. 513734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// | v v | 514734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// child1 child2 515734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 516dbeb53581d4595a0513d879ba884b108bd3e571enjn// (Note that malformed stack traces can lead to difficulties. See the 517dbeb53581d4595a0513d879ba884b108bd3e571enjn// comment at the bottom of get_XCon.) 518dbeb53581d4595a0513d879ba884b108bd3e571enjn// 519734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// XTrees and XPts are mirrored by SXTrees and SXPts, where the 'S' is short 520734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// for "saved". When the XTree is duplicated for a snapshot, we duplicate 521734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// it as an SXTree, which is similar but omits some things it does not need, 522734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// and aggregates up insignificant nodes. This is important as an SXTree is 523734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// typically much smaller than an XTree. 524734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 525734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// XXX: make XPt and SXPt extensible arrays, to avoid having to do two 526734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// allocations per Pt. 527734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 528734b805cb3af82ddd7d3ba22a0e22aba29b78305njntypedef struct _XPt XPt; 529734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstruct _XPt { 530734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Addr ip; // code address 531734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 532734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Bottom-XPts: space for the precise context. 533734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Other XPts: space of all the descendent bottom-XPts. 534734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Nb: this value goes up and down as the program executes. 535734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SizeT szB; 536734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 537734b805cb3af82ddd7d3ba22a0e22aba29b78305njn XPt* parent; // pointer to parent XPt 538734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 539734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Children. 540734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // n_children and max_children are 32-bit integers. 16-bit integers 541734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // are too small -- a very big program might have more than 65536 542734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // allocation points (ie. top-XPts) -- Konqueror starting up has 1800. 543734b805cb3af82ddd7d3ba22a0e22aba29b78305njn UInt n_children; // number of children 544734b805cb3af82ddd7d3ba22a0e22aba29b78305njn UInt max_children; // capacity of children array 545734b805cb3af82ddd7d3ba22a0e22aba29b78305njn XPt** children; // pointers to children XPts 546734b805cb3af82ddd7d3ba22a0e22aba29b78305njn}; 547734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 548734b805cb3af82ddd7d3ba22a0e22aba29b78305njntypedef 549734b805cb3af82ddd7d3ba22a0e22aba29b78305njn enum { 550734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SigSXPt, 551734b805cb3af82ddd7d3ba22a0e22aba29b78305njn InsigSXPt 552734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 553734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SXPtTag; 554734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 555734b805cb3af82ddd7d3ba22a0e22aba29b78305njntypedef struct _SXPt SXPt; 556734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstruct _SXPt { 557734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SXPtTag tag; 558734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SizeT szB; // memory size for the node, be it Sig or Insig 559734b805cb3af82ddd7d3ba22a0e22aba29b78305njn union { 560734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // An SXPt representing a single significant code location. Much like 561734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // an XPt, minus the fields that aren't necessary. 562734b805cb3af82ddd7d3ba22a0e22aba29b78305njn struct { 563734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Addr ip; 564734b805cb3af82ddd7d3ba22a0e22aba29b78305njn UInt n_children; 565734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SXPt** children; 566734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 567734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Sig; 568734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 569734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // An SXPt representing one or more code locations, all below the 570734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // significance threshold. 571734b805cb3af82ddd7d3ba22a0e22aba29b78305njn struct { 572734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int n_xpts; // number of aggregated XPts 573734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 574734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Insig; 575734b805cb3af82ddd7d3ba22a0e22aba29b78305njn }; 576734b805cb3af82ddd7d3ba22a0e22aba29b78305njn}; 577c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 578c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// Fake XPt representing all allocation functions like malloc(). Acts as 579c9f3692175ba544ecef6f905f5dcd755c3b153benethercote// parent node to all top-XPts. 580c9f3692175ba544ecef6f905f5dcd755c3b153benethercotestatic XPt* alloc_xpt; 581c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 582734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic XPt* new_XPt(Addr ip, XPt* parent) 583734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 5846e4b71339ecdf4accc77e86a892718516a531b0fphilippe // XPts are never freed, so we can use VG_(perm_malloc) to allocate them. 5856e4b71339ecdf4accc77e86a892718516a531b0fphilippe // Note that we cannot use VG_(perm_malloc) for the 'children' array, because 586734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // that needs to be resizable. 5876e4b71339ecdf4accc77e86a892718516a531b0fphilippe XPt* xpt = VG_(perm_malloc)(sizeof(XPt), vg_alignof(XPt)); 588734b805cb3af82ddd7d3ba22a0e22aba29b78305njn xpt->ip = ip; 589734b805cb3af82ddd7d3ba22a0e22aba29b78305njn xpt->szB = 0; 590734b805cb3af82ddd7d3ba22a0e22aba29b78305njn xpt->parent = parent; 591734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 592734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // We don't initially allocate any space for children. We let that 593734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // happen on demand. Many XPts (ie. all the bottom-XPts) don't have any 594734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // children anyway. 595734b805cb3af82ddd7d3ba22a0e22aba29b78305njn xpt->n_children = 0; 596734b805cb3af82ddd7d3ba22a0e22aba29b78305njn xpt->max_children = 0; 597734b805cb3af82ddd7d3ba22a0e22aba29b78305njn xpt->children = NULL; 598734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 599734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Update statistics 600734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_xpts++; 601c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 602734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return xpt; 603734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 604c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 605734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void add_child_xpt(XPt* parent, XPt* child) 606c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 607734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Expand 'children' if necessary. 608734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(parent->n_children <= parent->max_children); 609734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (parent->n_children == parent->max_children) { 61084f32b200936319bb716cefb38553c9ac414d30anjn if (0 == parent->max_children) { 611734b805cb3af82ddd7d3ba22a0e22aba29b78305njn parent->max_children = 4; 6129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj parent->children = VG_(malloc)( "ms.main.acx.1", 6139c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj parent->max_children * sizeof(XPt*) ); 614734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_xpt_init_expansions++; 615734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else { 616734b805cb3af82ddd7d3ba22a0e22aba29b78305njn parent->max_children *= 2; // Double size 6179c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj parent->children = VG_(realloc)( "ms.main.acx.2", 6189c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj parent->children, 619734b805cb3af82ddd7d3ba22a0e22aba29b78305njn parent->max_children * sizeof(XPt*) ); 620734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_xpt_later_expansions++; 621734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 622734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 623c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 624734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Insert new child XPt in parent's children list. 625734b805cb3af82ddd7d3ba22a0e22aba29b78305njn parent->children[ parent->n_children++ ] = child; 626734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 627c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 628734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Reverse comparison for a reverse sort -- biggest to smallest. 6296bd9dc18c043927c1196caba20a327238a179c42florianstatic Int SXPt_revcmp_szB(const void* n1, const void* n2) 630734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 6313e7986312a0ffc7646b0552d4c4ea3744a870e73florian const SXPt* sxpt1 = *(const SXPt *const *)n1; 6323e7986312a0ffc7646b0552d4c4ea3744a870e73florian const SXPt* sxpt2 = *(const SXPt *const *)n2; 633734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return ( sxpt1->szB < sxpt2->szB ? 1 634734b805cb3af82ddd7d3ba22a0e22aba29b78305njn : sxpt1->szB > sxpt2->szB ? -1 635734b805cb3af82ddd7d3ba22a0e22aba29b78305njn : 0); 636734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 637fc01635cb093d0b6cae883f8e347cdf9dceb01ddnethercote 638734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 639734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- XTree Operations ---// 640734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 641c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 642734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Duplicates an XTree as an SXTree. 643734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic SXPt* dup_XTree(XPt* xpt, SizeT total_szB) 644734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 645734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int i, n_sig_children, n_insig_children, n_child_sxpts; 646dbeb53581d4595a0513d879ba884b108bd3e571enjn SizeT sig_child_threshold_szB; 647734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SXPt* sxpt; 648734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 649734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Number of XPt children Action for SXPT 650734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // ------------------ --------------- 651734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // 0 sig, 0 insig alloc 0 children 652734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // N sig, 0 insig alloc N children, dup all 653734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // N sig, M insig alloc N+1, dup first N, aggregate remaining M 654734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // 0 sig, M insig alloc 1, aggregate M 655734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 656734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Work out how big a child must be to be significant. If the current 657734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // total_szB is zero, then we set it to 1, which means everything will be 658734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // judged insignificant -- this is sensible, as there's no point showing 659734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // any detail for this case. Unless they used --threshold=0, in which 660734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // case we show them everything because that's what they asked for. 661734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // 662734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Nb: We do this once now, rather than once per child, because if we do 663734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // that the cost of all the divisions adds up to something significant. 66484f32b200936319bb716cefb38553c9ac414d30anjn if (0 == total_szB && 0 != clo_threshold) { 665734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sig_child_threshold_szB = 1; 666734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else { 66762721e90cec685b202424719f7237620e2c5780dnjn sig_child_threshold_szB = (SizeT)((total_szB * clo_threshold) / 100); 668734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 669734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 670734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // How many children are significant? And do we need an aggregate SXPt? 671734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_sig_children = 0; 672734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < xpt->n_children; i++) { 673734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (xpt->children[i]->szB >= sig_child_threshold_szB) { 674734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_sig_children++; 675734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 676734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 677734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_insig_children = xpt->n_children - n_sig_children; 678734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_child_sxpts = n_sig_children + ( n_insig_children > 0 ? 1 : 0 ); 679734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 680734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Duplicate the XPt. 6819c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj sxpt = VG_(malloc)("ms.main.dX.1", sizeof(SXPt)); 682734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_sxpt_allocs++; 683734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sxpt->tag = SigSXPt; 684734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sxpt->szB = xpt->szB; 685734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sxpt->Sig.ip = xpt->ip; 686734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sxpt->Sig.n_children = n_child_sxpts; 687734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 688734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Create the SXPt's children. 689734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (n_child_sxpts > 0) { 690734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int j; 691dbeb53581d4595a0513d879ba884b108bd3e571enjn SizeT sig_children_szB = 0, insig_children_szB = 0; 6929c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj sxpt->Sig.children = VG_(malloc)("ms.main.dX.2", 6939c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj n_child_sxpts * sizeof(SXPt*)); 694734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 695dbeb53581d4595a0513d879ba884b108bd3e571enjn // Duplicate the significant children. (Nb: sig_children_szB + 696dbeb53581d4595a0513d879ba884b108bd3e571enjn // insig_children_szB doesn't necessarily equal xpt->szB.) 697734b805cb3af82ddd7d3ba22a0e22aba29b78305njn j = 0; 698734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < xpt->n_children; i++) { 699734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (xpt->children[i]->szB >= sig_child_threshold_szB) { 700734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sxpt->Sig.children[j++] = dup_XTree(xpt->children[i], total_szB); 701dbeb53581d4595a0513d879ba884b108bd3e571enjn sig_children_szB += xpt->children[i]->szB; 702dbeb53581d4595a0513d879ba884b108bd3e571enjn } else { 703dbeb53581d4595a0513d879ba884b108bd3e571enjn insig_children_szB += xpt->children[i]->szB; 704734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 705734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 706c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 707734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Create the SXPt for the insignificant children, if any, and put it 708734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // in the last child entry. 709734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (n_insig_children > 0) { 710734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Nb: We 'n_sxpt_allocs' here because creating an Insig SXPt 711734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // doesn't involve a call to dup_XTree(). 7129c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj SXPt* insig_sxpt = VG_(malloc)("ms.main.dX.3", sizeof(SXPt)); 713734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_sxpt_allocs++; 714734b805cb3af82ddd7d3ba22a0e22aba29b78305njn insig_sxpt->tag = InsigSXPt; 715734b805cb3af82ddd7d3ba22a0e22aba29b78305njn insig_sxpt->szB = insig_children_szB; 716734b805cb3af82ddd7d3ba22a0e22aba29b78305njn insig_sxpt->Insig.n_xpts = n_insig_children; 717734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sxpt->Sig.children[n_sig_children] = insig_sxpt; 718734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 719c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } else { 720734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sxpt->Sig.children = NULL; 721c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 722c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 723734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return sxpt; 724734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 725c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 726734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void free_SXTree(SXPt* sxpt) 727734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 728734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int i; 729734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(sxpt != NULL); 730734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 731734b805cb3af82ddd7d3ba22a0e22aba29b78305njn switch (sxpt->tag) { 732734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case SigSXPt: 733734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Free all children SXPts, then the children array. 734734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < sxpt->Sig.n_children; i++) { 735734b805cb3af82ddd7d3ba22a0e22aba29b78305njn free_SXTree(sxpt->Sig.children[i]); 736734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sxpt->Sig.children[i] = NULL; 737734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 738734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(free)(sxpt->Sig.children); sxpt->Sig.children = NULL; 739734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; 740734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 741734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case InsigSXPt: 742734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; 743734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 744734b805cb3af82ddd7d3ba22a0e22aba29b78305njn default: tl_assert2(0, "free_SXTree: unknown SXPt tag"); 745734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 746734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 747734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Free the SXPt itself. 748734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(free)(sxpt); sxpt = NULL; 749734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_sxpt_frees++; 750c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 751c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 752734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Sanity checking: we periodically check the heap XTree with 753734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// ms_expensive_sanity_check. 754734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void sanity_check_XTree(XPt* xpt, XPt* parent) 755c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 756734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(xpt != NULL); 757734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 758734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Check back-pointer. 759734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert2(xpt->parent == parent, 760734b805cb3af82ddd7d3ba22a0e22aba29b78305njn "xpt->parent = %p, parent = %p\n", xpt->parent, parent); 761734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 762734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Check children counts look sane. 763734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(xpt->n_children <= xpt->max_children); 764734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 765dbeb53581d4595a0513d879ba884b108bd3e571enjn // Unfortunately, xpt's size is not necessarily equal to the sum of xpt's 766dbeb53581d4595a0513d879ba884b108bd3e571enjn // children's sizes. See comment at the bottom of get_XCon. 767c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 768c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 769734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Sanity checking: we check SXTrees (which are in snapshots) after 770734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// snapshots are created, before they are deleted, and before they are 771734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// printed. 772734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void sanity_check_SXTree(SXPt* sxpt) 773c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 774734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int i; 775c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 776734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(sxpt != NULL); 777734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 778734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Check the sum of any children szBs equals the SXPt's szB. Check the 779734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // children at the same time. 780734b805cb3af82ddd7d3ba22a0e22aba29b78305njn switch (sxpt->tag) { 781734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case SigSXPt: { 782734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (sxpt->Sig.n_children > 0) { 783734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < sxpt->Sig.n_children; i++) { 784734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sanity_check_SXTree(sxpt->Sig.children[i]); 785734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 786734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 787734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; 788734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 789734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case InsigSXPt: 790734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; // do nothing 791734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 792734b805cb3af82ddd7d3ba22a0e22aba29b78305njn default: tl_assert2(0, "sanity_check_SXTree: unknown SXPt tag"); 793734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 794734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 795734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 796734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 797734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 798734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- XCon Operations ---// 799734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 800734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 801734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// This is the limit on the number of removed alloc-fns that can be in a 802734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// single XCon. 803734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#define MAX_OVERESTIMATE 50 804734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#define MAX_IPS (MAX_DEPTH + MAX_OVERESTIMATE) 805734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 806f6b0076ba64f5c22f9e09be70c351a9d4b095883njn// Determine if the given IP belongs to a function that should be ignored. 807f6b0076ba64f5c22f9e09be70c351a9d4b095883njnstatic Bool fn_should_be_ignored(Addr ip) 808f6b0076ba64f5c22f9e09be70c351a9d4b095883njn{ 80946cc04521acf2827eb33310fadc119bf2dc039e4florian const HChar *buf; 810f6b0076ba64f5c22f9e09be70c351a9d4b095883njn return 81146cc04521acf2827eb33310fadc119bf2dc039e4florian ( VG_(get_fnname)(ip, &buf) && is_member_fn(ignore_fns, buf) 812f6b0076ba64f5c22f9e09be70c351a9d4b095883njn ? True : False ); 813f6b0076ba64f5c22f9e09be70c351a9d4b095883njn} 814f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 815734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Get the stack trace for an XCon, filtering out uninteresting entries: 816734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// alloc-fns and entries above alloc-fns, and entries below main-or-below-main. 817734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Eg: alloc-fn1 / alloc-fn2 / a / b / main / (below main) / c 818734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// becomes: a / b / main 819734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Nb: it's possible to end up with an empty trace, eg. if 'main' is marked 820734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// as an alloc-fn. This is ok. 821734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic 822e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnInt get_IPs( ThreadId tid, Bool exclude_first_entry, Addr ips[]) 823734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 824734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int n_ips, i, n_alloc_fns_removed; 825734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int overestimate; 826734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Bool redo; 827734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 828734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // We ask for a few more IPs than clo_depth suggests we need. Then we 829734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // remove every entry that is an alloc-fn. Depending on the 830734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // circumstances, we may need to redo it all, asking for more IPs. 831734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Details: 832734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // - If the original stack trace is smaller than asked-for, redo=False 833734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // - Else if after filtering we have >= clo_depth IPs, redo=False 834734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // - Else redo=True 835734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // In other words, to redo, we'd have to get a stack trace as big as we 836734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // asked for and remove more than 'overestimate' alloc-fns. 837734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 838734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Main loop. 839734b805cb3af82ddd7d3ba22a0e22aba29b78305njn redo = True; // Assume this to begin with. 840734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (overestimate = 3; redo; overestimate += 6) { 841734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // This should never happen -- would require MAX_OVERESTIMATE 842734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // alloc-fns to be removed from the stack trace. 843734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (overestimate > MAX_OVERESTIMATE) 844734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(tool_panic)("get_IPs: ips[] too small, inc. MAX_OVERESTIMATE?"); 845734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 846734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Ask for more IPs than clo_depth suggests we need. 84739f3423cd68c385be301e6b44848b4c6276da7b5sewardj n_ips = VG_(get_StackTrace)( tid, ips, clo_depth + overestimate, 848b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj NULL/*array to dump SP values in*/, 849b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj NULL/*array to dump FP values in*/, 850b8b79addf04dd5d0b558916e26df0b1927cbd758sewardj 0/*first_ip_delta*/ ); 851734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(n_ips > 0); 852734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 853734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // If the original stack trace is smaller than asked-for, redo=False. 854734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (n_ips < clo_depth + overestimate) { redo = False; } 855734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 856e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // Filter out alloc fns. If requested, we automatically remove the 857e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // first entry (which presumably will be something like malloc or 858e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // __builtin_new that we're sure to filter out) without looking at it, 859e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // because VG_(get_fnname) is expensive. 860e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn n_alloc_fns_removed = ( exclude_first_entry ? 1 : 0 ); 861734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = n_alloc_fns_removed; i < n_ips; i++) { 86246cc04521acf2827eb33310fadc119bf2dc039e4florian const HChar *buf; 86346cc04521acf2827eb33310fadc119bf2dc039e4florian if (VG_(get_fnname)(ips[i], &buf)) { 864f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (is_member_fn(alloc_fns, buf)) { 865734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_alloc_fns_removed++; 866734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else { 867734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; 868734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 869734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 870734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 871734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Remove the alloc fns by shuffling the rest down over them. 872734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_ips -= n_alloc_fns_removed; 873734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < n_ips; i++) { 874734b805cb3af82ddd7d3ba22a0e22aba29b78305njn ips[i] = ips[i + n_alloc_fns_removed]; 875734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 876c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 877734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // If after filtering we have >= clo_depth IPs, redo=False 878734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (n_ips >= clo_depth) { 879734b805cb3af82ddd7d3ba22a0e22aba29b78305njn redo = False; 880734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_ips = clo_depth; // Ignore any IPs below --depth. 881734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 882734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 883734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (redo) { 884734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_XCon_redos++; 885c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 886c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 887734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return n_ips; 888734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 889734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 890734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Gets an XCon and puts it in the tree. Returns the XCon's bottom-XPt. 891f6b0076ba64f5c22f9e09be70c351a9d4b095883njn// Unless the allocation should be ignored, in which case we return NULL. 892e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic XPt* get_XCon( ThreadId tid, Bool exclude_first_entry ) 893734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 894f6b0076ba64f5c22f9e09be70c351a9d4b095883njn static Addr ips[MAX_IPS]; 895734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int i; 896734b805cb3af82ddd7d3ba22a0e22aba29b78305njn XPt* xpt = alloc_xpt; 897c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 898734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // After this call, the IPs we want are in ips[0]..ips[n_ips-1]. 899e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn Int n_ips = get_IPs(tid, exclude_first_entry, ips); 900c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 901f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Should we ignore this allocation? (Nb: n_ips can be zero, eg. if 902f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // 'main' is marked as an alloc-fn.) 903f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (n_ips > 0 && fn_should_be_ignored(ips[0])) { 904f6b0076ba64f5c22f9e09be70c351a9d4b095883njn return NULL; 905f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } 906f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 907734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Now do the search/insertion of the XCon. 908734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < n_ips; i++) { 909734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Addr ip = ips[i]; 910734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int ch; 911d01fef7de693582a6ce32bdbef7c9040ad6b356bnjn // Look for IP in xpt's children. 912734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Linear search, ugh -- about 10% of time for konqueror startup tried 913734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // caching last result, only hit about 4% for konqueror. 914c9f3692175ba544ecef6f905f5dcd755c3b153benethercote // Nb: this search hits about 98% of the time for konqueror 915734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (ch = 0; True; ch++) { 916734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (ch == xpt->n_children) { 917734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // IP not found in the children. 918734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Create and add new child XPt, then stop. 919734b805cb3af82ddd7d3ba22a0e22aba29b78305njn XPt* new_child_xpt = new_XPt(ip, xpt); 920734b805cb3af82ddd7d3ba22a0e22aba29b78305njn add_child_xpt(xpt, new_child_xpt); 921734b805cb3af82ddd7d3ba22a0e22aba29b78305njn xpt = new_child_xpt; 922734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; 923c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 924734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else if (ip == xpt->children[ch]->ip) { 925734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Found the IP in the children, stop. 926734b805cb3af82ddd7d3ba22a0e22aba29b78305njn xpt = xpt->children[ch]; 927c9f3692175ba544ecef6f905f5dcd755c3b153benethercote break; 928c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 929c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 930c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 931dbeb53581d4595a0513d879ba884b108bd3e571enjn 932dbeb53581d4595a0513d879ba884b108bd3e571enjn // [Note: several comments refer to this comment. Do not delete it 933dbeb53581d4595a0513d879ba884b108bd3e571enjn // without updating them.] 934dbeb53581d4595a0513d879ba884b108bd3e571enjn // 935dbeb53581d4595a0513d879ba884b108bd3e571enjn // A complication... If all stack traces were well-formed, then the 936dbeb53581d4595a0513d879ba884b108bd3e571enjn // returned xpt would always be a bottom-XPt. As a consequence, an XPt's 937dbeb53581d4595a0513d879ba884b108bd3e571enjn // size would always be equal to the sum of its children's sizes, which 938dbeb53581d4595a0513d879ba884b108bd3e571enjn // is an excellent sanity check. 939dbeb53581d4595a0513d879ba884b108bd3e571enjn // 940dbeb53581d4595a0513d879ba884b108bd3e571enjn // Unfortunately, stack traces occasionally are malformed, ie. truncated. 941dbeb53581d4595a0513d879ba884b108bd3e571enjn // This allows a stack trace to be a sub-trace of another, eg. a/b/c is a 942dbeb53581d4595a0513d879ba884b108bd3e571enjn // sub-trace of a/b/c/d. So we can't assume this xpt is a bottom-XPt; 943dbeb53581d4595a0513d879ba884b108bd3e571enjn // nor can we do sanity check an XPt's size against its children's sizes. 944dbeb53581d4595a0513d879ba884b108bd3e571enjn // This is annoying, but must be dealt with. (Older versions of Massif 945dbeb53581d4595a0513d879ba884b108bd3e571enjn // had this assertion in, and it was reported to fail by real users a 946dbeb53581d4595a0513d879ba884b108bd3e571enjn // couple of times.) Even more annoyingly, I can't come up with a simple 947dbeb53581d4595a0513d879ba884b108bd3e571enjn // test case that exhibit such a malformed stack trace, so I can't 948dbeb53581d4595a0513d879ba884b108bd3e571enjn // regression test it. Sigh. 949dbeb53581d4595a0513d879ba884b108bd3e571enjn // 950dbeb53581d4595a0513d879ba884b108bd3e571enjn // However, we can print a warning, so that if it happens (unexpectedly) 951dbeb53581d4595a0513d879ba884b108bd3e571enjn // in existing regression tests we'll know. Also, it warns users that 952dbeb53581d4595a0513d879ba884b108bd3e571enjn // the output snapshots may not add up the way they might expect. 953dbeb53581d4595a0513d879ba884b108bd3e571enjn // 954dbeb53581d4595a0513d879ba884b108bd3e571enjn //tl_assert(0 == xpt->n_children); // Must be bottom-XPt 955dbeb53581d4595a0513d879ba884b108bd3e571enjn if (0 != xpt->n_children) { 956dbeb53581d4595a0513d879ba884b108bd3e571enjn static Int n_moans = 0; 957dbeb53581d4595a0513d879ba884b108bd3e571enjn if (n_moans < 3) { 9585ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VG_(umsg)( 9595ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj "Warning: Malformed stack trace detected. In Massif's output,\n"); 9605ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VG_(umsg)( 9615ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj " the size of an entry's child entries may not sum up\n"); 9625ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VG_(umsg)( 9635ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj " to the entry's size as they normally do.\n"); 964dbeb53581d4595a0513d879ba884b108bd3e571enjn n_moans++; 965dbeb53581d4595a0513d879ba884b108bd3e571enjn if (3 == n_moans) 9665ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VG_(umsg)( 9675ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj " (And Massif now won't warn about this again.)\n"); 968dbeb53581d4595a0513d879ba884b108bd3e571enjn } 969dbeb53581d4595a0513d879ba884b108bd3e571enjn } 970734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return xpt; 971c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 972c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 973734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Update 'szB' of every XPt in the XCon, by percolating upwards. 974734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void update_XCon(XPt* xpt, SSizeT space_delta) 975c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 976e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(clo_heap); 977ca82cc01fb1580551144b69d3f17213a80d952e1njn tl_assert(NULL != xpt); 978c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 979734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (0 == space_delta) 980734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return; 981734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 982c9f3692175ba544ecef6f905f5dcd755c3b153benethercote while (xpt != alloc_xpt) { 983734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (space_delta < 0) tl_assert(xpt->szB >= -space_delta); 984734b805cb3af82ddd7d3ba22a0e22aba29b78305njn xpt->szB += space_delta; 985c9f3692175ba544ecef6f905f5dcd755c3b153benethercote xpt = xpt->parent; 986734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 987734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (space_delta < 0) tl_assert(alloc_xpt->szB >= -space_delta); 988734b805cb3af82ddd7d3ba22a0e22aba29b78305njn alloc_xpt->szB += space_delta; 989c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 990c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 991c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 992734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 993734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Snapshots ---// 994734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 995c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 996734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Snapshots are done in a way so that we always have a reasonable number of 997734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// them. We start by taking them quickly. Once we hit our limit, we cull 998734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// some (eg. half), and start taking them more slowly. Once we hit the 999734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// limit again, we again cull and then take them even more slowly, and so 1000734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// on. 1001c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 10021a2741aad64315cd5da0cc877f474d53af16b5a3njn// Time is measured either in i or ms or bytes, depending on the --time-unit 1003734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// option. It's a Long because it can exceed 32-bits reasonably easily, and 1004734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// because we need to allow negative values to represent unset times. 1005734b805cb3af82ddd7d3ba22a0e22aba29b78305njntypedef Long Time; 1006734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1007734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#define UNUSED_SNAPSHOT_TIME -333 // A conspicuous negative number. 1008c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1009c9f3692175ba544ecef6f905f5dcd755c3b153benethercotetypedef 1010734b805cb3af82ddd7d3ba22a0e22aba29b78305njn enum { 1011734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Normal = 77, 1012734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Peak, 1013734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Unused 1014c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 1015734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SnapshotKind; 1016c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1017734b805cb3af82ddd7d3ba22a0e22aba29b78305njntypedef 1018734b805cb3af82ddd7d3ba22a0e22aba29b78305njn struct { 1019734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SnapshotKind kind; 1020734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Time time; 1021734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SizeT heap_szB; 102232397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn SizeT heap_extra_szB;// Heap slop + admin bytes. 1023734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SizeT stacks_szB; 1024734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SXPt* alloc_sxpt; // Heap XTree root, if a detailed snapshot, 102532397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn } // otherwise NULL. 1026734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Snapshot; 1027734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1028734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic UInt next_snapshot_i = 0; // Index of where next snapshot will go. 1029734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic Snapshot* snapshots; // Array of snapshots. 1030734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1031734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic Bool is_snapshot_in_use(Snapshot* snapshot) 1032c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1033734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (Unused == snapshot->kind) { 1034734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // If snapshot is unused, check all the fields are unset. 1035734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(snapshot->time == UNUSED_SNAPSHOT_TIME); 103632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn tl_assert(snapshot->heap_extra_szB == 0); 1037734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(snapshot->heap_szB == 0); 1038734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(snapshot->stacks_szB == 0); 1039734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(snapshot->alloc_sxpt == NULL); 1040734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return False; 1041734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else { 1042734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(snapshot->time != UNUSED_SNAPSHOT_TIME); 1043734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return True; 1044734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1045c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1046c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1047734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic Bool is_detailed_snapshot(Snapshot* snapshot) 1048c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1049734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return (snapshot->alloc_sxpt ? True : False); 1050c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1051c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1052734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic Bool is_uncullable_snapshot(Snapshot* snapshot) 1053c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1054734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return &snapshots[0] == snapshot // First snapshot 1055734b805cb3af82ddd7d3ba22a0e22aba29b78305njn || &snapshots[next_snapshot_i-1] == snapshot // Last snapshot 1056734b805cb3af82ddd7d3ba22a0e22aba29b78305njn || snapshot->kind == Peak; // Peak snapshot 1057c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1058734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1059734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void sanity_check_snapshot(Snapshot* snapshot) 1060c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1061734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (snapshot->alloc_sxpt) { 1062734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sanity_check_SXTree(snapshot->alloc_sxpt); 1063c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 1064c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1065c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1066734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// All the used entries should look used, all the unused ones should be clear. 1067734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void sanity_check_snapshots_array(void) 1068c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1069734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int i; 1070734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < next_snapshot_i; i++) { 1071734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert( is_snapshot_in_use( & snapshots[i] )); 1072734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1073734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for ( ; i < clo_max_snapshots; i++) { 1074734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(!is_snapshot_in_use( & snapshots[i] )); 1075734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1076c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1077c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1078734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// This zeroes all the fields in the snapshot, but does not free the heap 1079734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// XTree if present. It also does a sanity check unless asked not to; we 1080734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// can't sanity check at startup when clearing the initial snapshots because 1081734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// they're full of junk. 1082734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void clear_snapshot(Snapshot* snapshot, Bool do_sanity_check) 1083c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1084734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (do_sanity_check) sanity_check_snapshot(snapshot); 1085734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->kind = Unused; 1086734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->time = UNUSED_SNAPSHOT_TIME; 108732397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn snapshot->heap_extra_szB = 0; 1088734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->heap_szB = 0; 1089734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->stacks_szB = 0; 1090734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->alloc_sxpt = NULL; 1091c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1092c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1093734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// This zeroes all the fields in the snapshot, and frees the heap XTree if 1094734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// present. 1095734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void delete_snapshot(Snapshot* snapshot) 1096c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1097734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Nb: if there's an XTree, we free it after calling clear_snapshot, 1098734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // because clear_snapshot does a sanity check which includes checking the 1099734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // XTree. 1100734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SXPt* tmp_sxpt = snapshot->alloc_sxpt; 1101734b805cb3af82ddd7d3ba22a0e22aba29b78305njn clear_snapshot(snapshot, /*do_sanity_check*/True); 1102734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (tmp_sxpt) { 1103734b805cb3af82ddd7d3ba22a0e22aba29b78305njn free_SXTree(tmp_sxpt); 1104734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1105c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1106c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1107e58e8a7a82f81c9237e7cae9a1b70a31dec67d36florianstatic void VERB_snapshot(Int verbosity, const HChar* prefix, Int i) 1108c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1109734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Snapshot* snapshot = &snapshots[i]; 1110e58e8a7a82f81c9237e7cae9a1b70a31dec67d36florian const HChar* suffix; 1111734b805cb3af82ddd7d3ba22a0e22aba29b78305njn switch (snapshot->kind) { 1112734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case Peak: suffix = "p"; break; 1113734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case Normal: suffix = ( is_detailed_snapshot(snapshot) ? "d" : "." ); break; 1114734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case Unused: suffix = "u"; break; 1115734b805cb3af82ddd7d3ba22a0e22aba29b78305njn default: 1116734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert2(0, "VERB_snapshot: unknown snapshot kind: %d", snapshot->kind); 1117734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 11185ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(verbosity, "%s S%s%3d (t:%lld, hp:%ld, ex:%ld, st:%ld)\n", 1119734b805cb3af82ddd7d3ba22a0e22aba29b78305njn prefix, suffix, i, 1120734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->time, 1121734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->heap_szB, 112232397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn snapshot->heap_extra_szB, 1123734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->stacks_szB 1124734b805cb3af82ddd7d3ba22a0e22aba29b78305njn ); 1125734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1126c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1127734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Cull half the snapshots; we choose those that represent the smallest 1128734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// time-spans, because that gives us the most even distribution of snapshots 1129734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// over time. (It's possible to lose interesting spikes, however.) 1130734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 1131734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Algorithm for N snapshots: We find the snapshot representing the smallest 1132734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// timeframe, and remove it. We repeat this until (N/2) snapshots are gone. 1133734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// We have to do this one snapshot at a time, rather than finding the (N/2) 1134734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// smallest snapshots in one hit, because when a snapshot is removed, its 1135734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// neighbours immediately cover greater timespans. So it's O(N^2), but N is 1136734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// small, and it's not done very often. 1137734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 1138734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Once we're done, we return the new smallest interval between snapshots. 1139734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// That becomes our minimum time interval. 1140734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic UInt cull_snapshots(void) 1141734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1142734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int i, jp, j, jn, min_timespan_i; 1143734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int n_deleted = 0; 1144734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Time min_timespan; 1145734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1146734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_cullings++; 1147734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1148734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Sets j to the index of the first not-yet-removed snapshot at or after i 1149734b805cb3af82ddd7d3ba22a0e22aba29b78305njn #define FIND_SNAPSHOT(i, j) \ 1150734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (j = i; \ 1151734b805cb3af82ddd7d3ba22a0e22aba29b78305njn j < clo_max_snapshots && !is_snapshot_in_use(&snapshots[j]); \ 1152734b805cb3af82ddd7d3ba22a0e22aba29b78305njn j++) { } 1153734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 11545ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(2, "Culling...\n"); 1155734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1156734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // First we remove enough snapshots by clearing them in-place. Once 1157734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // that's done, we can slide the remaining ones down. 1158734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < clo_max_snapshots/2; i++) { 1159734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Find the snapshot representing the smallest timespan. The timespan 1160734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // for snapshot n = d(N-1,N)+d(N,N+1), where d(A,B) is the time between 1161734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // snapshot A and B. We don't consider the first and last snapshots for 1162734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // removal. 1163734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Snapshot* min_snapshot; 1164734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int min_j; 116557e36b3e766c9e33c59f994319b66a51b37319f7nethercote 1166734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Initial triple: (prev, curr, next) == (jp, j, jn) 1167734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Initial min_timespan is the first one. 1168734b805cb3af82ddd7d3ba22a0e22aba29b78305njn jp = 0; 1169734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FIND_SNAPSHOT(1, j); 1170734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FIND_SNAPSHOT(j+1, jn); 1171734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_timespan = 0x7fffffffffffffffLL; 1172734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_j = -1; 1173734b805cb3af82ddd7d3ba22a0e22aba29b78305njn while (jn < clo_max_snapshots) { 1174734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Time timespan = snapshots[jn].time - snapshots[jp].time; 1175734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(timespan >= 0); 1176734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Nb: We never cull the peak snapshot. 1177734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (Peak != snapshots[j].kind && timespan < min_timespan) { 1178734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_timespan = timespan; 1179734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_j = j; 1180734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1181734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Move on to next triple 1182734b805cb3af82ddd7d3ba22a0e22aba29b78305njn jp = j; 1183734b805cb3af82ddd7d3ba22a0e22aba29b78305njn j = jn; 1184734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FIND_SNAPSHOT(jn+1, jn); 118557e36b3e766c9e33c59f994319b66a51b37319f7nethercote } 1186734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // We've found the least important snapshot, now delete it. First 1187734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // print it if necessary. 1188734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(-1 != min_j); // Check we found a minimum. 1189734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_snapshot = & snapshots[ min_j ]; 1190734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (VG_(clo_verbosity) > 1) { 1191ef901ff97a6a31684529a7e8c836087d2ec28026florian HChar buf[64]; // large enough 1192734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(snprintf)(buf, 64, " %3d (t-span = %lld)", i, min_timespan); 1193734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VERB_snapshot(2, buf, min_j); 1194734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1195734b805cb3af82ddd7d3ba22a0e22aba29b78305njn delete_snapshot(min_snapshot); 1196734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_deleted++; 119757e36b3e766c9e33c59f994319b66a51b37319f7nethercote } 119857e36b3e766c9e33c59f994319b66a51b37319f7nethercote 1199734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Slide down the remaining snapshots over the removed ones. First set i 1200734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // to point to the first empty slot, and j to the first full slot after 1201734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // i. Then slide everything down. 1202734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; is_snapshot_in_use( &snapshots[i] ); i++) { } 1203734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (j = i; !is_snapshot_in_use( &snapshots[j] ); j++) { } 1204734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for ( ; j < clo_max_snapshots; j++) { 1205734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (is_snapshot_in_use( &snapshots[j] )) { 1206734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshots[i++] = snapshots[j]; 1207734b805cb3af82ddd7d3ba22a0e22aba29b78305njn clear_snapshot(&snapshots[j], /*do_sanity_check*/True); 1208734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1209c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 1210734b805cb3af82ddd7d3ba22a0e22aba29b78305njn next_snapshot_i = i; 1211734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1212734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Check snapshots array looks ok after changes. 1213734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sanity_check_snapshots_array(); 1214734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1215734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Find the minimum timespan remaining; that will be our new minimum 1216734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // time interval. Note that above we were finding timespans by measuring 1217734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // two intervals around a snapshot that was under consideration for 1218734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // deletion. Here we only measure single intervals because all the 1219734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // deletions have occurred. 1220734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // 1221734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // But we have to be careful -- some snapshots (eg. snapshot 0, and the 1222734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // peak snapshot) are uncullable. If two uncullable snapshots end up 1223734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // next to each other, they'll never be culled (assuming the peak doesn't 1224734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // change), and the time gap between them will not change. However, the 1225734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // time between the remaining cullable snapshots will grow ever larger. 1226734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // This means that the min_timespan found will always be that between the 1227734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // two uncullable snapshots, and it will be much smaller than it should 1228734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // be. To avoid this problem, when computing the minimum timespan, we 1229734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // ignore any timespans between two uncullable snapshots. 1230734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(next_snapshot_i > 1); 1231734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_timespan = 0x7fffffffffffffffLL; 1232734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_timespan_i = -1; 1233734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 1; i < next_snapshot_i; i++) { 1234734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (is_uncullable_snapshot(&snapshots[i]) && 1235734b805cb3af82ddd7d3ba22a0e22aba29b78305njn is_uncullable_snapshot(&snapshots[i-1])) 1236734b805cb3af82ddd7d3ba22a0e22aba29b78305njn { 12375ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(2, "(Ignoring interval %d--%d when computing minimum)\n", i-1, i); 1238734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else { 1239734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Time timespan = snapshots[i].time - snapshots[i-1].time; 1240734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(timespan >= 0); 1241734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (timespan < min_timespan) { 1242734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_timespan = timespan; 1243734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_timespan_i = i; 1244734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1245734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1246734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1247734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(-1 != min_timespan_i); // Check we found a minimum. 1248734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1249734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Print remaining snapshots, if necessary. 1250734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (VG_(clo_verbosity) > 1) { 12515ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(2, "Finished culling (%3d of %3d deleted)\n", 1252734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_deleted, clo_max_snapshots); 1253734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < next_snapshot_i; i++) { 1254734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VERB_snapshot(2, " post-cull", i); 1255734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 12565ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(2, "New time interval = %lld (between snapshots %d and %d)\n", 1257734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_timespan, min_timespan_i-1, min_timespan_i); 1258734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1259734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1260734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return min_timespan; 1261c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1262c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1263734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic Time get_time(void) 1264c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1265734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Get current time, in whatever time unit we're using. 12661a2741aad64315cd5da0cc877f474d53af16b5a3njn if (clo_time_unit == TimeI) { 12671a2741aad64315cd5da0cc877f474d53af16b5a3njn return guest_instrs_executed; 12681a2741aad64315cd5da0cc877f474d53af16b5a3njn } else if (clo_time_unit == TimeMS) { 1269734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Some stuff happens between the millisecond timer being initialised 1270734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // to zero and us taking our first snapshot. We determine that time 1271734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // gap so we can subtract it from all subsequent times so that our 1272734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // first snapshot is considered to be at t = 0ms. Unfortunately, a 1273734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // bunch of symbols get read after the first snapshot is taken but 1274734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // before the second one (which is triggered by the first allocation), 1275734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // so when the time-unit is 'ms' we always have a big gap between the 1276734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // first two snapshots. But at least users won't have to wonder why 1277734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // the first snapshot isn't at t=0. 1278734b805cb3af82ddd7d3ba22a0e22aba29b78305njn static Bool is_first_get_time = True; 1279734b805cb3af82ddd7d3ba22a0e22aba29b78305njn static Time start_time_ms; 1280734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (is_first_get_time) { 1281734b805cb3af82ddd7d3ba22a0e22aba29b78305njn start_time_ms = VG_(read_millisecond_timer)(); 1282734b805cb3af82ddd7d3ba22a0e22aba29b78305njn is_first_get_time = False; 1283734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return 0; 1284734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else { 1285734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return VG_(read_millisecond_timer)() - start_time_ms; 1286734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1287734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else if (clo_time_unit == TimeB) { 1288734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return total_allocs_deallocs_szB; 1289734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else { 1290734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert2(0, "bad --time-unit value"); 1291734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1292734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1293c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1294734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Take a snapshot, and only that -- decisions on whether to take a 1295734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// snapshot, or what kind of snapshot, are made elsewhere. 1296f76d27a697a7b0bf3b84490baf60623fc96a23afnjn// Nb: we call the arg "my_time" because "time" shadows a global declaration 1297f76d27a697a7b0bf3b84490baf60623fc96a23afnjn// in /usr/include/time.h on Darwin. 1298734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void 1299f76d27a697a7b0bf3b84490baf60623fc96a23afnjntake_snapshot(Snapshot* snapshot, SnapshotKind kind, Time my_time, 1300efc13c21199dbb35ad07a5e00d538aa884863c01njn Bool is_detailed) 1301734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1302734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(!is_snapshot_in_use(snapshot)); 1303e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (!clo_pages_as_heap) { 1304e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(have_started_executing_code); 1305e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 1306c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1307734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Heap and heap admin. 1308734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (clo_heap) { 1309734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->heap_szB = heap_szB; 1310734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (is_detailed) { 131132397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn SizeT total_szB = heap_szB + heap_extra_szB + stacks_szB; 1312734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->alloc_sxpt = dup_XTree(alloc_xpt, total_szB); 1313734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert( alloc_xpt->szB == heap_szB); 1314734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(snapshot->alloc_sxpt->szB == heap_szB); 1315734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 131632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn snapshot->heap_extra_szB = heap_extra_szB; 1317734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1318c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1319734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Stack(s). 1320734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (clo_stacks) { 1321734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->stacks_szB = stacks_szB; 1322734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 132357e36b3e766c9e33c59f994319b66a51b37319f7nethercote 1324734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Rest of snapshot. 1325734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot->kind = kind; 1326f76d27a697a7b0bf3b84490baf60623fc96a23afnjn snapshot->time = my_time; 1327734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sanity_check_snapshot(snapshot); 1328c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1329734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Update stats. 1330734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (Peak == kind) n_peak_snapshots++; 1331734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (is_detailed) n_detailed_snapshots++; 1332734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_real_snapshots++; 1333c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1334c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1335c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1336734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Take a snapshot, if it's time, or if we've hit a peak. 1337734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void 1338e58e8a7a82f81c9237e7cae9a1b70a31dec67d36florianmaybe_take_snapshot(SnapshotKind kind, const HChar* what) 1339c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1340734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // 'min_time_interval' is the minimum time interval between snapshots. 1341734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // If we try to take a snapshot and less than this much time has passed, 1342734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // we don't take it. It gets larger as the program runs longer. It's 1343734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // initialised to zero so that we begin by taking snapshots as quickly as 1344734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // possible. 1345734b805cb3af82ddd7d3ba22a0e22aba29b78305njn static Time min_time_interval = 0; 1346734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Zero allows startup snapshot. 1347734b805cb3af82ddd7d3ba22a0e22aba29b78305njn static Time earliest_possible_time_of_next_snapshot = 0; 1348734b805cb3af82ddd7d3ba22a0e22aba29b78305njn static Int n_snapshots_since_last_detailed = 0; 1349734b805cb3af82ddd7d3ba22a0e22aba29b78305njn static Int n_skipped_snapshots_since_last_snapshot = 0; 1350734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1351734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Snapshot* snapshot; 1352734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Bool is_detailed; 1353f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Nb: we call this variable "my_time" because "time" shadows a global 1354f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // declaration in /usr/include/time.h on Darwin. 1355f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Time my_time = get_time(); 1356734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1357734b805cb3af82ddd7d3ba22a0e22aba29b78305njn switch (kind) { 1358734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case Normal: 1359734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Only do a snapshot if it's time. 1360f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (my_time < earliest_possible_time_of_next_snapshot) { 1361734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_skipped_snapshots++; 1362734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_skipped_snapshots_since_last_snapshot++; 1363734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return; 1364734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1365734b805cb3af82ddd7d3ba22a0e22aba29b78305njn is_detailed = (clo_detailed_freq-1 == n_snapshots_since_last_detailed); 1366734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; 1367734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1368734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case Peak: { 1369734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Because we're about to do a deallocation, we're coming down from a 1370734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // local peak. If it is (a) actually a global peak, and (b) a certain 1371734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // amount bigger than the previous peak, then we take a peak snapshot. 1372734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // By not taking a snapshot for every peak, we save a lot of effort -- 1373734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // because many peaks remain peak only for a short time. 137432397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn SizeT total_szB = heap_szB + heap_extra_szB + stacks_szB; 1375734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SizeT excess_szB_for_new_peak = 137662721e90cec685b202424719f7237620e2c5780dnjn (SizeT)((peak_snapshot_total_szB * clo_peak_inaccuracy) / 100); 1377734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (total_szB <= peak_snapshot_total_szB + excess_szB_for_new_peak) { 1378734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return; 1379734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1380734b805cb3af82ddd7d3ba22a0e22aba29b78305njn is_detailed = True; 1381734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; 1382734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1383734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1384734b805cb3af82ddd7d3ba22a0e22aba29b78305njn default: 1385734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert2(0, "maybe_take_snapshot: unrecognised snapshot kind"); 1386734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1387734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1388734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Take the snapshot. 1389734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot = & snapshots[next_snapshot_i]; 1390f76d27a697a7b0bf3b84490baf60623fc96a23afnjn take_snapshot(snapshot, kind, my_time, is_detailed); 1391734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1392734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Record if it was detailed. 1393734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (is_detailed) { 1394734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_snapshots_since_last_detailed = 0; 1395734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else { 1396734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_snapshots_since_last_detailed++; 1397734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1398734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1399734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Update peak data, if it's a Peak snapshot. 1400734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (Peak == kind) { 1401734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int i, number_of_peaks_snapshots_found = 0; 1402734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1403734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Sanity check the size, then update our recorded peak. 1404734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SizeT snapshot_total_szB = 140532397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn snapshot->heap_szB + snapshot->heap_extra_szB + snapshot->stacks_szB; 1406734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert2(snapshot_total_szB > peak_snapshot_total_szB, 1407734b805cb3af82ddd7d3ba22a0e22aba29b78305njn "%ld, %ld\n", snapshot_total_szB, peak_snapshot_total_szB); 1408734b805cb3af82ddd7d3ba22a0e22aba29b78305njn peak_snapshot_total_szB = snapshot_total_szB; 1409734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1410734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Find the old peak snapshot, if it exists, and mark it as normal. 1411734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < next_snapshot_i; i++) { 1412734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (Peak == snapshots[i].kind) { 1413734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshots[i].kind = Normal; 1414734b805cb3af82ddd7d3ba22a0e22aba29b78305njn number_of_peaks_snapshots_found++; 1415734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1416734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1417734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(number_of_peaks_snapshots_found <= 1); 1418734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1419734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1420734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Finish up verbosity and stats stuff. 1421734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (n_skipped_snapshots_since_last_snapshot > 0) { 14225ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(2, " (skipped %d snapshot%s)\n", 1423734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_skipped_snapshots_since_last_snapshot, 142484f32b200936319bb716cefb38553c9ac414d30anjn ( 1 == n_skipped_snapshots_since_last_snapshot ? "" : "s") ); 1425734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1426734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VERB_snapshot(2, what, next_snapshot_i); 1427734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_skipped_snapshots_since_last_snapshot = 0; 1428734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1429734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Cull the entries, if our snapshot table is full. 1430734b805cb3af82ddd7d3ba22a0e22aba29b78305njn next_snapshot_i++; 1431734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (clo_max_snapshots == next_snapshot_i) { 1432734b805cb3af82ddd7d3ba22a0e22aba29b78305njn min_time_interval = cull_snapshots(); 1433734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1434734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1435734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Work out the earliest time when the next snapshot can happen. 1436f76d27a697a7b0bf3b84490baf60623fc96a23afnjn earliest_possible_time_of_next_snapshot = my_time + min_time_interval; 1437c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1438c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1439734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1440734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1441734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Sanity checking ---// 1442734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1443734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1444734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic Bool ms_cheap_sanity_check ( void ) 1445c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1446734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return True; // Nothing useful we can cheaply check. 1447c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1448c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1449734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic Bool ms_expensive_sanity_check ( void ) 1450c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1451734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sanity_check_XTree(alloc_xpt, /*parent*/NULL); 1452734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sanity_check_snapshots_array(); 1453734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return True; 1454c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1455c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1456734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1457734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1458734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Heap management ---// 1459734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1460734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1461734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Metadata for heap blocks. Each one contains a pointer to a bottom-XPt, 1462734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// which is a foothold into the XCon at which it was allocated. From 1463734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// HP_Chunks, XPt 'space' fields are incremented (at allocation) and 1464734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// decremented (at deallocation). 1465734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// 1466734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// Nb: first two fields must match core's VgHashNode. 1467734b805cb3af82ddd7d3ba22a0e22aba29b78305njntypedef 1468734b805cb3af82ddd7d3ba22a0e22aba29b78305njn struct _HP_Chunk { 1469734b805cb3af82ddd7d3ba22a0e22aba29b78305njn struct _HP_Chunk* next; 147032397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn Addr data; // Ptr to actual block 147132397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn SizeT req_szB; // Size requested 147232397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn SizeT slop_szB; // Extra bytes given above those requested 147332397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn XPt* where; // Where allocated; bottom-XPt 1474734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1475734b805cb3af82ddd7d3ba22a0e22aba29b78305njn HP_Chunk; 1476734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 147709a4c794458cdb9dea743fa40e450150a2725257florianstatic VgHashTable *malloc_list = NULL; // HP_Chunks 1478734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1479734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void update_alloc_stats(SSizeT szB_delta) 148051f3ff144429823396f58a91b0268eebb966233cfitzhardinge{ 1481734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Update total_allocs_deallocs_szB. 1482734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (szB_delta < 0) szB_delta = -szB_delta; 1483734b805cb3af82ddd7d3ba22a0e22aba29b78305njn total_allocs_deallocs_szB += szB_delta; 148451f3ff144429823396f58a91b0268eebb966233cfitzhardinge} 148551f3ff144429823396f58a91b0268eebb966233cfitzhardinge 148632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjnstatic void update_heap_stats(SSizeT heap_szB_delta, Int heap_extra_szB_delta) 1487c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 148832397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn if (heap_szB_delta < 0) 148932397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn tl_assert(heap_szB >= -heap_szB_delta); 149032397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn if (heap_extra_szB_delta < 0) 149132397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn tl_assert(heap_extra_szB >= -heap_extra_szB_delta); 149232397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn 149332397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn heap_extra_szB += heap_extra_szB_delta; 149432397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn heap_szB += heap_szB_delta; 1495734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 149632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn update_alloc_stats(heap_szB_delta + heap_extra_szB_delta); 1497c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1498c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1499734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic 1500e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid* record_block( ThreadId tid, void* p, SizeT req_szB, SizeT slop_szB, 1501e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn Bool exclude_first_entry, Bool maybe_snapshot ) 1502c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1503734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Make new HP_Chunk node, add to malloc_list 1504e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn HP_Chunk* hc = VG_(malloc)("ms.main.rb.1", sizeof(HP_Chunk)); 150532397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn hc->req_szB = req_szB; 150632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn hc->slop_szB = slop_szB; 150732397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn hc->data = (Addr)p; 150832397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn hc->where = NULL; 1509734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(HT_add_node)(malloc_list, hc); 1510734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1511734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (clo_heap) { 1512e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VERB(3, "<<< record_block (%lu, %lu)\n", req_szB, slop_szB); 1513734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1514e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn hc->where = get_XCon( tid, exclude_first_entry ); 1515734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1516f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (hc->where) { 1517f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Update statistics. 1518f6b0076ba64f5c22f9e09be70c351a9d4b095883njn n_heap_allocs++; 1519734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1520f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Update heap stats. 1521f6b0076ba64f5c22f9e09be70c351a9d4b095883njn update_heap_stats(req_szB, clo_heap_admin + slop_szB); 1522f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 1523f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Update XTree. 1524f6b0076ba64f5c22f9e09be70c351a9d4b095883njn update_XCon(hc->where, req_szB); 1525f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 1526f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Maybe take a snapshot. 1527e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (maybe_snapshot) { 1528e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn maybe_take_snapshot(Normal, " alloc"); 1529e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 1530f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 1531f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } else { 1532f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Ignored allocation. 1533f6b0076ba64f5c22f9e09be70c351a9d4b095883njn n_ignored_heap_allocs++; 1534734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 15355ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, "(ignored)\n"); 1536f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } 1537734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 15385ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, ">>>\n"); 1539734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1540734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1541734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return p; 1542c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1543c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1544734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic __inline__ 1545e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid* alloc_and_record_block ( ThreadId tid, SizeT req_szB, SizeT req_alignB, 1546e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn Bool is_zeroed ) 1547e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn{ 1548e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn SizeT actual_szB, slop_szB; 1549e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn void* p; 1550e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1551e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if ((SSizeT)req_szB < 0) return NULL; 1552e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1553e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // Allocate and zero if necessary. 1554e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn p = VG_(cli_malloc)( req_alignB, req_szB ); 1555e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (!p) { 1556e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn return NULL; 1557e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 1558e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (is_zeroed) VG_(memset)(p, 0, req_szB); 1559e464e80d4f2e22ebb6787b555b58d73c9e027ff8florian actual_szB = VG_(cli_malloc_usable_size)(p); 1560e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(actual_szB >= req_szB); 1561e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn slop_szB = actual_szB - req_szB; 1562e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1563e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // Record block. 1564e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn record_block(tid, p, req_szB, slop_szB, /*exclude_first_entry*/True, 1565e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn /*maybe_snapshot*/True); 1566e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1567e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn return p; 1568e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn} 1569e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1570e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic __inline__ 1571e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid unrecord_block ( void* p, Bool maybe_snapshot ) 1572c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1573734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Remove HP_Chunk from malloc_list 15747081c1a48e1097e910f3d83853b68bc030231814njn HP_Chunk* hc = VG_(HT_remove)(malloc_list, (UWord)p); 1575734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (NULL == hc) { 1576734b805cb3af82ddd7d3ba22a0e22aba29b78305njn return; // must have been a bogus free() 1577734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1578734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1579734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (clo_heap) { 1580e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VERB(3, "<<< unrecord_block\n"); 1581734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1582f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (hc->where) { 1583f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Update statistics. 1584f6b0076ba64f5c22f9e09be70c351a9d4b095883njn n_heap_frees++; 1585734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1586f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Maybe take a peak snapshot, since it's a deallocation. 1587e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (maybe_snapshot) { 1588e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn maybe_take_snapshot(Peak, "de-PEAK"); 1589e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 1590734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1591f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Update heap stats. 1592f6b0076ba64f5c22f9e09be70c351a9d4b095883njn update_heap_stats(-hc->req_szB, -clo_heap_admin - hc->slop_szB); 1593734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1594f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Update XTree. 1595f6b0076ba64f5c22f9e09be70c351a9d4b095883njn update_XCon(hc->where, -hc->req_szB); 1596734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1597f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Maybe take a snapshot. 1598e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (maybe_snapshot) { 1599e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn maybe_take_snapshot(Normal, "dealloc"); 1600e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 1601f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 1602f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } else { 1603f6b0076ba64f5c22f9e09be70c351a9d4b095883njn n_ignored_heap_frees++; 1604f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 16055ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, "(ignored)\n"); 1606f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } 1607734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 16085ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, ">>> (-%lu, -%lu)\n", hc->req_szB, hc->slop_szB); 1609734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1610734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1611734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Actually free the chunk, and the heap block (if necessary) 1612734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(free)( hc ); hc = NULL; 1613c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1614c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1615f6b0076ba64f5c22f9e09be70c351a9d4b095883njn// Nb: --ignore-fn is tricky for realloc. If the block's original alloc was 1616f6b0076ba64f5c22f9e09be70c351a9d4b095883njn// ignored, but the realloc is not requested to be ignored, and we are 1617f6b0076ba64f5c22f9e09be70c351a9d4b095883njn// shrinking the block, then we have to ignore the realloc -- otherwise we 1618f6b0076ba64f5c22f9e09be70c351a9d4b095883njn// could end up with negative heap sizes. This isn't a danger if we are 1619f6b0076ba64f5c22f9e09be70c351a9d4b095883njn// growing such a block, but for consistency (it also simplifies things) we 1620f6b0076ba64f5c22f9e09be70c351a9d4b095883njn// ignore such reallocs as well. 1621734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic __inline__ 1622e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid* realloc_block ( ThreadId tid, void* p_old, SizeT new_req_szB ) 1623c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 16245cc5d7e2b8f361ac222b2cd34fd365abba82dc8enjn HP_Chunk* hc; 16255cc5d7e2b8f361ac222b2cd34fd365abba82dc8enjn void* p_new; 162632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn SizeT old_req_szB, old_slop_szB, new_slop_szB, new_actual_szB; 16275cc5d7e2b8f361ac222b2cd34fd365abba82dc8enjn XPt *old_where, *new_where; 1628f6b0076ba64f5c22f9e09be70c351a9d4b095883njn Bool is_ignored = False; 1629734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1630a079365fef42a43a2c7b4d5742dc23c0c86e250fnjn // Remove the old block 16319a46324fe85e70f08777cf7e37863293a25637banjn hc = VG_(HT_remove)(malloc_list, (UWord)p_old); 1632c9f3692175ba544ecef6f905f5dcd755c3b153benethercote if (hc == NULL) { 16335cc5d7e2b8f361ac222b2cd34fd365abba82dc8enjn return NULL; // must have been a bogus realloc() 1634c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 1635c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 163632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn old_req_szB = hc->req_szB; 163732397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn old_slop_szB = hc->slop_szB; 1638734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1639e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(!clo_pages_as_heap); // Shouldn't be here if --pages-as-heap=yes. 1640734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (clo_heap) { 1641e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VERB(3, "<<< realloc_block (%lu)\n", new_req_szB); 1642734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1643f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (hc->where) { 1644f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Update statistics. 1645f6b0076ba64f5c22f9e09be70c351a9d4b095883njn n_heap_reallocs++; 1646734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1647f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Maybe take a peak snapshot, if it's (effectively) a deallocation. 1648f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (new_req_szB < old_req_szB) { 1649f6b0076ba64f5c22f9e09be70c351a9d4b095883njn maybe_take_snapshot(Peak, "re-PEAK"); 1650f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } 1651f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } else { 1652f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // The original malloc was ignored, so we have to ignore the 1653f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // realloc as well. 1654f6b0076ba64f5c22f9e09be70c351a9d4b095883njn is_ignored = True; 1655734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1656734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1657734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1658734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Actually do the allocation, if necessary. 165932397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn if (new_req_szB <= old_req_szB + old_slop_szB) { 166032397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn // New size is smaller or same; block not moved. 1661c9f3692175ba544ecef6f905f5dcd755c3b153benethercote p_new = p_old; 166232397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn new_slop_szB = old_slop_szB + (old_req_szB - new_req_szB); 1663c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1664c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } else { 166532397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn // New size is bigger; make new block, copy shared contents, free old. 166632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn p_new = VG_(cli_malloc)(VG_(clo_alignment), new_req_szB); 166732397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn if (!p_new) { 166832397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn // Nb: if realloc fails, NULL is returned but the old block is not 166932397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn // touched. What an awful function. 167032397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn return NULL; 16710cd42f0881519a581909b670a4aebe27e53155detom } 1672dfa408c71a5fa3181cb0329269f939f18f5aeb6enjn VG_(memcpy)(p_new, p_old, old_req_szB + old_slop_szB); 167332397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn VG_(cli_free)(p_old); 1674e464e80d4f2e22ebb6787b555b58d73c9e027ff8florian new_actual_szB = VG_(cli_malloc_usable_size)(p_new); 167532397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn tl_assert(new_actual_szB >= new_req_szB); 167632397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn new_slop_szB = new_actual_szB - new_req_szB; 1677c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 1678c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 16790cd42f0881519a581909b670a4aebe27e53155detom if (p_new) { 1680734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Update HP_Chunk. 168132397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn hc->data = (Addr)p_new; 168232397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn hc->req_szB = new_req_szB; 168332397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn hc->slop_szB = new_slop_szB; 168432397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn old_where = hc->where; 168532397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn hc->where = NULL; 16860cd42f0881519a581909b670a4aebe27e53155detom 1687734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Update XTree. 16880cd42f0881519a581909b670a4aebe27e53155detom if (clo_heap) { 1689e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn new_where = get_XCon( tid, /*exclude_first_entry*/True); 1690f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (!is_ignored && new_where) { 1691f6b0076ba64f5c22f9e09be70c351a9d4b095883njn hc->where = new_where; 1692f6b0076ba64f5c22f9e09be70c351a9d4b095883njn update_XCon(old_where, -old_req_szB); 1693f6b0076ba64f5c22f9e09be70c351a9d4b095883njn update_XCon(new_where, new_req_szB); 1694f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } else { 1695f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // The realloc itself is ignored. 1696f6b0076ba64f5c22f9e09be70c351a9d4b095883njn is_ignored = True; 1697f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 1698f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Update statistics. 1699f6b0076ba64f5c22f9e09be70c351a9d4b095883njn n_ignored_heap_reallocs++; 1700f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } 17010cd42f0881519a581909b670a4aebe27e53155detom } 1702c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 1703c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 17045cc5d7e2b8f361ac222b2cd34fd365abba82dc8enjn // Now insert the new hc (with a possibly new 'data' field) into 17055cc5d7e2b8f361ac222b2cd34fd365abba82dc8enjn // malloc_list. If this realloc() did not increase the memory size, we 1706734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // will have removed and then re-added hc unnecessarily. But that's ok 17075cc5d7e2b8f361ac222b2cd34fd365abba82dc8enjn // because shrinking a block with realloc() is (presumably) much rarer 17085cc5d7e2b8f361ac222b2cd34fd365abba82dc8enjn // than growing it, and this way simplifies the growing case. 1709246a9d2e0c66b3f69d7a23f370205a48368843b7njn VG_(HT_add_node)(malloc_list, hc); 1710c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1711734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (clo_heap) { 1712f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (!is_ignored) { 1713f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Update heap stats. 1714f6b0076ba64f5c22f9e09be70c351a9d4b095883njn update_heap_stats(new_req_szB - old_req_szB, 1715f6b0076ba64f5c22f9e09be70c351a9d4b095883njn new_slop_szB - old_slop_szB); 1716f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 1717f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Maybe take a snapshot. 1718f6b0076ba64f5c22f9e09be70c351a9d4b095883njn maybe_take_snapshot(Normal, "realloc"); 1719f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } else { 172032397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn 17215ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, "(ignored)\n"); 1722f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } 1723734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 17245ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, ">>> (%ld, %ld)\n", 172532397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn new_req_szB - old_req_szB, new_slop_szB - old_slop_szB); 1726734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 1727734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1728c9f3692175ba544ecef6f905f5dcd755c3b153benethercote return p_new; 1729c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1730c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1731c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1732734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1733734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- malloc() et al replacement wrappers ---// 1734734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1735c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1736734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void* ms_malloc ( ThreadId tid, SizeT szB ) 1737c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1738e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn return alloc_and_record_block( tid, szB, VG_(clo_alignment), /*is_zeroed*/False ); 1739c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1740c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1741734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void* ms___builtin_new ( ThreadId tid, SizeT szB ) 1742c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1743e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn return alloc_and_record_block( tid, szB, VG_(clo_alignment), /*is_zeroed*/False ); 1744c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1745c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1746734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void* ms___builtin_vec_new ( ThreadId tid, SizeT szB ) 1747c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1748e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn return alloc_and_record_block( tid, szB, VG_(clo_alignment), /*is_zeroed*/False ); 1749c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1750c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1751734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void* ms_calloc ( ThreadId tid, SizeT m, SizeT szB ) 1752c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1753e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn return alloc_and_record_block( tid, m*szB, VG_(clo_alignment), /*is_zeroed*/True ); 1754734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1755c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1756734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void *ms_memalign ( ThreadId tid, SizeT alignB, SizeT szB ) 1757734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1758e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn return alloc_and_record_block( tid, szB, alignB, False ); 1759734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1760c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1761efc13c21199dbb35ad07a5e00d538aa884863c01njnstatic void ms_free ( ThreadId tid __attribute__((unused)), void* p ) 1762734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1763e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn unrecord_block(p, /*maybe_snapshot*/True); 1764e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VG_(cli_free)(p); 1765734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1766c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1767734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void ms___builtin_delete ( ThreadId tid, void* p ) 1768734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1769e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn unrecord_block(p, /*maybe_snapshot*/True); 1770e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VG_(cli_free)(p); 1771734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1772c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1773734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void ms___builtin_vec_delete ( ThreadId tid, void* p ) 1774734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1775e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn unrecord_block(p, /*maybe_snapshot*/True); 1776e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VG_(cli_free)(p); 1777734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1778c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1779734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void* ms_realloc ( ThreadId tid, void* p_old, SizeT new_szB ) 1780734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1781e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn return realloc_block(tid, p_old, new_szB); 1782734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1783c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1784efc13c21199dbb35ad07a5e00d538aa884863c01njnstatic SizeT ms_malloc_usable_size ( ThreadId tid, void* p ) 17858b140dee891a850c09d27f316df913acc7d7bae7njn{ 17868b140dee891a850c09d27f316df913acc7d7bae7njn HP_Chunk* hc = VG_(HT_lookup)( malloc_list, (UWord)p ); 17878b140dee891a850c09d27f316df913acc7d7bae7njn 17888b140dee891a850c09d27f316df913acc7d7bae7njn return ( hc ? hc->req_szB + hc->slop_szB : 0 ); 17898b140dee891a850c09d27f316df913acc7d7bae7njn} 1790c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1791734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1792e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn//--- Page handling ---// 1793e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn//------------------------------------------------------------// 1794e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1795e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic 1796e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid ms_record_page_mem ( Addr a, SizeT len ) 1797e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn{ 1798e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ThreadId tid = VG_(get_running_tid)(); 1799e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn Addr end; 1800e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(VG_IS_PAGE_ALIGNED(len)); 1801e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(len >= VKI_PAGE_SIZE); 1802e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // Record the first N-1 pages as blocks, but don't do any snapshots. 1803e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn for (end = a + len - VKI_PAGE_SIZE; a < end; a += VKI_PAGE_SIZE) { 1804e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn record_block( tid, (void*)a, VKI_PAGE_SIZE, /*slop_szB*/0, 1805e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn /*exclude_first_entry*/False, /*maybe_snapshot*/False ); 1806e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 1807e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // Record the last page as a block, and maybe do a snapshot afterwards. 1808e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn record_block( tid, (void*)a, VKI_PAGE_SIZE, /*slop_szB*/0, 1809e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn /*exclude_first_entry*/False, /*maybe_snapshot*/True ); 1810e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn} 1811e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1812e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic 1813e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid ms_unrecord_page_mem( Addr a, SizeT len ) 1814e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn{ 1815e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn Addr end; 1816e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(VG_IS_PAGE_ALIGNED(len)); 1817e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(len >= VKI_PAGE_SIZE); 1818e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn for (end = a + len - VKI_PAGE_SIZE; a < end; a += VKI_PAGE_SIZE) { 1819e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn unrecord_block((void*)a, /*maybe_snapshot*/False); 1820e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 1821e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn unrecord_block((void*)a, /*maybe_snapshot*/True); 1822e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn} 1823e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1824e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn//------------------------------------------------------------// 1825e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1826e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic 1827e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid ms_new_mem_mmap ( Addr a, SizeT len, 1828e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn Bool rr, Bool ww, Bool xx, ULong di_handle ) 1829e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn{ 1830e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(VG_IS_PAGE_ALIGNED(len)); 1831e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ms_record_page_mem(a, len); 1832e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn} 1833e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1834e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic 1835e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid ms_new_mem_startup( Addr a, SizeT len, 1836e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn Bool rr, Bool ww, Bool xx, ULong di_handle ) 1837e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn{ 1838e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // startup maps are always be page-sized, except the trampoline page is 1839e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // marked by the core as only being the size of the trampoline itself, 1840e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // which is something like 57 bytes. Round it up to page size. 1841e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn len = VG_PGROUNDUP(len); 1842e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ms_record_page_mem(a, len); 1843e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn} 1844e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1845e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic 1846e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid ms_new_mem_brk ( Addr a, SizeT len, ThreadId tid ) 1847e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn{ 1848e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe // brk limit is not necessarily aligned on a page boundary. 1849e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe // If new memory being brk-ed implies to allocate a new page, 1850e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe // then call ms_record_page_mem with page aligned parameters 1851e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe // otherwise just ignore. 1852e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe Addr old_bottom_page = VG_PGROUNDDN(a - 1); 1853e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe Addr new_top_page = VG_PGROUNDDN(a + len - 1); 1854e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe if (old_bottom_page != new_top_page) 1855e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe ms_record_page_mem(VG_PGROUNDDN(a), 1856e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe (new_top_page - old_bottom_page)); 1857e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn} 1858e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1859e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic 1860e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid ms_copy_mem_remap( Addr from, Addr to, SizeT len) 1861e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn{ 1862e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(VG_IS_PAGE_ALIGNED(len)); 1863e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ms_unrecord_page_mem(from, len); 1864e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ms_record_page_mem(to, len); 1865e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn} 1866e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1867e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic 1868e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid ms_die_mem_munmap( Addr a, SizeT len ) 1869e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn{ 1870e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(VG_IS_PAGE_ALIGNED(len)); 1871e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ms_unrecord_page_mem(a, len); 1872e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn} 1873e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1874e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnstatic 1875e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjnvoid ms_die_mem_brk( Addr a, SizeT len ) 1876e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn{ 1877e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe // Call ms_unrecord_page_mem only if one or more pages are de-allocated. 1878e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe // See ms_new_mem_brk for more details. 1879e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe Addr new_bottom_page = VG_PGROUNDDN(a - 1); 1880e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe Addr old_top_page = VG_PGROUNDDN(a + len - 1); 1881e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe if (old_top_page != new_bottom_page) 1882e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe ms_unrecord_page_mem(VG_PGROUNDDN(a), 1883e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe (old_top_page - new_bottom_page)); 1884e6a26cc2fd3877993e14b1e3caffeb1324dd23a8philippe 1885e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn} 1886e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 1887e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn//------------------------------------------------------------// 1888734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Stacks ---// 1889734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1890c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1891734b805cb3af82ddd7d3ba22a0e22aba29b78305njn// We really want the inlining to occur... 1892734b805cb3af82ddd7d3ba22a0e22aba29b78305njn#define INLINE inline __attribute__((always_inline)) 1893c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1894734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void update_stack_stats(SSizeT stack_szB_delta) 1895734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1896734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (stack_szB_delta < 0) tl_assert(stacks_szB >= -stack_szB_delta); 1897734b805cb3af82ddd7d3ba22a0e22aba29b78305njn stacks_szB += stack_szB_delta; 1898c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1899734b805cb3af82ddd7d3ba22a0e22aba29b78305njn update_alloc_stats(stack_szB_delta); 1900734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1901c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1902e58e8a7a82f81c9237e7cae9a1b70a31dec67d36florianstatic INLINE void new_mem_stack_2(SizeT len, const HChar* what) 1903734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1904734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (have_started_executing_code) { 19055ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, "<<< new_mem_stack (%ld)\n", len); 1906734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_stack_allocs++; 1907734b805cb3af82ddd7d3ba22a0e22aba29b78305njn update_stack_stats(len); 1908734b805cb3af82ddd7d3ba22a0e22aba29b78305njn maybe_take_snapshot(Normal, what); 19095ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, ">>>\n"); 1910c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 1911734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1912c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1913e58e8a7a82f81c9237e7cae9a1b70a31dec67d36florianstatic INLINE void die_mem_stack_2(SizeT len, const HChar* what) 1914734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1915734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (have_started_executing_code) { 19165ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, "<<< die_mem_stack (%ld)\n", -len); 1917734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_stack_frees++; 1918734b805cb3af82ddd7d3ba22a0e22aba29b78305njn maybe_take_snapshot(Peak, "stkPEAK"); 1919734b805cb3af82ddd7d3ba22a0e22aba29b78305njn update_stack_stats(-len); 1920734b805cb3af82ddd7d3ba22a0e22aba29b78305njn maybe_take_snapshot(Normal, what); 19215ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(3, ">>>\n"); 1922c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 1923734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1924c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1925734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void new_mem_stack(Addr a, SizeT len) 1926734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1927efc13c21199dbb35ad07a5e00d538aa884863c01njn new_mem_stack_2(len, "stk-new"); 1928734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1929c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1930734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void die_mem_stack(Addr a, SizeT len) 1931734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 1932efc13c21199dbb35ad07a5e00d538aa884863c01njn die_mem_stack_2(len, "stk-die"); 1933734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 1934c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 19357cf4e6b6aed533af53339f36099ed244dc4a5b7fsewardjstatic void new_mem_stack_signal(Addr a, SizeT len, ThreadId tid) 1936c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1937efc13c21199dbb35ad07a5e00d538aa884863c01njn new_mem_stack_2(len, "sig-new"); 1938c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1939c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 19408b5f40c481a89483c1738e5d5e9e718b418948d4nethercotestatic void die_mem_stack_signal(Addr a, SizeT len) 1941c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1942efc13c21199dbb35ad07a5e00d538aa884863c01njn die_mem_stack_2(len, "sig-die"); 1943c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 1944c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 1945734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 1946734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1947734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Client Requests ---// 1948734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 1949c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 19503b290486cd4cd601b20e04340e593c9ed9717e5fsewardjstatic void print_monitor_help ( void ) 19513b290486cd4cd601b20e04340e593c9ed9717e5fsewardj{ 19523b290486cd4cd601b20e04340e593c9ed9717e5fsewardj VG_(gdb_printf) ("\n"); 19533b290486cd4cd601b20e04340e593c9ed9717e5fsewardj VG_(gdb_printf) ("massif monitor commands:\n"); 195430b3eca94e609214d9ac8dabfee9be3f3ab46d85sewardj VG_(gdb_printf) (" snapshot [<filename>]\n"); 195530b3eca94e609214d9ac8dabfee9be3f3ab46d85sewardj VG_(gdb_printf) (" detailed_snapshot [<filename>]\n"); 1956868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe VG_(gdb_printf) (" takes a snapshot (or a detailed snapshot)\n"); 1957868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe VG_(gdb_printf) (" and saves it in <filename>\n"); 1958868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe VG_(gdb_printf) (" default <filename> is massif.vgdb.out\n"); 1959868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe VG_(gdb_printf) (" all_snapshots [<filename>]\n"); 1960868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe VG_(gdb_printf) (" saves all snapshot(s) taken so far in <filename>\n"); 19613b290486cd4cd601b20e04340e593c9ed9717e5fsewardj VG_(gdb_printf) (" default <filename> is massif.vgdb.out\n"); 19623b290486cd4cd601b20e04340e593c9ed9717e5fsewardj VG_(gdb_printf) ("\n"); 19633b290486cd4cd601b20e04340e593c9ed9717e5fsewardj} 19643b290486cd4cd601b20e04340e593c9ed9717e5fsewardj 19653b290486cd4cd601b20e04340e593c9ed9717e5fsewardj 19663b290486cd4cd601b20e04340e593c9ed9717e5fsewardj/* Forward declaration. 19673b290486cd4cd601b20e04340e593c9ed9717e5fsewardj return True if request recognised, False otherwise */ 196819f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic Bool handle_gdb_monitor_command (ThreadId tid, HChar *req); 196951d827bcd88ce045a383ea1ca81768757df2d1fanjnstatic Bool ms_handle_client_request ( ThreadId tid, UWord* argv, UWord* ret ) 1970c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 1971c9f3692175ba544ecef6f905f5dcd755c3b153benethercote switch (argv[0]) { 1972c9f3692175ba544ecef6f905f5dcd755c3b153benethercote case VG_USERREQ__MALLOCLIKE_BLOCK: { 1973734b805cb3af82ddd7d3ba22a0e22aba29b78305njn void* p = (void*)argv[1]; 1974734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SizeT szB = argv[2]; 1975e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn record_block( tid, p, szB, /*slop_szB*/0, /*exclude_first_entry*/False, 1976e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn /*maybe_snapshot*/True ); 1977734b805cb3af82ddd7d3ba22a0e22aba29b78305njn *ret = 0; 1978c9f3692175ba544ecef6f905f5dcd755c3b153benethercote return True; 1979c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 1980913473803432ee37d6edaf232e21978d4f426125bart case VG_USERREQ__RESIZEINPLACE_BLOCK: { 1981913473803432ee37d6edaf232e21978d4f426125bart void* p = (void*)argv[1]; 1982913473803432ee37d6edaf232e21978d4f426125bart SizeT newSizeB = argv[3]; 1983913473803432ee37d6edaf232e21978d4f426125bart 1984913473803432ee37d6edaf232e21978d4f426125bart unrecord_block(p, /*maybe_snapshot*/True); 1985913473803432ee37d6edaf232e21978d4f426125bart record_block(tid, p, newSizeB, /*slop_szB*/0, 1986913473803432ee37d6edaf232e21978d4f426125bart /*exclude_first_entry*/False, /*maybe_snapshot*/True); 1987913473803432ee37d6edaf232e21978d4f426125bart return True; 1988913473803432ee37d6edaf232e21978d4f426125bart } 1989c9f3692175ba544ecef6f905f5dcd755c3b153benethercote case VG_USERREQ__FREELIKE_BLOCK: { 1990734b805cb3af82ddd7d3ba22a0e22aba29b78305njn void* p = (void*)argv[1]; 1991e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn unrecord_block(p, /*maybe_snapshot*/True); 1992734b805cb3af82ddd7d3ba22a0e22aba29b78305njn *ret = 0; 1993c9f3692175ba544ecef6f905f5dcd755c3b153benethercote return True; 1994c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 19953b290486cd4cd601b20e04340e593c9ed9717e5fsewardj case VG_USERREQ__GDB_MONITOR_COMMAND: { 199619f91bbaedb4caef8a60ce94b0f507193cc0bc10florian Bool handled = handle_gdb_monitor_command (tid, (HChar*)argv[1]); 19973b290486cd4cd601b20e04340e593c9ed9717e5fsewardj if (handled) 19983b290486cd4cd601b20e04340e593c9ed9717e5fsewardj *ret = 1; 19993b290486cd4cd601b20e04340e593c9ed9717e5fsewardj else 20003b290486cd4cd601b20e04340e593c9ed9717e5fsewardj *ret = 0; 20013b290486cd4cd601b20e04340e593c9ed9717e5fsewardj return handled; 20023b290486cd4cd601b20e04340e593c9ed9717e5fsewardj } 20033b290486cd4cd601b20e04340e593c9ed9717e5fsewardj 2004c9f3692175ba544ecef6f905f5dcd755c3b153benethercote default: 2005c9f3692175ba544ecef6f905f5dcd755c3b153benethercote *ret = 0; 2006c9f3692175ba544ecef6f905f5dcd755c3b153benethercote return False; 2007c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 2008c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 2009c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2010734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 2011734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Instrumentation ---// 2012734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 2013c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 20141a2741aad64315cd5da0cc877f474d53af16b5a3njnstatic void add_counter_update(IRSB* sbOut, Int n) 20151a2741aad64315cd5da0cc877f474d53af16b5a3njn{ 20161a2741aad64315cd5da0cc877f474d53af16b5a3njn #if defined(VG_BIGENDIAN) 20171a2741aad64315cd5da0cc877f474d53af16b5a3njn # define END Iend_BE 20181a2741aad64315cd5da0cc877f474d53af16b5a3njn #elif defined(VG_LITTLEENDIAN) 20191a2741aad64315cd5da0cc877f474d53af16b5a3njn # define END Iend_LE 20201a2741aad64315cd5da0cc877f474d53af16b5a3njn #else 20211a2741aad64315cd5da0cc877f474d53af16b5a3njn # error "Unknown endianness" 20221a2741aad64315cd5da0cc877f474d53af16b5a3njn #endif 20231a2741aad64315cd5da0cc877f474d53af16b5a3njn // Add code to increment 'guest_instrs_executed' by 'n', like this: 20241a2741aad64315cd5da0cc877f474d53af16b5a3njn // WrTmp(t1, Load64(&guest_instrs_executed)) 20251a2741aad64315cd5da0cc877f474d53af16b5a3njn // WrTmp(t2, Add64(RdTmp(t1), Const(n))) 20261a2741aad64315cd5da0cc877f474d53af16b5a3njn // Store(&guest_instrs_executed, t2) 20271a2741aad64315cd5da0cc877f474d53af16b5a3njn IRTemp t1 = newIRTemp(sbOut->tyenv, Ity_I64); 20281a2741aad64315cd5da0cc877f474d53af16b5a3njn IRTemp t2 = newIRTemp(sbOut->tyenv, Ity_I64); 20291a2741aad64315cd5da0cc877f474d53af16b5a3njn IRExpr* counter_addr = mkIRExpr_HWord( (HWord)&guest_instrs_executed ); 20301a2741aad64315cd5da0cc877f474d53af16b5a3njn 2031db5907d7b94ce492f29a96c95e186fdcda23a149sewardj IRStmt* st1 = IRStmt_WrTmp(t1, IRExpr_Load(END, Ity_I64, counter_addr)); 20321a2741aad64315cd5da0cc877f474d53af16b5a3njn IRStmt* st2 = 20331a2741aad64315cd5da0cc877f474d53af16b5a3njn IRStmt_WrTmp(t2, 20341a2741aad64315cd5da0cc877f474d53af16b5a3njn IRExpr_Binop(Iop_Add64, IRExpr_RdTmp(t1), 20351a2741aad64315cd5da0cc877f474d53af16b5a3njn IRExpr_Const(IRConst_U64(n)))); 2036db5907d7b94ce492f29a96c95e186fdcda23a149sewardj IRStmt* st3 = IRStmt_Store(END, counter_addr, IRExpr_RdTmp(t2)); 20371a2741aad64315cd5da0cc877f474d53af16b5a3njn 20381a2741aad64315cd5da0cc877f474d53af16b5a3njn addStmtToIRSB( sbOut, st1 ); 20391a2741aad64315cd5da0cc877f474d53af16b5a3njn addStmtToIRSB( sbOut, st2 ); 20401a2741aad64315cd5da0cc877f474d53af16b5a3njn addStmtToIRSB( sbOut, st3 ); 20411a2741aad64315cd5da0cc877f474d53af16b5a3njn} 20421a2741aad64315cd5da0cc877f474d53af16b5a3njn 20431a2741aad64315cd5da0cc877f474d53af16b5a3njnstatic IRSB* ms_instrument2( IRSB* sbIn ) 20441a2741aad64315cd5da0cc877f474d53af16b5a3njn{ 20451a2741aad64315cd5da0cc877f474d53af16b5a3njn Int i, n = 0; 20461a2741aad64315cd5da0cc877f474d53af16b5a3njn IRSB* sbOut; 20471a2741aad64315cd5da0cc877f474d53af16b5a3njn 20481a2741aad64315cd5da0cc877f474d53af16b5a3njn // We increment the instruction count in two places: 20491a2741aad64315cd5da0cc877f474d53af16b5a3njn // - just before any Ist_Exit statements; 20501a2741aad64315cd5da0cc877f474d53af16b5a3njn // - just before the IRSB's end. 20511a2741aad64315cd5da0cc877f474d53af16b5a3njn // In the former case, we zero 'n' and then continue instrumenting. 20521a2741aad64315cd5da0cc877f474d53af16b5a3njn 20531a2741aad64315cd5da0cc877f474d53af16b5a3njn sbOut = deepCopyIRSBExceptStmts(sbIn); 20541a2741aad64315cd5da0cc877f474d53af16b5a3njn 20551a2741aad64315cd5da0cc877f474d53af16b5a3njn for (i = 0; i < sbIn->stmts_used; i++) { 20561a2741aad64315cd5da0cc877f474d53af16b5a3njn IRStmt* st = sbIn->stmts[i]; 20571a2741aad64315cd5da0cc877f474d53af16b5a3njn 20581a2741aad64315cd5da0cc877f474d53af16b5a3njn if (!st || st->tag == Ist_NoOp) continue; 20591a2741aad64315cd5da0cc877f474d53af16b5a3njn 20601a2741aad64315cd5da0cc877f474d53af16b5a3njn if (st->tag == Ist_IMark) { 20611a2741aad64315cd5da0cc877f474d53af16b5a3njn n++; 20621a2741aad64315cd5da0cc877f474d53af16b5a3njn } else if (st->tag == Ist_Exit) { 20631a2741aad64315cd5da0cc877f474d53af16b5a3njn if (n > 0) { 20641a2741aad64315cd5da0cc877f474d53af16b5a3njn // Add an increment before the Exit statement, then reset 'n'. 20651a2741aad64315cd5da0cc877f474d53af16b5a3njn add_counter_update(sbOut, n); 20661a2741aad64315cd5da0cc877f474d53af16b5a3njn n = 0; 20671a2741aad64315cd5da0cc877f474d53af16b5a3njn } 20681a2741aad64315cd5da0cc877f474d53af16b5a3njn } 20691a2741aad64315cd5da0cc877f474d53af16b5a3njn addStmtToIRSB( sbOut, st ); 20701a2741aad64315cd5da0cc877f474d53af16b5a3njn } 20711a2741aad64315cd5da0cc877f474d53af16b5a3njn 20721a2741aad64315cd5da0cc877f474d53af16b5a3njn if (n > 0) { 20731a2741aad64315cd5da0cc877f474d53af16b5a3njn // Add an increment before the SB end. 20741a2741aad64315cd5da0cc877f474d53af16b5a3njn add_counter_update(sbOut, n); 20751a2741aad64315cd5da0cc877f474d53af16b5a3njn } 20761a2741aad64315cd5da0cc877f474d53af16b5a3njn return sbOut; 20771a2741aad64315cd5da0cc877f474d53af16b5a3njn} 20781a2741aad64315cd5da0cc877f474d53af16b5a3njn 20794ba057cce1d81a949f5a899b5abb99e90a731bccsewardjstatic 20800b9d74abd0a663b530d290b2b788ddeda46e5400sewardjIRSB* ms_instrument ( VgCallbackClosure* closure, 20811a2741aad64315cd5da0cc877f474d53af16b5a3njn IRSB* sbIn, 20823c0c94777f547bcb5eadbe8cb4328debf0f51875florian const VexGuestLayout* layout, 20833c0c94777f547bcb5eadbe8cb4328debf0f51875florian const VexGuestExtents* vge, 20843c0c94777f547bcb5eadbe8cb4328debf0f51875florian const VexArchInfo* archinfo_host, 20854ba057cce1d81a949f5a899b5abb99e90a731bccsewardj IRType gWordTy, IRType hWordTy ) 2086c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 2087734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (! have_started_executing_code) { 2088734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Do an initial sample to guarantee that we have at least one. 2089734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // We use 'maybe_take_snapshot' instead of 'take_snapshot' to ensure 2090734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // 'maybe_take_snapshot's internal static variables are initialised. 2091734b805cb3af82ddd7d3ba22a0e22aba29b78305njn have_started_executing_code = True; 2092734b805cb3af82ddd7d3ba22a0e22aba29b78305njn maybe_take_snapshot(Normal, "startup"); 2093c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 20941a2741aad64315cd5da0cc877f474d53af16b5a3njn 20951a2741aad64315cd5da0cc877f474d53af16b5a3njn if (clo_time_unit == TimeI) { return ms_instrument2(sbIn); } 20961a2741aad64315cd5da0cc877f474d53af16b5a3njn else if (clo_time_unit == TimeMS) { return sbIn; } 20971a2741aad64315cd5da0cc877f474d53af16b5a3njn else if (clo_time_unit == TimeB) { return sbIn; } 20981a2741aad64315cd5da0cc877f474d53af16b5a3njn else { tl_assert2(0, "bad --time-unit value"); } 2099c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 2100c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2101c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2102734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 2103734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Writing snapshots ---// 2104734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 2105c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 210612d2eb58c09505f8b1a171bcdd8352c9713591b4florian#define FP(format, args...) ({ VG_(fprintf)(fp, format, ##args); }) 2107b11e5aaab306bbbf5280a3d0efc473664a48a306njn 210812d2eb58c09505f8b1a171bcdd8352c9713591b4florianstatic void pp_snapshot_SXPt(VgFile *fp, SXPt* sxpt, Int depth, 210912d2eb58c09505f8b1a171bcdd8352c9713591b4florian HChar* depth_str, Int depth_str_len, 211012d2eb58c09505f8b1a171bcdd8352c9713591b4florian SizeT snapshot_heap_szB, SizeT snapshot_total_szB) 2111c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 2112466ed6e1efeab3b32a30a9002622fb03c0686688njn Int i, j, n_insig_children_sxpts; 2113734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SXPt* child = NULL; 2114734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2115f330ae85d6b6c603dedb10bf1c70606c8df92dd1sewardj // Used for printing function names. Is made static to keep it out 2116f330ae85d6b6c603dedb10bf1c70606c8df92dd1sewardj // of the stack frame -- this function is recursive. Obviously this 2117f330ae85d6b6c603dedb10bf1c70606c8df92dd1sewardj // now means its contents are trashed across the recursive call. 2118770a8d23e40b980b5745e59ecb8e4037d81af357florian const HChar* ip_desc; 2119f330ae85d6b6c603dedb10bf1c70606c8df92dd1sewardj 2120734b805cb3af82ddd7d3ba22a0e22aba29b78305njn switch (sxpt->tag) { 2121734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case SigSXPt: 2122734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Print the SXPt itself. 212384f32b200936319bb716cefb38553c9ac414d30anjn if (0 == depth) { 2124e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (clo_heap) { 2125e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ip_desc = 2126e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ( clo_pages_as_heap 2127e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ? "(page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc." 2128e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn : "(heap allocation functions) malloc/new/new[], --alloc-fns, etc." 2129e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn ); 2130e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } else { 2131e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // XXX: --alloc-fns? 21326bd9dc18c043927c1196caba20a327238a179c42florian 2133ef901ff97a6a31684529a7e8c836087d2ec28026florian // Nick thinks this case cannot happen. ip_desc would be 21346bd9dc18c043927c1196caba20a327238a179c42florian // conceptually uninitialised here. Therefore: 21356bd9dc18c043927c1196caba20a327238a179c42florian tl_assert2(0, "pp_snapshot_SXPt: unexpected"); 2136e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 2137c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } else { 2138734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // If it's main-or-below-main, we (if appropriate) ignore everything 2139734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // below it by pretending it has no children. 21406882443ef154bca367bc591287de641e43a9e108njn if ( ! VG_(clo_show_below_main) ) { 21416882443ef154bca367bc591287de641e43a9e108njn Vg_FnNameKind kind = VG_(get_fnname_kind_from_IP)(sxpt->Sig.ip); 21426882443ef154bca367bc591287de641e43a9e108njn if (Vg_FnNameMain == kind || Vg_FnNameBelowMain == kind) { 21436882443ef154bca367bc591287de641e43a9e108njn sxpt->Sig.n_children = 0; 21446882443ef154bca367bc591287de641e43a9e108njn } 2145c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 21466882443ef154bca367bc591287de641e43a9e108njn 2147734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // We need the -1 to get the line number right, But I'm not sure why. 2148770a8d23e40b980b5745e59ecb8e4037d81af357florian ip_desc = VG_(describe_IP)(sxpt->Sig.ip-1, NULL); 2149c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 2150466ed6e1efeab3b32a30a9002622fb03c0686688njn 2151466ed6e1efeab3b32a30a9002622fb03c0686688njn // Do the non-ip_desc part first... 2152466ed6e1efeab3b32a30a9002622fb03c0686688njn FP("%sn%d: %lu ", depth_str, sxpt->Sig.n_children, sxpt->szB); 2153466ed6e1efeab3b32a30a9002622fb03c0686688njn 2154466ed6e1efeab3b32a30a9002622fb03c0686688njn // For ip_descs beginning with "0xABCD...:" addresses, we first 2155466ed6e1efeab3b32a30a9002622fb03c0686688njn // measure the length of the "0xabcd: " address at the start of the 2156466ed6e1efeab3b32a30a9002622fb03c0686688njn // ip_desc. 2157466ed6e1efeab3b32a30a9002622fb03c0686688njn j = 0; 2158466ed6e1efeab3b32a30a9002622fb03c0686688njn if ('0' == ip_desc[0] && 'x' == ip_desc[1]) { 2159466ed6e1efeab3b32a30a9002622fb03c0686688njn j = 2; 2160466ed6e1efeab3b32a30a9002622fb03c0686688njn while (True) { 2161466ed6e1efeab3b32a30a9002622fb03c0686688njn if (ip_desc[j]) { 2162466ed6e1efeab3b32a30a9002622fb03c0686688njn if (':' == ip_desc[j]) break; 2163466ed6e1efeab3b32a30a9002622fb03c0686688njn j++; 2164466ed6e1efeab3b32a30a9002622fb03c0686688njn } else { 2165466ed6e1efeab3b32a30a9002622fb03c0686688njn tl_assert2(0, "ip_desc has unexpected form: %s\n", ip_desc); 2166466ed6e1efeab3b32a30a9002622fb03c0686688njn } 2167466ed6e1efeab3b32a30a9002622fb03c0686688njn } 2168466ed6e1efeab3b32a30a9002622fb03c0686688njn } 2169770a8d23e40b980b5745e59ecb8e4037d81af357florian // It used to be that ip_desc was truncated at the end. 2170770a8d23e40b980b5745e59ecb8e4037d81af357florian // But there does not seem to be a good reason for that. Besides, 2171770a8d23e40b980b5745e59ecb8e4037d81af357florian // the string was truncated at the right, which is less than ideal. 2172770a8d23e40b980b5745e59ecb8e4037d81af357florian // Truncation at the beginning of the string would have been preferable. 2173770a8d23e40b980b5745e59ecb8e4037d81af357florian // Think several nested namespaces in C++.... 2174770a8d23e40b980b5745e59ecb8e4037d81af357florian // Anyhow, we spit out the full-length string now. 2175ef901ff97a6a31684529a7e8c836087d2ec28026florian FP("%s\n", ip_desc); 2176734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2177734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Indent. 2178734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(depth+1 < depth_str_len-1); // -1 for end NUL char 2179734b805cb3af82ddd7d3ba22a0e22aba29b78305njn depth_str[depth+0] = ' '; 2180734b805cb3af82ddd7d3ba22a0e22aba29b78305njn depth_str[depth+1] = '\0'; 2181734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2182734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Sort SXPt's children by szB (reverse order: biggest to smallest). 2183734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Nb: we sort them here, rather than earlier (eg. in dup_XTree), for 2184734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // two reasons. First, if we do it during dup_XTree, it can get 2185734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // expensive (eg. 15% of execution time for konqueror 2186734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // startup/shutdown). Second, this way we get the Insig SXPt (if one 2187734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // is present) in its sorted position, not at the end. 2188734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(ssort)(sxpt->Sig.children, sxpt->Sig.n_children, sizeof(SXPt*), 2189734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SXPt_revcmp_szB); 2190734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2191734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Print the SXPt's children. They should already be in sorted order. 2192734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_insig_children_sxpts = 0; 2193734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < sxpt->Sig.n_children; i++) { 2194734b805cb3af82ddd7d3ba22a0e22aba29b78305njn child = sxpt->Sig.children[i]; 2195734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2196734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (InsigSXPt == child->tag) 2197734b805cb3af82ddd7d3ba22a0e22aba29b78305njn n_insig_children_sxpts++; 2198734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2199770a8d23e40b980b5745e59ecb8e4037d81af357florian // Ok, print the child. NB: contents of ip_desc will be 2200f330ae85d6b6c603dedb10bf1c70606c8df92dd1sewardj // trashed by this recursive call. Doesn't matter currently, 2201f330ae85d6b6c603dedb10bf1c70606c8df92dd1sewardj // but worth noting. 220212d2eb58c09505f8b1a171bcdd8352c9713591b4florian pp_snapshot_SXPt(fp, child, depth+1, depth_str, depth_str_len, 2203734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot_heap_szB, snapshot_total_szB); 2204c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 2205dbeb53581d4595a0513d879ba884b108bd3e571enjn 2206dbeb53581d4595a0513d879ba884b108bd3e571enjn // Unindent. 2207dbeb53581d4595a0513d879ba884b108bd3e571enjn depth_str[depth+0] = '\0'; 2208dbeb53581d4595a0513d879ba884b108bd3e571enjn depth_str[depth+1] = '\0'; 2209dbeb53581d4595a0513d879ba884b108bd3e571enjn 2210734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // There should be 0 or 1 Insig children SXPts. 2211734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert(n_insig_children_sxpts <= 1); 2212734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; 2213734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2214734b805cb3af82ddd7d3ba22a0e22aba29b78305njn case InsigSXPt: { 2215e58e8a7a82f81c9237e7cae9a1b70a31dec67d36florian const HChar* s = ( 1 == sxpt->Insig.n_xpts ? "," : "s, all" ); 2216227a1ecca7f44cb07e74aa8f1bd24b29df629499florian FP("%sn0: %lu in %d place%s below massif's threshold (%.2f%%)\n", 2217227a1ecca7f44cb07e74aa8f1bd24b29df629499florian depth_str, sxpt->szB, sxpt->Insig.n_xpts, s, clo_threshold); 2218734b805cb3af82ddd7d3ba22a0e22aba29b78305njn break; 2219734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 2220734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2221734b805cb3af82ddd7d3ba22a0e22aba29b78305njn default: 2222734b805cb3af82ddd7d3ba22a0e22aba29b78305njn tl_assert2(0, "pp_snapshot_SXPt: unrecognised SXPt tag"); 2223c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 2224c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 2225c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 222612d2eb58c09505f8b1a171bcdd8352c9713591b4florianstatic void pp_snapshot(VgFile *fp, Snapshot* snapshot, Int snapshot_n) 2227c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 2228734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sanity_check_snapshot(snapshot); 2229734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2230734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("#-----------\n"); 2231734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("snapshot=%d\n", snapshot_n); 2232734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("#-----------\n"); 2233734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("time=%lld\n", snapshot->time); 2234734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("mem_heap_B=%lu\n", snapshot->heap_szB); 223532397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn FP("mem_heap_extra_B=%lu\n", snapshot->heap_extra_szB); 2236734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("mem_stacks_B=%lu\n", snapshot->stacks_szB); 2237734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2238734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (is_detailed_snapshot(snapshot)) { 2239734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Detailed snapshot -- print heap tree. 2240734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int depth_str_len = clo_depth + 3; 224119f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar* depth_str = VG_(malloc)("ms.main.pps.1", 224219f91bbaedb4caef8a60ce94b0f507193cc0bc10florian sizeof(HChar) * depth_str_len); 2243734b805cb3af82ddd7d3ba22a0e22aba29b78305njn SizeT snapshot_total_szB = 224432397c0c26fd49181e87a409ad986b9e1b5b0dfdnjn snapshot->heap_szB + snapshot->heap_extra_szB + snapshot->stacks_szB; 2245734b805cb3af82ddd7d3ba22a0e22aba29b78305njn depth_str[0] = '\0'; // Initialise depth_str to "". 2246734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2247734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("heap_tree=%s\n", ( Peak == snapshot->kind ? "peak" : "detailed" )); 224812d2eb58c09505f8b1a171bcdd8352c9713591b4florian pp_snapshot_SXPt(fp, snapshot->alloc_sxpt, 0, depth_str, 2249734b805cb3af82ddd7d3ba22a0e22aba29b78305njn depth_str_len, snapshot->heap_szB, 2250734b805cb3af82ddd7d3ba22a0e22aba29b78305njn snapshot_total_szB); 2251734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2252734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(free)(depth_str); 225343a15ce615589c8a44d19b1b7d1531a04618913anethercote 2254734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } else { 2255734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("heap_tree=empty\n"); 2256734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 2257c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 2258c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 225919f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic void write_snapshots_to_file(const HChar* massif_out_file, 22603b290486cd4cd601b20e04340e593c9ed9717e5fsewardj Snapshot snapshots_array[], 22613b290486cd4cd601b20e04340e593c9ed9717e5fsewardj Int nr_elements) 2262c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 226312d2eb58c09505f8b1a171bcdd8352c9713591b4florian Int i; 226412d2eb58c09505f8b1a171bcdd8352c9713591b4florian VgFile *fp; 2265c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 226612d2eb58c09505f8b1a171bcdd8352c9713591b4florian fp = VG_(fopen)(massif_out_file, VKI_O_CREAT|VKI_O_TRUNC|VKI_O_WRONLY, 226712d2eb58c09505f8b1a171bcdd8352c9713591b4florian VKI_S_IRUSR|VKI_S_IWUSR); 226812d2eb58c09505f8b1a171bcdd8352c9713591b4florian if (fp == NULL) { 2269734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // If the file can't be opened for whatever reason (conflict 2270734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // between multiple cachegrinded processes?), give up now. 22715ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VG_(umsg)("error: can't open output file '%s'\n", massif_out_file ); 22725ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VG_(umsg)(" ... so profiling results will be missing.\n"); 2273c9f3692175ba544ecef6f905f5dcd755c3b153benethercote return; 2274c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 2275c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2276734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Print massif-specific options that were used. 2277734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // XXX: is it worth having a "desc:" line? Could just call it "options:" 2278734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // -- this file format isn't as generic as Cachegrind's, so the 2279734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // implied genericity of "desc:" is bogus. 2280734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("desc:"); 2281734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < VG_(sizeXA)(args_for_massif); i++) { 228219f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar* arg = *(HChar**)VG_(indexXA)(args_for_massif, i); 2283734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP(" %s", arg); 2284c9f3692175ba544ecef6f905f5dcd755c3b153benethercote } 2285734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (0 == i) FP(" (none)"); 2286734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("\n"); 2287c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2288734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Print "cmd:" line. 2289734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("cmd: "); 2290b16609bf952bf381154cb6cba87efc99c2c86a23florian FP("%s", VG_(args_the_exename)); 2291b16609bf952bf381154cb6cba87efc99c2c86a23florian for (i = 0; i < VG_(sizeXA)( VG_(args_for_client) ); i++) { 2292b16609bf952bf381154cb6cba87efc99c2c86a23florian HChar* arg = * (HChar**) VG_(indexXA)( VG_(args_for_client), i ); 22935980e9df10ed1b0497bc09f4b2fa708b52c9addaflorian FP(" %s", arg); 2294d111d100b250215516c66f0fceda76815191afa0njn } 2295734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("\n"); 2296c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2297734b805cb3af82ddd7d3ba22a0e22aba29b78305njn FP("time_unit: %s\n", TimeUnit_to_string(clo_time_unit)); 2298c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 22993b290486cd4cd601b20e04340e593c9ed9717e5fsewardj for (i = 0; i < nr_elements; i++) { 23003b290486cd4cd601b20e04340e593c9ed9717e5fsewardj Snapshot* snapshot = & snapshots_array[i]; 230112d2eb58c09505f8b1a171bcdd8352c9713591b4florian pp_snapshot(fp, snapshot, i); // Detailed snapshot! 2302734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 230312d2eb58c09505f8b1a171bcdd8352c9713591b4florian VG_(fclose) (fp); 23043b290486cd4cd601b20e04340e593c9ed9717e5fsewardj} 23053b290486cd4cd601b20e04340e593c9ed9717e5fsewardj 23063b290486cd4cd601b20e04340e593c9ed9717e5fsewardjstatic void write_snapshots_array_to_file(void) 23073b290486cd4cd601b20e04340e593c9ed9717e5fsewardj{ 23083b290486cd4cd601b20e04340e593c9ed9717e5fsewardj // Setup output filename. Nb: it's important to do this now, ie. as late 23093b290486cd4cd601b20e04340e593c9ed9717e5fsewardj // as possible. If we do it at start-up and the program forks and the 23103b290486cd4cd601b20e04340e593c9ed9717e5fsewardj // output file format string contains a %p (pid) specifier, both the 23113b290486cd4cd601b20e04340e593c9ed9717e5fsewardj // parent and child will incorrectly write to the same file; this 23123b290486cd4cd601b20e04340e593c9ed9717e5fsewardj // happened in 3.3.0. 231319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar* massif_out_file = 23143b290486cd4cd601b20e04340e593c9ed9717e5fsewardj VG_(expand_file_name)("--massif-out-file", clo_massif_out_file); 23153b290486cd4cd601b20e04340e593c9ed9717e5fsewardj write_snapshots_to_file (massif_out_file, snapshots, next_snapshot_i); 23163b290486cd4cd601b20e04340e593c9ed9717e5fsewardj VG_(free)(massif_out_file); 2317c9f3692175ba544ecef6f905f5dcd755c3b153benethercote} 2318c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 231919f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic void handle_snapshot_monitor_command (const HChar *filename, 232019f91bbaedb4caef8a60ce94b0f507193cc0bc10florian Bool detailed) 2321d142f99836471d4245250247cc9ac7bc5a1391fasewardj{ 2322d142f99836471d4245250247cc9ac7bc5a1391fasewardj Snapshot snapshot; 2323d142f99836471d4245250247cc9ac7bc5a1391fasewardj 232427c9f0d1a2193440791748efd3821828dff5ff70philippe if (!clo_pages_as_heap && !have_started_executing_code) { 232527c9f0d1a2193440791748efd3821828dff5ff70philippe // See comments of variable have_started_executing_code. 232627c9f0d1a2193440791748efd3821828dff5ff70philippe VG_(gdb_printf) 232727c9f0d1a2193440791748efd3821828dff5ff70philippe ("error: cannot take snapshot before execution has started\n"); 232827c9f0d1a2193440791748efd3821828dff5ff70philippe return; 232927c9f0d1a2193440791748efd3821828dff5ff70philippe } 233027c9f0d1a2193440791748efd3821828dff5ff70philippe 2331d142f99836471d4245250247cc9ac7bc5a1391fasewardj clear_snapshot(&snapshot, /* do_sanity_check */ False); 2332d142f99836471d4245250247cc9ac7bc5a1391fasewardj take_snapshot(&snapshot, Normal, get_time(), detailed); 233327c9f0d1a2193440791748efd3821828dff5ff70philippe write_snapshots_to_file ((filename == NULL) ? 233419f91bbaedb4caef8a60ce94b0f507193cc0bc10florian "massif.vgdb.out" : filename, 2335d142f99836471d4245250247cc9ac7bc5a1391fasewardj &snapshot, 2336d142f99836471d4245250247cc9ac7bc5a1391fasewardj 1); 2337d142f99836471d4245250247cc9ac7bc5a1391fasewardj delete_snapshot(&snapshot); 2338d142f99836471d4245250247cc9ac7bc5a1391fasewardj} 2339d142f99836471d4245250247cc9ac7bc5a1391fasewardj 2340868bfa276b0c84071cf9bd00f1958ba4c53397aephilippestatic void handle_all_snapshots_monitor_command (const HChar *filename) 2341868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe{ 2342868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe if (!clo_pages_as_heap && !have_started_executing_code) { 2343868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe // See comments of variable have_started_executing_code. 2344868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe VG_(gdb_printf) 2345868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe ("error: cannot take snapshot before execution has started\n"); 2346868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe return; 2347868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe } 2348868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe 2349868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe write_snapshots_to_file ((filename == NULL) ? 2350868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe "massif.vgdb.out" : filename, 2351868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe snapshots, next_snapshot_i); 2352868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe} 2353868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe 235419f91bbaedb4caef8a60ce94b0f507193cc0bc10florianstatic Bool handle_gdb_monitor_command (ThreadId tid, HChar *req) 23553b290486cd4cd601b20e04340e593c9ed9717e5fsewardj{ 235619f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar* wcmd; 2357c29761f54236f27d3bb3663998121bf1c7cbec8cdejanj HChar s[VG_(strlen(req)) + 1]; /* copy for strtok_r */ 235819f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar *ssaveptr; 23593b290486cd4cd601b20e04340e593c9ed9717e5fsewardj 23603b290486cd4cd601b20e04340e593c9ed9717e5fsewardj VG_(strcpy) (s, req); 23613b290486cd4cd601b20e04340e593c9ed9717e5fsewardj 23623b290486cd4cd601b20e04340e593c9ed9717e5fsewardj wcmd = VG_(strtok_r) (s, " ", &ssaveptr); 2363868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe switch (VG_(keyword_id) ("help snapshot detailed_snapshot all_snapshots", 23643b290486cd4cd601b20e04340e593c9ed9717e5fsewardj wcmd, kwd_report_duplicated_matches)) { 23653b290486cd4cd601b20e04340e593c9ed9717e5fsewardj case -2: /* multiple matches */ 23663b290486cd4cd601b20e04340e593c9ed9717e5fsewardj return True; 23673b290486cd4cd601b20e04340e593c9ed9717e5fsewardj case -1: /* not found */ 23683b290486cd4cd601b20e04340e593c9ed9717e5fsewardj return False; 23693b290486cd4cd601b20e04340e593c9ed9717e5fsewardj case 0: /* help */ 23703b290486cd4cd601b20e04340e593c9ed9717e5fsewardj print_monitor_help(); 23713b290486cd4cd601b20e04340e593c9ed9717e5fsewardj return True; 237230b3eca94e609214d9ac8dabfee9be3f3ab46d85sewardj case 1: { /* snapshot */ 237319f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar* filename; 2374d142f99836471d4245250247cc9ac7bc5a1391fasewardj filename = VG_(strtok_r) (NULL, " ", &ssaveptr); 2375d142f99836471d4245250247cc9ac7bc5a1391fasewardj handle_snapshot_monitor_command (filename, False /* detailed */); 2376d142f99836471d4245250247cc9ac7bc5a1391fasewardj return True; 2377d142f99836471d4245250247cc9ac7bc5a1391fasewardj } 237830b3eca94e609214d9ac8dabfee9be3f3ab46d85sewardj case 2: { /* detailed_snapshot */ 237919f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar* filename; 2380d142f99836471d4245250247cc9ac7bc5a1391fasewardj filename = VG_(strtok_r) (NULL, " ", &ssaveptr); 2381d142f99836471d4245250247cc9ac7bc5a1391fasewardj handle_snapshot_monitor_command (filename, True /* detailed */); 23823b290486cd4cd601b20e04340e593c9ed9717e5fsewardj return True; 23833b290486cd4cd601b20e04340e593c9ed9717e5fsewardj } 2384868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe case 3: { /* all_snapshots */ 2385868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe HChar* filename; 2386868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe filename = VG_(strtok_r) (NULL, " ", &ssaveptr); 2387868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe handle_all_snapshots_monitor_command (filename); 2388868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe return True; 2389868bfa276b0c84071cf9bd00f1958ba4c53397aephilippe } 23903b290486cd4cd601b20e04340e593c9ed9717e5fsewardj default: 23913b290486cd4cd601b20e04340e593c9ed9717e5fsewardj tl_assert(0); 23923b290486cd4cd601b20e04340e593c9ed9717e5fsewardj return False; 23933b290486cd4cd601b20e04340e593c9ed9717e5fsewardj } 23943b290486cd4cd601b20e04340e593c9ed9717e5fsewardj} 2395c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2396f066315b49748c77424220bb822f603120bdf139philippestatic void ms_print_stats (void) 2397c9f3692175ba544ecef6f905f5dcd755c3b153benethercote{ 2398f066315b49748c77424220bb822f603120bdf139philippe#define STATS(format, args...) \ 2399f066315b49748c77424220bb822f603120bdf139philippe VG_(dmsg)("Massif: " format, ##args) 2400734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 24012d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("heap allocs: %u\n", n_heap_allocs); 24022d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("heap reallocs: %u\n", n_heap_reallocs); 24032d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("heap frees: %u\n", n_heap_frees); 24042d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("ignored heap allocs: %u\n", n_ignored_heap_allocs); 24052d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("ignored heap frees: %u\n", n_ignored_heap_frees); 24062d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("ignored heap reallocs: %u\n", n_ignored_heap_reallocs); 24072d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("stack allocs: %u\n", n_stack_allocs); 24082d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("stack frees: %u\n", n_stack_frees); 24092d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("XPts: %u\n", n_xpts); 24102d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("top-XPts: %u (%d%%)\n", 2411734b805cb3af82ddd7d3ba22a0e22aba29b78305njn alloc_xpt->n_children, 2412734b805cb3af82ddd7d3ba22a0e22aba29b78305njn ( n_xpts ? alloc_xpt->n_children * 100 / n_xpts : 0)); 24132d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("XPt init expansions: %u\n", n_xpt_init_expansions); 24142d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("XPt later expansions: %u\n", n_xpt_later_expansions); 24152d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("SXPt allocs: %u\n", n_sxpt_allocs); 24162d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("SXPt frees: %u\n", n_sxpt_frees); 24172d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("skipped snapshots: %u\n", n_skipped_snapshots); 24182d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("real snapshots: %u\n", n_real_snapshots); 24192d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("detailed snapshots: %u\n", n_detailed_snapshots); 24202d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("peak snapshots: %u\n", n_peak_snapshots); 24212d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("cullings: %u\n", n_cullings); 24222d9e874b7a628ada216f09cc4f065798c65fffa4sewardj STATS("XCon redos: %u\n", n_XCon_redos); 2423f066315b49748c77424220bb822f603120bdf139philippe#undef STATS 2424f066315b49748c77424220bb822f603120bdf139philippe} 2425f066315b49748c77424220bb822f603120bdf139philippe 2426f066315b49748c77424220bb822f603120bdf139philippe//------------------------------------------------------------// 2427f066315b49748c77424220bb822f603120bdf139philippe//--- Finalisation ---// 2428f066315b49748c77424220bb822f603120bdf139philippe//------------------------------------------------------------// 2429f066315b49748c77424220bb822f603120bdf139philippe 2430f066315b49748c77424220bb822f603120bdf139philippestatic void ms_fini(Int exit_status) 2431f066315b49748c77424220bb822f603120bdf139philippe{ 2432f066315b49748c77424220bb822f603120bdf139philippe // Output. 2433f066315b49748c77424220bb822f603120bdf139philippe write_snapshots_array_to_file(); 2434f066315b49748c77424220bb822f603120bdf139philippe 2435f066315b49748c77424220bb822f603120bdf139philippe // Stats 2436f066315b49748c77424220bb822f603120bdf139philippe tl_assert(n_xpts > 0); // always have alloc_xpt 2437f066315b49748c77424220bb822f603120bdf139philippe 2438f066315b49748c77424220bb822f603120bdf139philippe if (VG_(clo_stats)) 2439f066315b49748c77424220bb822f603120bdf139philippe ms_print_stats(); 2440734b805cb3af82ddd7d3ba22a0e22aba29b78305njn} 2441c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2442c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2443734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 2444734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- Initialisation ---// 2445734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//------------------------------------------------------------// 2446c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2447734b805cb3af82ddd7d3ba22a0e22aba29b78305njnstatic void ms_post_clo_init(void) 2448734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 2449734b805cb3af82ddd7d3ba22a0e22aba29b78305njn Int i; 245019f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar* LD_PRELOAD_val; 245119f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar* s; 245219f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar* s2; 2453c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2454734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Check options. 2455e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (clo_pages_as_heap) { 2456e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (clo_stacks) { 24575b99e6669a0b2a925bb3fb2604259cc317963b6dflorian VG_(fmsg_bad_option)("--pages-as-heap=yes", 24585b99e6669a0b2a925bb3fb2604259cc317963b6dflorian "Cannot be used together with --stacks=yes"); 2459e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 2460e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 2461734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (!clo_heap) { 2462e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn clo_pages_as_heap = False; 2463e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 2464e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 2465e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // If --pages-as-heap=yes we don't want malloc replacement to occur. So we 2466e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // disable vgpreload_massif-$PLATFORM.so by removing it from LD_PRELOAD (or 2467e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // platform-equivalent). We replace it entirely with spaces because then 2468e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // the linker doesn't complain (it does complain if we just change the name 2469e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // to a bogus file). This is a bit of a hack, but LD_PRELOAD is setup well 2470e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // before tool initialisation, so this seems the best way to do it. 2471e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (clo_pages_as_heap) { 2472e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn clo_heap_admin = 0; // No heap admin on pages. 2473e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 247419f91bbaedb4caef8a60ce94b0f507193cc0bc10florian LD_PRELOAD_val = VG_(getenv)( VG_(LD_PRELOAD_var_name) ); 2475e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(LD_PRELOAD_val); 2476e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 2477e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // Make sure the vgpreload_core-$PLATFORM entry is there, for sanity. 2478e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn s2 = VG_(strstr)(LD_PRELOAD_val, "vgpreload_core"); 2479e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(s2); 2480e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 2481e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // Now find the vgpreload_massif-$PLATFORM entry. 2482e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn s2 = VG_(strstr)(LD_PRELOAD_val, "vgpreload_massif"); 2483e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn tl_assert(s2); 2484e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 2485e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // Blank out everything to the previous ':', which must be there because 2486e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // of the preceding vgpreload_core-$PLATFORM entry. 2487e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn for (s = s2; *s != ':'; s--) { 2488e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn *s = ' '; 2489e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 2490e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 2491e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // Blank out everything to the end of the entry, which will be '\0' if 2492e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn // LD_PRELOAD was empty before Valgrind started, or ':' otherwise. 2493e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn for (s = s2; *s != ':' && *s != '\0'; s++) { 2494e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn *s = ' '; 2495e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 2496734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 2497c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2498f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Print alloc-fns and ignore-fns, if necessary. 2499734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (VG_(clo_verbosity) > 1) { 25005ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(1, "alloc-fns:\n"); 2501734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < VG_(sizeXA)(alloc_fns); i++) { 250219f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar** fn_ptr = VG_(indexXA)(alloc_fns, i); 25035ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(1, " %s\n", *fn_ptr); 2504f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } 2505f6b0076ba64f5c22f9e09be70c351a9d4b095883njn 25065ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(1, "ignore-fns:\n"); 2507f6b0076ba64f5c22f9e09be70c351a9d4b095883njn if (0 == VG_(sizeXA)(ignore_fns)) { 25085ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(1, " <empty>\n"); 2509f6b0076ba64f5c22f9e09be70c351a9d4b095883njn } 2510f6b0076ba64f5c22f9e09be70c351a9d4b095883njn for (i = 0; i < VG_(sizeXA)(ignore_fns); i++) { 251119f91bbaedb4caef8a60ce94b0f507193cc0bc10florian HChar** fn_ptr = VG_(indexXA)(ignore_fns, i); 25125ea0f390fb3f7bf1a618d03b6144dc50b4ae96b8sewardj VERB(1, " %d: %s\n", i, *fn_ptr); 2513734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 2514734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 251551d827bcd88ce045a383ea1ca81768757df2d1fanjn 2516734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Events to track. 2517734b805cb3af82ddd7d3ba22a0e22aba29b78305njn if (clo_stacks) { 2518734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(track_new_mem_stack) ( new_mem_stack ); 2519734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(track_die_mem_stack) ( die_mem_stack ); 2520734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(track_new_mem_stack_signal) ( new_mem_stack_signal ); 2521734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(track_die_mem_stack_signal) ( die_mem_stack_signal ); 2522734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 252351d827bcd88ce045a383ea1ca81768757df2d1fanjn 2524e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn if (clo_pages_as_heap) { 2525e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VG_(track_new_mem_startup) ( ms_new_mem_startup ); 2526e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VG_(track_new_mem_brk) ( ms_new_mem_brk ); 2527e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VG_(track_new_mem_mmap) ( ms_new_mem_mmap ); 2528e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 2529e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VG_(track_copy_mem_remap) ( ms_copy_mem_remap ); 2530e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 2531e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VG_(track_die_mem_brk) ( ms_die_mem_brk ); 2532e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn VG_(track_die_mem_munmap) ( ms_die_mem_munmap ); 2533e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn } 2534e323a6bf5d28a9fe6f3dae9b3f02b9ccd25fc7ecnjn 2535734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Initialise snapshot array, and sanity-check it. 25369c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj snapshots = VG_(malloc)("ms.main.mpoci.1", 25379c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj sizeof(Snapshot) * clo_max_snapshots); 2538734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // We don't want to do snapshot sanity checks here, because they're 2539734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // currently uninitialised. 2540734b805cb3af82ddd7d3ba22a0e22aba29b78305njn for (i = 0; i < clo_max_snapshots; i++) { 2541734b805cb3af82ddd7d3ba22a0e22aba29b78305njn clear_snapshot( & snapshots[i], /*do_sanity_check*/False ); 2542734b805cb3af82ddd7d3ba22a0e22aba29b78305njn } 2543734b805cb3af82ddd7d3ba22a0e22aba29b78305njn sanity_check_snapshots_array(); 254451d827bcd88ce045a383ea1ca81768757df2d1fanjn} 254551d827bcd88ce045a383ea1ca81768757df2d1fanjn 2546151a639d523a1d9b4cbd6629992e48ed8ee9408etomstatic void ms_pre_clo_init(void) 2547734b805cb3af82ddd7d3ba22a0e22aba29b78305njn{ 254851d827bcd88ce045a383ea1ca81768757df2d1fanjn VG_(details_name) ("Massif"); 254951d827bcd88ce045a383ea1ca81768757df2d1fanjn VG_(details_version) (NULL); 25501a2741aad64315cd5da0cc877f474d53af16b5a3njn VG_(details_description) ("a heap profiler"); 25519a0cba4e767f487c2abaa35f95a3452d6bd0ff66njn VG_(details_copyright_author)( 25520f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj "Copyright (C) 2003-2013, and GNU GPL'd, by Nicholas Nethercote"); 255351d827bcd88ce045a383ea1ca81768757df2d1fanjn VG_(details_bug_reports_to) (VG_BUGS_TO); 255451d827bcd88ce045a383ea1ca81768757df2d1fanjn 25551e0fff690e9c571275e8025eb2dcff7bf29b53afsewardj VG_(details_avg_translation_sizeB) ( 330 ); 25561e0fff690e9c571275e8025eb2dcff7bf29b53afsewardj 25578d47a61e503b69ffbc783717f5faf09d0bbc4723sewardj VG_(clo_vex_control).iropt_register_updates_default 25588d47a61e503b69ffbc783717f5faf09d0bbc4723sewardj = VG_(clo_px_file_backed) 25595b240c20b48c86955e574d5880a145927c60a686philippe = VexRegUpdSpAtMemAccess; // overridable by the user. 25605b240c20b48c86955e574d5880a145927c60a686philippe 2561f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Basic functions. 256251d827bcd88ce045a383ea1ca81768757df2d1fanjn VG_(basic_tool_funcs) (ms_post_clo_init, 256351d827bcd88ce045a383ea1ca81768757df2d1fanjn ms_instrument, 256451d827bcd88ce045a383ea1ca81768757df2d1fanjn ms_fini); 256551d827bcd88ce045a383ea1ca81768757df2d1fanjn 2566f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Needs. 256751d827bcd88ce045a383ea1ca81768757df2d1fanjn VG_(needs_libc_freeres)(); 256851d827bcd88ce045a383ea1ca81768757df2d1fanjn VG_(needs_command_line_options)(ms_process_cmd_line_option, 256951d827bcd88ce045a383ea1ca81768757df2d1fanjn ms_print_usage, 257051d827bcd88ce045a383ea1ca81768757df2d1fanjn ms_print_debug_usage); 257151d827bcd88ce045a383ea1ca81768757df2d1fanjn VG_(needs_client_requests) (ms_handle_client_request); 2572734b805cb3af82ddd7d3ba22a0e22aba29b78305njn VG_(needs_sanity_checks) (ms_cheap_sanity_check, 2573734b805cb3af82ddd7d3ba22a0e22aba29b78305njn ms_expensive_sanity_check); 2574f066315b49748c77424220bb822f603120bdf139philippe VG_(needs_print_stats) (ms_print_stats); 2575fc51f8d9538eda285c2ea0974f29b075168f3433njn VG_(needs_malloc_replacement) (ms_malloc, 257651d827bcd88ce045a383ea1ca81768757df2d1fanjn ms___builtin_new, 257751d827bcd88ce045a383ea1ca81768757df2d1fanjn ms___builtin_vec_new, 257851d827bcd88ce045a383ea1ca81768757df2d1fanjn ms_memalign, 257951d827bcd88ce045a383ea1ca81768757df2d1fanjn ms_calloc, 258051d827bcd88ce045a383ea1ca81768757df2d1fanjn ms_free, 258151d827bcd88ce045a383ea1ca81768757df2d1fanjn ms___builtin_delete, 258251d827bcd88ce045a383ea1ca81768757df2d1fanjn ms___builtin_vec_delete, 258351d827bcd88ce045a383ea1ca81768757df2d1fanjn ms_realloc, 25848b140dee891a850c09d27f316df913acc7d7bae7njn ms_malloc_usable_size, 258551d827bcd88ce045a383ea1ca81768757df2d1fanjn 0 ); 258651d827bcd88ce045a383ea1ca81768757df2d1fanjn 2587f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // HP_Chunks. 2588734b805cb3af82ddd7d3ba22a0e22aba29b78305njn malloc_list = VG_(HT_construct)( "Massif's malloc list" ); 258951d827bcd88ce045a383ea1ca81768757df2d1fanjn 259051d827bcd88ce045a383ea1ca81768757df2d1fanjn // Dummy node at top of the context structure. 2591734b805cb3af82ddd7d3ba22a0e22aba29b78305njn alloc_xpt = new_XPt(/*ip*/0, /*parent*/NULL); 2592734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2593f6b0076ba64f5c22f9e09be70c351a9d4b095883njn // Initialise alloc_fns and ignore_fns. 2594734b805cb3af82ddd7d3ba22a0e22aba29b78305njn init_alloc_fns(); 2595f6b0076ba64f5c22f9e09be70c351a9d4b095883njn init_ignore_fns(); 2596734b805cb3af82ddd7d3ba22a0e22aba29b78305njn 2597734b805cb3af82ddd7d3ba22a0e22aba29b78305njn // Initialise args_for_massif. 25989c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj args_for_massif = VG_(newXA)(VG_(malloc), "ms.main.mprci.1", 25999c606bd8634cd6b67bb41fa645b5c639668cfa2dsewardj VG_(free), sizeof(HChar*)); 260051d827bcd88ce045a383ea1ca81768757df2d1fanjn} 260151d827bcd88ce045a383ea1ca81768757df2d1fanjn 260245f4e7c91119c7d01a59f5e827c67841632c9314sewardjVG_DETERMINE_INTERFACE_VERSION(ms_pre_clo_init) 2603c9f3692175ba544ecef6f905f5dcd755c3b153benethercote 2604734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--------------------------------------------------------------------// 2605734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--- end ---// 2606734b805cb3af82ddd7d3ba22a0e22aba29b78305njn//--------------------------------------------------------------------// 2607